WEBVTT

00:00:00.001 --> 00:00:03.880
Hey there, thanks for listening. Before we jump into this episode, I just want to remind you

00:00:03.880 --> 00:00:09.680
that this episode is brought to you by us over at Talk Python Training and Brian through his pytest

00:00:09.680 --> 00:00:14.940
book. So if you want to get hands-on and learn something with Python, be sure to consider our

00:00:14.940 --> 00:00:21.720
courses over at Talk Python Training. Visit them via pythonbytes.fm/courses. And if you're

00:00:21.720 --> 00:00:27.320
looking to do testing and get better with pytest, check out Brian's book at pythonbytes.fm slash

00:00:27.320 --> 00:00:31.980
pytest. Enjoy the episode. Hello and welcome to Python Bytes, where we deliver Python news and

00:00:31.980 --> 00:00:39.340
headlines directly to your earbuds. This is episode 252, recorded September 29th, 2021. I'm

00:00:39.340 --> 00:00:45.580
Michael Kennedy. And I'm Brian Okken. And I'm Ethan Swan. Ethan, welcome to Python Bytes. You've been

00:00:45.580 --> 00:00:50.220
over on Talk Python, where you talked about some really cool data science stuff, and now you're

00:00:50.220 --> 00:00:54.900
over here. So thanks for being here. Tell people a bit about yourself. Yeah, I was on Talk Python

00:00:54.900 --> 00:01:00.300
236. So it was a while ago, but that was really cool. I work for a company called 8451. It's the

00:01:00.300 --> 00:01:05.840
data science subsidiary of Kroger. And I'm a data scientist, but basically what I do is build tools,

00:01:05.840 --> 00:01:11.220
mostly which are in Python, for our data science department. So we have like 250 data scientists,

00:01:11.220 --> 00:01:15.860
pretty large department. And I build like packages and some dashboard sort of things,

00:01:15.860 --> 00:01:18.500
just like various technology helper stuff for data science.

00:01:18.500 --> 00:01:23.140
Yeah, it sounds really fun. And you all run what we were talking about before we hit record.

00:01:23.560 --> 00:01:28.240
Probably one of the larger data science groups out there, right? I think of data science as being

00:01:28.240 --> 00:01:32.620
like, there's a couple of folks that are embedded with like a marketing team or a product team or the

00:01:32.620 --> 00:01:37.860
software development team a lot of times, but you are a properly large group of data scientists.

00:01:37.860 --> 00:01:42.460
I mean, in theory, that's what the whole company does. So it's a very cool experience. And often,

00:01:42.460 --> 00:01:47.480
I think that's nice for the team I'm on, because you don't usually get so many customers on internal

00:01:47.480 --> 00:01:51.680
tools. You know, we're building stuff for literally hundreds of people to use. And it's a little bit

00:01:51.680 --> 00:01:55.240
like releasing software externally. So it's yeah, it's a lot of fun.

00:01:55.240 --> 00:02:00.120
Yeah, fantastic. All right. Well, we're definitely looking forward to having your insights here

00:02:00.120 --> 00:02:05.520
for the show. Now, Brian, I do want to start off here. I want to talk about some deck staining.

00:02:05.520 --> 00:02:06.740
Thanks. Yeah.

00:02:06.800 --> 00:02:14.620
So because those of us who are very attentive on Twitter saw that Brian kindly responded to somebody

00:02:14.620 --> 00:02:18.900
who sent us a message and said, Oh, I see you were talking about pallets. We should also talk about

00:02:18.900 --> 00:02:24.600
deck stain and other DIY project resources. And maybe you could put that stupid article on your

00:02:24.600 --> 00:02:29.140
blog. You're like, we're not a blog. We talk about pallets because it's on Flask. And then

00:02:29.140 --> 00:02:34.200
Twitter decided, Oh, you are now classified under the home improvement category. So are we changing

00:02:34.200 --> 00:02:35.020
our theme or what?

00:02:35.020 --> 00:02:42.380
Apparently just me. That's most of you. I've got a few new followers now. And most of them are people

00:02:42.380 --> 00:02:43.840
that like to make things. So.

00:02:43.840 --> 00:02:48.920
Well, it's fun to make things as well. But maybe we'll maybe we'll talk more about SQL and stuff

00:02:48.920 --> 00:02:49.740
like that. What do you think?

00:02:50.080 --> 00:02:56.200
Yeah. So this, this was sent to us by Dave Cochesa. Thanks, Dave. I want to talk about

00:02:56.200 --> 00:03:03.560
SQL fluff. So I had never heard of this, but it looks pretty cool. So SQL fluff is a Python,

00:03:03.560 --> 00:03:10.760
a Python package that is basically a linter for SQL. So that's how interesting. I haven't really

00:03:10.760 --> 00:03:13.920
thought about linting SQL code, but it makes perfect sense.

00:03:14.380 --> 00:03:19.580
Yeah. Well, I mean, there, there is like, I don't really think about it too much either,

00:03:19.580 --> 00:03:23.800
but there's like things like, should you capitalize all the keywords? And some people just like it

00:03:23.800 --> 00:03:30.480
like that. So there is style. There's like both style guides around a SQL. I assume there's style

00:03:30.480 --> 00:03:36.680
guides. And this lets you help, helps you enforce it. Not, not just style guides, but just, you know,

00:03:36.680 --> 00:03:43.240
looking for mistakes and things. The, the page looks really slick for, I like the logo,

00:03:43.380 --> 00:03:48.300
the fluff logo, but, but the, one of the things that's great about it is the documentation. So

00:03:48.300 --> 00:03:55.240
the documentation looks wonderful. And there's one of the neat things about this is there's a

00:03:55.240 --> 00:04:01.500
different rules or different dialects set up so that it treats different things like ANSI and

00:04:01.500 --> 00:04:09.100
Postgres and MySQL different. And, and I'm not sure if these are, or if these are style differences or,

00:04:09.100 --> 00:04:14.380
or, or, or what they're doing different, but, but it's kind of interesting that they'll, they'll,

00:04:14.380 --> 00:04:15.980
there is a difference there.

00:04:16.020 --> 00:04:20.580
Well, one of the things that comes to mind for me, if this reports errors and I suspect it probably

00:04:20.580 --> 00:04:24.900
does, one of the things that comes to mind for me is if using like Microsoft SQL server and you're

00:04:24.900 --> 00:04:30.260
using a parameterized query, because you don't want little Bobby tables in your school, you would say

00:04:30.260 --> 00:04:35.920
at parameter name, whereas in with like MySQL or Oracle, it'd be like a question mark. Right. And I think

00:04:35.940 --> 00:04:41.560
one is illegal in the other syntax. So at least in that regard, I think, I don't know for sure it's

00:04:41.560 --> 00:04:46.600
illegal, but I'm pretty sure like it may be, and it could be that you've got to say what type of

00:04:46.600 --> 00:04:51.300
parameterized specifications and other extensions are valid. And even, I think there's some keywords,

00:04:51.300 --> 00:04:55.480
right? Aren't there some different keywords in some cases? So it would make sense to have to know

00:04:55.480 --> 00:05:00.280
the dialect. Yeah. Yeah. And also like you were saying, if, if there are really are big differences

00:05:00.280 --> 00:05:05.140
differences or even minor differences, there might be some queries that you don't run all the time.

00:05:05.140 --> 00:05:10.520
And so you're not sure if you switch databases that they might be broken if you're trying to port. So

00:05:10.520 --> 00:05:16.400
kind of cool. There's a list of, so it has rules, like a lot of linters, rules for failure. And I like

00:05:16.400 --> 00:05:23.280
the rules page because it talks about the rules, but also shows you the anti-pattern and best practice.

00:05:23.280 --> 00:05:29.180
I kind of like that style. I don't know if I like the terms anti-pattern and I really don't like the

00:05:29.180 --> 00:05:35.600
term best practice, but nonetheless, the, what it's looking for and what you should do different is,

00:05:35.600 --> 00:05:38.540
is a good thing to have in the documentation. It's pretty cool.

00:05:38.540 --> 00:05:43.300
Yeah. I do like the anti-pattern aspect. I, maybe pattern. You're going to have an anti-pattern,

00:05:43.300 --> 00:05:44.260
just have the pattern. I don't know.

00:05:44.260 --> 00:05:48.340
I'm not sure. One of the things that's in the documentation, I can't remember where,

00:05:48.340 --> 00:05:53.540
there it is, that people should be aware of. Supposedly this, even though it has like

00:05:53.540 --> 00:06:02.240
1982. That's interesting. Stars. It's still in alpha phase. So there's a note here that says,

00:06:02.240 --> 00:06:05.960
expect significant changes. So just be aware of that.

00:06:05.960 --> 00:06:11.200
Cool. It doesn't seem major because you're not doing runtime behavior on it, right? It's a thing

00:06:11.200 --> 00:06:13.280
you run against your code and then you look at the output.

00:06:13.280 --> 00:06:20.000
I mean, maybe it's in your CI system or something, but. Yeah. But it's not in production. Right. So like

00:06:20.000 --> 00:06:26.460
you are, you won't get called on a weekend because the site went down because this thing got automatically

00:06:26.460 --> 00:06:31.640
updated or something to that effect. Yep. I guess it could have broken your, your queries, but you know,

00:06:31.640 --> 00:06:38.400
whatever. and it's good to have an audience because, we did have a Paul from the chat say,

00:06:38.460 --> 00:06:43.200
Ethan's correct. There are different keywords between different SQL dialects. Yeah. We use a,

00:06:43.200 --> 00:06:47.940
Oh, sorry, Michael. No, go ahead. Go ahead. No, we, we use a lot of SQL as I would assume most data

00:06:47.940 --> 00:06:53.980
science shops do. but one, what this made me think of was, one contentious topic in people

00:06:53.980 --> 00:06:57.840
who write a lot of SQL is, especially when you have a bunch of column names and you're selecting

00:06:57.840 --> 00:07:03.040
regularly, you know, five to 10 columns, the comma first, I don't know if you've seen the

00:07:03.040 --> 00:07:08.040
approach where you do a new line, comma, column, comma, column. So it lines up really nicely and it

00:07:08.040 --> 00:07:13.420
makes it easier to delete things. that's a very common thing that people feel strongly about.

00:07:13.420 --> 00:07:17.560
So I could imagine linter as being very handy to at least enforce one style throughout a company

00:07:17.560 --> 00:07:23.220
because you know, we don't have that. Yeah. Nice. And then I was going to add that Pamphil Roy on the

00:07:23.220 --> 00:07:30.020
audience says it would be a cool if there was a plugin for D Beaver and Sam Morley asks, I wonder if it

00:07:30.020 --> 00:07:35.700
checks if inputs are sanitized. I don't know if it should, but Paul also asks if it validates for

00:07:35.700 --> 00:07:41.300
syntactical correctness beyond just style. He does say that it catches errors and bad SQL before it

00:07:41.300 --> 00:07:45.540
hits your database. So I'm going to go with the yes. That's pretty cool. Yeah. Ethan, I was thinking

00:07:45.540 --> 00:07:51.520
as I was watching Brian present this, that you probably do way more SQL than I do, even though I

00:07:51.520 --> 00:07:56.800
run in production websites that are backed by databases, not just because there's no SQL, but

00:07:56.800 --> 00:08:02.280
because I use ORMs and the data structure doesn't change. But for, data science,

00:08:02.280 --> 00:08:06.720
you're kind of in a more exploratory mode, right? Yeah. I think it's pretty interesting because,

00:08:06.720 --> 00:08:11.200
um, you know, like listening to this podcast, people talk about using ORMs a lot, but in data science,

00:08:11.200 --> 00:08:16.840
you don't really think of data in that relational model as much. I mean, you can, but like thinking of,

00:08:16.840 --> 00:08:21.980
as of rows as objects is really not common. So I feel like my relationship with databases is totally

00:08:21.980 --> 00:08:27.340
different. My first couple of years, I was mostly writing SQL, but it was, it was literally just

00:08:27.340 --> 00:08:31.060
asking questions for analyses, which is such a different use case than what people use it for,

00:08:31.060 --> 00:08:34.820
for web development. Right. Yeah, absolutely. It's, it's super different, super different.

00:08:34.820 --> 00:08:41.520
But if you were to explore data, wouldn't it be nice to have a desktop application instead of a web

00:08:41.520 --> 00:08:46.880
browser for doing so? So Jupyter and JupyterLab have got to be the most popular way that people

00:08:46.880 --> 00:08:50.820
interact with data on the data science side. It's certainly an exploration stage anyway.

00:08:50.820 --> 00:08:58.160
So super big news that is old news is new again, but better. JupyterLab desktop app is a thing.

00:08:58.160 --> 00:09:04.600
Like I can download JupyterLab. It's an icon on my doc or on my task bar. I click it,

00:09:04.600 --> 00:09:10.060
it runs like an app, but inside of it is Jupyter notebook, like the whole JupyterLab with terminal

00:09:10.060 --> 00:09:15.320
and Python consoles and kernels and all those things. That's cool. That's, that's very nice.

00:09:15.740 --> 00:09:20.980
Yeah. Have you played with this yet, Ethan? No, we, so I don't know how common this is,

00:09:20.980 --> 00:09:25.560
but I think for us, at least mostly people aren't working on their local machines. They're really

00:09:25.560 --> 00:09:31.460
connecting to a session of Python on a remote server. So mostly what we do is we fire up Jupyter

00:09:31.460 --> 00:09:36.320
on, on a remote server. And then from our laptops, we hit that URL to actually look at the notebook.

00:09:36.320 --> 00:09:40.620
So I'm not sure a desktop app would work as well for us, although maybe it's, it's definitely

00:09:40.620 --> 00:09:45.140
interesting. And I wonder if there's some native features of desktop apps that are available,

00:09:45.140 --> 00:09:46.620
that are going to be a reason to switch.

00:09:46.620 --> 00:09:53.660
Well, what I would say right now is it's a really nice self-contained thing. So I'll just

00:09:53.660 --> 00:09:58.740
read the description real quick. JupyterLab app is a cross-platform standalone application.

00:09:58.740 --> 00:10:03.920
Distribution of JupyterLab is a self-contained desktop application, which bundles the Python

00:10:03.920 --> 00:10:09.740
environment and several popular libraries to use and scientific computing, like surely pandas and

00:10:09.740 --> 00:10:14.980
NumPy and those kinds of things. So what you get is you get just an app that's, it's ready to go that

00:10:14.980 --> 00:10:19.340
you could just have somebody install and you can say, here, open this notebook and run it. And long

00:10:19.340 --> 00:10:23.640
as you're using core libraries and stuff like that, you don't have to think, okay, go to the terminal,

00:10:24.080 --> 00:10:30.500
you know, set up the environment and then type JupyterLab. Oh, you need to activate the kernel

00:10:30.500 --> 00:10:35.120
and you got to do this and that, you know, it's just like, it's, it's a real simple, here's, here's the

00:10:35.120 --> 00:10:36.980
thing. No nonsense type of app.

00:10:37.560 --> 00:10:40.500
And you lost a whole bunch of people with just open the command line.

00:10:40.500 --> 00:10:41.900
Yeah. That's so true.

00:10:41.900 --> 00:10:45.460
Yeah. Yeah. So you don't have to hear, right? You just, it's on your doc. You click it just like,

00:10:45.460 --> 00:10:51.460
like you would with Word or Firefox or whatever. And it's, you're there. It starts and manages the

00:10:51.460 --> 00:10:58.080
Jupyter server in the background. There may be a whole host of command line arguments. You can give

00:10:58.080 --> 00:11:04.140
it to say like run, but use that server and other things along those lines or run and use this conda

00:11:04.140 --> 00:11:10.140
environment. I didn't see any of those. And so from what I can tell is it's kind of a local version

00:11:10.140 --> 00:11:14.080
of Jupyter. So it might be super interesting for you all in your workflow.

00:11:14.080 --> 00:11:19.880
One place where I think this would be really handy is teaching beginners. So I actually teach some

00:11:19.880 --> 00:11:24.420
Python, especially for data science classes at the university of Cincinnati. And one thing that

00:11:24.420 --> 00:11:28.420
regularly is really confusing to people is that you can't double click on a notebook file and have it

00:11:28.420 --> 00:11:32.440
open because that's such a typical experience of files on a computer, double click. And there's an

00:11:32.440 --> 00:11:37.600
application that opens that file. Oh, interesting. Yeah. And there are workarounds. If you have

00:11:37.600 --> 00:11:43.540
Anaconda Navigator, it kind of works, although it's, it's a little hitchy. But I would assume

00:11:43.540 --> 00:11:47.080
that if you have a desktop app, you'd be able to register that with the operating system, whatever

00:11:47.080 --> 00:11:53.740
that process is to say, like when I click on .ipynbs, open it. Because I find I have to teach students,

00:11:53.740 --> 00:11:58.500
no, start up Jupyter, open your browser, navigate to that file in the browser.

00:11:58.500 --> 00:12:02.520
Were you in the wrong folder in the terminal when you ran Jupyter? Which is, well, sorry,

00:12:02.520 --> 00:12:06.000
you're now locked out of that tree, that, that part of the tree of the folders.

00:12:06.000 --> 00:12:10.320
And then suddenly you're having a conversation about paths. Yeah. You go down. It really is like

00:12:10.320 --> 00:12:14.380
something I don't like to deal with. So maybe this is what I should recommend for people when I teach.

00:12:14.380 --> 00:12:20.020
What I would recommend is just check it out and try. So I do have a bit of a comment here from Dean

00:12:20.020 --> 00:12:25.040
out in the audience. I like the concept of JupyterLab app, but I'm afraid it'll be a V in V in V,

00:12:25.040 --> 00:12:31.760
V in V, virtual environment nightmare. So what I found interesting is it's discovered, you know,

00:12:31.760 --> 00:12:38.140
when you're creating kernels for Jupyter, you have to run a command. I always forget it and always have

00:12:38.140 --> 00:12:43.860
to duck, duck, go or search this to figure out how to do it again. But I have to get the command to say,

00:12:43.860 --> 00:12:50.000
create this environment and then register that as, so Jupyter finds that content environment,

00:12:50.100 --> 00:12:55.080
that V in V, right? It's IPI kernel install. I have to do this all the time.

00:12:55.080 --> 00:12:59.340
Yeah, exactly. And I know that it's basically that, but the exact command, I always forget.

00:12:59.340 --> 00:13:05.680
So that command, it seems like it picked up the ones that I had run previously for standalone

00:13:05.680 --> 00:13:13.260
terminal JupyterLab. So the virtual environment story is the same as Jupyter itself without that.

00:13:13.260 --> 00:13:19.480
I think all we're getting here is we're getting the libraries plus Python plus the server starting

00:13:19.480 --> 00:13:24.220
all bundled together. And it's basically the same as if you just run it on the command prompt.

00:13:24.220 --> 00:13:30.220
I think as long as was it Dean, as long as Dean doesn't want to be starting Jupyter from the virtual

00:13:30.220 --> 00:13:33.760
environment, it should be fine. Like when you said, Michael, about the kernels, that's the much more,

00:13:33.760 --> 00:13:37.660
I recommend people do it that way. Cause some people do like to just install Jupyter in whatever

00:13:37.660 --> 00:13:42.440
environment they work in and launch it there. But I have a hard time imagining how that would work in this

00:13:42.440 --> 00:13:47.740
case. Yeah, I do as well. And Dean makes the point that once you have to go and register all that kind

00:13:47.740 --> 00:13:51.340
of stuff on you, like when you're down in the terminal doing this, you've kind of lost those

00:13:51.340 --> 00:13:57.100
same people. And that may well be the case, but I can see, you know, this is sort of a first version

00:13:57.100 --> 00:14:01.420
of this. I can see that those are some of the desktop things that could add, right? It could add a

00:14:01.420 --> 00:14:06.600
setting section where you, you have a dialogue for managing these things and creating new ones and so on.

00:14:06.600 --> 00:14:10.420
So it could be pretty neat. Yeah. Definitely something to watch. All right. Before we move on,

00:14:10.700 --> 00:14:17.240
Paul out in the audience has a quick question for you, Ethan, a tangential one. Python has some

00:14:17.240 --> 00:14:23.280
really great SAST tools like Bandit, but I'm not able to find good options for R. And I know that

00:14:23.280 --> 00:14:28.300
you live in a world that does both R and Python. Yeah. Do you have any thoughts on this? I have no

00:14:28.300 --> 00:14:35.980
ideas. I'm going to come off as a fraud, but I don't know what SAST is. I have to, I have to admit,

00:14:36.080 --> 00:14:40.500
like what I do. I know I said, I'm, I'm a data scientist, but in some ways that's nominal.

00:14:40.500 --> 00:14:43.920
Like really a lot of what I do is software development for the data scientists.

00:14:43.920 --> 00:14:48.140
Data scientists are your customer in a sense, or your, your target user. Yeah.

00:14:48.140 --> 00:14:53.040
Yeah. So I think a lot of what I hear from users is that there are certain measurement tools and

00:14:53.040 --> 00:14:57.180
certain statistical tools that are available in R that take longer to get to Python. So I wouldn't

00:14:57.180 --> 00:15:01.220
be surprised if that really is what's happening here, but I don't personally have any suggestions.

00:15:01.220 --> 00:15:07.780
Yeah. Okay. Yeah. So Bandit, is like a tool that will scan for known security vulnerabilities,

00:15:07.780 --> 00:15:12.240
like leaving debug settings on in Django. Oh, see, I was wondering if that was okay. Then,

00:15:12.240 --> 00:15:15.820
then that I also don't know. That's a little different than what I was imagining.

00:15:15.820 --> 00:15:21.900
Yeah. Awesome. All right. Well, since you got the floor, tell us about your first item.

00:15:21.900 --> 00:15:28.840
Sure. So, I found this requests cache package, in a newsletter recently,

00:15:28.840 --> 00:15:32.260
and this might be a little bit of a shorter one because unfortunately I haven't had a reason to

00:15:32.260 --> 00:15:38.460
use it yet. but basically what this does, scrolling down here is you can instantiate

00:15:38.460 --> 00:15:44.580
sessions just like you would with the traditional requests library. So probably, request is one

00:15:44.580 --> 00:15:48.440
of the most commonly used Python packages, I would guess. Yeah. For anybody who's not familiar,

00:15:48.440 --> 00:15:53.660
you use it to make HTTP requests, which is basically to bring anything back from me. And, the tagline,

00:15:53.660 --> 00:15:58.680
I think is HTTP for humans, but it's just known for being easy to use and you can access the internet.

00:15:58.680 --> 00:16:04.360
But one thing that I have found is that, especially if I'm, if I'm testing something in an interactive

00:16:04.360 --> 00:16:09.760
way, not mocking, but I really want to see if my code pulls back what I expect. sometimes I rerun

00:16:09.760 --> 00:16:15.080
the same request over and over and I say, go get this, go get this, go get this often the same data.

00:16:15.080 --> 00:16:20.280
And sometimes that data is large. and that takes a really long time. So requests cache is a way of

00:16:20.280 --> 00:16:26.760
creating a session object that looks and acts the same. But when you call, a get or a post

00:16:26.760 --> 00:16:32.820
request on the same URL, what, with the same data, what you get back is actually just the cached

00:16:32.820 --> 00:16:37.640
version of that data. so you're not waiting every time the first time you incur the network

00:16:37.640 --> 00:16:42.680
latency. And if the server has to do anything to like compute the data, or if it's enough data that

00:16:42.680 --> 00:16:46.760
it takes some time to get to you, you wait for that. But the second time everything runs instantly,

00:16:46.760 --> 00:16:51.360
which is really a big advantage. So I've done some things with web scraping where I'm

00:16:51.360 --> 00:16:55.520
building some kind of, I want to build like a function that pulls some things down and makes,

00:16:55.520 --> 00:17:00.280
uh, or pull some things out of that, but just waiting every time to run the function for it to

00:17:00.280 --> 00:17:05.200
pull from several different pages and, you know, do some computation on that actually makes it pretty

00:17:05.200 --> 00:17:08.000
slow. But if you were able to cache it like this, that'd be a lot faster.

00:17:08.000 --> 00:17:12.360
Yeah. This is nice. I love the fact that it's just a stand in replacement for the request

00:17:12.360 --> 00:17:17.440
session itself. Yeah. And if you scroll down a little more, it actually shows a way to do that

00:17:17.440 --> 00:17:21.500
with the regular requests library. And this actually scares me a little bit. This is kind of,

00:17:21.500 --> 00:17:25.900
kind of magical what's going on here. You just run a one-liner with requests cache,

00:17:25.900 --> 00:17:30.180
and then suddenly the requests library itself works differently. So I wonder if that's a monkey

00:17:30.180 --> 00:17:36.000
patching or what's going on. It probably is, but it is, it is really slick. so I would imagine I'll,

00:17:36.000 --> 00:17:40.000
I'll have a reason to use this soon, but I haven't tested that yet. It does offer a lot of

00:17:40.000 --> 00:17:45.800
configuration options. And one thing I thought was, was a good, idea to look at is an expiration

00:17:45.800 --> 00:17:50.500
date. and that's sort of like, when should you invalidate the cache and actually pull again?

00:17:50.500 --> 00:17:53.880
Cause you maybe should trust that the website is sending you all the same stuff today, but if you

00:17:53.880 --> 00:17:58.480
rerun your code in a week, make sure that it still responds the same way. So it's got some nice options

00:17:58.480 --> 00:18:02.760
like that. I really like that. That's interesting. So you could use it not even just for testing. It could

00:18:02.760 --> 00:18:07.340
be for, actual data, but you know, it's not getting updated very often. So.

00:18:07.720 --> 00:18:12.280
Yeah. For large data is what I was imagining. So I, yeah, like I said, there's, there's been some

00:18:12.280 --> 00:18:15.760
times where I've like pulled things from APIs where they send back a lot of data and you don't want to

00:18:15.760 --> 00:18:20.720
be waiting for that. Yeah. Or even you just want to make sure that, multiple calls to it are

00:18:20.720 --> 00:18:25.720
getting the same data, even if it does change. that's true. Yeah. So keep consistency.

00:18:25.720 --> 00:18:30.440
Interesting. This reminded me a little bit of the, I don't know if people are familiar with the

00:18:30.440 --> 00:18:35.440
at cache, or LRU cache. It used to be another, there's a new one just called at cache in the func

00:18:35.440 --> 00:18:40.720
tools module built into Python. And that's very, very handy once you know, it's there because often

00:18:40.720 --> 00:18:44.420
you have a function that you don't want to recompute the work for. And this is almost like somebody

00:18:44.420 --> 00:18:46.960
rewrote requests with cache in it, which is pretty cool.

00:18:46.960 --> 00:18:52.660
Yeah. It's got a lot of nice features. You know, I think a question from handful out in the audience,

00:18:52.660 --> 00:18:58.800
can it cache to redis because production in memory production caching, you could blow it up,

00:18:58.800 --> 00:19:02.960
right? Blow up the memory. So a couple of things that stood out to me that were interesting there

00:19:02.960 --> 00:19:10.080
was, yeah, you could throw a func tools, LRU cache decorator onto an expensive thing, which is fine,

00:19:10.080 --> 00:19:14.780
but that's in memory, right? And plus things have to be hashable and whatnot, but you could do that.

00:19:14.960 --> 00:19:19.640
but it's in memory. And a lot of times if you have scale out as you do on web apps,

00:19:19.640 --> 00:19:26.540
like in production, as in, Brian was talking about, you have web farms, like five or 10 copies

00:19:26.540 --> 00:19:31.200
of micro whiskey or something running. So then there's still five times you got to do it before

00:19:31.200 --> 00:19:38.100
it really gets cached. And then also it goes to SQLite. So it gets stored to disc, right? So it's

00:19:38.100 --> 00:19:42.500
not even in memory. It's, it's on disc. So like you said, there's other backends as well, but I think

00:19:42.500 --> 00:19:48.120
having just by default going to a SQLite file with an possible expiration means you could just turn

00:19:48.120 --> 00:19:53.020
this on and leave it expire after a day. Go tell us about the backends. There's more than just SQLite.

00:19:53.020 --> 00:19:57.140
Yeah. It does seem like you have some options. I mean, like I said, I haven't had a reason to use

00:19:57.140 --> 00:20:01.140
this. So I haven't toyed around with all these, but it, this, the way this is documented leads me to

00:20:01.140 --> 00:20:05.180
believe that it really is just a drop in replacement, that you can configure what you want to use as

00:20:05.180 --> 00:20:09.040
your backend. And I do wonder, so yeah, what you were saying, Michael, about having multiple instances,

00:20:09.040 --> 00:20:13.700
I do wonder how that would work. Would it check to see if any of the instances had cached this yet?

00:20:13.700 --> 00:20:18.280
would it like proactively go reach out to the cache or? Yeah. Well, I think if you have some

00:20:18.280 --> 00:20:22.880
memory one, it's going to be a hassle, right? Like one of the options is memory. but all the other

00:20:22.880 --> 00:20:29.260
ones, file system, grid FS, Redis, SQLite, those are all support, you know, concurrency. They support.

00:20:29.260 --> 00:20:32.780
Yeah, exactly. So, so then it will scale across process seamlessly.

00:20:33.280 --> 00:20:36.820
Yeah. So that, that could be actually really helpful for something like that, where you have

00:20:36.820 --> 00:20:42.720
a distributed set of workers. Yeah. Yeah, for sure. let's see some fun stuff about your monkey

00:20:42.720 --> 00:20:46.880
patching comment. And Dean says monkey patch is like having a real monkey. It's very cool when other

00:20:46.880 --> 00:20:53.180
people have it, but having it in my house is scary. And yeah, Sam just, has a too much experience at

00:20:53.180 --> 00:20:58.100
the zoo, I think, with that as well. So yeah, monkey patching is a little sketch.

00:20:58.440 --> 00:21:06.820
Oh, nice. All right, Brian, you're up next. Okay. What do we got next? I, so I did something,

00:21:06.820 --> 00:21:14.780
uh, kind of dumb the other day. so I went ahead and I needed, I pushed a new package

00:21:14.780 --> 00:21:21.160
out on PyPI. Really. I was just trying to, to remember how to, the whole process, because I

00:21:21.160 --> 00:21:25.860
wanted to just remind myself of like, if I have something new, something cool I wanted to share,

00:21:26.040 --> 00:21:30.980
how do I get it out there to PyPI? So I was walking through that process and I was doing it

00:21:30.980 --> 00:21:37.580
for a plugin. You did your own typo squatting. Apparently. so I published pytest Slow,

00:21:37.580 --> 00:21:46.120
uh, and then, but who was it? Brian Skin said, cool, but, maybe pytest Skip Slow would be

00:21:46.120 --> 00:21:51.080
better. And I'm like, oh man, that is a better name. cause that's what it does. It skips the slow

00:21:51.080 --> 00:21:56.580
tests by default. So, and this is totally lifted from the pytest documentation about,

00:21:56.580 --> 00:22:01.480
um, they have this example, but nobody's written a plugin for it. So I did this. It's a little tiny

00:22:01.480 --> 00:22:07.720
thing, but so I renamed it, but how do you rename it? So I went out and searched. So how do you rename

00:22:07.720 --> 00:22:14.280
something in PyPI? You can't really do it, but you can create another one. And then, so this is nice.

00:22:14.280 --> 00:22:21.200
Well, who was it? Simon Willison wrote this up. It's a PyPI renamed cookie cutter template.

00:22:21.200 --> 00:22:27.460
And I didn't actually use the template, but I did use these steps. So the steps really are create a

00:22:27.460 --> 00:22:33.640
renamed version of the package, which I did then publish it to PyPI under the new name and create a

00:22:33.640 --> 00:22:40.140
final release for the old name that points to the new one and, depends on it and have dependencies

00:22:40.140 --> 00:22:44.760
so that if somebody installed the old one, they'll really get the new one. it sounds more

00:22:44.760 --> 00:22:49.440
complicated than it is. It's just a few steps, but, there's a cookie cutter you can use.

00:22:49.440 --> 00:22:55.940
The cookie cutter uses setup tools and I didn't want to do that, but, so I used, I did basically

00:22:55.940 --> 00:23:02.220
copied his, the entire thing. and then he's got a demo. So if you, you look at it, so if you go to

00:23:02.220 --> 00:23:07.960
the old one, old version, it'll just have a thing that says, Hey, I'm going to the new one now.

00:23:08.380 --> 00:23:15.420
so I did that and, and it was neat. I really appreciate the steps. and it's,

00:23:15.420 --> 00:23:16.160
it's all good.

00:23:16.160 --> 00:23:16.580
Yeah.

00:23:16.580 --> 00:23:22.140
That's cool. You can also use it for aliases. Like you can install BS for or beautiful soup for,

00:23:22.140 --> 00:23:23.960
right. And it's kind of the same.

00:23:23.960 --> 00:23:26.460
Oh, is that how, is that how they do that?

00:23:26.460 --> 00:23:29.660
I I'm guessing, I don't know, but it sounds like the same.

00:23:29.660 --> 00:23:30.080
I didn't know that.

00:23:31.040 --> 00:23:36.640
So now, so now when I go to pytest, if you go to the old one, it just shows it's now a new name,

00:23:36.640 --> 00:23:37.600
go to the other one instead.

00:23:37.600 --> 00:23:41.180
So, but if I install the old one, it, it kind of just pulls in the new one.

00:23:41.180 --> 00:23:41.780
Yes.

00:23:41.780 --> 00:23:42.400
Yeah.

00:23:42.400 --> 00:23:43.400
Yeah. Very cool.

00:23:43.400 --> 00:23:48.320
Yeah. Brian, you were, you were refreshing on PyPI, but I actually just pushed my first ever

00:23:48.320 --> 00:23:52.060
package to PyPI a couple of weeks ago. And so that was, you know, a bit of a trial, but I was

00:23:52.060 --> 00:23:55.960
amazed at how straightforward it is. The documentation is excellent. It really is,

00:23:55.960 --> 00:23:59.840
is pretty seamless actually for somebody who's never done it before. So who knows, hopefully I

00:23:59.840 --> 00:24:03.460
don't make any mistakes on the one package I have and need to read. Yeah. But we'll see.

00:24:03.460 --> 00:24:05.600
The immutability of it is a little scary, but yeah.

00:24:05.600 --> 00:24:12.400
So for me, the hard part was just understanding that it really was pretty simple. and then also,

00:24:12.400 --> 00:24:16.940
uh, getting the hashes right. So you have to like, you have to get like, you know,

00:24:16.940 --> 00:24:22.000
signatures and stuff to make sure that you can push to the PyPI correctly. So, yeah.

00:24:22.000 --> 00:24:25.040
Yeah. But even the documentation there, it's a little intimidating, but it actually

00:24:25.040 --> 00:24:28.980
turned out to be only a few minutes of work. So that was, that was pretty nice. Good for them.

00:24:28.980 --> 00:24:31.720
I guess PyPI is the people to praise for that.

00:24:31.720 --> 00:24:33.280
Yeah. So what was your package?

00:24:33.280 --> 00:24:40.900
Oh, I, it, it's called pre-mark. It's, it's a spinoff of a JavaScript library for making

00:24:40.900 --> 00:24:46.400
slides. And I just make a lot of slides for teaching. And I actually found, an existing

00:24:46.400 --> 00:24:51.980
package by man. I want to, I mean, yeah, here it is. It is not ready. That's why

00:24:51.980 --> 00:24:57.740
it's a release candidate. but I, I, yeah, I based it on this existing package by

00:24:57.740 --> 00:25:01.880
at Tyler Dave on GitHub, and talk to him a little bit about it. He had already built a really

00:25:01.880 --> 00:25:05.960
lightweight tool and I just expanded on it, but I like to write my slides in Markdown, which is really

00:25:05.960 --> 00:25:09.720
what this is for. You write your slides in Markdown and a bunch of different files. It stitches them

00:25:09.720 --> 00:25:14.720
together and creates a, what's called remark JS presentation. so I use this for my own teaching.

00:25:14.720 --> 00:25:16.420
Nice. I'll check it out.

00:25:16.740 --> 00:25:21.720
But it's, it really is largely a sample project to just like learn how to use PyPI and things like

00:25:21.720 --> 00:25:22.000
that.

00:25:22.000 --> 00:25:28.800
Yeah. Very cool. All right. Up next we have caching. Oh wait, we just talked about caching. No, I have

00:25:28.800 --> 00:25:35.980
more caching. So Django, I have two, two pieces of news on Django. this one comes from Carlton

00:25:35.980 --> 00:25:42.700
Gibson. I'm one of the Django guys and also, one of the hosts at Django chat, the podcast. So

00:25:42.700 --> 00:25:51.800
they are adding a Redis cache backend to Django. So traditionally Django has shipped with Memcache,

00:25:51.800 --> 00:25:57.860
Memcached D, that cache backend with multiple implementations, I think even. So you can go

00:25:57.860 --> 00:26:02.800
there like Django as an ORM, it can talk to stuff. So it has a cache backend as well. And it could talk

00:26:02.800 --> 00:26:08.660
to Memcache, but it couldn't talk to Redis. And they found that the vast majority of people are using

00:26:08.660 --> 00:26:12.780
Redis and they said, well, why don't we have a backend for it? Well, guess what? It's going to.

00:26:12.780 --> 00:26:18.540
So this was merged and this whole conversation here around the PR and the issue is pretty interesting.

00:26:18.540 --> 00:26:25.300
So it starts out and says, this PR aims to support, to add support for Redis to be used as a caching

00:26:25.300 --> 00:26:30.720
backend with Django as Redis is the most popular caching backend. Adding it to Django core dot,

00:26:30.720 --> 00:26:36.220
the Django dot core dot cache module would be a great addition for developers who previously had to rely

00:26:36.220 --> 00:26:40.760
on third party packages and check out how they've got this little checklist and progress.

00:26:40.760 --> 00:26:47.080
These are the things for this PR to come along and work. So create the Redis cache class, do a pickle

00:26:47.080 --> 00:26:51.940
serializer, et cetera, et cetera. Waiting for this other task. Here's some open-ended documentation.

00:26:51.940 --> 00:26:57.620
So I don't think I've seen this really before, like this project tracking in the PR.

00:26:57.620 --> 00:26:58.880
I like it's really cool.

00:26:58.880 --> 00:27:03.480
Yeah, I do too. The other thing to note that this came in on May 23rd and there's a

00:27:03.480 --> 00:27:09.780
large conversation. If you go there, there's 30 pages of conversation about it and you can see

00:27:09.780 --> 00:27:13.640
it evolving. Like, okay, we finally got the test pass and we finally got it implemented. Now let's

00:27:13.640 --> 00:27:19.160
move on to the documentation now, et cetera, et cetera. And then finally, boom, September 15th,

00:27:19.160 --> 00:27:23.380
that's three, three and a half months, something like that. It's closed. So you can actually sort of

00:27:23.380 --> 00:27:29.260
track what the Django team is doing for adding features, like core important features to Django.

00:27:29.340 --> 00:27:34.060
It's always so interesting to watch open source communities like this, especially on somewhat

00:27:34.060 --> 00:27:38.120
contentious issues where people disagree and how they manage these things. I think it's really

00:27:38.120 --> 00:27:43.700
impressive because a lot of teams that even meet in person regularly in our small teams still struggle

00:27:43.700 --> 00:27:48.280
with that kind of stuff, but these huge open source projects manage it. Somehow they implemented the

00:27:48.280 --> 00:27:49.840
feature at the end. So pretty impressive.

00:27:49.840 --> 00:28:16.820
Yeah, absolutely. It's very impressive. Also, I said this was from Carlton. He participated a lot. I'm not 100% sure that he was the originator. This might be Daniel Abasi. So sorry if I misattributed credit there, but for whoever did this, the original issue, I think Carlton had put up. So I'm not sure who was really sort of the initiator there, but I think it's cool. And it's also neat how out in the open, this whole thing is.

00:28:16.820 --> 00:28:19.020
Yeah. Putting the open in open source.

00:28:19.020 --> 00:28:21.540
That's right. Hi, Brian. What you got?

00:28:21.540 --> 00:28:26.380
It's me again. Are we done with our things?

00:28:26.380 --> 00:28:28.840
All right. No, I think I got one more.

00:28:28.840 --> 00:28:33.020
Oh, no, sorry. I totally, I was for some reason in wrong order. Yes, Ethan, you're up next. Sorry.

00:28:33.020 --> 00:28:44.000
Totally fine. So yeah, so I wanted to highlight PEP 612. So I happened upon this, I forget, there was some other PEP I was looking at and they'd linked off to this one.

00:28:44.540 --> 00:28:53.460
But a little bit of background. A PEP is a Python enhancement proposal. It's basically like how ideas are proposed in terms of what to do with Python as a community or as a language.

00:28:54.400 --> 00:29:05.240
And I recently have been really kind of diving into type hinting Python. So there's a surprising number of PEPs about type hinting. And what this one does is something I guess I didn't really realize I needed.

00:29:05.240 --> 00:29:08.320
It was a bit of an annoyance, but I didn't realize there was a fix coming.

00:29:08.980 --> 00:29:18.040
Basically, what it comes down to is quite often you write functions that take in a function and return another function. So there's this example.

00:29:18.540 --> 00:29:26.800
And this, where's the first case where they use it? I think here, param spec. I'll find it while I talk about this.

00:29:26.800 --> 00:29:28.400
But basically...

00:29:28.400 --> 00:29:29.660
A lot of decorator time, yeah.

00:29:29.800 --> 00:29:41.940
Yeah. What you do with decorators is you write functions that take in other functions and return a function that has the same signature, which is to say it takes in the same parameters of the same types and returns the same return type.

00:29:42.520 --> 00:29:45.480
It may have some other modifications of the function, but that's very frequent.

00:29:45.480 --> 00:29:55.520
And so sometimes what you want to say is my decorator, if I want to type the decorator, say what types of things it takes in, it takes in something that is essentially a generic function type.

00:29:55.520 --> 00:30:02.720
Any kind of function is fine that takes in any parameters and returns any return type, as long as it returns the same thing.

00:30:02.720 --> 00:30:04.820
So it's like generics, which you would do with type bars.

00:30:05.860 --> 00:30:14.140
But in this case, you create something called a param spec, and then you pass that as the...

00:30:14.140 --> 00:30:15.940
Oh, man, I lost it where it is in here.

00:30:15.940 --> 00:30:18.200
Oh, here we go. This is what I wanted.

00:30:18.200 --> 00:30:27.620
So you pass it as the type of callable when you type the function that's taken in, and then you say you're returning a callable with the same parameter specification.

00:30:27.620 --> 00:30:29.840
This P is a parameter specification.

00:30:30.280 --> 00:30:38.260
And you make essentially your callables generic on both this parameter specification and on the return value.

00:30:38.260 --> 00:30:40.280
So I know there's a lot to that.

00:30:40.280 --> 00:30:46.200
And I think for people who are typing everything every day, maybe this doesn't seem terribly pertinent.

00:30:46.200 --> 00:30:57.420
What I do, I said I write a lot of Python packages for people to use, and it's important both for quality control and so people know what the return values are and what they should pass into functions to have a lot of typing.

00:30:57.420 --> 00:31:03.880
But really, what this got me thinking about a little bit is just that the Python typing ecosystem is still really evolving.

00:31:03.880 --> 00:31:09.880
Like for somebody who's not super close to following it, it appears that like this is how Python works now.

00:31:09.880 --> 00:31:12.020
And maybe it's always been this way, but it really hasn't.

00:31:12.020 --> 00:31:14.040
And there's a lot of holes in how it works.

00:31:14.040 --> 00:31:15.500
There was no way to do this before.

00:31:15.500 --> 00:31:16.740
And this isn't finished yet.

00:31:16.740 --> 00:31:18.340
This is a pep, but it isn't implemented.

00:31:19.040 --> 00:31:22.680
And so right now, you don't have a way to do typing for this particular feature.

00:31:22.680 --> 00:31:23.760
And that...

00:31:23.760 --> 00:31:27.000
Yeah, flowing type information through different things.

00:31:27.000 --> 00:31:29.260
That is something we haven't done a lot of in Python.

00:31:29.260 --> 00:31:32.720
But as you called out generics and templates, that's like all you do.

00:31:32.720 --> 00:31:34.640
That's the bread and butter of those things.

00:31:34.640 --> 00:31:35.240
Yeah.

00:31:35.240 --> 00:31:37.720
And it's the same idea, but features that aren't there yet.

00:31:37.720 --> 00:31:41.380
So it's just kind of interesting to remember that this stuff is still being added.

00:31:41.500 --> 00:31:45.280
Keeping an eye on when this stuff comes in, it can really make things easier.

00:31:45.280 --> 00:31:49.640
And in the meantime, don't lose too much sleep not being able to type certain things.

00:31:49.640 --> 00:31:52.100
If you can't type it perfectly, that's okay.

00:31:52.100 --> 00:31:55.720
I've actually been reading Luciano Romajo's book, Fluent Python.

00:31:55.720 --> 00:32:00.220
And he makes that point really well, that Python isn't a statically typed language.

00:32:00.220 --> 00:32:02.780
And you shouldn't get too carried away trying to type things.

00:32:02.780 --> 00:32:05.180
As much as is possible, it helps you is worth it.

00:32:05.180 --> 00:32:06.760
But you shouldn't be religious about it.

00:32:06.760 --> 00:32:07.280
Right.

00:32:07.280 --> 00:32:10.800
But if you are building tools and you put this into there eventually.

00:32:11.040 --> 00:32:11.480
Yeah.

00:32:11.480 --> 00:32:14.140
It might help other people who consume your libraries.

00:32:14.140 --> 00:32:18.400
It might help the editors give better autocomplete and error checking and stuff.

00:32:18.400 --> 00:32:19.980
And we catch bugs all the time.

00:32:19.980 --> 00:32:22.500
So as much as is feasible, I think it's totally worth it.

00:32:22.500 --> 00:32:26.240
And actually, there's a couple other peps on that note of things still changing.

00:32:26.240 --> 00:32:28.460
There's a couple other peps that are worth looking at.

00:32:28.460 --> 00:32:31.900
There's a new, more convenient way to write optional types.

00:32:31.900 --> 00:32:33.840
So right now you can say, I know.

00:32:33.840 --> 00:32:35.120
Oh my gosh.

00:32:35.120 --> 00:32:37.000
I've wanted this for so long.

00:32:37.000 --> 00:32:37.420
Yes.

00:32:37.420 --> 00:32:38.020
Yeah.

00:32:38.020 --> 00:32:40.300
So you have to say optional left bracket.

00:32:40.300 --> 00:32:41.880
Then the thing that is optional.

00:32:41.880 --> 00:32:42.360
And then right.

00:32:42.360 --> 00:32:45.120
Like optional bracket string or optional bracket user or whatever.

00:32:45.120 --> 00:32:45.360
Yeah.

00:32:45.360 --> 00:32:46.420
And you got to import optional.

00:32:46.420 --> 00:32:47.100
Don't forget that.

00:32:47.100 --> 00:32:47.260
Yeah.

00:32:47.260 --> 00:32:47.960
That's true.

00:32:47.960 --> 00:32:48.940
You got to import it too.

00:32:48.940 --> 00:32:52.740
And so now there's, there's a, a pet proposing that you could just put a question mark, which

00:32:52.740 --> 00:32:54.940
I guess isn't a problem for the parser, which is pretty nice.

00:32:55.500 --> 00:32:57.220
This one also is in process.

00:32:57.220 --> 00:32:59.620
Maybe this was something that was needed.

00:32:59.620 --> 00:33:02.380
The peg parser, which recently went into, what was that?

00:33:02.380 --> 00:33:03.200
Three, nine, right?

00:33:03.200 --> 00:33:05.820
Where it couldn't do it before, but maybe that's a good point now.

00:33:05.820 --> 00:33:09.420
But yeah, I, you know, they have that in C# and they have that in Swift.

00:33:09.420 --> 00:33:12.700
And I just love like this thing, question mark, right?

00:33:12.700 --> 00:33:17.740
Rather than a null check or specifying into question mark rather than optional bracket of

00:33:17.740 --> 00:33:18.000
int.

00:33:18.000 --> 00:33:18.800
It's just clear.

00:33:18.800 --> 00:33:20.660
I didn't know that was in other languages that, okay.

00:33:20.660 --> 00:33:21.660
That makes a lot more sense.

00:33:21.660 --> 00:33:22.820
And it's phonetic, right?

00:33:22.820 --> 00:33:25.380
Like if it's, if it's an int, you just say int.

00:33:25.460 --> 00:33:27.800
If it's a question mark, it's int, right?

00:33:27.800 --> 00:33:29.620
So you can even just like speak it out really well.

00:33:29.620 --> 00:33:30.020
Like int?

00:33:30.020 --> 00:33:30.540
Maybe.

00:33:30.540 --> 00:33:30.740
Okay.

00:33:30.740 --> 00:33:31.360
That could be null.

00:33:31.360 --> 00:33:31.640
Maybe.

00:33:31.640 --> 00:33:32.340
Could be none.

00:33:32.340 --> 00:33:34.180
That's not obvious to me.

00:33:34.180 --> 00:33:35.260
Really?

00:33:35.260 --> 00:33:35.780
Oh, interesting.

00:33:35.780 --> 00:33:38.240
I feel like that's a nice, a nice syntax, but maybe it isn't.

00:33:38.240 --> 00:33:38.560
Who knows?

00:33:38.560 --> 00:33:39.740
Maybe that won't get approved.

00:33:39.740 --> 00:33:40.320
Yeah.

00:33:40.320 --> 00:33:43.160
I think, I think it may not, but I do, I do hope it does.

00:33:43.160 --> 00:33:44.240
I mean, it's the question mark.

00:33:44.240 --> 00:33:45.940
There's an int or is there, right?

00:33:45.940 --> 00:33:46.740
Like, is it there?

00:33:46.740 --> 00:33:47.400
You're not sure.

00:33:47.400 --> 00:33:50.200
Like there's, there's some subtle symbolism there.

00:33:50.200 --> 00:33:52.860
See, I prefer the int or none.

00:33:52.860 --> 00:33:55.300
I like that as well.

00:33:55.440 --> 00:33:55.740
I agree.

00:33:55.740 --> 00:33:55.940
Yeah.

00:33:55.940 --> 00:33:56.300
That's not bad.

00:33:56.300 --> 00:33:58.400
Now that that's more convenient to write, but that's what, that's only 310.

00:33:58.400 --> 00:34:01.840
And the other languages that support this, and I don't know, I didn't read that PEP well

00:34:01.840 --> 00:34:06.540
enough to know, there's a runtime behavior, not just a type specification behavior.

00:34:06.540 --> 00:34:12.520
So I could say X equals like user question mark dot name.

00:34:12.520 --> 00:34:17.400
It'll either, if the user is none, the name is none, or it'll follow down that, that path

00:34:17.400 --> 00:34:18.740
and say, okay, user's not none.

00:34:18.740 --> 00:34:19.740
So then I'll say dot name.

00:34:19.740 --> 00:34:22.140
Oh, that avoids the none type has no attribute.

00:34:22.140 --> 00:34:22.400
Yeah.

00:34:22.400 --> 00:34:22.540
Yeah.

00:34:22.540 --> 00:34:22.780
Exactly.

00:34:22.780 --> 00:34:23.360
That's really nice.

00:34:23.360 --> 00:34:23.820
Yeah.

00:34:23.820 --> 00:34:24.700
Wow.

00:34:24.700 --> 00:34:25.280
Very cool.

00:34:25.420 --> 00:34:31.180
So, Will is, in the chat and he's got, Oh, I did the wrong one.

00:34:31.180 --> 00:34:32.700
I love that.

00:34:32.700 --> 00:34:35.820
Hey, Will.

00:34:35.820 --> 00:34:37.960
That was pretty good.

00:34:37.960 --> 00:34:38.560
All right.

00:34:38.560 --> 00:34:41.040
And then Ethan, you want to tell us about one more before we wrap it up?

00:34:41.040 --> 00:34:42.240
Oh, just another pep.

00:34:42.240 --> 00:34:42.400
Yeah.

00:34:42.400 --> 00:34:45.860
I, just another thing that is potentially changed how typing works.

00:34:45.860 --> 00:34:49.960
There's right now, there's no way to specify if you've used a type dict, which is to say,

00:34:49.960 --> 00:34:53.260
um, a dictionary with some keys having certain types.

00:34:53.260 --> 00:34:59.300
there was no way to specify what, what keys were optional and which ones weren't.

00:34:59.300 --> 00:35:02.060
You'd either say they were all optional or they were all required and there was nothing

00:35:02.060 --> 00:35:04.520
in between, but there's also a PEP to do that.

00:35:04.660 --> 00:35:07.320
So just, there's a lot of stuff on the horizon to keep an eye out for.

00:35:07.320 --> 00:35:09.840
And these three peps, I think are a good reminder of that.

00:35:09.840 --> 00:35:10.320
Yeah.

00:35:10.320 --> 00:35:10.860
Yeah.

00:35:10.860 --> 00:35:11.380
Yeah.

00:35:11.380 --> 00:35:11.740
Very cool.

00:35:11.740 --> 00:35:12.280
All right.

00:35:12.280 --> 00:35:13.760
Now, now can we throw it to you, Brian?

00:35:14.340 --> 00:35:14.700
Yeah.

00:35:14.700 --> 00:35:14.820
Yeah.

00:35:14.820 --> 00:35:18.860
Now, so this was, this is a suggestion by John Hagan.

00:35:18.860 --> 00:35:23.620
And I just thought I'd throw it in as a, as a, an extra, just one extra.

00:35:23.620 --> 00:35:28.900
So there, we've talked about, the effort at Microsoft and Guido and others, to make

00:35:28.900 --> 00:35:29.700
Python faster.

00:35:29.700 --> 00:35:36.820
and, like there's a, a whole bunch of ideas up on, on a, in the faster C

00:35:36.820 --> 00:35:37.720
Python ideas.

00:35:37.720 --> 00:35:43.280
and in one of this links to a couple of slide decks, talking about the making C

00:35:43.280 --> 00:35:45.280
faster or making Python faster.

00:35:45.280 --> 00:35:52.100
And, one of the things is a slide deck from Guido in, in it, he mentions, various

00:35:52.100 --> 00:35:55.880
other optimizations like maybe zero overhead exception to handling.

00:35:55.880 --> 00:35:59.640
Well, that's neat because that's already in three 11.

00:35:59.640 --> 00:36:06.320
So in three 11, we have, Mark Shannon implementing, zero cost exceptions.

00:36:06.320 --> 00:36:12.100
so if, if, if you have a try statement that doesn't, doesn't catch anything, there's

00:36:12.100 --> 00:36:13.160
no cost to it.

00:36:13.160 --> 00:36:14.660
So that's, that is very cool.

00:36:14.660 --> 00:36:19.840
I, I did a little playing around with this idea and I wrote a program here that calls

00:36:19.840 --> 00:36:22.500
string upper, like a hundred million times in a loop.

00:36:22.500 --> 00:36:26.260
And it does that also in a try except block with no errors.

00:36:26.260 --> 00:36:32.300
And, and so my understanding of this was that it will make entering the tri block in the case

00:36:32.300 --> 00:36:33.920
there's not an exception cheaper.

00:36:33.920 --> 00:36:39.600
and I ran it a hundred million times and I got, you know, not exactly the same, but it's

00:36:39.600 --> 00:36:40.460
really similar.

00:36:40.600 --> 00:36:44.980
But one of the other things, which I'm not doing in my example here, this is a gist

00:36:44.980 --> 00:36:45.960
I'll, I'll put it in the show notes.

00:36:45.960 --> 00:36:52.940
The looking into this comment, Brian is they talk about the number of the, basically the

00:36:52.940 --> 00:36:54.140
size of the call stack.

00:36:54.140 --> 00:36:59.480
And some of the other things, that happen in there about not pushing the exception onto

00:36:59.480 --> 00:37:03.040
the call stack or something, unless it actually happens and those kinds of things.

00:37:03.040 --> 00:37:05.440
So it's supposed to make function calls faster as well.

00:37:05.440 --> 00:37:10.300
So even if my little example wasn't necessarily faster, maybe, maybe something else, there's

00:37:10.300 --> 00:37:12.560
maybe other situations where it is nice.

00:37:12.560 --> 00:37:13.580
Yeah.

00:37:13.580 --> 00:37:13.980
Cool.

00:37:13.980 --> 00:37:16.520
Ethan, anything else you want to just throw out there for people?

00:37:16.520 --> 00:37:21.200
Well, one thing I did want to mention real fast about, about the zero cost exception handling

00:37:21.200 --> 00:37:25.060
is I think it's always tough to teach people about try except blocks and then introduce to

00:37:25.060 --> 00:37:28.980
them that they're actually pretty slow, especially if you use them in a function that gets called

00:37:28.980 --> 00:37:29.600
many times.

00:37:29.600 --> 00:37:32.520
And to be honest, I don't know the reasons for the internals being like that.

00:37:32.820 --> 00:37:35.980
so it's really nice to feel like that might not be true anymore because they're a

00:37:35.980 --> 00:37:39.720
good practice to have, to be able to say like, yeah, be careful, when you write code, especially

00:37:39.720 --> 00:37:44.000
for people like data scientists who aren't day-to-day programmers to say like, oh, it's good practice

00:37:44.000 --> 00:37:45.800
to use these and you shouldn't have to worry about performance.

00:37:45.800 --> 00:37:47.020
So glad to see that.

00:37:47.020 --> 00:37:47.960
Yeah, absolutely.

00:37:47.960 --> 00:37:50.160
And just following up on that real quick.

00:37:50.160 --> 00:37:55.880
if you look at the issue underlying this, where was it?

00:37:55.880 --> 00:37:56.720
This is the right one.

00:37:56.720 --> 00:37:56.860
Yeah.

00:37:56.860 --> 00:38:01.300
They, there's an issue that's linked in the show notes and it actually shows you the disassembly

00:38:01.300 --> 00:38:06.300
into bytecode of what it currently is and what it, it's going to be.

00:38:06.300 --> 00:38:08.660
And it's really, really similar.

00:38:08.660 --> 00:38:13.160
So you can see currently it does like a, the first thing it does is set up a finally and

00:38:13.160 --> 00:38:18.880
then, stuff right at the beginning, but now just do like a no op and then do a return

00:38:18.880 --> 00:38:19.720
value in the good case.

00:38:19.720 --> 00:38:23.640
Otherwise it'll do a push exception and then work with it and so on.

00:38:23.640 --> 00:38:29.500
So it, it pushes off some of the bytecode operations that add like to the call stack, like pushing

00:38:29.500 --> 00:38:34.300
things onto it and so on at the C eval.c level of CPython.

00:38:34.300 --> 00:38:34.940
Yeah.

00:38:34.940 --> 00:38:35.980
Oh, that's very cool.

00:38:35.980 --> 00:38:36.480
Yeah.

00:38:36.480 --> 00:38:41.460
Well, the one thing I wanted to mention, well, I don't know if people have heard of

00:38:41.460 --> 00:38:41.860
pedal board.

00:38:41.860 --> 00:38:43.700
I think Spotify just announced this recently.

00:38:43.700 --> 00:38:46.900
It's, it's basically a Python package that lets you do some things that you might usually

00:38:46.900 --> 00:38:49.820
do using an audio editing tool and it's cool on its own.

00:38:49.820 --> 00:38:53.720
but I had just listened to, I forgot if it was last week.

00:38:53.720 --> 00:38:57.760
So the weeks before episode where Brett Cannon was on, on Python bytes.

00:38:57.760 --> 00:39:02.560
And he talked about how, you know, anytime you see an issue with documentation, just put

00:39:02.560 --> 00:39:03.200
in a pull request.

00:39:03.200 --> 00:39:04.360
Most of the time it'll get accepted.

00:39:04.360 --> 00:39:09.180
And, and he said he's, he's contributed to like 200 or 300 repositories that way.

00:39:09.180 --> 00:39:10.480
So I found this last week.

00:39:10.480 --> 00:39:13.500
And then in this week I was thinking about what I wanted to talk about on the show.

00:39:13.700 --> 00:39:17.900
So I went back to this link and, lo and behold, the last, the last commit was made

00:39:17.900 --> 00:39:21.500
by Brett Cannon and it's removing a stray back tick in the read me.

00:39:21.500 --> 00:39:23.400
So he really practices what he preaches.

00:39:23.400 --> 00:39:25.080
so he seems to be very active.

00:39:25.080 --> 00:39:29.260
He's one of only, nine contributors to this and probably the rest work at Spotify.

00:39:29.260 --> 00:39:31.100
So good for him.

00:39:31.100 --> 00:39:31.780
Nice.

00:39:31.780 --> 00:39:32.000
Yeah.

00:39:32.000 --> 00:39:32.660
That's fantastic.

00:39:32.660 --> 00:39:35.620
Nice to, for that, a little bit of real time follow-up.

00:39:35.620 --> 00:39:35.960
Fantastic.

00:39:35.960 --> 00:39:36.780
All right.

00:39:36.780 --> 00:39:41.480
So I have a few extras and again, I have my, my, banner for extras, extras, extras.

00:39:41.480 --> 00:39:43.620
So, a couple of things here.

00:39:43.620 --> 00:39:50.560
Let's talk about something that Kelly Schuster-Perdes talked about, you know, she and Sean doing

00:39:50.560 --> 00:39:54.580
the, teaching Python podcasts and they're doing great work over there.

00:39:54.580 --> 00:40:00.240
So one of the things that she found for teaching is this thing called ear sketch.

00:40:00.240 --> 00:40:01.600
You probably haven't heard of this.

00:40:01.600 --> 00:40:02.200
I'm guessing.

00:40:02.200 --> 00:40:09.640
So ear sketch is a project from Georgia tech that teaches coding, but through like a DJ

00:40:09.640 --> 00:40:10.860
type of experience.

00:40:11.020 --> 00:40:12.460
She's got a cool video up there.

00:40:12.460 --> 00:40:14.480
It says five minutes and four lines of code.

00:40:14.480 --> 00:40:16.400
And I got this up there going.

00:40:16.400 --> 00:40:17.100
So, yeah.

00:40:17.100 --> 00:40:18.660
Thanks Tony for pointing that out.

00:40:18.660 --> 00:40:20.880
So here I'll just play what she created for everyone real quick.

00:40:32.960 --> 00:40:34.580
People are teaching.

00:40:34.580 --> 00:40:37.100
I want to get folks involved through music and Python.

00:40:37.100 --> 00:40:38.720
That's a real cool project that ear sketch.

00:40:38.720 --> 00:40:41.820
And I told you good stuff about Django before.

00:40:41.820 --> 00:40:43.060
Let me tell you some bad stuff.

00:40:43.060 --> 00:40:43.820
Oh no.

00:40:43.820 --> 00:40:48.740
You might, you might meet little Bobby tables in the Django ORM.

00:40:48.920 --> 00:40:57.180
If you're, running query set order by, and passing some piece of user input into

00:40:57.180 --> 00:41:03.180
what you might be ordering by, you might be ordering by back tick, semi colon drop table

00:41:03.180 --> 00:41:05.520
--or something like that, which you wouldn't want to.

00:41:05.520 --> 00:41:09.080
So basically there's a SQL injection vulnerability in Django.

00:41:09.080 --> 00:41:10.080
What is it?

00:41:10.080 --> 00:41:17.920
320 up to 325 and 300 up to 313.

00:41:17.920 --> 00:41:20.440
But yeah, less than that, right?

00:41:20.440 --> 00:41:22.780
Less than 325 and less than 313.

00:41:22.780 --> 00:41:25.380
So if you have those,

00:41:25.380 --> 00:41:27.500
you definitely want to patch it straight away.

00:41:27.500 --> 00:41:28.800
That's a critical vulnerability.

00:41:28.800 --> 00:41:30.460
So check that out.

00:41:30.460 --> 00:41:32.560
And also that's on untrusted input.

00:41:32.560 --> 00:41:35.000
Yes, that is untrusted input.

00:41:35.000 --> 00:41:36.740
Don't freak if you're not taking,

00:41:36.740 --> 00:41:38.280
what would you like to sort by?

00:41:38.280 --> 00:41:39.100
Please type here.

00:41:39.100 --> 00:41:46.040
But still, you know, it's easy enough to just do a GitHub update,

00:41:46.040 --> 00:41:47.520
just an update to the requirements.

00:41:47.520 --> 00:41:51.460
Now, if you're on, your code is on GitHub and this is the requirement,

00:41:51.460 --> 00:41:52.760
you pinned your version,

00:41:52.760 --> 00:41:57.020
you probably have already gotten this as a security announcement

00:41:57.020 --> 00:41:58.480
and an email sent to you.

00:41:58.480 --> 00:41:59.720
Yeah, that's such a nice feature.

00:41:59.720 --> 00:42:01.100
It is such a nice feature.

00:42:01.100 --> 00:42:02.240
But if you don't pin your version,

00:42:02.240 --> 00:42:03.420
they're like, well, you're on the latest version.

00:42:03.420 --> 00:42:04.380
You're good, right?

00:42:04.420 --> 00:42:04.900
You won't know.

00:42:04.900 --> 00:42:06.600
So it still may slip through.

00:42:06.600 --> 00:42:07.200
All right.

00:42:07.200 --> 00:42:07.940
Yeah.

00:42:07.940 --> 00:42:11.300
And Chris May on the live stream has some philosophical thoughts for us.

00:42:11.300 --> 00:42:13.620
He says sometimes he doesn't even trust his own input.

00:42:13.620 --> 00:42:15.620
Yes, we all, we've all been there.

00:42:15.620 --> 00:42:17.320
Chris, don't inject yourself.

00:42:17.320 --> 00:42:19.480
All right.

00:42:19.480 --> 00:42:21.820
Shall we wrap this up with some laughs?

00:42:21.820 --> 00:42:22.640
Yes.

00:42:23.080 --> 00:42:25.240
Brian, this is going to take some role-playing again.

00:42:25.240 --> 00:42:26.820
A nice little cartoon for us.

00:42:26.820 --> 00:42:27.860
This is QA101.

00:42:27.860 --> 00:42:30.960
Speaking of the CVE I just spoke about,

00:42:30.960 --> 00:42:33.280
and, you know, if you fix a minor bug,

00:42:33.280 --> 00:42:34.860
you might get credit, like, whatever.

00:42:34.860 --> 00:42:36.780
We fixed a little tiny bug, right?

00:42:36.780 --> 00:42:37.880
Formatting a log file.

00:42:37.880 --> 00:42:41.040
If you fix a critical bug, like, wow, that seems super important.

00:42:41.040 --> 00:42:42.560
You've been doing good work this week, right?

00:42:42.600 --> 00:42:46.340
So here's two developers in an open office sort of space.

00:42:46.340 --> 00:42:47.360
Brian, you be the guy.

00:42:47.360 --> 00:42:48.540
I'll be the woman developer.

00:42:48.540 --> 00:42:49.280
Okay.

00:42:49.280 --> 00:42:51.360
Which priority should I give this bug?

00:42:51.360 --> 00:42:52.980
Well, is it easy to fix?

00:42:52.980 --> 00:42:53.860
Yep.

00:42:53.860 --> 00:42:55.060
I'll fix it immediately.

00:42:55.060 --> 00:42:56.420
Critical.

00:42:56.420 --> 00:42:57.560
Critical.

00:42:57.560 --> 00:43:00.980
Finding the correct bug priority is key, they say.

00:43:00.980 --> 00:43:01.980
So very nice.

00:43:01.980 --> 00:43:03.920
I'll link to that little cartoon in the show notes.

00:43:03.920 --> 00:43:04.980
I don't get it.

00:43:04.980 --> 00:43:07.920
Because you're going to get more credit for fixing critical bugs.

00:43:08.040 --> 00:43:09.200
And if you can fix it right away.

00:43:09.200 --> 00:43:10.880
Yeah, it looks like you did way more work.

00:43:10.880 --> 00:43:12.460
You did so much more work.

00:43:12.460 --> 00:43:15.780
Brian over there only fixed, like, medium bugs.

00:43:15.780 --> 00:43:17.560
Ethan and I took out the critical.

00:43:17.560 --> 00:43:18.000
Exactly.

00:43:18.000 --> 00:43:19.860
You do your T-shirt sizing after you finish.

00:43:19.860 --> 00:43:21.780
After you take all the work,

00:43:21.780 --> 00:43:23.300
you assume everything you took was a large.

00:43:23.300 --> 00:43:24.800
Yeah.

00:43:24.800 --> 00:43:26.120
So, yep.

00:43:26.120 --> 00:43:26.560
Exactly.

00:43:26.560 --> 00:43:28.120
I keep asking people,

00:43:28.120 --> 00:43:30.440
so what are the points equal in hours?

00:43:30.440 --> 00:43:32.320
No, we can't talk about that.

00:43:32.320 --> 00:43:32.840
Okay.

00:43:32.840 --> 00:43:36.080
Do I use powers of two?

00:43:36.080 --> 00:43:36.900
What do I do?

00:43:36.900 --> 00:43:37.460
Yeah.

00:43:37.460 --> 00:43:37.700
Anyway.

00:43:38.060 --> 00:43:38.260
Cool.

00:43:38.260 --> 00:43:40.280
Well, thanks, Ethan, for coming on the show.

00:43:40.280 --> 00:43:40.880
It was fun.

00:43:40.880 --> 00:43:41.700
Yeah, this was great.

00:43:41.700 --> 00:43:42.440
Thanks for having me.

00:43:42.440 --> 00:43:44.060
Yeah, it's been fantastic to have you here.

00:43:44.060 --> 00:43:44.940
Thanks for being here.

00:43:44.940 --> 00:43:46.040
Brian, thanks as always.

00:43:46.040 --> 00:43:46.760
Thanks.

00:43:46.760 --> 00:43:47.500
Bye, everyone.

00:43:47.500 --> 00:43:49.340
Thanks for listening to Python Bytes.

00:43:49.340 --> 00:43:52.160
Follow the show on Twitter via at Python Bytes.

00:43:52.160 --> 00:43:55.280
That's Python Bytes as in B-Y-T-E-S.

00:43:55.280 --> 00:43:58.140
Get the full show notes over at Pythonbytes.fm.

00:43:58.140 --> 00:44:00.240
If you have a news item we should cover,

00:44:00.240 --> 00:44:03.480
just visit Pythonbytes.fm and click Submit in the nav bar.

00:44:03.480 --> 00:44:05.600
We're always on the lookout for sharing something cool.

00:44:05.600 --> 00:44:07.500
If you want to join us for the live recording,

00:44:07.680 --> 00:44:10.140
just visit the website and click Livestream

00:44:10.140 --> 00:44:13.020
to get notified of when our next episode goes live.

00:44:13.020 --> 00:44:17.420
That's usually happening at noon Pacific on Wednesdays over at YouTube.

00:44:17.420 --> 00:44:19.620
On behalf of myself and Brian Okken,

00:44:19.620 --> 00:44:20.800
this is Michael Kennedy.

00:44:20.800 --> 00:44:23.060
Thank you for listening and sharing this podcast

00:44:23.060 --> 00:44:24.520
with your friends and colleagues.

