WEBVTT

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

00:00:05.260 --> 00:00:12.240
your earbuds. This is episode 115, recorded January 29th, 2019. I'm Michael Kennedy.

00:00:12.240 --> 00:00:13.160
And I'm Brian Okken.

00:00:13.160 --> 00:00:15.000
And Brian, we got a special guest, don't we?

00:00:15.000 --> 00:00:15.340
Yeah.

00:00:15.340 --> 00:00:18.580
Nina Zagarenko. Say hello, Nina. How you doing?

00:00:18.580 --> 00:00:22.520
Hey, everyone. I'm very proud of you for pronouncing my last name correctly.

00:00:22.520 --> 00:00:27.920
Thank you. Brian and I, we specialize in mangling people's last names on this show,

00:00:27.920 --> 00:00:29.300
but we try.

00:00:29.520 --> 00:00:30.700
This time you nailed it.

00:00:30.700 --> 00:00:31.580
Thank you.

00:00:31.580 --> 00:00:35.320
For those who don't know me, I'm a senior cloud developer advocate at Microsoft,

00:00:35.320 --> 00:00:42.080
and my focus is on Python. You can find me on Twitter at NNJA. That's like ninja, but without

00:00:42.080 --> 00:00:42.400
the I.

00:00:42.400 --> 00:00:46.400
Yeah, that's a pretty cool Twitter handle. Awesome. And also, this episode is brought to you by

00:00:46.400 --> 00:00:51.240
Datadog. Check them out at pythonbytes.fm/Datadog. Tell you more about that. You know,

00:00:51.240 --> 00:00:56.580
Brian, I expect quite a bit of stuff out of Datadog. I would say I have great expectations

00:00:56.580 --> 00:00:59.300
when I go use their stuff. What do you think? How about you?

00:00:59.300 --> 00:01:06.620
Yeah, yeah. I do too. Yes. For our first item, we have great expectations. And it is a package

00:01:06.620 --> 00:01:11.240
that was shared by a listener. And I don't know the listener because they shared it with you,

00:01:11.240 --> 00:01:12.740
Michael, and you didn't tell me who it was.

00:01:12.820 --> 00:01:16.220
I just sent you over the link and I forgot. But thank you for sending it in. Next time,

00:01:16.220 --> 00:01:17.020
we'll do a better job.

00:01:17.020 --> 00:01:22.800
Well, we're just also trying to make it so that sharing information with everybody else is not

00:01:22.800 --> 00:01:26.080
an ego-boosting exercise because we won't remember your name.

00:01:26.080 --> 00:01:27.240
Or we'll mispronounce it.

00:01:27.240 --> 00:01:28.760
Unless it's important to you, then let us know.

00:01:28.760 --> 00:01:29.440
Yeah.

00:01:29.440 --> 00:01:29.660
Yeah.

00:01:29.660 --> 00:01:35.560
No, great expectations. It's kind of cool. It's this idea that we have a lot of tools out,

00:01:35.760 --> 00:01:42.700
for instance, pytest, to test your code. But there's in a lot of stuff, the data that you're

00:01:42.700 --> 00:01:50.220
running your code through, like in data science or a lot of data pipelines, the data is important too.

00:01:50.380 --> 00:01:56.540
And being able to check to make sure your data fits what you expect it to fit, what look like, is important.

00:01:56.540 --> 00:02:00.580
So these are some really cool expect calls.

00:02:00.580 --> 00:02:02.980
They're a bunch of functions that start with expect.

00:02:02.980 --> 00:02:07.280
They aren't assertions, so they aren't going to throw an exception.

00:02:07.280 --> 00:02:11.860
But what happens is you, like maybe on some of them, you pass them a data frame.

00:02:11.860 --> 00:02:16.360
Like I'll just give one as an example. You expect a column to exist.

00:02:16.660 --> 00:02:21.780
So you give it a data frame and you give it a specific column, and you want that column to actually be there.

00:02:21.780 --> 00:02:28.600
And if it's not, you get, actually, regardless of whether the answer, it comes back in the form of a JSON object.

00:02:28.600 --> 00:02:35.120
And it has like a valid, and you can say whether or not, you know, if it failed or passed the test.

00:02:35.120 --> 00:02:37.680
But it also shows you the parts where it didn't.

00:02:37.680 --> 00:02:43.940
So this is, there's a little video, actually, demo video that they have, where you can see it in action using a Jupyter notebook.

00:02:44.560 --> 00:02:48.020
And it's kind of cool. It shows you exactly where it's failing.

00:02:48.020 --> 00:02:52.920
So I imagine doing this interactively to look at your data would be helpful.

00:02:52.920 --> 00:02:58.500
But also you could probably put this in place in some data cleaning steps to make sure things are around.

00:02:58.500 --> 00:03:00.940
Like making sure there aren't any nulls in a column.

00:03:00.940 --> 00:03:05.460
There's a whole bunch of different things you can assert on or expect on your data.

00:03:05.460 --> 00:03:06.300
It's pretty fun.

00:03:06.300 --> 00:03:07.060
Yeah, it's pretty cool.

00:03:07.060 --> 00:03:08.400
Some of them are totally straightforward.

00:03:08.400 --> 00:03:10.420
Like expect these values to be in the set.

00:03:11.020 --> 00:03:20.640
Others, a little more data science, mathematical focused, like expect the chi-squared test p-value to be greater than such and such, right?

00:03:20.640 --> 00:03:26.580
I honestly haven't done a lot of chi-squared lately, but I don't do that much data science, you know, on the web.

00:03:26.580 --> 00:03:29.840
It's more we use addition and like stuff like that.

00:03:30.920 --> 00:03:42.080
Yeah, but some of the fun things, like it was in the video example, he expected some data from a column to be in a particular set.

00:03:42.080 --> 00:03:44.360
And it was either male or female.

00:03:45.200 --> 00:03:47.840
And first off, like how binary of this.

00:03:47.840 --> 00:03:51.800
But anyway, the males, a lot of them came back with spaces in them.

00:03:51.800 --> 00:03:59.340
So doing some of this exploratory thing might tell you where you need to add some cleaning steps or dealing with nulls or things like that.

00:03:59.340 --> 00:04:06.060
The follow-up, I'd like to hear how people might be able to use this, how it's used exploratory-wise.

00:04:06.220 --> 00:04:12.040
But how, I'd like to see somebody using it in their pipeline stages and how that works.

00:04:12.040 --> 00:04:21.080
Whether you, I guess I imagine if you had it in production, you'd have some code that would, if it failed an expectation, you'd write a log entry or something?

00:04:21.080 --> 00:04:22.620
Or I don't know what you'd do.

00:04:22.640 --> 00:04:26.700
Yeah, or maybe return, if you were accepting data over a web method, right?

00:04:26.700 --> 00:04:30.640
Somebody's doing ETL and they're like, here, we're submitting this new set of data.

00:04:30.640 --> 00:04:35.740
You could return like 400 bad requests to indicate, no, no, something's wrong with the data you sent me.

00:04:35.740 --> 00:04:36.740
Things like that, possible.

00:04:36.740 --> 00:04:37.100
Yeah.

00:04:37.100 --> 00:04:38.360
You know, what do you think about this?

00:04:38.360 --> 00:04:42.100
I think it's very cool and is probably going to be pretty helpful.

00:04:42.100 --> 00:04:43.080
I like it as well.

00:04:43.080 --> 00:04:52.880
What I like about it is it lets you take what would be a little algorithm you'd have to write to, say, go through and test all, say, the chi-square values and then compare them and then assert on that.

00:04:52.880 --> 00:04:56.080
Now you just do one line and it does it on the whole data set, the whole data frame.

00:04:56.080 --> 00:04:56.580
That's pretty sweet.

00:04:56.580 --> 00:04:59.000
Yeah, I'm going to be watching the video demo after the show.

00:04:59.000 --> 00:04:59.960
Yeah, right on.

00:04:59.960 --> 00:05:04.700
So the thing that you are going to cover next, the timing is incredible, Nina.

00:05:04.700 --> 00:05:11.180
I literally got a notification that I had ordered one of these and it shipped today and it's on its way to my house.

00:05:11.180 --> 00:05:12.080
So I'm very excited.

00:05:12.320 --> 00:05:14.120
Tell people what is on its way.

00:05:14.120 --> 00:05:17.740
Would that be the Circuit Playground Express?

00:05:17.740 --> 00:05:18.920
It would be.

00:05:18.920 --> 00:05:19.300
Yeah.

00:05:19.300 --> 00:05:19.840
Awesome.

00:05:19.840 --> 00:05:20.620
Yeah.

00:05:20.620 --> 00:05:28.800
So I wanted to chat a little bit about using CircuitPython and MicroPython to write Python for wearable electronics and embedded platforms.

00:05:28.800 --> 00:05:34.040
I've been playing with electronics projects as a hobby for probably about the past two years now.

00:05:34.040 --> 00:05:39.200
In the past few months, I've been focusing my attention on Python for microcontrollers.

00:05:39.200 --> 00:05:39.640
Right on.

00:05:39.640 --> 00:05:42.400
And what kind of little things are you making with your projects?

00:05:42.400 --> 00:05:45.760
My last one was Python powered LED earrings.

00:05:45.760 --> 00:05:49.720
And I dropped a link to the repo for the code as well as a photo.

00:05:49.720 --> 00:05:50.660
So you can see that.

00:05:50.660 --> 00:05:51.340
Okay.

00:05:51.340 --> 00:05:53.780
So what I know I've heard of MicroPython.

00:05:53.780 --> 00:05:55.260
And I think I've heard of CircuitPython.

00:05:55.260 --> 00:05:56.320
Are they the same?

00:05:56.320 --> 00:05:56.820
Are they different?

00:05:56.820 --> 00:05:57.520
Tell everyone about it.

00:05:57.580 --> 00:06:00.600
Yeah, there's definitely a little bit of confusion about that.

00:06:00.600 --> 00:06:02.920
So MicroPython is the original.

00:06:02.920 --> 00:06:09.320
It's a lean and efficient implementation of Python 3 that can run on these tiny little microcontrollers.

00:06:09.320 --> 00:06:15.060
And all it needs is 256 kilobytes of code space and 16 kilobytes of RAM.

00:06:15.060 --> 00:06:16.040
It's incredible.

00:06:16.040 --> 00:06:17.120
It's truly awesome.

00:06:17.120 --> 00:06:17.780
Yeah.

00:06:17.800 --> 00:06:19.500
It's so super low level too.

00:06:19.500 --> 00:06:19.700
Yeah.

00:06:19.700 --> 00:06:23.600
And CircuitPython is a port of MicroPython.

00:06:23.600 --> 00:06:26.240
And it's optimized for Adafruit devices.

00:06:26.240 --> 00:06:26.700
Cool.

00:06:26.700 --> 00:06:29.060
So I guess that's the one I'm going to be learning about.

00:06:29.060 --> 00:06:29.260
Yeah.

00:06:29.260 --> 00:06:30.160
Yeah.

00:06:30.560 --> 00:06:34.800
And some of these, the devices that Adafruit sells, they're as small as a quarter.

00:06:34.800 --> 00:06:36.260
That would be the trinket.

00:06:36.260 --> 00:06:42.360
But of course, my favorite Python hardware platform for beginners is that the Adafruit Circuit Playground

00:06:42.360 --> 00:06:42.660
Express.

00:06:42.660 --> 00:06:47.900
It has everything you need to get started with programming hardware without even needing to

00:06:47.900 --> 00:06:48.560
learn how to solder.

00:06:48.560 --> 00:06:52.120
All you need is some alligator clips for the conductive pads.

00:06:52.120 --> 00:06:55.760
And the board has a ring of neopixel LEDs.

00:06:56.160 --> 00:07:02.640
It has buttons, switches, temperature sensors, motion detectors, sound sensors, a tiny little

00:07:02.640 --> 00:07:04.820
speaker, and a lot more stuff.

00:07:04.820 --> 00:07:09.540
Like you can even use it to control servos, which are those tiny little motor arms.

00:07:09.540 --> 00:07:10.020
Wow.

00:07:10.020 --> 00:07:11.060
That's really awesome.

00:07:11.060 --> 00:07:11.500
Yeah.

00:07:11.500 --> 00:07:13.020
It's a tiny little thing.

00:07:13.020 --> 00:07:13.320
Yeah.

00:07:13.320 --> 00:07:17.960
What I really like about this and the reason that I ordered it was I can go to Adafruit and

00:07:17.960 --> 00:07:20.900
look around and I'm just like, this is too low level for me.

00:07:20.900 --> 00:07:22.340
I don't really know what I need.

00:07:22.340 --> 00:07:25.860
I don't even know if I have a power supply, if I get this little chip or that.

00:07:25.980 --> 00:07:26.840
Like how to put together.

00:07:26.840 --> 00:07:31.440
I'm like, okay, give me like one thing that has all the stuff to do little projects like

00:07:31.440 --> 00:07:31.900
you're describing.

00:07:31.900 --> 00:07:33.200
And I think it's awesome.

00:07:33.200 --> 00:07:35.400
And doing it in Python is super cool.

00:07:35.400 --> 00:07:36.600
It only costs $25.

00:07:36.600 --> 00:07:37.320
Yeah.

00:07:37.320 --> 00:07:38.120
It's not too expensive.

00:07:38.120 --> 00:07:38.560
No.

00:07:38.560 --> 00:07:44.780
And then if you don't want to use Python to program this, there's a tool that you can use

00:07:44.780 --> 00:07:46.280
called Microsoft MakeCode.

00:07:46.280 --> 00:07:51.740
And it lets you program these little devices with a drag and drop style kind of scratch

00:07:51.740 --> 00:07:52.580
like interface.

00:07:52.580 --> 00:07:54.900
So that's perfect for kids.

00:07:54.900 --> 00:07:57.000
And you'll find a lot of examples on their site.

00:07:57.000 --> 00:08:01.420
Oh, that's awesome that you point that out because I might get my daughter to do some kind

00:08:01.420 --> 00:08:04.320
of little game, you know, like a Simon Says or something with the LEDs.

00:08:04.320 --> 00:08:05.080
Who knows?

00:08:05.080 --> 00:08:05.660
That'd be fun.

00:08:05.660 --> 00:08:06.000
Yeah.

00:08:06.080 --> 00:08:09.280
The Mu editor has some tutorials on using these as well.

00:08:09.280 --> 00:08:09.620
Right.

00:08:09.620 --> 00:08:10.340
That's awesome.

00:08:10.340 --> 00:08:10.940
Super cool.

00:08:10.940 --> 00:08:11.560
All right.

00:08:11.560 --> 00:08:12.900
And I like you threw in the link.

00:08:12.900 --> 00:08:13.340
Yeah.

00:08:13.340 --> 00:08:14.320
To your code.

00:08:14.320 --> 00:08:16.300
So people can do the earrings as well.

00:08:16.300 --> 00:08:16.680
Yeah.

00:08:16.800 --> 00:08:20.680
And like you said earlier, there are tons of guides for Python projects on the Adafruit

00:08:20.680 --> 00:08:21.180
website.

00:08:21.180 --> 00:08:26.720
Stuff from making your own synthesizers to jewelry to silly little robots.

00:08:26.720 --> 00:08:28.560
So definitely make sure to check that out.

00:08:28.560 --> 00:08:28.760
Cool.

00:08:28.760 --> 00:08:28.960
Yeah.

00:08:28.960 --> 00:08:31.280
Well, I can almost recommend it.

00:08:31.280 --> 00:08:32.300
It looks really, really good.

00:08:32.300 --> 00:08:35.320
And when I get it, I'm going to play with it and let everyone know what I think.

00:08:35.320 --> 00:08:38.340
But yeah, it seems like a great little package that you can get.

00:08:38.340 --> 00:08:39.060
25 bucks.

00:08:39.060 --> 00:08:42.800
You know, it's like, you know, as software developers, you could just try it, right?

00:08:42.800 --> 00:08:43.700
It's not that big of a risk.

00:08:43.700 --> 00:08:45.500
It's not like you're getting a new MacBook or something.

00:08:45.500 --> 00:08:45.920
Mm-hmm.

00:08:45.920 --> 00:08:51.040
And Adafruit has a Python for microcontrollers mailing list.

00:08:51.040 --> 00:08:54.640
And they always drop kind of hot news and interesting new things.

00:08:54.640 --> 00:08:57.220
So there's a link to sign up for that in the show notes.

00:08:57.220 --> 00:08:57.600
Awesome.

00:08:57.600 --> 00:08:58.200
That's a great one.

00:08:58.200 --> 00:09:04.400
So this next one, I think, is a really interesting use of Python 3.7.

00:09:04.400 --> 00:09:10.600
So when you think of the main features of Python 3.7, certainly data classes has to be

00:09:10.600 --> 00:09:11.100
one of them.

00:09:11.100 --> 00:09:13.360
Have either of you found any use for data classes yet?

00:09:13.360 --> 00:09:14.280
Yeah, I just love them.

00:09:14.280 --> 00:09:15.900
I use them like named tuples.

00:09:15.900 --> 00:09:16.120
Yeah.

00:09:16.120 --> 00:09:16.420
Yeah.

00:09:16.420 --> 00:09:17.440
They're awesome.

00:09:17.440 --> 00:09:20.260
Trey Hunter has a great talk on data classes.

00:09:20.260 --> 00:09:20.740
Definitely.

00:09:20.740 --> 00:09:24.820
So this is a library that's derived from data classes.

00:09:24.820 --> 00:09:26.840
And it's a CSV file reader.

00:09:26.840 --> 00:09:29.780
Now, Python comes with pretty good support for CSV readers.

00:09:29.780 --> 00:09:33.780
You import CSV and then you create a dict reader based on a file stream.

00:09:33.780 --> 00:09:36.040
And it'll read the header and figure out the columns.

00:09:36.040 --> 00:09:38.620
And then it gives you little dictionaries based on the column names.

00:09:38.620 --> 00:09:39.480
And that's pretty sweet.

00:09:39.480 --> 00:09:44.560
But what you get back is a whole bunch of strings corresponding to those values.

00:09:44.560 --> 00:09:44.880
Right?

00:09:45.340 --> 00:09:51.520
And with this, what you can do is you can actually define a data class that maps the schema of

00:09:51.520 --> 00:09:53.560
your CSV file.

00:09:53.560 --> 00:09:54.220
Right?

00:09:54.220 --> 00:09:59.580
So I could define a data class that maybe has an ID and a name and a value or price.

00:09:59.580 --> 00:09:59.800
Right?

00:09:59.800 --> 00:10:00.700
Maybe it's like products.

00:10:00.700 --> 00:10:04.220
So like the ID could be an integer defined in the data class.

00:10:04.220 --> 00:10:05.160
The name could be a string.

00:10:05.160 --> 00:10:07.780
And the value, the price could be, say, a float.

00:10:07.880 --> 00:10:13.020
And it'll actually do all those conversions for you and give you meaningful errors if like

00:10:13.020 --> 00:10:15.320
it's a non-parsable float or something like that.

00:10:15.320 --> 00:10:15.880
Isn't that nice?

00:10:15.880 --> 00:10:16.560
That's incredible.

00:10:16.560 --> 00:10:19.580
Working with CSV is the bane of my existence.

00:10:19.580 --> 00:10:20.020
Yeah.

00:10:20.020 --> 00:10:21.460
So you can just define these things.

00:10:21.460 --> 00:10:26.640
You get autocomplete in, you know, PyCharm or Visual Studio Code for your types, for your

00:10:26.640 --> 00:10:28.660
rows, because they come back as these data classes.

00:10:28.660 --> 00:10:31.200
And you get validation.

00:10:31.200 --> 00:10:33.420
And on top of that, you can actually do cool stuff.

00:10:33.520 --> 00:10:39.280
Like you can say, with data classes, you can specify either just the type or the type and

00:10:39.280 --> 00:10:40.200
a value.

00:10:40.200 --> 00:10:42.060
And that value becomes the default value.

00:10:42.060 --> 00:10:45.740
So if like only sometimes the price is there, you could put zero or minus one.

00:10:45.740 --> 00:10:48.400
And it'll just go through and substitute that value.

00:10:48.400 --> 00:10:50.120
So a lot of cool little nice touches here.

00:10:50.120 --> 00:10:50.420
Nice.

00:10:50.420 --> 00:10:50.660
Yeah.

00:10:50.660 --> 00:10:54.440
I'm definitely going to check this out the next time that I have to do some sort of CSV parsing

00:10:54.440 --> 00:10:59.060
because it's way better to let this thing do the validation and the type conversion and

00:10:59.060 --> 00:11:00.760
all that and just, you know, not worry.

00:11:00.760 --> 00:11:03.880
I don't think I've been this excited about CSV files in a long time.

00:11:03.880 --> 00:11:04.200
I know.

00:11:04.200 --> 00:11:05.860
They are.

00:11:05.860 --> 00:11:07.180
They are pretty amazing.

00:11:07.180 --> 00:11:09.980
No, this really makes working with them nice.

00:11:09.980 --> 00:11:11.340
And I'm excited, too.

00:11:11.340 --> 00:11:12.320
All right.

00:11:12.320 --> 00:11:14.380
Speaking of excited, I do want to tell you about Datadog.

00:11:14.380 --> 00:11:15.980
They're helping make this show possible.

00:11:15.980 --> 00:11:18.680
So before we get to our next item, let me tell you about them.

00:11:18.680 --> 00:11:21.320
This show is brought to you by Datadog.

00:11:21.320 --> 00:11:25.880
They're a cloud scale monitoring platform that brings like metrics and logs, distributed traces

00:11:25.880 --> 00:11:26.460
all together.

00:11:26.760 --> 00:11:32.580
You can do auto instrumenting of frameworks like Django and Flask and PostgreSQL, which

00:11:32.580 --> 00:11:37.980
means you can track requests across service boundaries, across machines, things like that, which is

00:11:37.980 --> 00:11:38.300
awesome.

00:11:38.300 --> 00:11:43.140
It makes it really easy to troubleshoot your slow Python apps and figure out overall where

00:11:43.140 --> 00:11:44.000
the time is being spent.

00:11:44.000 --> 00:11:48.260
So you can get started for free at pythonbytes.fm/Datadog.

00:11:48.340 --> 00:11:53.240
And they'll also give you a cool t-shirt with a Datadog character on it, which is nice and

00:11:53.240 --> 00:11:53.420
cute.

00:11:53.420 --> 00:11:54.700
So check them out.

00:11:54.700 --> 00:11:56.160
It helps keep the show going.

00:11:56.160 --> 00:12:01.780
Now, Brian, I want to come to a topic that we haven't really covered very much on the show,

00:12:01.780 --> 00:12:05.180
but maybe I think a while ago we did talk about packaging ones, right?

00:12:05.180 --> 00:12:06.940
Yeah.

00:12:06.940 --> 00:12:08.640
You want to catch us up on it?

00:12:08.640 --> 00:12:11.140
I think it's only second to GUIs so far.

00:12:11.140 --> 00:12:12.160
That's right.

00:12:12.160 --> 00:12:17.780
There's a fun article called How to Rock Python Packaging with Poetry in Briefcase.

00:12:17.780 --> 00:12:22.220
Plus, it has the phrase how to rock something, and I'm a sucker for that.

00:12:22.220 --> 00:12:25.360
It's actually kind of a nice tutorial on packaging.

00:12:25.360 --> 00:12:30.820
So for those of you that just joined us and haven't learned all of our discussions on packaging,

00:12:30.820 --> 00:12:36.440
this is a nice introduction to packaging and how it fits in Python and also kind of how

00:12:36.440 --> 00:12:43.760
the changing of things, changing of packaging, like where Flit, Pipenv, and Poetry sort of fit in

00:12:43.760 --> 00:12:44.940
with all of this.

00:12:44.940 --> 00:12:46.780
It's kind of a nice run through of that.

00:12:46.780 --> 00:12:53.380
Poetry is one of those things for packaging, and it uses the pyproject.toml file.

00:12:53.380 --> 00:12:57.220
And of course, we talked about poetry in episode 100.

00:12:57.220 --> 00:13:04.940
And the nitty-gritty details of pyproject.toml was in testing code 52 with Brett Cannon.

00:13:04.940 --> 00:13:09.980
But the neat thing, one of the neat things why I picked this is it also talks about Briefcase.

00:13:09.980 --> 00:13:12.720
And we haven't talked about Briefcase yet.

00:13:12.720 --> 00:13:17.860
And Briefcase is one of those tools from Py, the Beware project.

00:13:17.860 --> 00:13:24.560
And it's something that you can, it packages your, a Python application as a standalone native

00:13:24.560 --> 00:13:27.080
application for lots of stuff.

00:13:27.080 --> 00:13:31.640
It claims Mac, Windows, Linux, even iOS and Android, which is interesting.

00:13:31.640 --> 00:13:33.140
I haven't tried any of this.

00:13:33.140 --> 00:13:38.760
The tutorial talks about desktop distribution of code through Briefcase.

00:13:38.760 --> 00:13:40.040
And it's kind of cool.

00:13:40.040 --> 00:13:42.020
And how to get that done with poetry.

00:13:42.020 --> 00:13:43.920
I think poetry is definitely nice.

00:13:43.920 --> 00:13:49.920
It's, you know, sort of an alternative philosophy to PipInv, which is, we talked about that as well.

00:13:49.920 --> 00:13:56.880
And Briefcase is part of that whole set of small independent tools from Beware, which also is

00:13:56.880 --> 00:13:57.220
pretty cool.

00:13:57.220 --> 00:13:58.700
And it's nice to see them working together.

00:13:58.820 --> 00:14:02.620
Also, we got Cookie Cutter doing some magic in here as well.

00:14:02.620 --> 00:14:03.040
Definitely.

00:14:03.040 --> 00:14:08.120
And then one of the things that I like at the end of this, there's several tutorials on publishing,

00:14:08.120 --> 00:14:12.120
like how to push your new package to PyPI.

00:14:12.560 --> 00:14:17.420
But this one I really like because instead of telling you exactly how to push it to PyPI,

00:14:17.420 --> 00:14:19.940
they tell you how to push it to the test server.

00:14:19.940 --> 00:14:23.040
And I think that's an important step for people to do.

00:14:23.040 --> 00:14:28.120
Before you subject the world to your code, try it out at the test server first.

00:14:28.120 --> 00:14:29.220
So it's nice.

00:14:29.220 --> 00:14:29.960
Of course.

00:14:29.960 --> 00:14:31.340
Yeah, of course.

00:14:31.400 --> 00:14:32.420
Why don't more of them do that?

00:14:32.420 --> 00:14:34.660
I don't know.

00:14:34.660 --> 00:14:39.500
But please, everybody, like save the world and push it here first.

00:14:39.500 --> 00:14:39.740
Yeah.

00:14:39.740 --> 00:14:42.820
The packages on PyPI cannot be changed when they're uploaded.

00:14:42.820 --> 00:14:44.340
You can only add newer ones.

00:14:44.340 --> 00:14:50.700
So although you've got to admire the rate at which you'll increase your version of your package

00:14:50.700 --> 00:14:52.860
if you screw it up a few times trying to publish it.

00:14:52.860 --> 00:14:56.060
Yeah.

00:14:56.140 --> 00:14:57.160
That's productivity, right?

00:14:57.160 --> 00:14:57.640
That's right.

00:14:57.640 --> 00:15:04.100
So Nina, this next one that you found for us is one of these awesome lists.

00:15:04.100 --> 00:15:08.480
And I think these awesome lists are coming along really faster and faster these days, right?

00:15:08.480 --> 00:15:10.840
We've got awesome Python, awesome Python applications.

00:15:10.840 --> 00:15:13.660
What's the next one that's in that category?

00:15:13.660 --> 00:15:17.280
And this is a new one I came across called Awesome Python Security.

00:15:17.280 --> 00:15:22.340
It's a collection of tools, techniques, and resources to make your Python more secure.

00:15:22.340 --> 00:15:23.120
Oh, that's cool.

00:15:23.120 --> 00:15:23.640
Yeah.

00:15:23.700 --> 00:15:27.880
And it's got a lot of stuff for web apps like the secure.py, which is awesome.

00:15:27.880 --> 00:15:28.600
We've covered that.

00:15:28.600 --> 00:15:32.920
And the Flask, Flask Talesman, Django sessions, all kinds of stuff, right?

00:15:32.920 --> 00:15:34.340
But not just the web.

00:15:34.340 --> 00:15:35.300
There's a whole bunch of other ones.

00:15:35.300 --> 00:15:39.640
I think, and hopefully all of you agree, that all of your production and client-facing code

00:15:39.640 --> 00:15:41.280
should be written with security in mind.

00:15:42.280 --> 00:15:47.940
And this list features a few resources that I'd come across before, like Anthony Shaw's excellent

00:15:47.940 --> 00:15:54.060
10 common security gotchas article that highlights problems like input ejection and depending on

00:15:54.060 --> 00:15:55.360
assert statements in production.

00:15:56.100 --> 00:15:58.600
And I also came across a few that were new to me.

00:15:58.600 --> 00:16:01.360
So the OWASP Python resources.

00:16:01.360 --> 00:16:04.980
OWASP stands for Open Web Application Security Project.

00:16:04.980 --> 00:16:08.380
And there's tons of OWASP resources out there.

00:16:08.380 --> 00:16:10.740
I didn't know that there was a Python-specific one.

00:16:10.740 --> 00:16:13.440
You can find that one at pythonsecurity.org.

00:16:13.680 --> 00:16:17.980
I came across Bandit, which is a tool to find common security issues in Python.

00:16:17.980 --> 00:16:24.180
And now Bandit has a lot of really useful plugins that test for some issues like hard-coded password

00:16:24.180 --> 00:16:31.060
strings in production, leaving Flask debug on in production, using exec in your code, and

00:16:31.060 --> 00:16:31.820
a lot more.

00:16:31.820 --> 00:16:33.960
I linked to the full list in the show notes.

00:16:33.960 --> 00:16:40.020
And then a few other cool ones like Detect Secrets, which is a tool to detect secrets that

00:16:40.020 --> 00:16:42.120
were accidentally left in your Python code base.

00:16:42.120 --> 00:16:42.700
That's cool.

00:16:42.700 --> 00:16:42.980
Yeah.

00:16:42.980 --> 00:16:43.280
Yeah.

00:16:43.420 --> 00:16:44.400
Let's open source that.

00:16:44.400 --> 00:16:44.940
Oh, wait.

00:16:44.940 --> 00:16:48.480
Was our full access AWS or Azure key in there?

00:16:48.480 --> 00:16:48.940
Whoopsie.

00:16:48.940 --> 00:16:50.660
Oops.

00:16:50.660 --> 00:16:52.500
Oopsie doops.

00:16:52.500 --> 00:16:54.540
We'll just check it in again without that in there.

00:16:54.540 --> 00:16:55.400
I'm sure it'll be fine.

00:16:55.400 --> 00:16:56.140
There's no history.

00:16:56.140 --> 00:17:00.840
And something I really like about this list in particular is it also includes resources

00:17:00.840 --> 00:17:03.720
for learning about security concepts like cryptography.

00:17:03.720 --> 00:17:04.140
Yeah.

00:17:04.140 --> 00:17:09.060
You know, out of that cryptography section, they listed one of my all-time favorite packages,

00:17:09.060 --> 00:17:09.980
which is PassLib.

00:17:10.120 --> 00:17:16.200
So if you're going to store user secrets and you want to hash them, like passwords are

00:17:16.200 --> 00:17:19.500
probably the most common, but there could be other things as well that you don't want

00:17:19.500 --> 00:17:23.120
to store directly, but you want to accept from user and see if you have it.

00:17:23.120 --> 00:17:23.820
All right.

00:17:23.820 --> 00:17:26.220
Like you can hash it and that's a good idea.

00:17:26.220 --> 00:17:30.920
But what you really should do is like take that result, add some salt, then hash it again,

00:17:30.920 --> 00:17:33.940
take that, do it again, maybe a hundred thousand times, right?

00:17:33.940 --> 00:17:39.620
PassLib, that's like one function, like dot encrypt rounds equal 150,000, 200,000, whatever.

00:17:39.620 --> 00:17:40.700
It's really nice.

00:17:40.800 --> 00:17:41.320
That's awesome.

00:17:41.320 --> 00:17:41.660
Yep.

00:17:41.660 --> 00:17:44.380
To make sure your password doesn't end up on have I been pwned.

00:17:44.380 --> 00:17:44.860
Exactly.

00:17:44.860 --> 00:17:45.820
Exactly.

00:17:45.820 --> 00:17:51.500
So basically you can say, I want it to take, you know, 0.2 seconds to determine, to brute

00:17:51.500 --> 00:17:53.500
force or to check each version of the password.

00:17:53.500 --> 00:17:57.960
And it automatically, because of that, will slow down dictionary attacks against your site

00:17:57.960 --> 00:18:00.960
because you can only do them point, you know, it'd take only five per second, right?

00:18:00.960 --> 00:18:03.640
So, and then there's another one called let's be bad guys.

00:18:03.640 --> 00:18:04.280
That's interesting.

00:18:04.280 --> 00:18:05.560
So yeah, a lot of cool stuff here.

00:18:07.100 --> 00:18:08.420
It's a great project name.

00:18:08.420 --> 00:18:08.780
I know.

00:18:08.780 --> 00:18:10.200
It's like a hacker playground.

00:18:10.200 --> 00:18:10.920
Yeah.

00:18:10.920 --> 00:18:12.460
So check out the full list on GitHub.

00:18:12.460 --> 00:18:16.740
And then if there's something missing that you think should be there, maybe open a pull

00:18:16.740 --> 00:18:17.120
request.

00:18:17.120 --> 00:18:17.720
Yeah, absolutely.

00:18:17.720 --> 00:18:18.720
That's a cool one.

00:18:18.720 --> 00:18:19.480
I'm glad you found it.

00:18:19.480 --> 00:18:20.360
All right.

00:18:20.360 --> 00:18:27.340
The last official item I want to cover is PyDBG, which is the implementation of a, of a

00:18:27.340 --> 00:18:29.760
Rust macro called DBG.

00:18:29.760 --> 00:18:31.540
So just put the pie on the front.

00:18:31.540 --> 00:18:34.140
Now I haven't done that much Rust.

00:18:34.140 --> 00:18:35.520
I've actually been wanting to learn Rust.

00:18:35.600 --> 00:18:41.200
It looks pretty interesting to me, but the basic idea of this DBG macro is instead of

00:18:41.200 --> 00:18:47.560
just printing out, like I'm here, I'm here, the value is, you know, printing X as the value,

00:18:47.560 --> 00:18:51.600
it'll actually give you a higher level statement without doing more work.

00:18:51.600 --> 00:18:54.940
So if you're trying to debug something through print statements and that kind of thing, this

00:18:54.940 --> 00:18:55.740
makes it a lot easier.

00:18:56.160 --> 00:19:00.080
So you can go and say, like, I have a equals two, b equals three.

00:19:00.080 --> 00:19:06.840
If I could say DBG of a plus b, the output is the file of the line a plus b equals five.

00:19:06.840 --> 00:19:08.200
Things like that.

00:19:08.200 --> 00:19:09.600
Really, really nice.

00:19:09.600 --> 00:19:14.400
It sort of shows you in your message where you are in the file, what thing is you're actually

00:19:14.400 --> 00:19:17.840
printing without having to like come up with elaborate print statements.

00:19:18.160 --> 00:19:19.100
So pretty cool.

00:19:19.100 --> 00:19:20.940
Oh man, I'm going to use this like every day.

00:19:20.940 --> 00:19:25.740
Do you still use print statements to debug brain?

00:19:25.740 --> 00:19:26.560
Yes, I do.

00:19:26.560 --> 00:19:27.800
I love print statements.

00:19:29.000 --> 00:19:32.840
I use the debugger a lot, but every now and then I'm just like, you know, I just want

00:19:32.840 --> 00:19:35.160
to print this out and just see what is happening.

00:19:35.160 --> 00:19:41.500
Like I don't primarily use print statements for debugging, but sometimes I do when I'm kind

00:19:41.500 --> 00:19:45.040
of exploring that I want it to run, but I kind of want to see what's happening.

00:19:45.040 --> 00:19:46.640
I'm like, Oh, what am I getting back from that API?

00:19:46.640 --> 00:19:48.040
What is this value?

00:19:48.040 --> 00:19:49.180
Things like that.

00:19:49.180 --> 00:19:51.400
Have either of you used watch statements?

00:19:51.400 --> 00:19:52.240
No, tell us about it.

00:19:52.240 --> 00:19:55.280
You can just set up a variable or an expression to watch.

00:19:55.740 --> 00:19:59.740
And, you know, every time you hit a break point, you're like, Oh, I see what's in there.

00:19:59.740 --> 00:20:00.800
I don't have to type it again.

00:20:00.800 --> 00:20:02.080
With VS Code or PyCharm?

00:20:02.080 --> 00:20:02.540
Yeah.

00:20:02.540 --> 00:20:06.560
I believe you can set up watches with PDB2, but I don't know.

00:20:06.560 --> 00:20:08.460
I usually do those in a graphical debugger.

00:20:08.460 --> 00:20:09.320
Yeah, me too.

00:20:09.320 --> 00:20:10.600
Yeah, I definitely have used those.

00:20:10.600 --> 00:20:14.320
I was, I was thinking something different, but so what, where, where I'm going to use this

00:20:14.320 --> 00:20:20.040
DBG, PyDBG thing is a lot of times I've got, we've got test code that generates

00:20:20.040 --> 00:20:23.160
huge amounts of data, like trace data.

00:20:23.820 --> 00:20:30.660
And, these are stored and the test runs are really long and throwing a couple

00:20:30.660 --> 00:20:33.660
of these extra ones for intermediate values.

00:20:33.660 --> 00:20:39.940
So the failing tests or failing test runs, we can take a look at those postmortem, things

00:20:39.940 --> 00:20:40.280
like that.

00:20:40.280 --> 00:20:41.640
It'd be just save.

00:20:41.640 --> 00:20:44.080
It's an elegant way to, to have that be done.

00:20:44.080 --> 00:20:44.380
Yeah.

00:20:44.380 --> 00:20:44.700
Yeah.

00:20:44.700 --> 00:20:45.200
It's pretty cool.

00:20:45.200 --> 00:20:47.060
What I like about it is this like so simple, right?

00:20:47.060 --> 00:20:50.720
Like you place the word print with DBG and you, you kind of got something going on here.

00:20:50.720 --> 00:20:51.960
It also kind of like that.

00:20:51.960 --> 00:20:52.680
It's more explicit.

00:20:52.780 --> 00:20:54.880
You're like, this is not really supposed to be a print statement.

00:20:54.880 --> 00:20:57.860
This is just here till I figure out what's going on.

00:20:57.860 --> 00:20:59.080
And then we're going to stop this.

00:20:59.080 --> 00:20:59.480
Yeah.

00:20:59.480 --> 00:21:00.500
But cool.

00:21:00.500 --> 00:21:01.300
People can check it out.

00:21:01.300 --> 00:21:04.460
Thanks for sending that in to our listeners.

00:21:04.460 --> 00:21:05.020
All right.

00:21:05.020 --> 00:21:09.400
So I guess that's it for all of our main topics, but looking at our show notes here, Brian,

00:21:09.400 --> 00:21:12.020
we all like kind of had a second round in the extra.

00:21:12.020 --> 00:21:14.260
So maybe we'll do like a lightning round one more time.

00:21:14.260 --> 00:21:14.960
What do you got for us?

00:21:14.960 --> 00:21:24.040
This is just a quickie that pytest has temporary directories and temperature factory fixtures for dealing with temporary files.

00:21:24.040 --> 00:21:33.020
But they've added, as of pytest 3.9, there's path versions that return pathlib path objects.

00:21:33.020 --> 00:21:35.780
And those are just quite fun.

00:21:35.780 --> 00:21:37.200
And I'll drop a link in the show notes.

00:21:37.400 --> 00:21:37.620
Okay.

00:21:37.620 --> 00:21:38.140
That's great.

00:21:38.140 --> 00:21:44.520
So I want to bring your attention to something, let's say, non-standard in terms of conference presentations.

00:21:44.520 --> 00:21:46.160
So this is something at PyCon US.

00:21:46.680 --> 00:22:01.120
So in May, Cleveland, 2019, there's a project called The Art of Python, which is a miniature arts festival focusing on narrative performance and visual art around programming and Python.

00:22:01.120 --> 00:22:08.300
And basically showcase novel art that helps us share our emotionally charged programming experiences, particularly to do with Python.

00:22:08.300 --> 00:22:12.160
So it's like five to 20 minute presentations in a separate little track.

00:22:12.160 --> 00:22:13.500
And the call for papers are open.

00:22:13.680 --> 00:22:17.960
So if you've always been a theater fan and you program, here you go.

00:22:17.960 --> 00:22:19.260
Oh, this looks very cool.

00:22:19.260 --> 00:22:20.100
Yeah.

00:22:20.100 --> 00:22:20.560
Yeah.

00:22:20.560 --> 00:22:21.140
That's pretty interesting.

00:22:21.140 --> 00:22:23.180
So people can check that out if that connects with them.

00:22:23.180 --> 00:22:31.140
The other one is one of my favorite surveys and sort of put your finger on the pulse of the community items is the Stack Overflow survey.

00:22:31.140 --> 00:22:33.740
Well, the 2019 one is open.

00:22:33.740 --> 00:22:39.180
So everyone should go out there and represent for Python and fill out the 2019 Stack Overflow survey.

00:22:39.180 --> 00:22:40.520
So that's good.

00:22:40.840 --> 00:22:44.160
And then finally, this gets a little bit back to your pick, Nina.

00:22:44.160 --> 00:22:50.940
NumPy is awaiting a fix for a critical remote, remote code execution bug.

00:22:50.940 --> 00:22:52.440
That's bad.

00:22:52.440 --> 00:22:55.300
That doesn't sound super good.

00:22:55.300 --> 00:22:59.360
So, yeah, I don't know if it has been entirely fixed yet.

00:22:59.440 --> 00:23:01.660
I don't, you know, this is a couple days ago.

00:23:01.660 --> 00:23:02.320
It was not.

00:23:02.320 --> 00:23:06.260
So the idea is basically there's a problem with the pickle module.

00:23:06.260 --> 00:23:11.700
Have you ever, could you imagine there'd be a problem with accepting user input straight in pickle form?

00:23:11.700 --> 00:23:12.900
I can't imagine.

00:23:13.580 --> 00:23:19.000
So the idea is there's some part of NumPy that you can load pickled data.

00:23:19.000 --> 00:23:28.980
And, you know, for those who don't know, like part of the pickle statement is here's some Python code as a module and here's arbitrary code to run as part of deserializing that.

00:23:28.980 --> 00:23:30.320
So good luck.

00:23:30.320 --> 00:23:30.820
Oh, boy.

00:23:31.080 --> 00:23:33.000
Yeah, yeah, that's not so, that's not so good.

00:23:33.000 --> 00:23:39.980
So this goes up to at least version 110 through 116, which at least is January 14th.

00:23:39.980 --> 00:23:40.620
This hadn't been fixed.

00:23:40.620 --> 00:23:42.260
So hopefully it's been fixed.

00:23:42.340 --> 00:23:50.980
But more importantly, if you're using NumPy and you're accepting user input through the load function, you want to upgrade and you want to be a little careful around that.

00:23:50.980 --> 00:23:51.920
All right.

00:23:51.920 --> 00:23:53.780
Then last one I just want to throw out there really quick.

00:23:53.780 --> 00:23:58.500
I ran across this and I've known about it for a long time, but it turns out to be more useful than I thought.

00:23:58.500 --> 00:24:06.780
So I use Google Docs a lot and I have like sheets in there and I've got Word, like documents and stuff.

00:24:07.080 --> 00:24:13.400
But the problem is if you use like Google Drive, what ends up on your hard drive is like a hyperlink back to the actual sheet, right?

00:24:13.400 --> 00:24:14.760
So how do you back that stuff up?

00:24:14.760 --> 00:24:20.280
It turns out if you go to takeout.google.com slash settings slash takeout, that's a lot of repetition.

00:24:20.280 --> 00:24:26.400
Anyway, you go there, you can say, give me all my document format, all my documents, and it'll give them to you in Microsoft Office format.

00:24:26.400 --> 00:24:33.320
Like it'll convert the sheets to Excel, it'll convert the docs to Word docs, and then let you download them so you have like a sort of permanent version.

00:24:33.320 --> 00:24:36.060
Anyway, I thought that was cool and people might find that useful too.

00:24:36.060 --> 00:24:36.360
Cool.

00:24:36.360 --> 00:24:36.680
Yeah.

00:24:36.680 --> 00:24:38.800
All right, Nina, you got some as well.

00:24:38.800 --> 00:24:40.380
You're teaching a class that looks really interesting.

00:24:40.380 --> 00:24:41.120
That's right.

00:24:41.120 --> 00:24:47.260
Yeah, I'm teaching a two-day introduction to an intermediate Python course on March 19th and 20th.

00:24:47.260 --> 00:24:52.440
And that class is going to live stream for free at Front End Masters on each day.

00:24:52.440 --> 00:24:55.760
And all the course materials I'm going to release for free as well.

00:24:55.760 --> 00:24:56.540
That's really excellent.

00:24:56.540 --> 00:25:00.160
And it has an in-person component if you happen to be, where is it, Minneapolis?

00:25:00.160 --> 00:25:01.580
In Minneapolis, that's right.

00:25:01.580 --> 00:25:02.600
You can come to the class.

00:25:02.600 --> 00:25:04.320
Will Minneapolis be thought out by then?

00:25:04.320 --> 00:25:06.120
The class size is about 20 people.

00:25:06.180 --> 00:25:08.520
That I cannot promise.

00:25:08.520 --> 00:25:10.220
Hopefully in March it's a little warmer.

00:25:10.220 --> 00:25:12.740
Yeah, so up to 20 people could drop in in person.

00:25:12.740 --> 00:25:13.500
That'd be really cool.

00:25:13.500 --> 00:25:17.620
The next thing, I recently recorded a series of videos with Carlton Gibson.

00:25:17.620 --> 00:25:32.920
He's a Django maintainer, maintains a lot of other projects on developing Django web apps with VS Code, deploying them to Azure with just a few clicks, setting up continuous integration and continuous delivery, as well as creating serverless applications.

00:25:33.300 --> 00:25:36.760
You can watch that video series at aka.ms.com.au.

00:25:36.760 --> 00:25:40.220
Python-virus.com.au.

00:25:40.220 --> 00:25:40.720
Check that out, too.

00:25:40.720 --> 00:25:41.540
Yeah, it's great.

00:25:41.540 --> 00:25:44.540
We got to film in the Microsoft Channel 9 studio.

00:25:44.540 --> 00:25:47.740
And it's a very well-done series.

00:25:47.740 --> 00:25:49.420
All the bright lights and everything, huh?

00:25:49.420 --> 00:25:50.520
Not just screencasts.

00:25:50.520 --> 00:25:51.040
That's cool.

00:25:51.040 --> 00:25:52.440
Yeah, we feel like newscasters.

00:25:53.300 --> 00:25:59.260
I'm also planning on being a mentor at a brand new hatchery event at PyCon US 2019.

00:25:59.260 --> 00:26:04.800
That's going to be mentored sprints for diverse beginners organized by Tanya Allard.

00:26:04.800 --> 00:26:10.400
The goal is to help underrepresented folks at PyCon contribute to open source in a supportive environment.

00:26:10.760 --> 00:26:15.240
The details aren't out yet, but I dropped a link to where they'll be when they're finalized.

00:26:15.240 --> 00:26:16.180
Oh, that's super cool.

00:26:16.180 --> 00:26:25.520
And there's also things like scholarships or something like that to help folks get actually physically to the event if they need some help as well, right?

00:26:25.520 --> 00:26:27.700
They can apply for that at the PyCon site.

00:26:27.700 --> 00:26:30.380
Yeah, PyCon US offers a lot of financial aid.

00:26:30.380 --> 00:26:42.320
Lastly, if you're interested in Python for hardware, like we talked about earlier, you can catch my talk about electronics projects in Python with LEDs at PyCascades in Seattle on February 24th.

00:26:42.320 --> 00:26:44.640
Currently, tickets for that are still on sale.

00:26:44.640 --> 00:26:44.960
Excellent.

00:26:44.960 --> 00:26:46.900
Yeah, and Brian and I are definitely going to be there.

00:26:46.900 --> 00:26:50.080
We're all going to PyCascades, so we're going to catch it.

00:26:50.080 --> 00:26:51.240
Hopefully, everyone else does as well.

00:26:51.240 --> 00:26:51.600
Great.

00:26:51.600 --> 00:26:52.900
I'm excited to see you there.

00:26:52.900 --> 00:27:00.080
And I do have one last thing to sneak in, and that is if you haven't tried the Python extension for VS Code yet,

00:27:00.500 --> 00:27:01.900
now is a really good time.

00:27:01.900 --> 00:27:10.140
The December release included some really killer features like remote Jupyter support and exporting Python files as Jupyter notebooks.

00:27:10.140 --> 00:27:15.960
And if you're interested in keeping up with future releases, I dropped a link to the Python at Microsoft blog.

00:27:15.960 --> 00:27:16.300
Nice.

00:27:16.300 --> 00:27:21.160
And didn't you as a group, I'm speaking to you as a Microsoft, as VS Code,

00:27:21.160 --> 00:27:28.280
didn't you guys just release like an AI-powered autocomplete backend for Python as well?

00:27:28.400 --> 00:27:30.200
That's been around for a few months.

00:27:30.200 --> 00:27:34.040
I believe it's still in preview mode, but it works really well.

00:27:34.040 --> 00:27:37.540
The dataset was trained on a bunch of open source projects.

00:27:37.540 --> 00:27:38.740
Yeah, it looks super cool.

00:27:38.740 --> 00:27:40.160
So I definitely want to check that.

00:27:40.160 --> 00:27:42.940
I think I installed it just the other day, so it should be fun.

00:27:42.940 --> 00:27:43.320
Yeah.

00:27:43.320 --> 00:27:44.280
Try it.

00:27:44.280 --> 00:27:45.100
Let me know what you think.

00:27:45.100 --> 00:27:45.560
Absolutely.

00:27:45.560 --> 00:27:47.580
Brian, we've come to our joke section, right?

00:27:47.580 --> 00:27:47.880
Yeah.

00:27:47.880 --> 00:27:50.620
Nina, you want to kick us off?

00:27:50.620 --> 00:27:51.320
Yeah.

00:27:51.580 --> 00:27:55.160
I found a bunch of really cheesy snake jokes, so here they go.

00:27:55.160 --> 00:27:58.340
What do you call a snake that only eats dessert?

00:27:58.340 --> 00:27:58.840
I don't know.

00:27:58.840 --> 00:28:00.800
It's a pie-thon.

00:28:00.800 --> 00:28:02.940
Nice.

00:28:02.940 --> 00:28:03.900
I'll do the next one.

00:28:03.900 --> 00:28:05.540
How do you measure a Python?

00:28:05.540 --> 00:28:06.680
In inches.

00:28:06.680 --> 00:28:07.600
They don't have any feet.

00:28:07.600 --> 00:28:10.980
Brian, what's the last one?

00:28:10.980 --> 00:28:13.420
What is a Python's favorite subject?

00:28:13.420 --> 00:28:13.940
I don't know.

00:28:13.940 --> 00:28:14.320
What is it?

00:28:14.320 --> 00:28:14.800
History?

00:28:14.800 --> 00:28:15.560
That's bad.

00:28:15.560 --> 00:28:16.600
These are all bad.

00:28:16.600 --> 00:28:17.400
History.

00:28:17.400 --> 00:28:17.920
Lovely.

00:28:19.740 --> 00:28:21.120
And I will not apologize.

00:28:21.120 --> 00:28:22.060
No, those are great.

00:28:22.060 --> 00:28:23.480
Thank you for finding those, Nina.

00:28:23.480 --> 00:28:24.380
We're coming up with them.

00:28:24.380 --> 00:28:25.180
Either way, they're great.

00:28:25.180 --> 00:28:26.240
All right, folks.

00:28:26.240 --> 00:28:27.960
Well, thank you for listening.

00:28:27.960 --> 00:28:30.500
And Nina and Brian, thank you for being here today, of course.

00:28:30.500 --> 00:28:30.960
Thank you.

00:28:30.960 --> 00:28:31.860
Thanks for having me.

00:28:31.860 --> 00:28:32.120
You bet.

00:28:32.120 --> 00:28:32.500
Bye.

00:28:32.500 --> 00:28:32.740
Bye.

00:28:32.740 --> 00:28:33.140
Bye.

00:28:33.140 --> 00:28:35.120
Thank you for listening to Python Bytes.

00:28:35.120 --> 00:28:37.640
Follow the show on Twitter via at Python Bytes.

00:28:37.640 --> 00:28:40.540
That's Python Bytes as in B-Y-T-E-S.

00:28:40.540 --> 00:28:43.940
And get the full show notes at pythonbytes.fm.

00:28:43.940 --> 00:28:48.300
If you have a news item you want featured, just visit pythonbytes.fm and send it our way.

00:28:48.300 --> 00:28:51.020
We're always on the lookout for sharing something cool.

00:28:51.020 --> 00:28:54.400
On behalf of myself and Brian Okken, this is Michael Kennedy.

00:28:54.400 --> 00:28:57.900
Thank you for listening and sharing this podcast with your friends and colleagues.

