WEBVTT

00:00:00.001 --> 00:00:04.880
Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to

00:00:04.880 --> 00:00:11.660
your earbuds. This is episode 132, recorded May 22nd, 2019. I'm Michael Kennedy. And I'm Brian

00:00:11.660 --> 00:00:15.820
Aitken. And this episode is brought to you by DigitalOcean. Check them out at pythonbytes.fm

00:00:15.820 --> 00:00:20.660
slash DigitalOcean. More about that later. Brian, how you been? I'm good, but I'm giggling right now

00:00:20.660 --> 00:00:24.460
because I've been looking up jokes, but we'll get to those later. Yeah, I always look forward to the

00:00:24.460 --> 00:00:28.420
jokes. And I think a lot of people out there seem to appreciate them. So yeah, we won't disappoint

00:00:28.420 --> 00:00:33.680
this time. We got more lined up, as always. Yeah, okay. I mean, like in the past, you maybe used to

00:00:33.680 --> 00:00:38.720
have to come up with these, but we have the internet. Yeah, I know. It's beautiful. It's easy to be a dad

00:00:38.720 --> 00:00:43.420
now. That's right. All right, you want to kick us off with a little embedded Python? Yeah, I was

00:00:43.420 --> 00:00:48.420
really excited to watch this. So I did meet, so this, the first one I've got up is the history of

00:00:48.420 --> 00:00:56.780
CircuitPython. And this was actually on the PSF blog. And I think that a Jesse Jerry Davis put it up.

00:00:56.840 --> 00:01:02.740
But anyway, it's about the history of CircuitPython and Adafruit and Scott Showcroft,

00:01:02.740 --> 00:01:08.300
which I met Scott at PyCon and I knew he was involved with CircuitPython, but I guess I didn't

00:01:08.300 --> 00:01:14.000
realize he was, he's the CircuitPython guy. So what happened was, and I always kind of wondered

00:01:14.000 --> 00:01:17.360
about this, like the relationship between MicroPython and CircuitPython.

00:01:17.360 --> 00:01:22.360
Right. I knew about MicroPython being for embedded devices. And I'm like, oh, there's now CircuitPython.

00:01:22.360 --> 00:01:27.440
Like, are they friends? Are they frenemies? Like, are they, one is a specialization of the other? What

00:01:27.440 --> 00:01:33.820
are they? So what happened was Adafruit thought MicroPython was a pretty cool thing and hired Scott

00:01:33.820 --> 00:01:40.880
to port it to their, I guess their SAMD21 chip that's used on many of the boards. So he did it,

00:01:40.880 --> 00:01:47.580
he's working on it. And it's a, at first it was just a fork, but now it's a fairly big changed fork.

00:01:47.780 --> 00:01:54.740
There's a lot of differences, but Scott said it's a friendly fork. So they, he works closely with the

00:01:54.740 --> 00:01:59.520
MicroPython people too, and they share code back and forth. So there's no, no hard feelings there,

00:01:59.520 --> 00:02:06.080
but it's focused on the Adafruit boards, but it's also, MicroPython is also focused really just on

00:02:06.080 --> 00:02:14.060
embedded stuff. Whereas CircuitPython is focused on beginners. And one of Scott's quotes is,

00:02:14.060 --> 00:02:19.980
our goal is to focus on the first five minutes someone has ever coded. That's a strong lofty

00:02:19.980 --> 00:02:25.660
goal. But watching some of their demos with the CircuitPython, it isn't surprising to me, you know,

00:02:25.660 --> 00:02:30.500
doing, they just hook it up and a few minutes later, they've got stuff running. It's kind of incredible.

00:02:30.500 --> 00:02:34.880
Yeah, that's really awesome. And that is a very, I don't know, impressive goal to say we're

00:02:34.880 --> 00:02:39.300
focused on the first five to 10 minutes of somebody programming, because yeah, that's,

00:02:39.900 --> 00:02:44.040
that's an early point in the life cycle, but I guess you got, you know, it's, it's got to start

00:02:44.040 --> 00:02:49.280
somewhere. And I do think these embedded devices really do bring like some realism to programming

00:02:49.280 --> 00:02:54.620
for people who may be programming just in the more theoretical way, didn't necessarily connect.

00:02:54.620 --> 00:02:56.160
So it's, it's great.

00:02:56.160 --> 00:03:00.760
One of the things I didn't know about was with, one of the things that CircuitPython does is

00:03:00.760 --> 00:03:06.500
it outputs, like all the print statements go automatically to the serial output. So if you could,

00:03:06.600 --> 00:03:11.180
if you hook up your serial output to a connected display, you don't even have to have any other

00:03:11.180 --> 00:03:14.900
device. You can just see your prints and stuff. So that's kind of neat.

00:03:14.900 --> 00:03:20.800
That's awesome. And Nina Zakarenko actually said, showed how to use this. And like, I think it was

00:03:20.800 --> 00:03:26.340
Visual Studio Code. She had that serial output connected. So just within Visual Studio Code,

00:03:26.340 --> 00:03:29.260
like the devices output would just like stream at the bottom.

00:03:29.400 --> 00:03:37.400
That's so cool. And then, we're also including a link to the release notes for, CircuitPython 4.0.0.

00:03:37.400 --> 00:03:43.080
So it's a new major number. So there's some breaking, a couple of breaking things, but it looks kind of neat.

00:03:43.080 --> 00:03:47.000
Yeah, that's super. And apparently they're not on the zero ver, philosophy.

00:03:47.000 --> 00:03:49.820
Yeah, no, that's good.

00:03:50.320 --> 00:03:59.400
Maybe you read it reverse for zero ver, like zero, zero, four. I don't know. Anyway, if you must, but no, that's cool. It's, it's great that there's a new version of that out.

00:03:59.400 --> 00:04:08.880
And it's, I really think they're doing a lot of cool stuff. The Adafruit folks are doing a lot of cool things. And some of those devices, I think were given out at PyCon this year as well, which is pretty neat.

00:04:09.000 --> 00:04:12.140
So, we've talked about Python being popular, right?

00:04:12.140 --> 00:04:12.620
Yes.

00:04:12.620 --> 00:04:21.700
Yeah, absolutely. So this next article that I want to cover is by dice.com doing a little bit of analysis of the TOB index.

00:04:21.700 --> 00:04:27.620
So we've talked about TOB before. This is a programming index talks about how popular languages are.

00:04:27.620 --> 00:04:37.000
And one of the areas of major growth in Python has to do with the data science space and just the scientific computing in general.

00:04:37.000 --> 00:04:45.820
So this article that I want to highlight, the title is R risks Python, R risks Python swallowing it whole, according to TOB.

00:04:45.820 --> 00:04:50.940
So that's pretty interesting. There used to be like kind of a debate. Do I use R? Do I use Python?

00:04:50.940 --> 00:04:58.240
Well, it looks like there's a lot of consolidation and all this growth in Python is somewhat a zero sum game for the other languages.

00:04:58.240 --> 00:05:03.960
So it might be, might be interesting to check out if you're thinking, should I learn R? Should I learn Python?

00:05:03.960 --> 00:05:10.820
R has a lot of interesting advantages over Python, but it seems like Python is kind of, kind of winning the day.

00:05:10.820 --> 00:05:16.300
And so R has tumbled out of the top 20 languages and now is somewhere below that.

00:05:16.300 --> 00:05:20.880
It's a very popular with a lot of people, but I didn't even hear about it until like maybe a year ago.

00:05:20.880 --> 00:05:24.460
For sure. Yeah. It's definitely focused on a, on a more of a niche space.

00:05:24.600 --> 00:05:37.420
So the article speculates sort of not super effectively why they think that is like the acid question, like, well, it seems that Python is winning in data science, but why?

00:05:37.540 --> 00:05:39.980
And so I thought maybe I'd throw my own commentary in here.

00:05:39.980 --> 00:05:47.440
And there's this idea, like, I really like to talk about with Python being a full spectrum programming language.

00:05:48.180 --> 00:05:53.880
And what I mean by that is like, you can get started with the absolute minimum amount of effort.

00:05:53.880 --> 00:05:56.680
There's no compilers, no linkers, there's no header files.

00:05:56.680 --> 00:06:01.720
There's a single file and you can say print, parentheses, quote, hello world.

00:06:01.720 --> 00:06:02.500
Right. And that's it.

00:06:03.380 --> 00:06:10.680
You don't need to think about generators or all the other stuff that like rich programming languages have.

00:06:10.680 --> 00:06:12.700
Like think C#, Java, C++, right?

00:06:12.700 --> 00:06:16.080
You've got to like do all this ceremony to get going.

00:06:16.080 --> 00:06:24.800
But the value of those other languages is like you can go build, you know, video games or operating systems or, you know, whatever.

00:06:24.800 --> 00:06:28.520
Right. And you can do much of that kind of stuff, not operating systems necessarily,

00:06:28.520 --> 00:06:31.620
but like you can build real apps, professional apps in Python.

00:06:31.620 --> 00:06:43.740
And it kind of scales from this ultra beginner part where you can partially understand the language and be effective all the way up to using meta classes and decorators and generators to build, I don't know, Instagram or whatever.

00:06:43.740 --> 00:06:52.180
And I think that that's actually why Python is winning in the space because the data scientists and scientific computing folks are coming in and they're like, I don't want to be like a programmer.

00:06:52.180 --> 00:06:54.600
I want to use programming to solve my problem.

00:06:54.600 --> 00:07:00.200
And Python lets them start that super easy path, but grow into where they eventually find themselves.

00:07:00.200 --> 00:07:10.120
One of the things also is that people that have to reach towards R or some other programming language, that's not their only software issue that they may have.

00:07:10.120 --> 00:07:16.920
And if you can solve it with Python, you learn Python and then you can solve other automation things within your workflow as well.

00:07:16.920 --> 00:07:18.960
Whereas R has very focused.

00:07:18.960 --> 00:07:22.680
I don't know how much you can do with it outside of data science.

00:07:22.680 --> 00:07:23.300
That's for sure.

00:07:23.300 --> 00:07:24.440
That's definitely part of the story.

00:07:24.440 --> 00:07:27.840
Speaking of stories, you got a little history lesson for us, right?

00:07:27.840 --> 00:07:32.440
I've had this on the list for a while, but it took me, I just went back and read it yesterday.

00:07:32.440 --> 00:07:39.900
It's an article by, I think it's Eamon L. Emery called The Missing Introduction to Containerization.

00:07:39.900 --> 00:07:45.400
And so container systems like Docker and stuff like that, lots of people use them.

00:07:45.400 --> 00:07:50.800
And I do want to ramp up learning how to use them more.

00:07:50.800 --> 00:07:54.520
I'm kind of one of those people that need a mental model of how all this stuff works.

00:07:54.520 --> 00:07:56.020
And this is it.

00:07:56.180 --> 00:08:02.540
So it starts with a 1979 release of something called, I don't even know how to pronounce this.

00:08:02.540 --> 00:08:03.140
Chroot?

00:08:03.140 --> 00:08:05.080
T-H-R-O-O-T?

00:08:05.080 --> 00:08:05.620
Chroot?

00:08:05.620 --> 00:08:06.440
Chroot?

00:08:06.440 --> 00:08:06.940
Chroot?

00:08:06.940 --> 00:08:07.740
Anyway.

00:08:07.740 --> 00:08:14.560
Chroot jail, which was a way to isolate a root process and its children from the rest of the OS.

00:08:14.700 --> 00:08:19.160
But there was a bunch of problems with, there wasn't really meant for security.

00:08:19.160 --> 00:08:22.260
And I'm not going to read the whole thing, but it, you know, builds up.

00:08:22.260 --> 00:08:32.000
Because of this is open source, FreeBSD improved on it, then Linux vServer, and then Oracle Solaris had some stuff, OpenVZ.

00:08:32.000 --> 00:08:35.480
And then Google chimed in with something called C Groups.

00:08:35.480 --> 00:08:39.680
And then a group called Linux Containers did LXC.

00:08:39.680 --> 00:08:42.100
And then, you know, it kind of built up.

00:08:42.100 --> 00:08:43.360
Cloud Foundry got involved.

00:08:43.520 --> 00:08:45.080
And then in 2013, Docker.

00:08:45.080 --> 00:08:49.140
And then Google's still doing more stuff with making things easier.

00:08:49.140 --> 00:08:51.340
But all of this stuff builds up on itself.

00:08:51.340 --> 00:08:55.100
And I really like that bit of a history lesson of how things built on itself.

00:08:55.100 --> 00:09:05.100
And then it jumps into talking about the differences, all the different terms you'll find, like a system virtual machine, a process virtual machine, and VPS.

00:09:05.100 --> 00:09:06.540
And what all those things mean.

00:09:06.540 --> 00:09:12.160
Also, kind of the difference between an operating system container system and an app container.

00:09:12.340 --> 00:09:16.280
And Docker is a little bit of a mix of both.

00:09:16.960 --> 00:09:19.580
So, it's kind of containers and platforms.

00:09:19.580 --> 00:09:23.940
Just why there's so many things around is kind of described in this.

00:09:23.940 --> 00:09:26.400
And then that's only like halfway through the article.

00:09:26.400 --> 00:09:33.860
The rest of the article jumps into, I think it's creating a container system from scratch based on some of these lib container things.

00:09:34.360 --> 00:09:35.880
And yeah, I don't want to do that.

00:09:35.880 --> 00:09:38.860
So, but the first half of it, definitely recommend.

00:09:38.860 --> 00:09:40.040
It's a good article.

00:09:40.240 --> 00:09:42.020
Yeah, the history here is really interesting.

00:09:42.020 --> 00:09:47.260
Like, I guess when I first learned about Docker, I thought like, oh, Docker invented containers.

00:09:47.260 --> 00:09:47.960
Right?

00:09:47.960 --> 00:09:49.120
But absolutely not.

00:09:49.120 --> 00:09:49.780
Right?

00:09:49.780 --> 00:09:52.720
They were building on LXC and all these other things.

00:09:52.720 --> 00:09:55.360
And eventually they sort of moved off that.

00:09:55.440 --> 00:10:01.960
But yeah, they were just, you know, making containers more accessible and easier for folks and popularizing it.

00:10:01.960 --> 00:10:05.000
I think these containers are super powerful and super interesting.

00:10:05.000 --> 00:10:06.420
To me, I don't know.

00:10:06.420 --> 00:10:07.380
Do you feel like they're complicated?

00:10:07.740 --> 00:10:14.520
It seems like the system is made to not be, but I know there's a lot of stuff behind the scenes going on.

00:10:14.520 --> 00:10:17.280
And I, you know, to be honest, I haven't played with them much or used them.

00:10:17.280 --> 00:10:21.460
I don't need them for my normal job, but I would like to learn more.

00:10:21.460 --> 00:10:22.160
How about you?

00:10:22.160 --> 00:10:23.100
I definitely like them.

00:10:23.100 --> 00:10:25.960
I'm not doing anything with them right now.

00:10:25.960 --> 00:10:29.100
And I've thought about how using containers might make sense.

00:10:29.100 --> 00:10:35.560
But at the same time, you'll have like lightweight VMs I just fire up and like they're dedicated to a single purpose.

00:10:35.560 --> 00:10:37.140
So I don't know.

00:10:37.280 --> 00:10:42.160
It's always a bit of a trade-off of like adding more complexity in one place.

00:10:42.160 --> 00:10:44.500
I feel like it's a little bit of a whack-a-mole problem.

00:10:44.500 --> 00:10:49.220
I can have more simplicity in some places, but I've like pushed it to another.

00:10:49.220 --> 00:10:57.940
So for example, right, people talk about containers often being a great way to simplify development environments for junior developers.

00:10:57.940 --> 00:10:58.360
Okay?

00:10:58.360 --> 00:10:58.660
Yeah.

00:10:58.660 --> 00:10:58.960
Right?

00:10:58.960 --> 00:11:00.620
So like I'm going to work in a new company.

00:11:00.620 --> 00:11:02.900
Our app infrastructure is super complicated.

00:11:03.640 --> 00:11:07.220
So what they do is they say, well, here's like three containers.

00:11:07.220 --> 00:11:08.320
One runs a database.

00:11:08.320 --> 00:11:09.640
One runs the web front end.

00:11:09.640 --> 00:11:11.800
One runs the caching tier or whatever the heck it is.

00:11:12.140 --> 00:11:13.680
And I'm going to just run those.

00:11:13.680 --> 00:11:17.020
And I'll just develop in that regardless of what my machine setup like.

00:11:17.020 --> 00:11:19.400
Well, that's on one hand like simpler.

00:11:19.400 --> 00:11:23.120
I say maybe Docker Compose up and boom, my little environment's working.

00:11:23.120 --> 00:11:29.420
But now I've got to figure out how does my editor do like remote debugging of Docker containers?

00:11:29.420 --> 00:11:35.140
And how do I like step across calls between containers in my debugger and all this other stuff?

00:11:35.140 --> 00:11:41.480
It's like, okay, so I've moved like setup complexity to like editor complexity or other stuff, right?

00:11:41.480 --> 00:11:42.020
So I don't know.

00:11:42.020 --> 00:11:43.160
It's super interesting.

00:11:43.160 --> 00:11:47.960
I'd certainly see them being really valuable for like zero downtime deployments and other kinds of stuff.

00:11:47.960 --> 00:11:49.340
But yeah, it's interesting.

00:11:49.340 --> 00:11:57.580
In my wacky corner of the universe, the place where I probably would use them is we often want to spin up a new build server or something like that.

00:11:57.580 --> 00:12:00.920
And we have it written down about how to build a build server.

00:12:00.920 --> 00:12:04.860
Even though it's on a virtual machine, we got to install a bunch of stuff.

00:12:04.860 --> 00:12:07.820
And it's a half a day to get it up and running.

00:12:07.820 --> 00:12:10.140
And having that just saved off.

00:12:10.140 --> 00:12:12.340
Yeah, that's a perfect example of Docker, right?

00:12:12.340 --> 00:12:15.460
Because you can build the container images to just do that setup.

00:12:15.460 --> 00:12:18.780
And you just say, you know, Docker build and boom, you're ready.

00:12:18.780 --> 00:12:19.740
Yeah, I like that.

00:12:19.740 --> 00:12:25.920
Speaking of containers and all those good things, let's talk really quick about DigitalOcean, some of the stuff they have to offer.

00:12:25.920 --> 00:12:33.580
So DigitalOcean just this week put their Kubernetes cluster into general availability and added some cool new features.

00:12:33.580 --> 00:12:36.640
So if you're using Docker, you've got to run it somewhere.

00:12:36.640 --> 00:12:39.040
And usually just running it directly is not what you want.

00:12:39.040 --> 00:12:45.220
You want to run it somewhere where you can upgrade versions and do zero downtime deployments and multi-container stuff.

00:12:45.220 --> 00:12:47.420
So Kubernetes is a great place for that.

00:12:47.540 --> 00:12:49.200
So check that out over at DigitalOcean.

00:12:49.200 --> 00:12:55.320
Just visit pythonbytes.fm/DigitalOcean and get $50 credit for new users.

00:12:55.320 --> 00:12:58.020
Yeah, so all sorts of cool stuff over there.

00:12:58.020 --> 00:13:01.760
You can provision your servers and optimize it and get it going.

00:13:01.760 --> 00:13:02.140
Right?

00:13:02.200 --> 00:13:03.080
Really, really nice.

00:13:03.080 --> 00:13:10.180
And one of the things they just added is free integrated monitoring that'll provide like insight across your clusters and your containers and stuff.

00:13:10.180 --> 00:13:11.160
So yeah, check them out.

00:13:11.160 --> 00:13:12.840
Pythonbytes.fm slash DigitalOcean.

00:13:12.840 --> 00:13:14.120
Super, super cool.

00:13:14.120 --> 00:13:18.380
So this next thing I want to cover, Brian, touches on something I've been a fan of for a long time.

00:13:18.380 --> 00:13:19.720
And that's design patterns.

00:13:19.720 --> 00:13:20.060
Okay.

00:13:20.160 --> 00:13:26.360
So design patterns, we talked a little bit about that previously, one of the shows just recently.

00:13:26.360 --> 00:13:32.800
But this time I want to focus on maybe a topic that is reversed from a lot of the advice that you hear.

00:13:32.800 --> 00:13:38.640
A lot of times you hear people say, hey, Python developers, stop using classes and stop using objects.

00:13:38.820 --> 00:13:41.120
Just write modules and functions, right?

00:13:41.120 --> 00:13:42.100
Yeah, sometimes.

00:13:42.100 --> 00:13:42.720
Yeah, sometimes.

00:13:42.720 --> 00:13:43.800
And that's totally reasonable.

00:13:43.800 --> 00:13:48.540
A lot of times people come from C# or Java where it's everything is an object.

00:13:48.540 --> 00:13:49.960
Everything has to be in a class.

00:13:49.960 --> 00:13:52.400
And so they think, well, I have to do that in Python.

00:13:52.400 --> 00:13:58.880
And if you've got a static variable in a class, that's, you know, just kind of like a module level variable in a function.

00:13:58.880 --> 00:14:00.660
Like there's no real value to breaking that apart.

00:14:00.660 --> 00:14:03.060
However, a lot of times there are.

00:14:03.060 --> 00:14:14.560
So there's a cool article that walks you through in super in-depth focused on sort of data science side of this object, no object debate called algorithms as objects.

00:14:14.560 --> 00:14:18.680
So it's usually we think of like algorithms as a single function with an input and an output.

00:14:18.680 --> 00:14:21.760
And algorithm textbooks reinforce this notion, right?

00:14:21.760 --> 00:14:24.460
Like everything fits nice onto a single page.

00:14:24.600 --> 00:14:35.060
But in reality, what you end up with are these like giant monolithic functions that are like full of details with lots of cyclomatic complexity and passing lots of data around and all sorts of stuff.

00:14:35.060 --> 00:14:36.600
And it's not nearly as nice.

00:14:36.600 --> 00:14:39.740
You end up with these functions that like lack readability.

00:14:39.740 --> 00:14:42.260
And because of that, they lack maintainability.

00:14:42.260 --> 00:14:45.920
Nobody wants to touch it because it's probably important.

00:14:45.920 --> 00:14:47.400
It's an algorithm, right?

00:14:47.400 --> 00:14:49.820
And if it's wrong, it's probably hard to tell if it's wrong.

00:14:49.820 --> 00:14:51.580
So you don't want to break it.

00:14:51.580 --> 00:14:53.960
It's just kind of scary, right?

00:14:54.240 --> 00:14:59.420
So they talk about taking these algorithms and turning them into functions.

00:14:59.420 --> 00:15:04.760
And one of the ideas I really like that they're starting with is like, well, should I do this or not?

00:15:04.760 --> 00:15:05.500
How do I know?

00:15:05.500 --> 00:15:08.060
So they talk about this idea of code smells.

00:15:08.060 --> 00:15:15.040
And the idea of code smells comes from Martin Fowler way back in the day, like 1999 or something like that when he wrote his refactoring book.

00:15:15.040 --> 00:15:21.700
And these are aspects of code that are not necessarily broken, but they're just like a little bit off.

00:15:21.700 --> 00:15:22.940
Have you heard of this idea, Brian?

00:15:22.940 --> 00:15:23.660
Yeah, definitely.

00:15:23.880 --> 00:15:25.140
It kind of makes you wrinkle up your nose.

00:15:25.140 --> 00:15:27.460
You're like, ew, something's not good here.

00:15:27.460 --> 00:15:29.060
But, you know, the code works, right?

00:15:29.060 --> 00:15:29.960
Like it would pass a test.

00:15:29.960 --> 00:15:30.740
So it's fine.

00:15:30.740 --> 00:15:39.440
So the code smells, they say, that you should be on the lookout for here are, number one, the function, the algorithm, the one giant function.

00:15:39.440 --> 00:15:41.680
It's too long or it's too deeply nested.

00:15:41.680 --> 00:15:43.740
Like we spoke about guarding clauses last time.

00:15:44.120 --> 00:15:45.380
Does it have banner comments?

00:15:45.380 --> 00:15:51.840
Like a huge comment at the top that describes what it does, how it works, the special cases, right?

00:15:51.840 --> 00:15:55.340
I often say that code comments are deodorant for bad code.

00:15:55.340 --> 00:15:57.440
So you should just write good code and not do that.

00:15:57.500 --> 00:15:58.460
So like that's an example.

00:15:58.460 --> 00:16:10.520
Helper functions that are maybe nested closures inside there, some weird thing like that, or maybe actual helper functions, but they're only used within this larger function.

00:16:10.880 --> 00:16:18.680
Passing a lot of states, all these things are sort of indicators that maybe an object would be much better for wrapping up your algorithm.

00:16:18.680 --> 00:16:22.300
So it's really, I think, got a lot of concrete advice here.

00:16:22.300 --> 00:16:23.900
This actually looks pretty interesting.

00:16:23.900 --> 00:16:24.760
It's super interesting.

00:16:24.760 --> 00:16:26.680
And it's full of examples.

00:16:26.680 --> 00:16:30.660
Like it's a really long article with lots of concrete examples of here's an algorithm.

00:16:30.660 --> 00:16:31.460
We did it this way.

00:16:31.460 --> 00:16:36.000
We refactor that to an object and look how much more understandable it is and how much simpler it is.

00:16:36.000 --> 00:16:40.140
So if this idea resonates with you, definitely check it out.

00:16:40.180 --> 00:16:49.380
And the guy who wrote it said, hey, when I present this idea to my colleagues or other folks, at first they're like, no, we shouldn't be using classes.

00:16:49.380 --> 00:16:50.480
Just functions will do.

00:16:50.480 --> 00:16:57.860
This is, you know, he encounters some pushback, but rarely does he encounter like prolonged pushback after people see the results.

00:16:57.860 --> 00:16:59.660
They're like, no, actually, this is pretty cool.

00:16:59.660 --> 00:17:00.580
I'm just chuckling.

00:17:00.580 --> 00:17:04.920
And one of the topics he has here is, I've got 99 problems.

00:17:04.920 --> 00:17:05.700
Give me two more.

00:17:05.700 --> 00:17:08.020
Yeah, it's a good article.

00:17:08.020 --> 00:17:08.960
Definitely check it out.

00:17:09.020 --> 00:17:11.200
If people are interested, it's very concrete and helpful.

00:17:11.200 --> 00:17:14.880
So, Brian, I know you're into testing and I know you're a fan of pytest.

00:17:14.880 --> 00:17:17.680
What are you into, like really small versions of pytest?

00:17:17.680 --> 00:17:18.280
Or what is this?

00:17:18.280 --> 00:17:27.320
I got into this because I've been using Python for testing purposes for since like a little out of like 2002 or something like that.

00:17:27.820 --> 00:17:32.940
There were often custom made Python frameworks or testing frameworks within our company.

00:17:32.940 --> 00:17:37.180
And then around 2010, I did the same thing and wrote my own.

00:17:37.180 --> 00:17:39.240
But it took me a while to get it down.

00:17:39.240 --> 00:17:45.480
I was arrogant and thought, oh, this would be trivial to because it's the basic algorithm isn't really doing much.

00:17:45.620 --> 00:17:55.260
But Oliver Best Balter, there was a comment somewhere on Twitter that the core of pytest could be written in like a couple dozen lines of code.

00:17:55.260 --> 00:17:57.600
And people were like, what, really?

00:17:57.600 --> 00:18:00.480
And so, of course, he's a brilliant person.

00:18:00.480 --> 00:18:01.560
He went out and just did it.

00:18:01.680 --> 00:18:04.060
So, he released a thing called Picopytest.

00:18:04.060 --> 00:18:09.220
It doesn't have a cert rewriting and it doesn't have like fixtures or any of the fun stuff.

00:18:09.220 --> 00:18:16.080
But it's a generally usable test framework that you could run some tests with written in 25 lines of code.

00:18:16.080 --> 00:18:16.480
Dang.

00:18:16.480 --> 00:18:20.320
And, you know, like the first five are just import statements or space.

00:18:20.320 --> 00:18:21.920
And one of them is a method.

00:18:21.920 --> 00:18:27.140
So, I think you could probably get it down to 19 if you were willing to go a little crazy on it.

00:18:27.140 --> 00:18:27.940
That's wild.

00:18:27.940 --> 00:18:31.040
So, some of the things that it uses are like import lib.

00:18:31.260 --> 00:18:41.900
Some of these things are clearly put in the language for tools like pytest and stuff like import libs, spec from file location, and module from spec.

00:18:41.900 --> 00:18:43.600
I don't know what those things do.

00:18:43.600 --> 00:18:50.820
But it looks like it's a way to sort of gradually load a module and then run parts of it because that's what this code does.

00:18:50.820 --> 00:18:57.900
One of the things I like about this and one of the reasons why I'm highlighting it is a lot of people think of test frameworks as this thing.

00:18:57.900 --> 00:18:58.640
They don't really know.

00:18:58.640 --> 00:19:00.240
It's a black box that does stuff.

00:19:00.840 --> 00:19:02.980
And I think this is a good way to highlight.

00:19:02.980 --> 00:19:09.040
It's not that this Python is very flexible and the heart of a test framework isn't that complicated.

00:19:09.040 --> 00:19:17.100
It's going out and finding files that match like a certain pattern, test underscore, and finding some functions inside those to call.

00:19:17.320 --> 00:19:20.700
And then just catching exceptions and logging failures.

00:19:20.700 --> 00:19:21.940
It's not that complicated.

00:19:21.940 --> 00:19:22.980
So, it's pretty cool.

00:19:22.980 --> 00:19:23.660
That's super cool.

00:19:23.660 --> 00:19:29.980
And I think anybody who cares about testing or maybe is being introduced to testing should read those 25 lines.

00:19:30.020 --> 00:19:36.380
Not necessarily for understanding, but just to get the sense of like, this is what happens when you run tests against your code.

00:19:36.380 --> 00:19:37.380
It finds your model.

00:19:37.380 --> 00:19:38.660
It loads up the functions.

00:19:38.660 --> 00:19:39.260
It calls it.

00:19:39.260 --> 00:19:40.800
It does this basic thing.

00:19:40.800 --> 00:19:41.800
And that's it.

00:19:41.800 --> 00:19:42.520
It's really nice.

00:19:42.520 --> 00:19:42.740
Yeah.

00:19:42.740 --> 00:19:43.280
Very, very cool.

00:19:43.280 --> 00:19:44.160
That is definitely...

00:19:44.160 --> 00:19:48.140
I don't know what the atomic unit of a test framework is, but that's nearly it.

00:19:48.140 --> 00:19:49.940
He popped this out in like two days.

00:19:49.940 --> 00:19:54.580
And it took me like two months to write my first version of my test framework.

00:19:54.580 --> 00:19:55.520
So, awesome.

00:19:55.680 --> 00:19:56.340
Yeah, super cool.

00:19:56.340 --> 00:19:56.820
Super cool.

00:19:56.820 --> 00:19:57.060
All right.

00:19:57.060 --> 00:19:59.440
Last one I want to cover has to do with Cython.

00:19:59.440 --> 00:20:01.240
Not CPython, but Cython.

00:20:01.240 --> 00:20:07.360
It's an article called An Introduction to Cython, the Secret Python Extension with Superpowers.

00:20:07.360 --> 00:20:09.660
And who wouldn't want an extension with superpowers?

00:20:09.660 --> 00:20:10.620
Yeah, exactly.

00:20:10.620 --> 00:20:14.800
They make the statement that they think Cython is one of the best kept secrets of Python.

00:20:14.800 --> 00:20:15.720
And I agree.

00:20:15.720 --> 00:20:22.080
Like, Cython will take almost arbitrary Python code and turn it into C.

00:20:22.080 --> 00:20:24.060
That right there is pretty impressive.

00:20:24.460 --> 00:20:29.540
If you have a, like, you've got some program and you find out like, oh, this part of, I

00:20:29.540 --> 00:20:33.940
don't know, some inner loop within an inner loop, you know, within another nested loop or

00:20:33.940 --> 00:20:35.580
something like that's a little bit too slow.

00:20:35.580 --> 00:20:41.980
You could probably write like a function in Cython that does that inner loop and make it

00:20:41.980 --> 00:20:43.180
way, way faster.

00:20:43.180 --> 00:20:44.680
Super cool.

00:20:44.680 --> 00:20:49.500
That's what we hear a lot about Python is you can take some slow parts in and then rewrite

00:20:49.500 --> 00:20:51.540
it and see if you need to.

00:20:51.540 --> 00:20:53.860
But you don't have to with Cython, right?

00:20:53.860 --> 00:20:54.300
Exactly.

00:20:54.300 --> 00:20:55.400
You don't have, that's the thing.

00:20:55.400 --> 00:20:56.760
You don't have to rewrite.

00:20:56.760 --> 00:21:02.460
You could rewrite it in C or in Rust or whatever, or you could just call Cython against it and

00:21:02.460 --> 00:21:08.140
make it, you know, it basically transpiles the Python into C and then compiles the C over

00:21:08.140 --> 00:21:09.420
to machine instructions.

00:21:09.420 --> 00:21:14.840
Now, depending on how you write your code, it may still interact with the Python interpreter

00:21:14.840 --> 00:21:16.460
and the Python gil or it might not.

00:21:17.100 --> 00:21:21.180
And that could actually significantly determine the performance benefits you get, right?

00:21:21.180 --> 00:21:25.700
So you can, it'll work with like an untyped item, but then it does it as a, I think, as a

00:21:25.700 --> 00:21:26.600
py object pointer.

00:21:26.600 --> 00:21:32.900
Whereas if you tell it this is an actual integer, it'll work with it as like a cint type of thing

00:21:32.900 --> 00:21:34.200
or something to that effect, right?

00:21:34.840 --> 00:21:39.240
So you get all sorts of benefits that'll, or, you know, ways to overcome shortcomings of

00:21:39.240 --> 00:21:39.500
Python.

00:21:39.500 --> 00:21:46.000
Say, for example, we talked about execution speed, but there's also a keyword in Cython that says,

00:21:46.000 --> 00:21:47.060
that's called no gil.

00:21:47.060 --> 00:21:52.420
So you can just create a context block in Python effectively say with no gil colon.

00:21:52.780 --> 00:21:56.320
And then that stuff works without the gil in threads.

00:21:56.320 --> 00:21:57.160
And that's it.

00:21:57.160 --> 00:22:02.440
You're just guaranteeing that that stuff isn't going outside of it or anything.

00:22:02.440 --> 00:22:08.000
What the requirement for using that keyword is, and if it doesn't match these requirements,

00:22:08.000 --> 00:22:14.020
it's like a compiler error for Cython, the Cython compiler, is that you don't interact with

00:22:14.020 --> 00:22:15.280
any Python objects.

00:22:15.280 --> 00:22:15.660
Okay.

00:22:15.660 --> 00:22:21.440
So you basically got to cast them into Cython native objects that can be represented in C.

00:22:21.640 --> 00:22:25.620
And then there's no reason for the gil because the gil's point, the purpose of the gil is

00:22:25.620 --> 00:22:30.040
to interact with the reference counting to make sure that that works in Python's object

00:22:30.040 --> 00:22:30.920
garbage collector.

00:22:30.920 --> 00:22:33.960
But if you're not working with Python objects, you don't need the gil.

00:22:33.960 --> 00:22:37.200
So it's a really great way to free up speed and whatnot.

00:22:37.200 --> 00:22:41.260
They talk about some of the projects written in Cython.

00:22:41.260 --> 00:22:47.480
So spaCy, the natural language processing, uv loop, which is a really fast asyncio event loop,

00:22:47.480 --> 00:22:51.600
significant parts of scikit-learn, numpy, pandas, all that kind of stuff.

00:22:51.600 --> 00:22:56.420
So I think the big value, like you said, is like you could go rewrite it in C, or you

00:22:56.420 --> 00:23:00.980
could just use Cython and make your Python run somewhat like C. Pretty cool.

00:23:00.980 --> 00:23:04.880
I actually want to play with this a little bit because I'm glad you found this article.

00:23:04.880 --> 00:23:06.100
Yeah, the article is super interesting.

00:23:06.100 --> 00:23:08.960
One thing that I've noticed, I mean, I didn't read it.

00:23:08.960 --> 00:23:13.800
I didn't like super inspect every code example, but I didn't see them using Python's type

00:23:13.800 --> 00:23:14.360
annotations.

00:23:14.360 --> 00:23:14.780
Right.

00:23:14.780 --> 00:23:20.300
So they're using like the C def to define types and like special Cython ways to define

00:23:20.300 --> 00:23:20.960
types.

00:23:20.960 --> 00:23:27.400
But the more modern versions of Cython, you can just say like value colon int equals something,

00:23:27.400 --> 00:23:31.300
you know, like the standard Python way of saying what a type is for type checking.

00:23:31.620 --> 00:23:36.200
And that'll actually also be understood and used by Cython for like native types.

00:23:36.200 --> 00:23:36.520
Okay.

00:23:36.520 --> 00:23:40.720
That's the question I had was, can you use native Python types?

00:23:40.720 --> 00:23:43.640
The answer used to be no, but now the answer is yes.

00:23:43.640 --> 00:23:44.380
Right.

00:23:44.380 --> 00:23:45.280
So, yeah.

00:23:45.280 --> 00:23:46.000
So it's super cool.

00:23:46.000 --> 00:23:46.980
All right.

00:23:46.980 --> 00:23:50.520
Well, if you think you need your Python code to go a little faster, check out this article,

00:23:50.520 --> 00:23:51.200
check out Cython.

00:23:51.200 --> 00:23:52.100
And it's pretty awesome.

00:23:52.100 --> 00:23:53.460
Just a good reminder, I guess.

00:23:53.460 --> 00:23:55.200
We both have a few extras.

00:23:55.200 --> 00:23:56.420
How about you kick off that section?

00:23:56.420 --> 00:23:57.020
Sure.

00:23:57.020 --> 00:24:01.340
I didn't really want to highlight this for too long, but he, Nick, wrote an article called

00:24:01.340 --> 00:24:02.600
The Price of the Hallway Track.

00:24:02.600 --> 00:24:04.440
It's just a reminder to everybody.

00:24:04.440 --> 00:24:10.500
I mean, we do hear about using, going to things like PyCon and other conferences and not actually

00:24:10.500 --> 00:24:13.060
going to the talks, but doing hallway stuff.

00:24:13.340 --> 00:24:17.000
He's pointing out that that's kind of lame for all the speakers that work really hard

00:24:17.000 --> 00:24:17.720
to do that.

00:24:17.720 --> 00:24:24.280
It's also, even if you intend to watch it later, it's disheartening for people to speak to an

00:24:24.280 --> 00:24:26.280
empty room or even a mostly empty room.

00:24:26.280 --> 00:24:32.280
And he's just asking, you know, don't fill up your day with talks, but pick some, especially

00:24:32.280 --> 00:24:37.520
ones that from people that are lesser known people and that sound interesting to you and

00:24:37.520 --> 00:24:38.520
at least go to a few talks.

00:24:38.520 --> 00:24:39.800
And I think that's a good advice.

00:24:39.800 --> 00:24:40.940
I'm going to try to do that next year.

00:24:40.940 --> 00:24:41.380
Yeah, cool.

00:24:41.380 --> 00:24:41.980
And what else?

00:24:41.980 --> 00:24:47.880
The second one is, who put Python in my Windows 10, May 19 update by Steve Dower.

00:24:47.880 --> 00:24:55.280
We did talk about this in the previous episode, but it is officially out and people are noticing

00:24:55.280 --> 00:24:55.480
it.

00:24:55.480 --> 00:24:55.680
Yeah.

00:24:55.680 --> 00:24:59.500
And Steve gave us a shout out to the Python Bytes episode we did together right there in

00:24:59.500 --> 00:25:00.360
the first paragraph.

00:25:00.360 --> 00:25:01.260
So thanks for that, Steve.

00:25:01.260 --> 00:25:02.260
This is massive.

00:25:02.260 --> 00:25:08.660
This is Windows 10 is shipping with Python 3 and that version of Python 3 is auto updating.

00:25:08.660 --> 00:25:09.820
Like, how cool is that?

00:25:09.820 --> 00:25:10.160
Okay.

00:25:10.160 --> 00:25:11.480
Within a major version.

00:25:11.480 --> 00:25:13.160
Yeah, but it ships within a little stub.

00:25:13.160 --> 00:25:15.000
So you don't get Python right away.

00:25:15.000 --> 00:25:16.700
You get a little thing that pops open.

00:25:16.700 --> 00:25:20.260
If you type Python, it pops open on the app store to download it.

00:25:20.260 --> 00:25:22.560
It doesn't ship with it because it doesn't need to.

00:25:22.560 --> 00:25:27.300
And still a lot of people, like, you know, a lot of people don't need Python, but that makes

00:25:27.300 --> 00:25:27.700
it easier.

00:25:27.700 --> 00:25:30.780
I guess when I say ships with, I mean from a user's perspective.

00:25:30.980 --> 00:25:35.720
Like, if you tell a user to go through a tutorial and you tell them to type Python 3 and they

00:25:35.720 --> 00:25:39.820
sit down and they type it, rather than getting error, it says, oh, you have to click this button

00:25:39.820 --> 00:25:40.720
for this line to work.

00:25:40.720 --> 00:25:42.200
They click the button and then it works.

00:25:42.200 --> 00:25:42.640
Like that.

00:25:42.640 --> 00:25:43.580
Yeah, exactly.

00:25:43.760 --> 00:25:44.880
I wouldn't ask for more, right?

00:25:44.880 --> 00:25:45.680
That's really cool.

00:25:45.680 --> 00:25:45.940
Yeah.

00:25:45.940 --> 00:25:46.440
How about you?

00:25:46.440 --> 00:25:47.040
Got any extras?

00:25:47.320 --> 00:25:47.600
Yeah.

00:25:47.600 --> 00:25:50.760
I got also something super small, a Pico thing.

00:25:50.760 --> 00:26:02.640
So Matt Trentini sent over a cool project called the Tiny Pico, which is an ESP32-based board.

00:26:02.640 --> 00:26:07.520
So a tiny little board that has first-class support for MicroPython.

00:26:07.520 --> 00:26:12.400
So Brian, if you click on that link, if you check this thing out, it's pretty wild.

00:26:12.400 --> 00:26:14.280
It's a project you can order.

00:26:14.280 --> 00:26:16.120
It's pretty cheap, like $26.

00:26:16.960 --> 00:26:18.080
It's so small.

00:26:18.080 --> 00:26:19.000
It's incredible.

00:26:19.000 --> 00:26:21.060
It's like two-thirds the size.

00:26:21.060 --> 00:26:24.340
So 60% of a AA battery.

00:26:24.340 --> 00:26:30.600
I mean, like maybe, you know, like the middle part of your pinky or something.

00:26:30.600 --> 00:26:34.660
I mean, it's a really small board, like both the width and the height.

00:26:34.660 --> 00:26:35.620
That is crazy.

00:26:35.620 --> 00:26:37.200
But listen to its specs.

00:26:37.200 --> 00:26:39.620
32-bit dual-core processor.

00:26:39.620 --> 00:26:45.740
Full-on Wi-Fi, 8211BGNN, Bluetooth.

00:26:46.600 --> 00:26:47.380
All sorts of stuff.

00:26:47.380 --> 00:26:49.480
Like for $26 at that size.

00:26:49.480 --> 00:26:50.360
It's so cool.

00:26:50.360 --> 00:26:52.900
So I want to give a shout out.

00:26:52.900 --> 00:26:54.340
MicroPython's pre-installed.

00:26:54.340 --> 00:26:55.200
That's cool.

00:26:55.200 --> 00:26:56.100
Isn't that super?

00:26:56.100 --> 00:27:01.060
So if people are looking at embedded stuff and little devices, things, this is really, really cool.

00:27:01.060 --> 00:27:01.380
Yeah.

00:27:01.760 --> 00:27:03.720
Good for your next spy cam project.

00:27:03.720 --> 00:27:04.340
Exactly.

00:27:04.340 --> 00:27:08.900
I got another one from Automation Panda, who we met at PyCon.

00:27:08.900 --> 00:27:10.340
And this is Andy.

00:27:10.340 --> 00:27:17.700
And he wrote a cool PyCon 2019 reflections, which I thought if you haven't been to PyCon, check out this article.

00:27:17.700 --> 00:27:21.120
It's like kind of his diary of like what he did and his experiences.

00:27:21.120 --> 00:27:23.460
It's like his second PyCon he ever went to.

00:27:23.460 --> 00:27:26.120
So it was kind of a fresh take on PyCon, which is great.

00:27:26.120 --> 00:27:27.000
That's cool.

00:27:27.000 --> 00:27:27.280
Yeah.

00:27:27.280 --> 00:27:27.520
Yeah.

00:27:27.520 --> 00:27:28.300
It was fun to meet him there.

00:27:28.760 --> 00:27:31.900
I just want to give a quick shout out to our Patreon page, which we don't do that enough.

00:27:31.900 --> 00:27:35.560
So if people want to support the show, obviously visiting the sponsors helps a lot.

00:27:35.560 --> 00:27:40.700
But you can help support with editing fees and other stuff by doing small contributions.

00:27:40.700 --> 00:27:44.620
So there's a link at the bottom of this episode to say here's the Patreon page.

00:27:44.620 --> 00:27:45.640
So people can check that out.

00:27:45.640 --> 00:27:48.160
And Brian, thanks to you for putting that together.

00:27:48.160 --> 00:27:53.120
And one of the things people get is the show notes emailed directly to their inbox if they do that.

00:27:53.120 --> 00:27:53.680
That is awesome.

00:27:54.100 --> 00:27:59.640
And then I just wanted to let people know I'm doing a free one hour webcast in a couple of weeks.

00:27:59.640 --> 00:28:03.180
And the title of the webcast probably more or less sums it up.

00:28:03.180 --> 00:28:07.220
But it's 10 tools and techniques Python web developers should explore.

00:28:07.220 --> 00:28:08.140
That looks interesting.

00:28:08.140 --> 00:28:08.540
Yeah.

00:28:08.540 --> 00:28:10.180
So it's all sorts of fun stuff.

00:28:10.180 --> 00:28:11.420
Like Docker is one of them.

00:28:11.420 --> 00:28:12.420
Vue.js is another.

00:28:12.420 --> 00:28:16.280
You know, Vue models and other sort of design patterns as well.

00:28:16.280 --> 00:28:19.340
A lot of fun things that people haven't maybe seen there.

00:28:19.340 --> 00:28:19.660
Yeah.

00:28:19.660 --> 00:28:21.740
Let's let you kick it off with our joke section.

00:28:21.740 --> 00:28:22.660
What do you got for us?

00:28:22.820 --> 00:28:24.500
Oh, you're going to give it to me.

00:28:24.500 --> 00:28:26.060
I'll steal one of your jokes.

00:28:26.060 --> 00:28:26.880
Yeah, steal it.

00:28:26.880 --> 00:28:27.060
Okay.

00:28:27.060 --> 00:28:27.700
Okay.

00:28:27.700 --> 00:28:29.240
What do you call eight hobbits?

00:28:29.240 --> 00:28:31.560
A hobbite.

00:28:31.560 --> 00:28:33.120
Oh, that's terrible.

00:28:33.120 --> 00:28:34.400
It's so bad.

00:28:34.400 --> 00:28:35.240
It's so bad.

00:28:35.240 --> 00:28:36.200
It wrapped around to good.

00:28:36.200 --> 00:28:38.820
It's like badness overflowed into the good level.

00:28:38.820 --> 00:28:40.500
What do you call eight hobbits?

00:28:40.500 --> 00:28:41.080
All right.

00:28:41.080 --> 00:28:43.060
So I got another one for you.

00:28:43.060 --> 00:28:44.600
This one may also be bad.

00:28:44.600 --> 00:28:46.600
This is a little more on the science-y, math-y side.

00:28:46.600 --> 00:28:49.860
Not quite programming, but it definitely has a computational bit to it.

00:28:50.460 --> 00:28:54.280
So you know Mandelbrot, Benoit B. Mandelbrot is his full name.

00:28:54.280 --> 00:28:58.160
The guy who came up with the Mandelbrot set and fractals and all that kind of stuff, right?

00:28:58.160 --> 00:28:58.480
Yeah.

00:28:58.480 --> 00:29:03.500
And one of the core principles of fractals is no matter how much you zoom into them, there's

00:29:03.500 --> 00:29:09.120
like always more details and often times there's like super weird reasons that it like repeats.

00:29:09.120 --> 00:29:13.280
Like you zoom way into the little branch of the Mandelbrot set, there's like a baby Mandelbrot set.

00:29:13.280 --> 00:29:13.740
Yeah.

00:29:13.740 --> 00:29:14.200
Okay?

00:29:14.200 --> 00:29:15.140
Yeah.

00:29:15.140 --> 00:29:21.540
So the question is for Benoit B. Mandelbrot, what is his middle name?

00:29:21.540 --> 00:29:22.500
What does the B stand for?

00:29:22.500 --> 00:29:25.360
Well, it stands for Benoit B. Mandelbrot.

00:29:25.580 --> 00:29:26.740
Of course it does.

00:29:26.740 --> 00:29:29.640
Yes.

00:29:29.640 --> 00:29:30.480
Oh, I love it.

00:29:30.480 --> 00:29:30.880
All right.

00:29:30.880 --> 00:29:32.320
Well, I guess we're going to leave it.

00:29:32.320 --> 00:29:33.360
We got to do the other one.

00:29:33.360 --> 00:29:33.980
It's so great.

00:29:33.980 --> 00:29:34.400
All right.

00:29:34.400 --> 00:29:34.680
Go for it.

00:29:34.680 --> 00:29:34.880
Okay.

00:29:34.880 --> 00:29:36.320
So two bites meet.

00:29:36.320 --> 00:29:38.700
The first bite asks, are you ill?

00:29:38.700 --> 00:29:42.600
And the second bite replies, no, just feeling a bit off.

00:29:42.600 --> 00:29:46.920
Totally left shift on that one.

00:29:46.920 --> 00:29:47.820
Yeah, absolutely.

00:29:47.820 --> 00:29:49.560
Beautiful.

00:29:49.560 --> 00:29:49.880
All right.

00:29:49.880 --> 00:29:52.260
Well, thanks as always for being here, Brian.

00:29:52.260 --> 00:29:54.220
It's a lot of fun to talk about these and share them with everyone.

00:29:54.220 --> 00:29:54.540
Yep.

00:29:54.540 --> 00:29:54.940
Bye.

00:29:54.940 --> 00:29:55.200
Yep.

00:29:55.200 --> 00:29:55.360
Bye.

00:29:55.360 --> 00:29:57.160
Thank you for listening to Python Bytes.

00:29:57.160 --> 00:29:59.700
Follow the show on Twitter via at Python Bytes.

00:29:59.700 --> 00:30:02.560
That's Python Bytes as in B-Y-T-E-S.

00:30:02.560 --> 00:30:05.800
And get the full show notes at pythonbytes.fm.

00:30:05.800 --> 00:30:10.000
If you have a news item you want featured, just visit pythonbytes.fm and send it our way.

00:30:10.000 --> 00:30:12.700
We're always on the lookout for sharing something cool.

00:30:12.700 --> 00:30:15.800
On behalf of myself and Brian Okken, this is Michael Kennedy.

00:30:15.800 --> 00:30:19.240
Thank you for listening and sharing this podcast with your friends and colleagues.

