WEBVTT 00:00:00.001 --> 00:00:04.260 Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds. 00:00:04.260 --> 00:00:09.000 This is episode 131, recorded May 15th, 2019. I'm Michael Kennedy. 00:00:09.000 --> 00:00:09.880 And I'm Brian Okken. 00:00:09.880 --> 00:00:10.700 Hey, Brian, how are you doing? 00:00:10.700 --> 00:00:12.520 I am good. How are you? 00:00:12.520 --> 00:00:15.720 I still have a little bit of a conference hangover. 00:00:15.720 --> 00:00:20.340 Two conferences in a row and then some parties definitely took it out of me. How about you? 00:00:20.340 --> 00:00:22.440 Oh, yeah. You went to build afterwards. How was that? 00:00:22.440 --> 00:00:25.180 It was good. I did a bunch of podcasting, met some other folks. 00:00:25.180 --> 00:00:29.440 I got to see what a different type of conference than Python looked like. 00:00:29.800 --> 00:00:30.900 And yeah, it's pretty different. 00:00:30.900 --> 00:00:35.200 Okay. So anybody out there from build listening, you can invite me next year. That'd be just fine. 00:00:35.200 --> 00:00:40.340 Yeah, absolutely. Absolutely. So yeah, it was fun. It was fun to be there. 00:00:40.340 --> 00:00:42.760 And it's but it's good to be back home from all the conferencing. 00:00:42.760 --> 00:00:45.500 Yeah, it is. So let's get back into Python. 00:00:45.500 --> 00:00:48.580 Let's get into it. So before we do, though, I want to say thank you to DigitalOcean. 00:00:48.580 --> 00:00:52.400 Check them out at pythonbytes.fm/DigitalOcean. More about that later. 00:00:52.400 --> 00:00:57.300 I feel like we kind of have a little bit of a PEP roundup for this episode, Brian. 00:00:57.600 --> 00:01:01.580 We got at least three peps. Yeah, we got at least three peps making an appearance. Maybe four. 00:01:01.580 --> 00:01:11.220 Okay, well, the ball is rolling now with the new steering council in place. And they're kicking butt and taking names. And it's great. 00:01:11.480 --> 00:01:27.880 So we'll start off with, I just saw this today. Pep 581 is accepted. And that is the GitHub issues for CPython. So CPython has traditionally had its own, I think it was its own custom made defect tracking system or something. 00:01:28.460 --> 00:01:37.980 It hasn't switched yet, but it will be switching to GitHub issues. We'll link to the PEP and also it has discussion of pros and cons, but it has been accepted. 00:01:38.200 --> 00:01:50.600 But the follow on PEP is 588. And I'll quote Barry Warsaw here. It's the migration will be a large effort with much planning, development and testing. And we welcome volunteers who wish to help make it a reality. 00:01:50.820 --> 00:02:02.140 I look forward to your contributions on PEP 588 and the actual work of migrating issues to GitHub. So 588 is, okay, now that we've decided to do it, how are we going to do it? How are we going to do the migration? 00:02:02.700 --> 00:02:05.920 And once they figure that out, they'll probably need some help to do it. 00:02:05.920 --> 00:02:14.900 That's cool. And you know, you spoke to Barry on our episode, our live episode at PyCon, about becoming a core developer and ways you can help. 00:02:14.900 --> 00:02:21.240 And here it sounds like another way you can contribute to CPython without actually writing C code potentially. 00:02:21.240 --> 00:02:27.820 Yeah, I'm not afraid of C code, but I know, I mean, especially in the Python community, there's some people that aren't involved with C code. 00:02:27.820 --> 00:02:30.820 So there's other places, ways to help. And this is one, yeah. 00:02:30.820 --> 00:02:44.040 Yeah, it's one thing to write C code. It's another to write on the core of CPython itself, right? I mean, that's like, it's a super highly polished piece of software and any change you make has like massive ramifications. 00:02:44.040 --> 00:02:47.380 So, right, I can see how it depends on it. No pressure. 00:02:47.380 --> 00:02:52.960 You're going to take down the Instagram influencers if you mess this up. So don't. 00:02:52.960 --> 00:02:53.260 Yeah. 00:02:53.260 --> 00:03:00.640 Maybe some science and other important things as well. I think this is good. You know, Brett Cannon was key in getting, 00:03:00.640 --> 00:03:16.900 CPython, the source code over to GitHub originally. And I feel like this is well overdue, right? Like, having the issues there means you can reference them in check-ins. It means that you get that integration for pull requests and all sorts of stuff. It just makes a lot of sense to do this. 00:03:16.900 --> 00:03:20.500 Yeah. And I have no idea what the migration path looks like. 00:03:20.560 --> 00:03:28.140 Yeah, I was wondering, like, are they going to copy every single issue across? Or is it this a chance to kind of like clean house? 00:03:28.140 --> 00:03:33.760 I go, well, if this bug comes back, it's important enough to worry about. If it doesn't, maybe it's not. 00:03:34.400 --> 00:03:48.480 I've been on projects like that, that we've gone to a different bug tracking system where we just said, well, we'll just leave the other one around. And if anybody really cares about moving them over, we will. But sometimes cleaning up is a good thing. 00:03:48.480 --> 00:03:51.380 Yeah, I totally agree. So how about cleaning up some code? 00:03:51.380 --> 00:03:52.880 Yes, let's clean up code. 00:03:52.880 --> 00:04:00.220 So I'm a big fan of design patterns in general, the solid principles, all these things. I really enjoy, like, thinking about how that influences code. 00:04:00.220 --> 00:04:08.900 And one of the things that makes me crazy when I read code is, like, ultra-nested, indented, conditional stuff. 00:04:08.900 --> 00:04:15.520 And when I see it, I feel like people write code like that because they don't believe there's another way. 00:04:15.520 --> 00:04:23.480 It's just like, well, this code is complicated, so it's, like, indented, you know, 16 spaces or whatever it happens to be indented as, right? 00:04:23.480 --> 00:04:26.800 Like, it doesn't have to be this way most of the time. 00:04:26.800 --> 00:04:33.160 So I just wanted to, like, call out a super easy-to-implement design pattern called guard clauses or guarding clauses. 00:04:33.160 --> 00:04:33.540 Okay. 00:04:33.540 --> 00:04:37.320 Okay, so this is, if you have, like, nested stuff. 00:04:37.320 --> 00:04:43.880 I have two little examples, like a bad one and a good one here in our show notes, and people can check that out. 00:04:44.100 --> 00:04:46.120 And it's, like, a little checkout for a user. 00:04:46.120 --> 00:04:48.600 So a user, they've got a shopping cart. 00:04:48.600 --> 00:04:49.900 They've got some items in there. 00:04:49.900 --> 00:04:50.980 Some of them are available. 00:04:50.980 --> 00:04:51.700 Some of them aren't. 00:04:51.700 --> 00:04:54.240 Some of them are selected to be express-shipped. 00:04:54.240 --> 00:04:56.340 Some of them are not and things like that. 00:04:56.340 --> 00:05:01.180 And so it's got, like, if user is not none, go through their carts. 00:05:01.180 --> 00:05:03.080 If the item is available, add it. 00:05:03.080 --> 00:05:07.640 In addition to that, if the item is selected to be express-shipped, add it. 00:05:07.640 --> 00:05:13.900 And that's, like, just, what is that, a 30 degrees down, 45 degrees down line of code, right? 00:05:13.900 --> 00:05:14.520 It's not vertical. 00:05:14.520 --> 00:05:16.800 It's, like, you know, at an angle, probably 45, right? 00:05:16.800 --> 00:05:17.040 Yeah. 00:05:17.040 --> 00:05:19.800 And every one of these is asserting a positive thing. 00:05:19.800 --> 00:05:23.400 The thing I want, if the user is good, I want to go through them. 00:05:23.400 --> 00:05:25.560 If the thing is available, I want to do this, right? 00:05:25.560 --> 00:05:26.520 And so on and so on. 00:05:26.520 --> 00:05:30.400 Guarding clauses basically check for the negative and bail out as soon as possible. 00:05:30.400 --> 00:05:34.540 So you could rewrite that and go, if the user is none, return empty stuff for their stuff. 00:05:34.540 --> 00:05:37.520 If it's not available, just skip through the loop with a continue and so on. 00:05:37.520 --> 00:05:38.660 And it's much simpler. 00:05:38.660 --> 00:05:41.360 And it's not just about visual code. 00:05:41.360 --> 00:05:45.160 It's not just, like, easier to read, but it's easier to reason about. 00:05:45.280 --> 00:05:50.340 Like, if you get into one of these super nested conditional structures, then it's really hard 00:05:50.340 --> 00:05:53.160 to think about, like, okay, I want this case and that case. 00:05:53.160 --> 00:05:54.400 Like, where does that go? 00:05:54.400 --> 00:05:56.400 Do I need another branch in this if? 00:05:56.400 --> 00:05:57.160 And so on. 00:05:57.160 --> 00:06:00.760 I feel like it's much easier to maintain and add to with these guarding clauses. 00:06:00.760 --> 00:06:04.700 And in the example you're showing, and we're going to have in the show notes, the better 00:06:04.700 --> 00:06:07.400 one actually ends up being more lines of code. 00:06:07.400 --> 00:06:12.420 However, you're visually going to skip over the top part because you're like, oh, I'm just 00:06:12.420 --> 00:06:14.520 making sure that things are the right. 00:06:14.520 --> 00:06:19.200 And then in the middle, I've got highlighted just, like, three lines of code where the actual 00:06:19.200 --> 00:06:19.840 work is. 00:06:19.840 --> 00:06:26.240 And highlighting where the real work is instead of dispersing the real work across lots of if 00:06:26.240 --> 00:06:26.660 clauses. 00:06:26.660 --> 00:06:27.860 I think that's a great idea. 00:06:27.860 --> 00:06:28.380 Yeah, thanks. 00:06:28.380 --> 00:06:29.160 I super love it. 00:06:29.160 --> 00:06:33.380 I'm linking to Martin Fowler's original little article on it, which is like C or JavaScript 00:06:33.380 --> 00:06:33.820 or something. 00:06:33.820 --> 00:06:35.600 But it's, you know, it's if statements. 00:06:35.600 --> 00:06:36.760 It's basically the same idea. 00:06:36.760 --> 00:06:43.540 As well as to one on, from a Go, a Medium article about line of sight programming, talking 00:06:43.540 --> 00:06:45.820 about, like, you can just, you know, see right down the line. 00:06:45.820 --> 00:06:47.360 Anyway, it's all pretty cool. 00:06:47.360 --> 00:06:50.580 I definitely, definitely think how those can be used. 00:06:50.580 --> 00:06:54.240 I find it to make it a lot nicer, a lot easier to maintain this code. 00:06:54.240 --> 00:06:57.420 It'll also reduce the cyclomatic complexity of your code. 00:06:57.420 --> 00:06:57.780 Yes. 00:06:57.780 --> 00:06:58.660 Yes, it will. 00:06:58.660 --> 00:07:03.240 And that also probably, you know, that's cool because it'll make Anthony Shaw happy in his 00:07:03.240 --> 00:07:03.580 Wiley. 00:07:04.460 --> 00:07:10.940 But it also means, like, it's less cognitive overhead to maintain, right? 00:07:10.940 --> 00:07:12.860 You can say, okay, I cleared out the stuff that's not good. 00:07:12.860 --> 00:07:13.740 Now we're in the good spot. 00:07:13.740 --> 00:07:14.740 It's not indented. 00:07:14.740 --> 00:07:15.900 It's not a lot going on. 00:07:15.900 --> 00:07:16.240 You're right. 00:07:16.240 --> 00:07:20.560 It's so simple that I don't, you know, if you're not using it, just check it out. 00:07:20.560 --> 00:07:21.100 It's great. 00:07:21.100 --> 00:07:21.660 Good reminder. 00:07:21.860 --> 00:07:23.160 Speaking of if you're not using it. 00:07:23.160 --> 00:07:23.620 Yeah. 00:07:23.620 --> 00:07:26.220 So the, so Python 3 is a thing. 00:07:26.220 --> 00:07:28.500 We've talked about it a few times in the past. 00:07:28.500 --> 00:07:30.320 There's probably a lot more people. 00:07:30.320 --> 00:07:31.640 Well, I don't know. 00:07:31.640 --> 00:07:36.620 There's probably more people, some people now still converting to Python 3 or starting to 00:07:36.620 --> 00:07:37.260 get used to it. 00:07:37.260 --> 00:07:43.380 The easy hurdles are just to start not using the stuff you can't anymore and some of the 00:07:43.380 --> 00:07:44.520 string changes and whatever. 00:07:44.680 --> 00:07:49.980 But here's an article we ran across called Things You're Probably Not Using in Python 3, 00:07:49.980 --> 00:07:50.600 but Should. 00:07:50.600 --> 00:07:56.120 So there's a lot of new items in Python 3, but this article goes through a handful. 00:07:56.120 --> 00:08:02.840 So there's some obvious, I think obvious, of course, items like fstrings, pathlib, and maybe 00:08:02.840 --> 00:08:03.580 data classes. 00:08:03.580 --> 00:08:05.780 I'm using them a lot, but, you know, maybe. 00:08:05.780 --> 00:08:09.100 fstrings and pathlib, definitely everybody should be using those. 00:08:09.100 --> 00:08:09.820 Those are awesome. 00:08:09.820 --> 00:08:12.360 I'm warming to type hinting a little bit more. 00:08:12.360 --> 00:08:14.820 I think it's feeling more natural. 00:08:14.820 --> 00:08:17.240 You know, I'm not really a zealot about it. 00:08:17.240 --> 00:08:23.700 But when I start trying to see myself start typing a comment to say what kind of stuff should 00:08:23.700 --> 00:08:27.840 go into a function or what should be in a variable, I'm like, oh, I could just put a type hint 00:08:27.840 --> 00:08:28.220 on there. 00:08:28.220 --> 00:08:29.240 Exactly. 00:08:29.240 --> 00:08:30.160 Yeah. 00:08:30.160 --> 00:08:30.460 Exactly. 00:08:30.460 --> 00:08:30.880 Yeah. 00:08:30.880 --> 00:08:32.260 Comments are deodorant, right? 00:08:32.260 --> 00:08:34.600 They go on to bad code to make it smell better. 00:08:34.600 --> 00:08:37.160 But maybe you should just make it better by putting some type hint. 00:08:37.160 --> 00:08:38.120 Maybe type hint. 00:08:38.220 --> 00:08:38.380 Yeah. 00:08:38.380 --> 00:08:43.020 So especially when it's, I'm only intending it for like the reader. 00:08:43.020 --> 00:08:45.920 I'm not using some testing tools around that. 00:08:45.920 --> 00:08:49.320 But there's some stuff that I knew about that I just kind of forgot. 00:08:49.320 --> 00:08:53.060 So I'm glad that I'm going to list three that he listed. 00:08:53.060 --> 00:08:59.800 Enumerations with the new enum package and enum and auto methods and classes. 00:08:59.800 --> 00:09:00.160 Yeah. 00:09:00.160 --> 00:09:01.160 I love enums. 00:09:01.160 --> 00:09:01.900 They're really great. 00:09:01.980 --> 00:09:04.740 I don't use them enough, but yeah, they're super enough. 00:09:04.740 --> 00:09:07.620 I want to use them a little bit more after this reminder. 00:09:07.620 --> 00:09:10.820 Also, LRU cache is built in. 00:09:10.820 --> 00:09:16.240 It's a decorator in func tools that you can use really easy memoization. 00:09:16.620 --> 00:09:22.280 So if anybody's not familiar with LRU cache or memoization, the gist of it is, is you just 00:09:22.280 --> 00:09:23.820 throw this decorator on a function. 00:09:23.820 --> 00:09:30.060 If it's really functional programming type stuff where you pass in some value and you get at 00:09:30.060 --> 00:09:35.420 and that has no behavioral side effects and it just returns some other, some value that's 00:09:35.420 --> 00:09:38.820 a one-to-one correlation between input and output. 00:09:38.820 --> 00:09:40.760 And it's called a lot. 00:09:41.100 --> 00:09:46.400 You can use memoization with LRU cache to speed it up and it just remembers the old stuff. 00:09:46.400 --> 00:09:46.580 Yeah. 00:09:46.580 --> 00:09:50.720 It just says like, if I see this argument come in, say you have a number in your example, 00:09:50.720 --> 00:09:56.080 like if the number 72 comes in and the answer was 7,000, the next time it's called, it just 00:09:56.080 --> 00:09:57.640 goes, that argument's 72. 00:09:57.640 --> 00:09:59.280 We know it's not changed. 00:09:59.280 --> 00:10:00.600 The answer is going to be 7,000. 00:10:00.600 --> 00:10:05.980 Anytime you have a function that basically is deterministic, you give it the same input, 00:10:05.980 --> 00:10:06.920 it gives you the same output. 00:10:06.920 --> 00:10:08.500 This is a super good option. 00:10:08.760 --> 00:10:08.820 Yeah. 00:10:08.820 --> 00:10:12.660 Especially if it's something that's like time consuming, it has to do some data crunching 00:10:12.660 --> 00:10:13.080 or something. 00:10:13.080 --> 00:10:13.340 Yep. 00:10:13.340 --> 00:10:19.600 The last one I'm going to highlight that I totally forgot about is extended iterable unpacking. 00:10:19.600 --> 00:10:25.240 And this one you kind of have to see to get it, but basically you can, when you like, for 00:10:25.240 --> 00:10:29.360 instance, if you're unpacking a list with a three element list, you can assign it to three 00:10:29.360 --> 00:10:29.820 variables. 00:10:29.820 --> 00:10:30.980 We know that. 00:10:30.980 --> 00:10:36.900 But if you have more than three, you can put a star on one of those things and it'll catch 00:10:36.900 --> 00:10:37.860 all of the rest. 00:10:37.860 --> 00:10:39.920 And that's cool. 00:10:39.920 --> 00:10:42.580 There's lots of places that I could use that that I forgot about. 00:10:42.580 --> 00:10:45.220 You know, you can even do the star in the middle, right? 00:10:45.220 --> 00:10:48.520 You've got like head, star, body, and tail for five things. 00:10:48.520 --> 00:10:50.060 And the body is three things. 00:10:50.060 --> 00:10:50.620 Pretty awesome. 00:10:50.620 --> 00:10:50.920 Yeah. 00:10:51.020 --> 00:10:54.720 When I look at this and I think about it, you know, obviously there's a lot of people 00:10:54.720 --> 00:10:59.340 moving to modern Python and using it in their code, right? 00:10:59.340 --> 00:11:06.060 But just like you could come from C and write non-Pythonic Python, you could move to Python 00:11:06.060 --> 00:11:08.980 3 and write non-Python 3-ic? 00:11:08.980 --> 00:11:09.520 I don't know. 00:11:09.520 --> 00:11:12.700 Like you could write code that's not idiomatic to Python 3, right? 00:11:12.700 --> 00:11:17.340 You still do everything in the Python 2 style, not taking advantage of any of these things, 00:11:18.140 --> 00:11:18.400 right? 00:11:18.400 --> 00:11:23.680 Like f-strings, pathlibs, type hinting, async and await, you know, like you said, enums. 00:11:23.680 --> 00:11:26.840 You could like do none of that and still be quote using Python 3. 00:11:26.840 --> 00:11:29.060 So I think it's cool. 00:11:29.060 --> 00:11:32.860 A cool reminder and example of things you could do to be more idiomatically Python 3. 00:11:32.860 --> 00:11:33.220 Yeah. 00:11:33.220 --> 00:11:37.520 Actually, when I was thinking about that, the author of this even says some of his old articles 00:11:37.520 --> 00:11:39.600 are written essentially for Python 2. 00:11:39.980 --> 00:11:44.980 And I think that's a great place for people if they're new to, they want to start doing 00:11:44.980 --> 00:11:48.640 technical blogging and they don't really have some ideas on what to do. 00:11:48.640 --> 00:11:54.760 You could go look at some common and popular articles that are written in Python 2 style and 00:11:54.760 --> 00:11:57.420 kind of make them your own and do a similar article. 00:11:57.420 --> 00:12:02.980 Don't copy it, but do a similar article with Python 3 syntax and you'll probably get some 00:12:02.980 --> 00:12:03.220 hits. 00:12:03.680 --> 00:12:04.400 Yeah, for sure. 00:12:04.400 --> 00:12:08.280 Or even if you really love that resource you're reading, you could send them a note like, 00:12:08.280 --> 00:12:10.900 hey, I'd love to upgrade these three articles to Python 3. 00:12:10.900 --> 00:12:11.520 Could I help you? 00:12:11.520 --> 00:12:11.960 Oh, yeah. 00:12:11.960 --> 00:12:12.920 That would be much nicer. 00:12:12.920 --> 00:12:13.400 Do that. 00:12:13.400 --> 00:12:13.640 Yeah. 00:12:16.220 --> 00:12:17.920 Well, they both have their own merits, right? 00:12:17.920 --> 00:12:18.180 Yeah. 00:12:18.180 --> 00:12:19.880 Speaking of merits, let me tell you about DigitalOcean. 00:12:19.880 --> 00:12:22.760 DigitalOcean is powering all of our things, which is awesome. 00:12:22.760 --> 00:12:25.280 And we talked about GitHub at the beginning. 00:12:25.280 --> 00:12:28.340 One of the big things GitHub is doing is GitHub Actions. 00:12:28.340 --> 00:12:34.440 So kind of automated workflow for things that happen, you know, check-ins and other stuff 00:12:34.440 --> 00:12:35.100 on GitHub. 00:12:35.100 --> 00:12:42.320 And DigitalOcean has a GitHub Actions for DigitalOcean that you can install and plug in there. 00:12:42.320 --> 00:12:47.500 So you can take your workflow that's happening on GitHub and automatically use that to do 00:12:47.500 --> 00:12:53.540 things like create a new virtual machine or push a new version to a Kubernetes, managed 00:12:53.540 --> 00:12:58.240 Kubernetes cluster based on a push or something like that, right? 00:12:58.240 --> 00:13:00.460 Or maybe snapshot it when an issue is filed. 00:13:00.460 --> 00:13:00.900 Who knows? 00:13:00.900 --> 00:13:05.260 But all sorts of cool stuff you can do with GitHub Actions and DigitalOcean mixed together 00:13:05.260 --> 00:13:05.620 with that. 00:13:05.620 --> 00:13:09.860 So check that out at pythonbytes.fm/DigitalOcean. 00:13:10.020 --> 00:13:11.720 Get $100 free credit for new users. 00:13:11.720 --> 00:13:13.660 Definitely can recommend them. 00:13:13.660 --> 00:13:14.640 They're doing good stuff. 00:13:14.640 --> 00:13:16.320 So how about some fun, Brian? 00:13:16.320 --> 00:13:18.300 Yeah, we got a couple of fun ones. 00:13:18.300 --> 00:13:18.820 Yeah, yeah. 00:13:18.820 --> 00:13:20.020 Let's play a few games here. 00:13:20.020 --> 00:13:23.060 It's awesome that these came up just right by each other. 00:13:23.060 --> 00:13:31.500 So I want to talk about this thing called the Python Arcade Library, which is at arcade.academy, 00:13:31.500 --> 00:13:34.940 which I didn't even know .academy was a top-level domain. 00:13:34.940 --> 00:13:37.140 But apparently, apparently it is. 00:13:37.140 --> 00:13:38.080 That's pretty awesome. 00:13:38.080 --> 00:13:46.720 So this is a library for easily building 2D games in Python that run at like 60 frames 00:13:46.720 --> 00:13:47.820 a second on OpenGL. 00:13:47.820 --> 00:13:48.280 Oh, neat. 00:13:48.280 --> 00:13:49.020 That's pretty cool, right? 00:13:49.020 --> 00:13:52.040 So it's really about like this is by a guy. 00:13:52.040 --> 00:13:53.180 I believe his name is Paul. 00:13:53.180 --> 00:13:55.420 Paul, hopefully I'm getting that right. 00:13:55.420 --> 00:13:58.020 He built this to help teach. 00:13:58.020 --> 00:13:59.320 He teaches at a college. 00:13:59.460 --> 00:14:03.000 And it helps teach his students a more visual way to learn programming. 00:14:03.000 --> 00:14:04.620 So it's not to teach game development. 00:14:04.620 --> 00:14:05.720 It's to teach programming. 00:14:05.720 --> 00:14:12.320 But because it's got a visual aspect and not just like a terminal version, you can see what 00:14:12.320 --> 00:14:14.280 you're creating more easily and see it working. 00:14:14.280 --> 00:14:15.040 So that's pretty cool. 00:14:15.040 --> 00:14:19.920 You can create like Minesweeper games, Hangman games, and in particular, platformer games, 00:14:19.920 --> 00:14:20.420 right? 00:14:20.420 --> 00:14:25.240 So if you wanted to recreate Lemmings or he wanted to do like Joust or whatever, like you 00:14:25.240 --> 00:14:26.340 could totally use this for that. 00:14:26.340 --> 00:14:26.920 Ooh, neat. 00:14:27.000 --> 00:14:30.180 Yeah, and you can check out the sample games made with that. 00:14:30.180 --> 00:14:33.500 So there's like a tower defense game. 00:14:33.500 --> 00:14:34.900 I'm a sucker for tower defense. 00:14:34.900 --> 00:14:37.060 There's like a little Angry Bird thing made. 00:14:37.060 --> 00:14:38.320 There's all sorts of fun stuff. 00:14:38.320 --> 00:14:39.680 There's tons of examples here. 00:14:39.680 --> 00:14:44.760 I think mostly because these are students who are taking the class but then submitting their 00:14:44.760 --> 00:14:45.220 projects. 00:14:45.220 --> 00:14:46.340 Oh, that's a great idea. 00:14:46.340 --> 00:14:47.020 Yeah, nice, right? 00:14:47.020 --> 00:14:48.220 Yeah. 00:14:48.220 --> 00:14:50.780 Yeah, and I like these 2D games. 00:14:50.780 --> 00:14:51.900 I do too. 00:14:52.500 --> 00:14:56.680 Yeah, and it also includes things like physics, which is nice because it's one thing to get 00:14:56.680 --> 00:14:57.720 the graphics on the screen. 00:14:57.720 --> 00:15:01.780 But hit detection, physics, sound, all these other things are super hard. 00:15:01.780 --> 00:15:04.820 And I believe sound is still like a little bit of an iffy feature here. 00:15:04.820 --> 00:15:06.660 I hear that that's tough in Python. 00:15:06.660 --> 00:15:10.040 So maybe that's like a cool C extension somebody should write. 00:15:10.040 --> 00:15:10.420 I don't know. 00:15:10.420 --> 00:15:12.600 But anyway, it's all based on OpenGL. 00:15:12.880 --> 00:15:14.160 And it looks pretty cool. 00:15:14.160 --> 00:15:17.440 So definitely want to recommend that people check that out. 00:15:17.440 --> 00:15:17.960 Yeah. 00:15:17.960 --> 00:15:19.600 And you guys, similar one. 00:15:19.600 --> 00:15:20.180 How about that? 00:15:20.180 --> 00:15:20.860 Yeah. 00:15:20.860 --> 00:15:26.600 So I wanted to highlight an article called Teaching a Kid to Code with Pygame Zero, written by Matt 00:15:26.600 --> 00:15:26.920 Lehman. 00:15:26.920 --> 00:15:30.600 So this is just this guy with his kids. 00:15:30.600 --> 00:15:32.280 He likes to play video games with his kid. 00:15:32.280 --> 00:15:35.420 And I thought, you know, I should try to teach him how to code. 00:15:36.100 --> 00:15:40.280 And they tried, his son did like a version of Scratch. 00:15:40.280 --> 00:15:45.540 But the worry is that Scratch is really far removed from actual coding. 00:15:45.540 --> 00:15:49.320 And the skills you build might not be transferable really easily. 00:15:49.320 --> 00:15:55.040 So I went ahead and decided to try Pygame Zero using the Mew editor. 00:15:55.040 --> 00:16:03.980 And I guess Pygame Zero is already pre-installed in Mew, as is a Python interpreter. 00:16:03.980 --> 00:16:05.060 I didn't know that. 00:16:05.060 --> 00:16:05.620 That's cool. 00:16:05.620 --> 00:16:06.480 Yeah, that's great. 00:16:06.480 --> 00:16:09.160 And so a quote from somewhere. 00:16:09.160 --> 00:16:14.620 Pygame Zero is intended for use in education so that teachers can teach basic programming 00:16:14.620 --> 00:16:19.240 without needing to explain the Pygame API or write an event loop. 00:16:19.240 --> 00:16:26.240 He worked with his son and they came up with a 29 line of code, including blank spaces. 00:16:26.240 --> 00:16:27.040 Little game. 00:16:27.040 --> 00:16:28.280 Doesn't really do much. 00:16:28.280 --> 00:16:30.060 But it teaches a lot. 00:16:30.060 --> 00:16:34.680 So he said that his son learned about naming things and variables and mutability. 00:16:35.140 --> 00:16:39.960 Fiddling with constants to see how those will affect the screen size and stuff like that. 00:16:39.960 --> 00:16:44.460 Writing functions that have side effects and interacting with mouse events. 00:16:44.700 --> 00:16:47.860 So he learned quite a bit with just this little bit of code. 00:16:47.860 --> 00:16:49.360 And it's actually Python. 00:16:49.360 --> 00:16:50.880 So that's kind of neat. 00:16:50.880 --> 00:16:56.520 And then one of the things I really like, because I do want to start, I haven't worked with my kids with coding yet, 00:16:56.520 --> 00:17:02.220 but the article also includes some tips on how to behave as the adult when you're working with kids with coding. 00:17:02.580 --> 00:17:03.360 This is good. 00:17:03.360 --> 00:17:13.160 Yeah, it's truly tricky to set up the right balance of it's interesting, but like quickly becomes too hard or it's easy enough to get kids started. 00:17:13.160 --> 00:17:18.000 But it's, you know, they have expectations of something they can do with their iPhone as a game. 00:17:18.000 --> 00:17:21.460 And what you build does not necessarily match, right? 00:17:21.860 --> 00:17:26.520 Yeah, and I'm, I like the tips at the end because I'm one of those kind of people that would just say, 00:17:26.520 --> 00:17:29.180 okay, you just sit on the side and I'll do it and you watch. 00:17:29.180 --> 00:17:30.480 It's not really teaching. 00:17:30.480 --> 00:17:31.860 Yeah, true, true, true. 00:17:32.660 --> 00:17:33.340 It's cool though. 00:17:33.340 --> 00:17:39.440 I think these are both really fun options for teaching kids programming and building a little game. 00:17:39.440 --> 00:17:42.960 Because, you know, not everybody cares about building games, but a lot of people who do, 00:17:42.960 --> 00:17:47.040 like a lot of people's introduction to programming was they wanted to build a game. 00:17:47.040 --> 00:17:50.040 Programming was just what was required to make that happen, right? 00:17:50.040 --> 00:17:54.300 And you can go do something else like a useful utility that somebody might need. 00:17:54.300 --> 00:17:59.180 But I mean, how many like six-year-olds really need a useful utility written in Python? 00:17:59.180 --> 00:18:00.200 Yeah, true, true, true. 00:18:00.200 --> 00:18:00.860 Anyway. 00:18:00.860 --> 00:18:02.000 Cool. 00:18:02.000 --> 00:18:06.020 While we're talking about games, like if kids are not quite ready for a game, 00:18:06.020 --> 00:18:13.060 but they're ready to do adventurous stuff, I guess, I want to throw a shout out to CodeCombat.com. 00:18:13.060 --> 00:18:14.600 That's a super cool place. 00:18:14.600 --> 00:18:21.000 It has a free version where you basically go into these dungeons and you solve the dungeon by writing Python programs. 00:18:21.000 --> 00:18:21.480 Oh, neat. 00:18:21.480 --> 00:18:25.080 And the editor has like autocomplete like nobody's business. 00:18:25.080 --> 00:18:26.540 It's super, super nice. 00:18:26.540 --> 00:18:28.300 So you have to like have your hero move around. 00:18:28.300 --> 00:18:31.100 You say like hero.attack and select like an enemy. 00:18:31.340 --> 00:18:34.100 You type the letter A, it'll autocomplete hero.attack. 00:18:34.100 --> 00:18:37.000 I mean, it's like really, really beginner friendly. 00:18:37.000 --> 00:18:40.120 So definitely, you know, that's maybe a first step. 00:18:40.120 --> 00:18:43.140 And then like one of these two that we just spoke about would be really good as well. 00:18:43.140 --> 00:18:44.280 Oh, I'll try that. 00:18:44.400 --> 00:18:46.740 Yeah, I was doing that one with my daughter and she was super into it. 00:18:46.740 --> 00:18:48.220 She got like 50 levels in or something. 00:18:48.220 --> 00:18:49.800 50 little dungeons. 00:18:49.800 --> 00:18:50.200 Cool. 00:18:50.200 --> 00:18:51.040 So, all right. 00:18:51.040 --> 00:18:53.780 So last one, let's round it up with something a little more serious. 00:18:54.360 --> 00:19:03.140 So, we talked before about whether or not the GIL will become obsolete with the introduction of PEP 554. 00:19:03.140 --> 00:19:06.160 And this was on episode 128, which is cool. 00:19:06.520 --> 00:19:11.040 So, Anthony Shaw wrote a cool article called Has the Python Gil been Slain? 00:19:11.040 --> 00:19:15.760 That really digs deeply into that idea that we were touching on back then. 00:19:15.760 --> 00:19:18.720 So, the answer is kind of, maybe. 00:19:18.720 --> 00:19:19.320 I don't know. 00:19:19.320 --> 00:19:20.560 Probably. 00:19:20.560 --> 00:19:22.220 But for a limited case. 00:19:22.880 --> 00:19:28.180 So, we've got a multi-threading in Python, which is pretty easy, but it's not actually concurrent because of the GIL. 00:19:28.180 --> 00:19:33.020 We have multi-processing, which is harder to exchange data and stuff. 00:19:33.020 --> 00:19:37.040 It carries a lot of overhead, but does escape the GIL because it's all these separate processes. 00:19:37.040 --> 00:19:38.180 Right? 00:19:38.180 --> 00:19:42.680 So, PEP 554 introduces this idea of sub-interpreters. 00:19:42.680 --> 00:19:44.200 Remember that from back then, right? 00:19:44.200 --> 00:19:44.460 Yeah. 00:19:44.460 --> 00:19:51.980 And we speculated that maybe the ability to have multiple sub-interpreters would remove the problem of the GIL. 00:19:52.040 --> 00:19:54.060 Because the GIL is not a process thing. 00:19:54.060 --> 00:19:55.340 It's an interpreter thing. 00:19:55.340 --> 00:19:56.820 It's a global interpreter lock. 00:19:56.820 --> 00:20:02.100 So, if we just take and run our threads on multiple sub-interpreters, there would be no GIL. 00:20:02.100 --> 00:20:05.480 Things would go potentially faster at least some of the time, right? 00:20:05.480 --> 00:20:11.980 The problem is if you actually try to share data across those sub-interpreters, things get pretty tricky. 00:20:11.980 --> 00:20:19.900 So, Anthony's article really digs into that and talks about how you might use shared memory and IPC, 00:20:20.120 --> 00:20:22.640 which is also another feature coming to multiprocessing. 00:20:22.640 --> 00:20:25.500 But that's also kind of slow and challenging. 00:20:25.500 --> 00:20:27.880 So, he highlights another PEP. 00:20:27.880 --> 00:20:29.620 So, here's our fourth PEP. 00:20:29.620 --> 00:20:33.540 PEP 574, which proposes a new Pickle protocol. 00:20:33.540 --> 00:20:34.620 Is that surprising? 00:20:34.620 --> 00:20:36.580 Yeah, a little bit. 00:20:36.580 --> 00:20:37.080 A little bit. 00:20:37.080 --> 00:20:38.500 Because, like people say, don't use Pickle. 00:20:38.580 --> 00:20:43.840 It has all these vulnerabilities and versioning issues and whatnot, except for it's a nice binary format. 00:20:43.840 --> 00:20:50.160 And if your goal is to just literally exchange data from sub-interpreter to sub-interpreter through shared memory, 00:20:50.160 --> 00:20:52.840 well, then, like, that's fine. 00:20:52.840 --> 00:20:54.960 That's, like, within the runtime of a process. 00:20:54.960 --> 00:20:56.360 It should be okay, right? 00:20:56.360 --> 00:20:57.680 You're not going to hack yourself. 00:20:57.680 --> 00:20:58.900 And if you do, you deserve it. 00:20:58.900 --> 00:20:59.140 Yeah. 00:20:59.140 --> 00:21:07.600 So, this is a special protocol version 5 that has support for allowing memory buffers to be handled separately for the rest of the Pickle stream, basically. 00:21:07.600 --> 00:21:13.620 So, all these things could be combined together to get us a cool, faster, more concurrent Python. 00:21:14.500 --> 00:21:16.060 And he answers the question, when? 00:21:16.060 --> 00:21:17.680 When will maybe these things be here? 00:21:17.680 --> 00:21:24.600 So, Pickle version 5 and shared memory will probably make it to Python 3.8, which will be October of this year, 2019. 00:21:24.600 --> 00:21:34.940 And sub-interpreters may make that, but they might take another version 3.9, which I believe at the time that's going to be 18 months later. 00:21:34.940 --> 00:21:38.200 I think we're still on the 18-month release cycle here. 00:21:38.200 --> 00:21:38.560 Yeah. 00:21:38.560 --> 00:21:43.120 What I really appreciate about this article isn't that there's suddenly stuff that I can use now. 00:21:43.520 --> 00:21:51.760 It's that we have been talking about the sub-interpreters, and I haven't really got my head around really how that affects us. 00:21:51.760 --> 00:21:54.980 And I think this is a good jump in, a good discussion about it. 00:21:54.980 --> 00:22:02.020 So, if you're curious about this, he talks about all the kind of the backstory and kind of where we're going from here. 00:22:02.020 --> 00:22:05.460 The where we're going from here, I think, is still kind of up in the air. 00:22:05.460 --> 00:22:09.340 I would like to see something more around like a shared memory. 00:22:09.340 --> 00:22:16.820 One of the discussions is having shared memory objects that are owned by one sub-interpreter at a time. 00:22:16.820 --> 00:22:21.560 So, you could say, well, I'm creating this data to have another interpreter take it over. 00:22:21.560 --> 00:22:21.800 Right. 00:22:21.800 --> 00:22:23.040 I'm handing it off to you. 00:22:23.040 --> 00:22:23.820 You can have it now. 00:22:23.820 --> 00:22:24.240 Yeah. 00:22:24.240 --> 00:22:26.280 And it would be nice if I didn't have to pickle that. 00:22:26.280 --> 00:22:34.920 If I could just, the data I'm creating is just normal data, but it happens to live in an area that I can hand over to a different process or something. 00:22:35.040 --> 00:22:35.700 Oh, that's interesting. 00:22:35.700 --> 00:22:42.920 Like, basically dereference it in the current garbage collector system and re-reference that information in the other one. 00:22:42.920 --> 00:22:43.300 Yeah. 00:22:43.300 --> 00:22:43.860 Somehow. 00:22:43.860 --> 00:22:44.600 Something like that. 00:22:44.600 --> 00:22:45.020 Yeah. 00:22:45.020 --> 00:22:45.200 Yeah. 00:22:45.200 --> 00:22:45.380 Okay. 00:22:45.380 --> 00:22:45.680 Cool. 00:22:45.680 --> 00:22:48.440 There's, I'm sure, lots of smart people working on the problem. 00:22:48.440 --> 00:22:49.560 But it is neat. 00:22:49.560 --> 00:22:51.360 It's neat to see it going forward. 00:22:51.360 --> 00:22:51.700 Absolutely. 00:22:51.920 --> 00:22:57.960 Plus, there's a really amusing video of a breakdancer where, like, six guys come out. 00:22:57.960 --> 00:23:01.080 None of them are doing anything except for one who's spitting on his head. 00:23:01.080 --> 00:23:02.560 Yeah. 00:23:02.560 --> 00:23:05.500 It's a very, I don't know even how to describe it. 00:23:05.500 --> 00:23:10.880 It's a very different interpretation of how the global interpreter lock kills concurrency through breakdancing. 00:23:10.880 --> 00:23:11.960 Yeah. 00:23:11.960 --> 00:23:12.820 Through breakdancing. 00:23:12.820 --> 00:23:15.160 I knew it all along, man. 00:23:15.160 --> 00:23:16.180 The rap beat was off. 00:23:16.180 --> 00:23:18.040 That's why we can't get this scene to run in parallel. 00:23:18.040 --> 00:23:18.480 Yeah. 00:23:19.780 --> 00:23:20.300 All right. 00:23:20.300 --> 00:23:20.480 Cool. 00:23:20.480 --> 00:23:22.900 Well, that's it for our main topics today. 00:23:22.900 --> 00:23:24.920 What else you got that you just want to quickly chat about? 00:23:24.920 --> 00:23:25.680 A couple things. 00:23:25.680 --> 00:23:29.900 PyCon seems like it just got over, but the videos are already all available. 00:23:29.900 --> 00:23:36.340 And I've already started watching them, including Ant's Complexity with Wiley Talk. 00:23:36.340 --> 00:23:46.420 And the other thing I wanted to bring up is I'm reviewing, I'm not reviewing it, but I bought the new Pragmatic Programmer book, the 20th Anniversary Edition. 00:23:46.420 --> 00:23:48.140 They rewrote it. 00:23:48.140 --> 00:23:50.900 And I'm reading the testing chapter starting there. 00:23:50.900 --> 00:23:52.420 And they bring up pytest. 00:23:52.420 --> 00:23:54.920 And they're using pytest and Hypothesis. 00:23:54.920 --> 00:23:55.600 And that's pretty cool. 00:23:55.600 --> 00:23:56.020 Oh, yeah. 00:23:56.020 --> 00:23:56.700 That's super cool. 00:23:56.700 --> 00:23:57.640 And Hypothesis. 00:23:57.640 --> 00:23:59.080 That's pretty interesting, that one. 00:23:59.080 --> 00:23:59.460 Yeah. 00:23:59.460 --> 00:23:59.740 All right. 00:23:59.740 --> 00:24:02.240 Well, I have a couple quick announcements for you all. 00:24:02.240 --> 00:24:03.800 So, first of all, quick and easy one. 00:24:03.800 --> 00:24:05.800 I've been creating a bunch of different things lately. 00:24:05.800 --> 00:24:10.600 The iOS and Android apps are both out for the Talk Python training stuff. 00:24:11.040 --> 00:24:14.900 But I just released new versions that have a couple of cool new features. 00:24:14.900 --> 00:24:16.840 So, if you have it installed, make sure you update it. 00:24:16.840 --> 00:24:21.480 If you don't have it installed, well, check it out at training.talkpython.fm. 00:24:21.480 --> 00:24:22.220 That's cool. 00:24:22.420 --> 00:24:26.920 So, Brian, I've joined you in the journey that is writing a book. 00:24:26.920 --> 00:24:27.480 Yes. 00:24:27.480 --> 00:24:28.440 You're an author now. 00:24:28.440 --> 00:24:28.920 Yeah. 00:24:28.920 --> 00:24:29.760 Apparently. 00:24:29.760 --> 00:24:31.340 Somehow. 00:24:31.340 --> 00:24:31.740 Somehow. 00:24:31.940 --> 00:24:38.400 I don't feel like I've gotten any official stamp or any letter or a little pamphlet that 00:24:38.400 --> 00:24:39.360 makes me officially an author. 00:24:39.360 --> 00:24:39.800 But, yeah. 00:24:39.800 --> 00:24:42.740 So, we have a book called Effective PyCharm that's out. 00:24:42.740 --> 00:24:44.000 And it has a digital version. 00:24:44.000 --> 00:24:45.680 It has a print version. 00:24:45.680 --> 00:24:48.120 It has sort of bundled stuff with some of the courses. 00:24:48.120 --> 00:24:50.100 So, I'll link to that in the show notes. 00:24:50.100 --> 00:24:52.980 People can check that out at effectivepicharm.com. 00:24:52.980 --> 00:24:54.120 So, that's pretty cool. 00:24:54.120 --> 00:24:57.620 And then, also, we just released a new course, 100 Days of Web. 00:24:57.620 --> 00:24:58.420 It's pretty neat. 00:24:58.420 --> 00:24:59.360 I've started watching it. 00:24:59.360 --> 00:25:00.060 I like it. 00:25:00.060 --> 00:25:00.240 Yeah. 00:25:00.240 --> 00:25:00.480 Thanks. 00:25:00.480 --> 00:25:01.700 Thanks for checking it out. 00:25:01.700 --> 00:25:02.340 That's awesome. 00:25:02.340 --> 00:25:03.600 So, it's kind of intense. 00:25:03.600 --> 00:25:06.640 It's like 28 little different web projects. 00:25:06.640 --> 00:25:08.740 So, one time you build an API in Flask. 00:25:08.740 --> 00:25:11.060 And one time we build, like, logins with Django. 00:25:11.060 --> 00:25:13.320 And migrations with SQLAlchemy. 00:25:13.320 --> 00:25:16.540 So, all these different things you might want to do all over. 00:25:16.540 --> 00:25:18.860 It's kind of like a super sampling of all the web stuff. 00:25:18.860 --> 00:25:19.880 So, check that out. 00:25:19.880 --> 00:25:23.040 You know, the links in the show notes at Talk Python Training as well. 00:25:23.040 --> 00:25:24.480 All right. 00:25:24.480 --> 00:25:26.380 Well, that's all I got for now. 00:25:26.380 --> 00:25:27.660 Do you got a joke for us? 00:25:27.660 --> 00:25:28.160 I don't. 00:25:28.160 --> 00:25:31.100 But I wanted to bring up something about your course. 00:25:31.220 --> 00:25:31.700 Oh, thank you. 00:25:31.700 --> 00:25:36.360 My first concern was that, like, 100 different web projects might seem overwhelming. 00:25:36.360 --> 00:25:37.800 But it isn't that. 00:25:37.800 --> 00:25:39.480 Like you said, it's 28 projects. 00:25:39.480 --> 00:25:40.140 Is that right? 00:25:40.140 --> 00:25:40.540 28? 00:25:40.540 --> 00:25:40.900 Yeah. 00:25:40.900 --> 00:25:42.620 And there's four of them that are super short. 00:25:42.620 --> 00:25:43.440 So, it's kind of 24. 00:25:43.760 --> 00:25:44.080 Yeah. 00:25:44.080 --> 00:25:44.080 Yeah. 00:25:44.080 --> 00:25:49.160 You get more into it than just some quick thing that you can do in one day. 00:25:49.160 --> 00:25:50.940 I appreciate that pacing. 00:25:50.940 --> 00:25:51.700 Yeah. 00:25:51.700 --> 00:25:52.360 Thanks a bunch. 00:25:52.360 --> 00:25:52.740 Yeah. 00:25:52.740 --> 00:25:53.940 We're trying to find a balance there. 00:25:53.940 --> 00:25:56.300 Because 100 separate projects, too small. 00:25:56.300 --> 00:25:56.760 Yeah. 00:25:56.860 --> 00:25:57.840 One huge project. 00:25:57.840 --> 00:26:00.540 You don't get enough variety of other things. 00:26:00.540 --> 00:26:01.780 So, 24. 00:26:01.780 --> 00:26:03.420 That was the slicing we came up with. 00:26:03.420 --> 00:26:04.340 All right. 00:26:04.340 --> 00:26:05.000 How about this? 00:26:05.000 --> 00:26:10.680 So, there's a programmer going to a coffee shop looking to get out of the cube. 00:26:10.680 --> 00:26:11.400 All right. 00:26:11.400 --> 00:26:12.720 Can't stand being a cube more. 00:26:12.720 --> 00:26:13.800 So, I'm going to get out. 00:26:13.920 --> 00:26:18.020 And there's a waiter that comes over and says, hey, welcome to the restaurant. 00:26:18.020 --> 00:26:20.100 Would you like coffee or tea? 00:26:20.100 --> 00:26:22.740 The programmer says, yes. 00:26:22.740 --> 00:26:23.580 Yes. 00:26:23.580 --> 00:26:24.200 Of course. 00:26:24.200 --> 00:26:27.880 Have you done this? 00:26:27.880 --> 00:26:29.360 No. 00:26:29.360 --> 00:26:31.560 But it sounds like it might be sort of fun. 00:26:31.560 --> 00:26:32.040 Yeah. 00:26:32.040 --> 00:26:33.640 I mean, I haven't done it with coffee or tea. 00:26:33.640 --> 00:26:39.320 But I definitely think that sometimes if somebody gives me an or question, I'll answer with yes. 00:26:39.320 --> 00:26:40.320 Yes. 00:26:40.320 --> 00:26:41.380 Yeah. 00:26:41.380 --> 00:26:43.100 They mean exclusive or, don't they? 00:26:43.100 --> 00:26:43.500 Yeah. 00:26:43.500 --> 00:26:45.640 Yeah. 00:26:45.640 --> 00:26:46.100 Pretty awesome. 00:26:46.100 --> 00:26:46.460 All right. 00:26:46.460 --> 00:26:46.700 Well. 00:26:46.700 --> 00:26:47.280 Thanks a lot. 00:26:47.280 --> 00:26:47.760 You bet. 00:26:47.760 --> 00:26:48.780 Good to chat with you. 00:26:48.780 --> 00:26:50.160 And I'll catch you next time around. 00:26:50.160 --> 00:26:50.500 Okay. 00:26:50.500 --> 00:26:50.940 Bye. 00:26:50.940 --> 00:26:51.180 Bye. 00:26:51.180 --> 00:26:53.140 Thank you for listening to Python Bytes. 00:26:53.140 --> 00:26:55.680 Follow the show on Twitter via at Python Bytes. 00:26:55.680 --> 00:26:58.520 That's Python Bytes as in B-Y-T-E-S. 00:26:58.520 --> 00:27:01.760 And get the full show notes at pythonbytes.fm. 00:27:01.760 --> 00:27:05.980 If you have a news item you want featured, just visit pythonbytes.fm and send it our way. 00:27:05.980 --> 00:27:08.680 We're always on the lookout for sharing something cool. 00:27:08.680 --> 00:27:11.780 On behalf of myself and Brian Okken, this is Michael Kennedy. 00:27:11.780 --> 00:27:12.900 Thank you for listening. 00:27:13.060 --> 00:27:15.220 and sharing this podcast with your friends and colleagues.