Transcript #186: The treebeard will guard your notebook
Return to episode page view on github00:00 Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to
00:04 your earbuds. This is episode 186, recorded June 10th, 2020. And I'm Brian Okken.
00:11 And I'm Michael Kennedy.
00:12 And this episode is actually brought to you by us. And we'll talk more about some of the ways
00:17 you can support myself and Michael a little later in the show. But first, let's side table that for
00:23 a little bit.
00:23 Side table it. Yeah, let's put it to the side and talk about side table. Yeah, so side table
00:29 is something that I noticed as new project from Chris Moffitt. And longtime listeners of the show
00:35 will definitely know that I'm inspired by visuals. And this is one of those that's really nice, right?
00:42 Like not long ago, when Guido was on the show, we talked about a missing number of visualizer for
00:49 pandas. So you could have a quick view of just like, I got this data, I just need to really quickly see
00:55 kind of what it looks like what's missing correlate missing elements and whatnot.
00:58 And so side table is in this general zen of things. It's like, I've loaded up some data,
01:04 I just want to quickly ask some questions and get a sense of what's going on. Like,
01:08 I've got a pandas data frame. And I want to be able to say, you know, can you just break this down by
01:13 like, show me the top 20% of this and then group the other stuff into just like an other category.
01:18 Also, instead of just getting like a plain text output, you get a cool, like alternating row color,
01:24 nice table with extra information, and whatnot. And it's usually something really, really simple. Like, I could go to the data frame and say,
01:33 just give me the frequency of state and just, you know, group it by that or something. And it's,
01:38 it does a group on those and a whole bunch of cool stuff. So really, really neat visualization. There's a picture in the show notes that shows you without it and with it. And given that the nicer version requires even less typing than the not nice version, I kind of like it.
01:54 Yeah, and just out of the box, having just like the alternating gray and white stripes is good.
02:02 Yeah, absolutely. So basically, all you have to do is a pip install, of course, but then import side table, and it adds an STB functionality to data frames to panda data frames. And then you can ask it questions like frequency. There's other stuff that you can also ask. There's like a bunch of different functionality there.
02:18 So really nice for exploring new data sets. And it's basically a supercharged version of pandas value counts with a little crosstab mixed in. So yeah, it's easy to use. And if you're working with pandas, especially in Jupyter context, you know, that's really where this makes sense. Give it a shot. I think it looks great.
02:36 Does it look good?
02:37 Good job, Chris.
02:37 Yeah, and I Yeah, go ahead.
02:39 No, I didn't. I totally didn't even intend to do another table one back to back. But
02:44 We're kicking it off with all the tables. Yeah, which one you got here?
02:46 So this was a suggestion from Tom McDermott. And for the tabulate package, this is not for it's not intended for Jupyter stuff. It's intended for just standard out sort of things. So you want to pretty print a tabular data in Python for command line utility. Actually, I've been using this for years. I was like, I'm sure we've covered this. And I looked it up. And I don't think we have or at least I can't find it.
03:14 I don't remember us covering either. And it's really sweet. It's like, it generates nice formatted tables, but in ASCII. So like before I said, you know, side tables awesome, if you're going to be doing this within Jupyter. But this is like if you're doing it within just a terminal command line app.
03:30 By default, you've got a list of lists or a list of tuples or something to represent the rows. And you just want to print it with tabulate. It just does it automatically. But you can also, I usually use it with headers. So you pass in the headers separate.
03:46 So header information. And by default, it just prints stuff out with prints of headers and then dashed lines and then your columns underneath. But it also like spaces it correctly because that mean actually that trying to get that right by yourself by hand is just a pain to try to figure out how wide things are supposed to be and whatever.
04:07 So this just does it. And it's great.
04:09 Not only does it do it by text, like the example that you have in the show notes really illustrates like the nuance here. So it's got a list of planets, their radius and masses.
04:19 And for the sun, it has it in scientific notation like 1.8, 1.989 times 10 to the ninth. And then for the other ones, it's like 5,973.6. It aligns the decimal places, not all to the right. I mean, it's glorious.
04:36 Yeah, the alignment is neat. I really appreciate that. So you have control over some of your number formatting and your alignment.
04:42 But also, if you're outputting for different things, there are multiple different formats, including like a simple markdown type table. But it also does GitHub flavored markdown tables and pipes that just look nice if they just kind of make it look like boxes.
04:59 And there's Jira style and MediaWiki and HTML and just plain if you don't want any sort of stuff in between, just spaces in between. It looks nice.
05:09 That's cool. So you could like output this in Jira format and like paste it into a Jira issue as like, here's what we're doing now or here's the problem or here's the data.
05:17 Yeah, definitely. It's a good one for keeping track of tables.
05:21 Yeah. Wow.
05:22 Another good thing is all the stuff that you and I have to offer people to learn more information about lots of stuff.
05:29 Yeah, absolutely. We have the podcast, but we also have other things as well.
05:32 Yeah. So if you want to support what we're doing, one of the things you can do is become a Patreon supporter. So there's a link on the page where you can throw a couple bucks at us a month if you want. But also, I've got a book.
05:43 If anybody was not aware of that, there's a pie test book.
05:47 You've written a pie test book?
05:48 Yeah, I did.
05:50 It's good. I really like it.
05:51 Another podcast called Testing Code. I'd love to have more people go check that out and suggest what you want. So I'd like to have people talk, tell me about what other topics should be covered there.
06:03 Yeah.
06:03 You also offer quite a few learning opportunities for people.
06:07 Yeah, absolutely. The main thing for me, if you want to support me, like obviously we have the Patreon and that's great. But if you want to support us and get something back, you could take one of our courses over at Talk Python Training.
06:18 We're doing all sorts of cool stuff there. We've got like 120 hours of Python courses and exercises beyond that.
06:24 But we recently just kicked off a cohort thing where people can go through as groups.
06:30 So that's something I'm trying to put together and, you know, it will probably be more opportunities to do that as well.
06:35 So, yeah, check it out if you want to learn Python. That's where I recommend people go.
06:38 Yeah. I want to bring something up about your courses. There's a lot of the courses that are, there's a lot of content there and it's wonderful information.
06:46 One of the things I really love, especially in this working from home environment where I don't often have a lot of time, is the way you've broken up all the courses into little tiny pieces.
06:56 So there's a table of contents so you can go through the course and see what you've seen and see what you haven't.
07:01 But you can keep track of what you haven't.
07:03 And there's often just, if you've got like three to five minutes, you can fit in a little extra video.
07:09 Yeah. Thank you so much. That's awesome.
07:11 And I like that you've done that.
07:12 Yeah. I really want to try to make the courses have meaning as a reference afterwards as well.
07:17 And like nobody wants to go back and scan a 30 minute video for that 30 second clip you're looking for.
07:22 Yeah. That's good.
07:22 Awesome. You know what else is really good?
07:24 Tree beards.
07:25 Yeah. For real. Tree beards are pretty awesome.
07:27 Is that like a neck beard?
07:30 But for a tree.
07:31 Okay.
07:32 Okay. Yeah.
07:33 So I actually have no idea the relationship of the neck beard to the tree beard.
07:36 But tree beard is continuous integration for notebooks, which is pretty cool, actually.
07:41 That is cool.
07:42 So this was recommended by Brian Skin.
07:43 And it's continuous integration for a particular subset of notebooks.
07:49 Those are the notebooks that are binder ready.
07:52 So if you're not familiar with binder, I recently did a Talk Python episode on this and came to appreciate binder way more than I originally did.
08:00 So binder is a place where you can basically point a GitHub repo or some repo at.
08:08 Go to binder, point it at your repo.
08:10 Say here's the notebook.
08:11 Here's the dependencies files and everything.
08:13 And then you just click a button and say, let me run this on binder.
08:17 Because if you go to GitHub, you see that possibly the output from the notebook.
08:20 But that's like cached what was run the last time.
08:23 If you want to actually run it and play with it, you can click launch a binder.
08:26 It'll fire up a little Docker image somewhere magically in the cloud.
08:30 And it'll just run it.
08:32 So you basically configure the repo to describe to binder what it needs to run successfully.
08:38 Right?
08:39 So that's how this works.
08:40 Is Treebeard basically says if there's something that can be run on binder, then it will use that same functionality to automatically install the dependencies, which could be like conda or pip or whatever.
08:52 And then it'll run the notebook using that cool library called Paper Mill, which sort of converts notebooks into kind of function type things.
09:00 It'll upload the output.
09:01 It'll upload the output and do an NB convert on the notebook to save it and create like a version stamped last run of your notebook that you can go back through your continuous integration and see the history of the outputs saved as HTML, which is pretty awesome.
09:17 And it integrates with a GitHub app that'll like push notifications back to your repo.
09:22 It integrates with Slack.
09:23 It has all kinds of interesting things like this.
09:26 So really a neat mechanism to make sure that your code just keeps running if it's a notebook.
09:32 Yeah.
09:32 It's even got like secret management.
09:33 So you can, if you have to connect with different things with passwords and stuff.
09:38 Don't you just put those in the notebook?
09:39 No.
09:40 No?
09:41 Darn it.
09:41 No.
09:43 Yeah.
09:44 No, that's really cool.
09:44 It has secret management and all kinds of stuff.
09:46 And basically, when I first saw this, I thought, okay, well, what's the criteria of success, right?
09:52 Like how do I write a test to indicate a successful notebook experience?
09:56 The way it works is basically it runs all the cells.
09:58 And if all the cells run without exceptions, then it's successful.
10:02 So it's not like it's making assertions, but it's kind of like a smoke test.
10:07 Like it didn't entirely explode.
10:09 So we think it's probably okay.
10:10 That's not bad for a starter.
10:12 I mean, conceptually, you could put asserts in there and that would throw an exception.
10:15 Exactly.
10:16 Right.
10:16 You could build in the test at like some layer in there.
10:19 Like have even a Python file that you import that like does the test.
10:22 I don't know.
10:23 Whatever.
10:23 There's a lot of options.
10:24 So you're right.
10:24 You could make your notebook report out.
10:27 Make some cells in there.
10:28 Yeah.
10:28 Make some cells that'll blow up if things go wrong for sure.
10:30 Yeah.
10:31 Somebody should get a hold of us and tell us why beard.
10:33 Yeah.
10:33 Because trees generally don't have beards.
10:36 Well, okay.
10:38 We live in Oregon, so they're often very mossy.
10:41 That's true.
10:42 They've got that little moss thing.
10:43 If it's just right, actually, it could totally do that.
10:45 You're sure?
10:46 Yeah.
10:46 Okay.
10:47 So one thing that surprises me, Brian, that seems to keep coming up and up and both of us
10:51 are talking about it next.
10:52 Like I feel like we've aligned perfectly so far.
10:56 Oh my gosh.
10:56 We are.
10:56 Dude.
10:57 We're both talking about virtual environments.
10:59 You go first.
11:00 Okay.
11:00 So there's a couple of things that we just, in episode 184, we discussed virtualenv and venv.
11:07 And actually I learned quite a bit to find out that virtualenv is still pretty cool and fast,
11:13 but that was in 184.
11:15 But we had people get a hold of us and say, hey, there's more information that you guys don't know.
11:19 And I love that.
11:20 Please keep it coming.
11:21 If we do half the story, give us the rest of it.
11:24 In Python 3.9, so venv, the built-in one, it has a cool new flag called upgrade depths for upgrading your dependencies.
11:34 It's like not all of your dependencies, but it's for virtual environments.
11:38 Every time you create one, we commented that you have to upgrade pip.
11:41 And this new flag allows it.
11:44 So when you install, create a new virtual environment, it automatically upgrades set of tools and pip for you.
11:52 Yeah, that's cool.
11:53 Which is nice.
11:53 That's in Python 3.9.
11:55 I tried it out already.
11:57 I tried it on beta 1.
11:58 Beta 3 is already out.
12:00 So you can try it out if you want.
12:01 The other news is the virtualenv is getting something new, and it's not there yet.
12:08 And I'm not sure when it's coming, but I think it's soon.
12:10 It's getting a feature called periodic update, which is super cool.
12:14 So one of the things, so virtualenv, since it's separate from your Python, or you can have it install, make virtual environments for multiple Pythons, for instance.
12:24 But it also keeps its own cache of new pip, new setup tools, and new wheel, that package you need if you're creating wheels.
12:33 And so it has those upgraded already.
12:35 But the periodic update, it will just have this extra thing that in the background goes off and checks to see if there's new ones around.
12:43 So whenever you actually need to create a new virtual environment, it'll automatically have an updated one that it can install right away, which is neat.
12:53 Yeah, that's pretty cool.
12:54 Nice.
12:55 And if you don't want it to go off and do it in the background, you can manually say, okay, right now I want you to go off and upgrade it right now.
13:01 Okay, that's a cool idea.
13:03 I like it.
13:04 So you've got a better chance of having updated stuff if you're working without an internet connection at the moment or something?
13:10 It already had kept its own version of it that would upgrade it.
13:15 So you already can, it's newer than if you're using VENV.
13:19 But I'm excited about it.
13:21 And one of the other things I wanted to mention is I kind of complained about that the prompt is different.
13:28 And I got a little bit of the skinny about why the prompt is different in virtualenv versus VENV.
13:34 And it had to do with the prompt formatting on different operating systems was different, which is weird.
13:41 But they coalesced it and made it a single prompt.
13:45 And the need for, like, sometimes you actually want to not have a space.
13:50 You might not want to have those parentheses.
13:52 So there may be reasons to not have the parentheses in space.
13:56 So there's reasoning behind it.
13:58 It just still annoys me.
14:00 But that's okay.
14:01 It's cool to actually know why, though.
14:03 That's really nice.
14:04 Yeah.
14:04 So all these things that make working with virtual environments better are great.
14:09 But how about we just don't have virtual environments, but we still do?
14:12 Wouldn't that be better?
14:13 I don't know.
14:14 So let me tell you what I'm thinking.
14:17 So a while ago, for the 3.8 timeframe, there was a proposal called PEP582.
14:25 And PEP582 is put together by a bunch of folks, Steve Dower and four or five other people.
14:32 I'm forgetting Donald Stuff.
14:33 And I know there's two other folks that I'm forgetting.
14:36 Sorry about that.
14:36 But anyway, it was put together.
14:38 And the idea is that it proposes to add a mechanism to automatically recognize a DunderPy packages and prefer importing packages installed in there over global packages.
14:50 So the idea is you just go to your project and say at the top of your project, go, here's the top of my project.
14:56 And then when you pip install stuff, it will put things there.
15:00 You won't have to activate a virtual environment because you're not changing anything outside the global system.
15:07 It's just going to drop it in right there.
15:10 Okay.
15:10 Basically, this is how Node.js works, right?
15:12 So if I'm by NPM install a thing, it just traverses up the directory until it finds a node modules.
15:19 And it's kind of like that, right?
15:21 So it says, if you have this folder here, we're going to automatically install stuff there.
15:25 And then Python will automatically know to look there.
15:28 So if you're anywhere in a subfolder without even activating the virtual environment and you type Python something to run a command, as long as you're in the folder structure, it's going to use that environment.
15:39 Oh, that's pretty cool.
15:39 Yeah, that's pretty cool, right?
15:41 So the motivation, at least, is it's like every time someone's new to Python, they're like, well, I can't install this thing.
15:48 It says access denied.
15:49 You're like, you know, permission denied.
15:51 You're like, well, okay, let me talk to you about virtual environments and why you need them.
15:53 And also to activate the environment on the different shells and the different platforms like Windows versus POSIX, you know, source versus not source and bin versus scripts is different.
16:06 And so that's kind of a pain.
16:07 So the idea also, every time you open up a new terminal or command prompt, you've got to reactivate it.
16:13 Like I've all all for all of these things.
16:15 I have aliases that make this happen, right?
16:18 Yeah.
16:18 So the idea here is that you don't have to worry about any of that stuff.
16:22 You just have to like init your Python project somehow.
16:25 It doesn't I don't remember seeing how that was supposed to happen.
16:27 But once that PyPackages folder is there, it's like, well, that's the top of the project.
16:32 We're going to install there.
16:33 And you presumably could have like a fallback one at the top of your user profile.
16:37 Or something along those lines.
16:39 Yeah, you have that.
16:40 So that's for the packages.
16:42 But what about in virtual environments?
16:44 You also have local scripts that come along entry points.
16:47 Yeah.
16:48 Do you know if it deals with that?
16:49 I don't know.
16:50 I don't know about it.
16:51 It's possible.
16:51 I didn't read like every word of it.
16:53 So it's in draft mode.
16:55 But I was a little confused because it says its version is Python 3.8.
16:59 I'm like, well, 3.8 shipped.
17:00 It should either be closed or published.
17:03 That seems weird.
17:05 So I sent a message to Steve Dower just a moment ago on Twitter.
17:08 And he said that Kushal Das, one of the folks proposing it, I think the primary guy, is still
17:16 working on it.
17:17 The text itself hasn't been updated before 3.8's release, which is why the header is still a
17:21 little bit out of date.
17:22 So it's probably more like a 3.10 thing or something.
17:26 But it's still pretty cool.
17:27 If you want to try to live in this world and see what it's like, David O'Connor has this
17:32 thing called PyFlow.
17:33 And PyFlow basically does this.
17:36 It integrates with PyProject.tom.
17:38 Well, man, we lined it up good this week.
17:40 And you go through, instead of saying pip install, you say PyFlow install.
17:45 Instead of saying Python run, you say Python script, you say PyFlow script.
17:50 Because it has to reinitialize that every time because it's not actually changing something.
17:55 Anyway, it's interesting.
17:57 I would like to see something kind of like this.
17:59 I think it's pretty neat.
18:00 There's also some interesting possibilities around DIRT ENV that I'm looking into.
18:05 Just talking to someone, Chris, who has got some cool ways to have DIRT ENV automatically
18:11 activate virtual environments, which would be kind of cool as well.
18:16 So there's a lot of stuff happening here.
18:18 It still kind of blows my mind.
18:19 There's so much action around something that feels like it's just a, I don't know, so plumbing
18:25 and foundational.
18:25 Yeah.
18:26 But like you said, it is plumbing and foundational, but it's also one of those things that's one
18:31 of those tripping things.
18:32 It's like the loose stone on the sidewalk that trips up all the new people all the time.
18:39 So far, what we've managed to do is we've managed to like spray paint a yellow line on both sides
18:45 of it.
18:45 You know?
18:46 Somebody needs to shave that bad boy down.
18:48 But right now, at least it's like got a little marker on it.
18:51 And I just want to say thanks to Louise Erbier on here.
18:55 Send that over and let me know about this whole project.
18:58 So thank you for that.
18:59 Yeah, that's nice.
19:00 Yeah.
19:00 So speaking of PyProjects.toml, I actually really love, I kind of like this.
19:05 I like awesome lists.
19:06 So awesome lists are a thing.
19:08 We've covered many of them in the past.
19:10 There's even a Python Bytes awesome list.
19:12 Yeah.
19:12 This one is awesome PyProjects.
19:15 PyProject.toml projects.
19:17 So this is one of the great things about different sorts of source code lists is to go and look at
19:24 examples.
19:24 So this is a list of other projects that are out there that already use PyProject.toml.
19:30 So you can look to see how other projects are doing it.
19:33 So if you want to figure out for your own project, this is helpful.
19:38 For instance, a lot of the testing and formatting stuff came along early.
19:41 So covers.py is in there.
19:43 pytest, Tox, Black, iSort.
19:46 I knew all of those.
19:48 Ward was a new one to me.
19:49 So Ward is apparently a way to test things without like string named test functions instead of function
19:56 names.
19:56 I haven't really played with it much other than looking at the documentation.
20:00 But it looks neat.
20:01 But there's a code analysis like PyLint and Unimport and the really long titled We Make Python
20:08 Style Guide, which is a linter and other stuff.
20:11 But it's pretty cool.
20:12 And then it has a couple links to articles about PyProject.toml.
20:16 And then what I think is also neat is a list of projects that are discussing switching to PyProject.toml.
20:25 So you can...
20:25 Oh, yeah.
20:26 That's probably pretty interesting if you're trying to decide yourself, right?
20:30 Yeah.
20:30 To figure out what sort of discussions are going on in other projects as to why to switch and
20:35 why not.
20:35 Yeah, for sure.
20:37 Very cool.
20:38 Very cool.
20:38 Yeah.
20:39 I think people switch.
20:40 I'm using it everywhere because it's just...
20:42 It's sort of easier.
20:43 What confused me for a little while was that it isn't...
20:47 I thought it was something you needed Flit or Poetry to be using.
20:51 But you can use PyProject.toml with setup tools projects also.
20:56 Okay.
20:56 Interesting.
20:57 Yeah.
20:57 I didn't know about that.
20:58 Yeah.
20:58 I kind of thought it was tied to some of these higher order management things like Poetry and
21:03 Flit and so on.
21:04 Yeah.
21:04 Yep.
21:05 Cool.
21:05 And like you said, there's a Python Bytes awesome list if people like awesome lists.
21:10 Sorry.
21:11 I put that at the end there.
21:12 People can check that out.
21:12 Thanks, Jack, for doing that.
21:13 Yeah.
21:14 So that's our six items, Michael.
21:16 Anything extra to share with us?
21:18 I got something for everyone.
21:19 I got two things, actually.
21:20 One follow-up and one new thing.
21:22 First of all, we had Calvin on a while ago, a couple shows ago.
21:27 Was that last show?
21:28 Show before?
21:29 I think a couple shows ago.
21:30 And we were talking about secrets.
21:32 And he also...
21:34 He's in your camp.
21:35 He doesn't put them in the notebook or in the right there in the source code.
21:38 He's doing something else.
21:39 But what he talked about is actually using 1Password as like a vault, right?
21:45 So 1Password has awesome encryption and security.
21:48 And so a lot of the challenges revolve around, well, if I'm going to put them somewhere else,
21:54 if I just put them straight in the virtual into an environment variables, well, people can
21:57 grab them there.
21:58 So maybe I want to put them some other place where it's like encrypted or something, right?
22:03 So he talked about his mechanism of finding all those environment variables at launch and
22:09 then like just as you run your virtual environment, injecting them there, but storing them in 1Password
22:14 instead of just on the file system or something like that.
22:16 So he did a blog post about how he's doing that.
22:19 And so I'm going to just link back to that.
22:20 Yeah, nice.
22:21 That looks pretty cool.
22:22 And also, I want to give a shout out to Talk Python.
22:26 Specifically, the last episode, at least the time of recording, it'll probably not be by the time we publish this.
22:32 But nonetheless, just recently, you were a guest on Talk Python where we talked about 15 awesome pytest plugins,
22:39 mostly a few extensions like using with or alongside, but mostly pytest plugins and went through things like pytest Sugar and Freeze Gun and all sorts of fun stuff.
22:48 So people can't get enough of us.
22:49 They can hear you being a guest over there talking about pytest the entire time.
22:54 Yeah, it's nice.
22:55 Yeah, that was fun.
22:55 Thanks for coming on there.
22:56 I like to hear myself talk so much that I also, we cross posted that on Testing Code as well.
23:03 Yeah, sounds good.
23:04 And one of the things, so as an extra bit, did you know that I wrote a book?
23:08 Yes.
23:09 Yeah, I've heard of that.
23:10 No, it's a great book.
23:11 I have it.
23:11 I published through Pragmatic Publishers, and I just wanted to bring up that Pragmatic has a shiny new website.
23:17 So the Pragmatic site is a little different, and there's an FAQ up there if people want to know why or what's different about it.
23:25 And for the most part, it looks a lot the same to me, but the entire backend is different.
23:29 Yeah, yeah, cool.
23:31 It's a little faster.
23:31 Faster is always nice.
23:33 Makes it nice to work with.
23:35 All right, I have a joke.
23:36 Let's pretend we're roommates.
23:37 You can be the first person, and I'll be the second person, okay?
23:40 Okay.
23:41 Okay.
23:42 Stop by the store on the way home from work.
23:48 Please stop at the market and buy one bottle of milk.
23:51 If they have eggs, bring six.
23:53 I came back with six bottles of milk.
23:56 Why the hell did you buy six bottles of milk?
23:58 I just said it's just the two of us.
24:01 What do you think, man?
24:02 Because they had eggs.
24:03 Obviously, taking this programming logic a little strong, right?
24:08 Stop by the store.
24:09 If they have eggs, get a bottle of milk.
24:11 If they have eggs, get six.
24:12 Cool.
24:13 That's funny.
24:14 Pretty good one, huh?
24:15 Takes a little bit of thinking.
24:17 So, glad we have it written down for people.
24:20 Yeah, yeah.
24:20 We can go back and study it, right?
24:21 Yeah.
24:21 All right.
24:22 Well, thanks a bunch, huh?
24:23 Cool.
24:23 All right.
24:24 Thank you.
24:25 Yep.
24:25 Bye.
24:25 Bye.
24:26 Thank you for listening to Python Bytes.
24:27 Follow the show on Twitter at Python Bytes.
24:30 That's Python Bytes as in B-Y-T-E-S.
24:33 And get the full show notes at pythonbytes.fm.
24:36 If you have a news item you want featured, just visit pythonbytes.fm and send it our way.
24:41 We're always on the lookout for sharing something cool.
24:43 This is Brian Okken.
24:44 And on behalf of myself and Michael Kennedy, thank you for listening and sharing this podcast
24:48 with your friends and colleagues.
24:49 Bye.