Hey there, thanks for listening. Before we jump into this episode, I just want to remind you
that this episode is brought to you by us over at Talk Python Training and Brian through his pytest
book. So if you want to get hands-on and learn something with Python, be sure to consider our
courses over at Talk Python Training. Visit them via pythonbytes.fm/courses. And if you're
looking to do testing and get better with pytest, check out Brian's book at pythonbytes.fm slash
pytest. Enjoy the episode. Hello and welcome to Python Bytes, where we deliver Python news and
headlines directly to your earbuds. This is episode 252, recorded September 29th, 2021. I'm
Michael Kennedy. And I'm Brian Okken. And I'm Ethan Swan. Ethan, welcome to Python Bytes. You've been
over on Talk Python, where you talked about some really cool data science stuff, and now you're
over here. So thanks for being here. Tell people a bit about yourself. Yeah, I was on Talk Python
236. So it was a while ago, but that was really cool. I work for a company called 8451. It's the
data science subsidiary of Kroger. And I'm a data scientist, but basically what I do is build tools,
mostly which are in Python, for our data science department. So we have like 250 data scientists,
pretty large department. And I build like packages and some dashboard sort of things,
just like various technology helper stuff for data science.
Yeah, it sounds really fun. And you all run what we were talking about before we hit record.
Probably one of the larger data science groups out there, right? I think of data science as being
like, there's a couple of folks that are embedded with like a marketing team or a product team or the
software development team a lot of times, but you are a properly large group of data scientists.
I mean, in theory, that's what the whole company does. So it's a very cool experience. And often,
I think that's nice for the team I'm on, because you don't usually get so many customers on internal
tools. You know, we're building stuff for literally hundreds of people to use. And it's a little bit
like releasing software externally. So it's yeah, it's a lot of fun.
Yeah, fantastic. All right. Well, we're definitely looking forward to having your insights here
for the show. Now, Brian, I do want to start off here. I want to talk about some deck staining.
Thanks. Yeah.
So because those of us who are very attentive on Twitter saw that Brian kindly responded to somebody
who sent us a message and said, Oh, I see you were talking about pallets. We should also talk about
deck stain and other DIY project resources. And maybe you could put that stupid article on your
blog. You're like, we're not a blog. We talk about pallets because it's on Flask. And then
Twitter decided, Oh, you are now classified under the home improvement category. So are we changing
our theme or what?
Apparently just me. That's most of you. I've got a few new followers now. And most of them are people
that like to make things. So.
Well, it's fun to make things as well. But maybe we'll maybe we'll talk more about SQL and stuff
like that. What do you think?
Yeah. So this, this was sent to us by Dave Cochesa. Thanks, Dave. I want to talk about
SQL fluff. So I had never heard of this, but it looks pretty cool. So SQL fluff is a Python,
a Python package that is basically a linter for SQL. So that's how interesting. I haven't really
thought about linting SQL code, but it makes perfect sense.
Yeah. Well, I mean, there, there is like, I don't really think about it too much either,
but there's like things like, should you capitalize all the keywords? And some people just like it
like that. So there is style. There's like both style guides around a SQL. I assume there's style
guides. And this lets you help, helps you enforce it. Not, not just style guides, but just, you know,
looking for mistakes and things. The, the, the page looks really slick for, I like the logo,
the fluff logo, but, but the, one of the things that's great about it is the documentation. So
the documentation looks wonderful. And there's one of the neat things about this is there's a
different rules or different dialects set up so that it treats different things like ANSI and
Postgres and MySQL different. And, and I'm not sure if these are, or if these are style differences or,
or, or, or what they're doing different, but, but it's kind of interesting that they'll, they'll,
there is a difference there.
Well, one of the things that comes to mind for me, if this reports errors and I suspect it probably
does, one of the things that comes to mind for me is if using like Microsoft SQL server and you're
using a parameterized query, because you don't want little Bobby tables in your school, you would say
at parameter name, whereas in with like MySQL or Oracle, it'd be like a question mark. Right. And I think
one is illegal in the other syntax. So at least in that regard, I think, I don't know for sure it's
illegal, but I'm pretty sure like it may be, and it could be that you've got to say what type of
parameterized specifications and other extensions are valid. And even, I think there's some keywords,
right? Aren't there some different keywords in some cases? So it would make sense to have to know
the dialect. Yeah. Yeah. And also like you were saying, if, if there are really are big differences
differences or even minor differences, there might be some queries that you don't run all the time.
And so you're not sure if you switch databases that they might be broken if you're trying to port. So
kind of cool. There's a list of, so it has rules, like a lot of linters, rules for failure. And I like
the rules page because it talks about the rules, but also shows you the anti-pattern and best practice.
I kind of like that style. I don't know if I like the terms anti-pattern and I really don't like the
term best practice, but nonetheless, the, what it's looking for and what you should do different is,
is a good thing to have in the documentation. It's pretty cool.
Yeah. I do like the anti-pattern aspect. I, maybe pattern. You're going to have an anti-pattern,
just have the pattern. I don't know.
I'm not sure. One of the things that's in the documentation, I can't remember where,
there it is, that people should be aware of. Supposedly this, even though it has like
1982. That's interesting. Stars. It's still in alpha phase. So there's a note here that says,
expect significant changes. So just be aware of that.
Cool. It doesn't seem major because you're not doing runtime behavior on it, right? It's a thing
you run against your code and then you look at the output.
I mean, maybe it's in your CI system or something, but. Yeah. But it's not in production. Right. So like
you are, you won't get called on a weekend because the site went down because this thing got automatically
updated or something to that effect. Yep. I guess it could have broken your, your queries, but you know,
whatever. and it's good to have an audience because, we did have a Paul from the chat say,
Ethan's correct. There are different keywords between different SQL dialects. Yeah. We use a,
Oh, sorry, Michael. No, go ahead. Go ahead. No, we, we use a lot of SQL as I would assume most data
science shops do. but one, what this made me think of was, one contentious topic in people
who write a lot of SQL is, especially when you have a bunch of column names and you're selecting
regularly, you know, five to 10 columns, the comma first, I don't know if you've seen the
approach where you do a new line, comma, column, comma, column. So it lines up really nicely and it
makes it easier to delete things. that's a very common thing that people feel strongly about.
So I could imagine linter as being very handy to at least enforce one style throughout a company
because you know, we don't have that. Yeah. Nice. And then I was going to add that Pamphil Roy on the
audience says it would be a cool if there was a plugin for D Beaver and Sam Morley asks, I wonder if it
checks if inputs are sanitized. I don't know if it should, but Paul also asks if it validates for
syntactical correctness beyond just style. He does say that it catches errors and bad SQL before it
hits your database. So I'm going to go with the yes. That's pretty cool. Yeah. Ethan, I was thinking
as I was watching Brian present this, that you probably do way more SQL than I do, even though I
run in production websites that are backed by databases, not just because there's no SQL, but
because I use ORMs and the data structure doesn't change. But for, data science,
you're kind of in a more exploratory mode, right? Yeah. I think it's pretty interesting because,
um, you know, like listening to this podcast, people talk about using ORMs a lot, but in data science,
you don't really think of data in that relational model as much. I mean, you can, but like thinking of,
as of rows as objects is really not common. So I feel like my relationship with databases is totally
different. My first couple of years, I was mostly writing SQL, but it was, it was literally just
asking questions for analyses, which is such a different use case than what people use it for,
for web development. Right. Yeah, absolutely. It's, it's super different, super different.
But if you were to explore data, wouldn't it be nice to have a desktop application instead of a web
browser for doing so? So Jupyter and JupyterLab have got to be the most popular way that people
interact with data on the data science side. It's certainly an exploration stage anyway.
So super big news that is old news is new again, but better. JupyterLab desktop app is a thing.
Like I can download JupyterLab. It's an icon on my doc or on my task bar. I click it,
it runs like an app, but inside of it is Jupyter notebook, like the whole JupyterLab with terminal
and Python consoles and kernels and all those things. That's cool. That's, that's very nice.
Yeah. Have you played with this yet, Ethan? No, we, so I don't know how common this is,
but I think for us, at least mostly people aren't working on their local machines. They're really
connecting to a session of Python on a remote server. So mostly what we do is we fire up Jupyter
on, on a remote server. And then from our laptops, we hit that URL to actually look at the notebook.
So I'm not sure a desktop app would work as well for us, although maybe it's, it's definitely
interesting. And I wonder if there's some native features of desktop apps that are available,
that are going to be a reason to switch.
Well, what I would say right now is it's a really nice self-contained thing. So I'll just
read the description real quick. JupyterLab app is a cross-platform standalone application.
Distribution of JupyterLab is a self-contained desktop application, which bundles the Python
environment and several popular libraries to use and scientific computing, like surely pandas and
NumPy and those kinds of things. So what you get is you get just an app that's, it's ready to go that
you could just have somebody install and you can say, here, open this notebook and run it. And long
as you're using core libraries and stuff like that, you don't have to think, okay, go to the terminal,
you know, set up the environment and then type JupyterLab. Oh, you need to activate the kernel
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
thing. No nonsense type of app.
And you lost a whole bunch of people with just open the command line.
Yeah. That's so true.
Yeah. Yeah. So you don't have to hear, right? You just, it's on your doc. You click it just like,
like you would with Word or Firefox or whatever. And it's, you're there. It starts and manages the
Jupyter server in the background. There may be a whole host of command line arguments. You can give
it to say like run, but use that server and other things along those lines or run and use this conda
environment. I didn't see any of those. And so from what I can tell is it's kind of a local version
of Jupyter. So it might be super interesting for you all in your workflow.
One place where I think this would be really handy is teaching beginners. So I actually teach some
Python, especially for data science classes at the university of Cincinnati. And one thing that
regularly is really confusing to people is that you can't double click on a notebook file and have it
open because that's such a typical experience of files on a computer, double click. And there's an
application that opens that file. Oh, interesting. Yeah. And there are workarounds. If you have
Anaconda Navigator, it kind of works, although it's, it's a little hitchy. But I would assume
that if you have a desktop app, you'd be able to register that with the operating system, whatever
that process is to say, like when I click on .ipynbs, open it. Because I find I have to teach students,
no, start up Jupyter, open your browser, navigate to that file in the browser.
Were you in the wrong folder in the terminal when you ran Jupyter? Which is, well, sorry,
you're now locked out of that tree, that, that part of the tree of the folders.
And then suddenly you're having a conversation about paths. Yeah. You go down. It really is like
something I don't like to deal with. So maybe this is what I should recommend for people when I teach.
What I would recommend is just check it out and try. So I do have a bit of a comment here from Dean
out in the audience. I like the concept of JupyterLab app, but I'm afraid it'll be a V in V in V,
V in V, virtual environment nightmare. So what I found interesting is it's discovered, you know,
when you're creating kernels for Jupyter, you have to run a command. I always forget it and always have
to duck, duck, go or search this to figure out how to do it again. But I have to get the command to say,
create this environment and then register that as, so Jupyter finds that content environment,
that V in V, right? It's IPI kernel install. I have to do this all the time.
Yeah, exactly. And I know that it's basically that, but the exact command, I always forget.
So that command, it seems like it picked up the ones that I had run previously for standalone
terminal JupyterLab. So the virtual environment story is the same as Jupyter itself without that.
I think all we're getting here is we're getting the libraries plus Python plus the server starting
all bundled together. And it's basically the same as if you just run it on the command prompt.
I think as long as was it Dean, as long as Dean doesn't want to be starting Jupyter from the virtual
environment, it should be fine. Like when you said, Michael, about the kernels, that's the much more,
I recommend people do it that way. Cause some people do like to just install Jupyter in whatever
environment they work in and launch it there. But I, I have a hard time imagining how that would work in this
case. Yeah, I do as well. And Dean makes the point that once you have to go and register all that kind
of stuff on you, like when you're down in the terminal doing this, you've kind of lost those
same people. And that may well be the case, but I can see, you know, this is sort of a first version
of this. I can see that those are some of the desktop things that could add, right? It could add a
setting section where you, you have a dialogue for managing these things and creating new ones and so on.
So it could be pretty neat. Yeah. Definitely something to watch. All right. Before we move on,
Paul out in the audience has a quick question for you, Ethan, a tangential one. Python has some
really great SAST tools like Bandit, but I'm not able to find good options for R. And I know that
you live in a world that does both R and Python. Yeah. Do you have any thoughts on this? I have no
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,
like what I do. I know I said, I'm, I'm a data scientist, but in some ways that's nominal.
Like really a lot of what I do is software development for the data scientists.
Data scientists are your customer in a sense, or your, your target user. Yeah.
Yeah. So I think a lot of what I hear from users is that there are certain measurement tools and
certain statistical tools that are available in R that take longer to get to Python. So I wouldn't
be surprised if that really is what's happening here, but I don't personally have any suggestions.
Yeah. Okay. Yeah. So Bandit, is like a tool that will scan for known security vulnerabilities,
like leaving debug settings on in Django. Oh, see, I was wondering if that was okay. Then,
then that I also don't know. That's a little different than what I was imagining.
Yeah. Awesome. All right. Well, since you got the floor, tell us about your first item.
Sure. So, I, I found this requests cache package, in a newsletter recently,
and this might be a little bit of a shorter one because unfortunately I haven't had a reason to
use it yet. but basically what this does, scrolling down here is you can instantiate
sessions just like you would with the traditional requests library. So probably, request is one
of the most commonly used Python packages, I would guess. Yeah. For anybody who's not familiar,
you use it to make HTTP requests, which is basically to bring anything back from me. And, the tagline,
I think is HTTP for humans, but it's just known for being easy to use and you can access the internet.
But one thing that I have found is that, especially if I'm, if I'm testing something in an interactive
way, not mocking, but I really want to see if my code pulls back what I expect. sometimes I rerun
the same request over and over and I say, go get this, go get this, go get this often the same data.
And sometimes that data is large. and that takes a really long time. So requests cache is a way of
creating a session object that looks and acts the same. But when you call, a get or a post
request on the same URL, what, with the same data, what you get back is actually just the cached
version of that data. so you're not waiting every time the first time you incur the network
latency. And if the server has to do anything to like compute the data, or if it's enough data that
it takes some time to get to you, you wait for that. But the second time everything runs instantly,
which is really a big advantage. So I've done some things with web scraping where I'm
building some kind of, I want to build like a function that pulls some things down and makes,
uh, or pull some things out of that, but just waiting every time to run the function for it to
pull from several different pages and, you know, do some computation on that actually makes it pretty
slow. But if you were able to cache it like this, that'd be a lot faster.
Yeah. This is nice. I love the fact that it's just a stand in replacement for the request
session itself. Yeah. And if you scroll down a little more, it actually shows a way to do that
with the regular requests library. And this actually scares me a little bit. This is kind of,
kind of magical what's going on here. You just run a one-liner with requests cache,
and then suddenly the requests library itself works differently. So I wonder if that's a monkey
patching or what's going on. It probably is, but it is, it is really slick. so I would imagine I'll,
I'll have a reason to use this soon, but I haven't tested that yet. It does offer a lot of
configuration options. And one thing I thought was, was a good, idea to look at is an expiration
date. and that's sort of like, when should you invalidate the cache and actually pull again?
Cause you maybe should trust that the website is sending you all the same stuff today, but if you
rerun your code in a week, make sure that it still responds the same way. So it's got some nice options
like that. I really like that. That's interesting. So you could use it not even just for testing. It could
be for, actual data, but you know, it's not getting updated very often. So.
Yeah. For large data is what I was imagining. So I, yeah, like I said, there's, there's been some
times where I've like pulled things from APIs where they send back a lot of data and you don't want to
be waiting for that. Yeah. Or even you just want to make sure that, multiple calls to it are
getting the same data, even if it does change. that's true. Yeah. So keep consistency.
Interesting. This reminded me a little bit of the, I don't know if people are familiar with the
at cache, or LRU cache. It used to be another, there's a new one just called at cache in the func
tools module built into Python. And that's very, very handy once you know, it's there because often
you have a function that you don't want to recompute the work for. And this is almost like somebody
rewrote requests with cache in it, which is pretty cool.
Yeah. It's got a lot of nice features. You know, I think a question from handful out in the audience,
can it cache to redis because production in memory production caching, you could blow it up,
right? Blow up the memory. So a couple of things that stood out to me that were interesting there
was, yeah, you could throw a func tools, LRU cache decorator onto an expensive thing, which is fine,
but that's in memory, right? And plus things have to be hashable and whatnot, but you could do that.
Um, but it's in memory. And a lot of times if you have scale out as you do on web apps,
like in production, as in, Brian was talking about, you have web farms, like five or 10 copies
of micro whiskey or something running. So then there's still five times you got to do it before
it really gets cached. And then also it goes to SQLite. So it gets stored to disc, right? So it's
not even in memory. It's, it's on disc. So like you said, there's other backends as well, but I think
having just by default going to a SQLite file with an possible expiration means you could just turn
this on and leave it expire after a day. Go tell us about the backends. There's more than just SQLite.
Yeah. It does seem like you have some options. I mean, like I said, I haven't had a reason to use
this. So I haven't toyed around with all these, but it, this, the way this is documented leads me to
believe that it really is just a drop in replacement, that you can configure what you want to use as
your backend. And I do wonder, so yeah, what you were saying, Michael, about having multiple instances,
I do wonder how that would work. Would it check to see if any of the instances had cached this yet?
Um, would it like proactively go reach out to the cache or? Yeah. Well, I think if you have some
memory one, it's going to be a hassle, right? Like one of the options is memory. but all the other
ones, file system, grid FS, Redis, SQLite, those are all support, you know, concurrency. They support.
Yeah, exactly. So, so then it will scale across process seamlessly.
Yeah. So that, that could be actually really helpful for something like that, where you have
a distributed set of workers. Yeah. Yeah, for sure. let's see some fun stuff about your monkey
patching comment. And Dean says monkey patch is like having a real monkey. It's very cool when other
people have it, but having it in my house is scary. And yeah, Sam just, has a too much experience at
the zoo, I think, with that as well. So yeah, monkey patching is a little sketch.
Oh, nice. All right, Brian, you're up next. Okay. What do we got next? I, so I, I did something,
uh, kind of dumb the other day. so I, I, I went ahead and I needed, I pushed a new package
out on PyPI. Really. I was just trying to, to remember how to, the whole process, because I
wanted to just remind myself of like, if I have something new, something cool I wanted to share,
how do I get it out there to PyPI? So I was walking through that process and I was doing it
for a plugin. You did your own typo squatting. Apparently. so I, I published pytest Slow,
uh, and then, but who was it? Brian Skin said, cool, but, maybe pytest Skip Slow would be
better. And I'm like, oh man, that is a better name. cause that's what it does. It skips the slow
tests by default. So, and this is totally lifted from the pytest documentation about,
um, they have this example, but nobody's written a plugin for it. So I did this. It's a little tiny
thing, but so I renamed it, but how do you rename it? So I went out and searched. So how do you rename
something in PyPI? You can't really do it, but you can create another one. And then, so this is nice.
Well, who was it? Simon Willison wrote this up. It's a PyPI renamed cookie cutter template.
And I didn't actually use the template, but I did use these steps. So the steps really are create a
renamed version of the package, which I did then publish it to PyPI under the new name and create a
final release for the old name that points to the new one and, depends on it and have dependencies
so that if somebody installed the old one, they'll really get the new one. it sounds more
complicated than it is. It's just a few steps, but, there's a cookie cutter you can use.
The cookie cutter uses setup tools and I didn't want to do that, but, so I used, I did basically
copied his, the entire thing. and then he's got a demo. So if you, you look at it, so if you go to
the old one, old version, it'll just have a thing that says, Hey, I'm going to the new one now.
Um, so I did that and, and it was neat. I really appreciate the steps. and it's,
it's all good.
Yeah.
That's cool. You can also use it for aliases. Like you can install BS for or beautiful soup for,
right. And it's kind of the same.
Oh, is that how, is that how they do that?
I I'm guessing, I don't know, but it sounds like the same.
I didn't know that.
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,
go to the other one instead.
So, but if I install the old one, it, it kind of just pulls in the new one.
Yes.
Yeah.
Yeah. Very cool.
Yeah. Brian, you were, you were refreshing on PyPI, but I actually just pushed my first ever
package to PyPI a couple of weeks ago. And so that was, you know, a bit of a trial, but I was
amazed at how straightforward it is. The documentation is excellent. It really is,
is pretty seamless actually for somebody who's never done it before. So who knows, hopefully I
don't make any mistakes on the one package I have and need to read. Yeah. But we'll see.
The immutability of it is a little scary, but yeah.
So for me, the hard part was just understanding that it really was pretty simple. and then also,
uh, getting the hashes right. So you have to like, you have to get like, you know,
signatures and stuff to make sure that you can push to the PyPI correctly. So, yeah.
Yeah. But even the documentation there, it's a little intimidating, but it actually
turned out to be only a few minutes of work. So that was, that was pretty nice. Good for them.
I guess PyPI is the people to praise for that.
Yeah. So what was your package?
Oh, I, it, it's called pre-mark. It's, it's a spinoff of a JavaScript library for making
slides. And I just make a lot of slides for teaching. And I actually found, an existing
package by man. I want to, I mean, yeah, here it is. It is not ready. That's why
it's a release candidate. but I, I, yeah, I based it on this existing package by
at Tyler Dave on GitHub, and talk to him a little bit about it. He had already built a really
lightweight tool and I just expanded on it, but I like to write my slides in Markdown, which is really
what this is for. You write your slides in Markdown and a bunch of different files. It stitches them
together and creates a, what's called remark JS presentation. so I use this for my own teaching.
Nice. I'll check it out.
But it's, it really is largely a sample project to just like learn how to use PyPI and things like
that.
Yeah. Very cool. All right. Up next we have caching. Oh wait, we just talked about caching. No, I have
more caching. So Django, I have two, two pieces of news on Django. this one comes from Carlton
Gibson. I'm one of the Django guys and also, one of the hosts at Django chat, the podcast. So
they are adding a Redis cache backend to Django. So traditionally Django has shipped with Memcache,
Memcached D, that cache backend with multiple implementations, I think even. So you can go
there like Django as an ORM, it can talk to stuff. So it has a cache backend as well. And it could talk
to Memcache, but it couldn't talk to Redis. And they found that the vast majority of people are using
Redis and they said, well, why don't we have a backend for it? Well, guess what? It's going to.
So this was merged and this whole conversation here around the PR and the issue is pretty interesting.
So it starts out and says, this PR aims to support, to add support for Redis to be used as a caching
backend with Django as Redis is the most popular caching backend. Adding it to Django core dot,
the Django dot core dot cache module would be a great addition for developers who previously had to rely
on third party packages and check out how they've got this little checklist and progress.
These are the things for this PR to come along and work. So create the Redis cache class, do a pickle
serializer, et cetera, et cetera. Waiting for this other task. Here's some open-ended documentation.
So I don't think I've seen this really before, like this project tracking in the PR.
I like it's really cool.
Yeah, I do too. The other thing to note that this came in on May 23rd and there's a
large conversation. If you go there, there's 30 pages of conversation about it and you can see
it evolving. Like, okay, we finally got the test pass and we finally got it implemented. Now let's
move on to the documentation now, et cetera, et cetera. And then finally, boom, September 15th,
that's three, three and a half months, something like that. It's closed. So you can actually sort of
track what the Django team is doing for adding features, like core important features to Django.
It's always so interesting to watch open source communities like this, especially on somewhat
contentious issues where people disagree and how they manage these things. I think it's really
impressive because a lot of teams that even meet in person regularly in our small teams still struggle
with that kind of stuff, but these huge open source projects manage it. Somehow they implemented the
feature at the end. So pretty impressive.
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.
Yeah. Putting the open in open source.
That's right. Hi, Brian. What you got?
It's me again. Are we done with our things?
All right. No, I think I got one more.
Oh, no, sorry. I totally, I was for some reason in wrong order. Yes, Ethan, you're up next. Sorry.
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.
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.
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.
It was a bit of an annoyance, but I didn't realize there was a fix coming.
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.
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.
But basically...
A lot of decorator time, yeah.
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.
It may have some other modifications of the function, but that's very frequent.
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.
Any kind of function is fine that takes in any parameters and returns any return type, as long as it returns the same thing.
So it's like generics, which you would do with type bars.
But in this case, you create something called a param spec, and then you pass that as the...
Oh, man, I lost it where it is in here.
Oh, here we go. This is what I wanted.
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.
This P is a parameter specification.
And you make essentially your callables generic on both this parameter specification and on the return value.
So I know there's a lot to that.
And I think for people who are typing everything every day, maybe this doesn't seem terribly pertinent.
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.
But really, what this got me thinking about a little bit is just that the Python typing ecosystem is still really evolving.
Like for somebody who's not super close to following it, it appears that like this is how Python works now.
And maybe it's always been this way, but it really hasn't.
And there's a lot of holes in how it works.
There was no way to do this before.
And this isn't finished yet.
This is a pep, but it isn't implemented.
And so right now, you don't have a way to do typing for this particular feature.
And that...
Yeah, flowing type information through different things.
That is something we haven't done a lot of in Python.
But as you called out generics and templates, that's like all you do.
That's the bread and butter of those things.
Yeah.
And it's the same idea, but features that aren't there yet.
So it's just kind of interesting to remember that this stuff is still being added.
Keeping an eye on when this stuff comes in, it can really make things easier.
And in the meantime, don't lose too much sleep not being able to type certain things.
If you can't type it perfectly, that's okay.
I've actually been reading Luciano Romajo's book, Fluent Python.
And he makes that point really well, that Python isn't a statically typed language.
And you shouldn't get too carried away trying to type things.
As much as is possible, it helps you is worth it.
But you shouldn't be religious about it.
Right.
But if you are building tools and you put this into there eventually.
Yeah.
It might help other people who consume your libraries.
It might help the editors give better autocomplete and error checking and stuff.
And we catch bugs all the time.
So as much as is feasible, I think it's totally worth it.
And actually, there's a couple other peps on that note of things still changing.
There's a couple other peps that are worth looking at.
There's a new, more convenient way to write optional types.
So right now you can say, I know.
Oh my gosh.
I've wanted this for so long.
Yes.
Yeah.
So you have to say optional left bracket.
Then the thing that is optional.
And then right.
Like optional bracket string or optional bracket user or whatever.
Yeah.
And you got to import optional.
Don't forget that.
Yeah.
That's true.
You got to import it too.
And so now there's, there's a, a pet proposing that you could just put a question mark, which
I guess isn't a problem for the parser, which is pretty nice.
This one also is in process.
Maybe this was something that was needed.
The peg parser, which recently went into, what was that?
Three, nine, right?
Where it couldn't do it before, but maybe that's a good point now.
But yeah, I, you know, they have that in C# and they have that in Swift.
And I just love like this thing, question mark, right?
Rather than a null check or specifying into question mark rather than optional bracket of
int.
It's just clear.
I didn't know that was in other languages that, okay.
That makes a lot more sense.
And it's phonetic, right?
Like if it's, if it's an int, you just say int.
If it's a question mark, it's int, right?
So you can even just like speak it out really well.
Like int?
Maybe.
Okay.
That could be null.
Maybe.
Could be none.
That's not obvious to me.
Really?
Oh, interesting.
I feel like that's a nice, a nice syntax, but maybe it isn't.
Who knows?
Maybe that won't get approved.
Yeah.
I think, I think it may not, but I do, I do hope it does.
I mean, it's the question mark.
There's an int or is there, right?
Like, is it there?
You're not sure.
Like there's, there's some subtle symbolism there.
See, I prefer the int or none.
I like that as well.
I agree.
Yeah.
That's not bad.
Now that that's more convenient to write, but that's what, that's only 310.
And the other languages that support this, and I don't know, I didn't read that PEP well
enough to know, there's a runtime behavior, not just a type specification behavior.
So I could say X equals like user question mark dot name.
It'll either, if the user is none, the name is none, or it'll follow down that, that path
and say, okay, user's not none.
So then I'll say dot name.
Oh, that avoids the none type has no attribute.
Yeah.
Exactly.
That's really nice.
Yeah.
Wow.
Very cool.
So, Will is, in the chat and he's got, Oh, I did the wrong one.
Uh, I love that.
Hey, Will.
That was pretty good.
All right.
And then Ethan, you want to tell us about one more before we wrap it up?
Oh, just another pep.
Yeah.
I, just another thing that is potentially changed how typing works.
There's right now, there's no way to specify if you've used a type dict, which is to say,
um, a dictionary with some keys having certain types.
Um, there was no way to specify what, what keys were optional and which ones weren't.
You'd either say they were all optional or they were all required and there was nothing
in between, but there's also a PEP to do that.
So just, there's a lot of stuff on the horizon to keep an eye out for.
And these three peps, I think are a good reminder of that.
Yeah.
Very cool.
All right.
Now, now can we throw it to you, Brian?
Yeah.
Now, so this was, this is a suggestion by John Hagan.
And I just thought I'd throw it in as a, as a, an extra, just one extra.
So there, we've talked about, the effort at Microsoft and Guido and others, to make
Python faster.
Um, and, like there's a, a whole bunch of ideas up on, on a, in the faster C
Python ideas.
Um, and in one of this links to a couple of slide decks, talking about the making C
faster or making Python faster.
And, one of the things is a slide deck from Guido in, in it, he mentions, various
other optimizations like maybe zero overhead exception to handling.
Well, that's neat because that's already in three 11.
So in three 11, we have, Mark Shannon implementing, zero cost exceptions.
Uh, so if, if, if you have a try statement that doesn't, doesn't catch anything, there's
no cost to it.
So that's, that is very cool.
I, I did a little playing around with this idea and I wrote a program here that calls
string upper, like a hundred million times in a loop.
And it does that also in a try except block with no errors.
And, and so my understanding of this was that it will make entering the tri block in the case
there's not an exception cheaper.
Uh, and I ran it a hundred million times and I got, you know, not exactly the same, but it's
really similar.
But one of the other things, which I'm not doing in my example here, this is a gist
I'll, I'll put it in the show notes.
The looking into this comment, Brian is they talk about the number of the, basically the
size of the call stack.
And some of the other things, that happen in there about not pushing the exception onto
the call stack or something, unless it actually happens and those kinds of things.
So it's supposed to make function calls faster as well.
So even if my little example wasn't necessarily faster, maybe, maybe something else, there's
maybe other situations where it is nice.
Yeah.
Cool.
Ethan, anything else you want to just throw out there for people?
Well, one thing I did want to mention real fast about, about the zero cost exception handling
is I think it's always tough to teach people about try except blocks and then introduce to
them that they're actually pretty slow, especially if you use them in a function that gets called
many times.
And to be honest, I don't know the reasons for the internals being like that.
Uh, so it's really nice to feel like that might not be true anymore because they're a
good practice to have, to be able to say like, yeah, be careful, when you write code, especially
for people like data scientists who aren't day-to-day programmers to say like, oh, it's good practice
to use these and you shouldn't have to worry about performance.
So glad to see that.
Yeah, absolutely.
And just following up on that real quick.
Um, if you look at the issue underlying this, where was it?
This is the right one.
Yeah.
They, there's an issue that's linked in the show notes and it actually shows you the disassembly
into bytecode of what it currently is and what it, it's going to be.
And it's really, really similar.
So you can see currently it does like a, the first thing it does is set up a finally and
then, stuff right at the beginning, but now just do like a no op and then do a return
value in the good case.
Otherwise it'll do a push exception and then work with it and so on.
So it, it pushes off some of the bytecode operations that add like to the call stack, like pushing
things onto it and so on at the C eval.c level of CPython.
Yeah.
Oh, that's very cool.
Yeah.
Well, the, the one thing I wanted to mention, well, I don't know if people have heard of
pedal board.
I think Spotify just announced this recently.
It's, it's basically a Python package that lets you do some things that you might usually
do using an audio editing tool and it's cool on its own.
Um, but I had just listened to, I forgot if it was last week.
So the weeks before episode where Brett Cannon was on, on Python bytes.
And he talked about how, you know, anytime you see an issue with documentation, just put
in a pull request.
Most of the time it'll get accepted.
And, and he said he's, he's contributed to like 200 or 300 repositories that way.
So I found this last week.
And then in this week I was thinking about what I wanted to talk about on the show.
So I went back to this link and, lo and behold, the last, the last commit was made
by Brett Cannon and it's removing a stray back tick in the read me.
So he really practices what he preaches.
Uh, so he seems to be very active.
He's one of only, nine contributors to this and probably the rest work at Spotify.
So good for him.
Nice.
Yeah.
That's fantastic.
Nice to, for that, a little bit of real time follow-up.
Fantastic.
All right.
So I have a few extras and again, I have my, my, banner for extras, extras, extras.
So, a couple of things here.
Let's talk about something that Kelly Schuster-Perdes talked about, you know, she and Sean doing
the, teaching Python podcasts and they're doing great work over there.
So one of the things that she found for teaching is this thing called ear sketch.
You probably haven't heard of this.
I'm guessing.
So ear sketch is a project from Georgia tech that teaches coding, but through like a DJ
type of experience.
She's got a cool video up there.
It says five minutes and four lines of code.
And I got this up there going.
So, yeah.
Thanks Tony for pointing that out.
So here I'll just play what she created for everyone real quick.
People are teaching.
Um, I want to get folks involved through music and Python.
That's a real cool project that ear sketch.
And I told you good stuff about Django before.
Let me tell you some bad stuff.
Oh no.
You might, you might meet little Bobby tables in the Django ORM.
If you're, running query set order by, and passing some piece of user input into
what you might be ordering by, you might be ordering by back tick, semi colon drop table
--or something like that, which you wouldn't want to.
So basically there's a SQL injection vulnerability in Django.
What is it?
320 up to 325 and 300 up to 313.
But yeah, less than that, right?
Less than 325 and less than 313.
So if you have those,
you definitely want to patch it straight away.
That's a critical vulnerability.
So check that out.
And also that's on untrusted input.
Yes, that is untrusted input.
Don't freak if you're not taking,
what would you like to sort by?
Please type here.
But still, you know, it's easy enough to just do a GitHub update,
just an update to the requirements.
Now, if you're on, your code is on GitHub and this is the requirement,
you pinned your version,
you probably have already gotten this as a security announcement
and an email sent to you.
Yeah, that's such a nice feature.
It is such a nice feature.
But if you don't pin your version,
they're like, well, you're on the latest version.
You're good, right?
You won't know.
So it still may slip through.
All right.
Yeah.
And Chris May on the live stream has some philosophical thoughts for us.
He says sometimes he doesn't even trust his own input.
Yes, we all, we've all been there.
Chris, don't inject yourself.
All right.
Shall we wrap this up with some laughs?
Yes.
Brian, this is going to take some role-playing again.
A nice little cartoon for us.
This is QA101.
Speaking of the CVE I just spoke about,
and, you know, if you fix a minor bug,
you might get credit, like, whatever.
We fixed a little tiny bug, right?
Formatting a log file.
If you fix a critical bug, like, wow, that seems super important.
You've been doing good work this week, right?
So here's two developers in an open office sort of space.
Brian, you be the guy.
I'll be the woman developer.
Okay.
Which priority should I give this bug?
Well, is it easy to fix?
Yep.
I'll fix it immediately.
Critical.
Finding the correct bug priority is key, they say.
So very nice.
I'll link to that little cartoon in the show notes.
I don't get it.
Because you're going to get more credit for fixing critical bugs.
And if you can fix it right away.
Yeah, it looks like you did way more work.
You did so much more work.
Brian over there only fixed, like, medium bugs.
Ethan and I took out the critical.
Exactly.
You do your T-shirt sizing after you finish.
After you take all the work,
you assume everything you took was a large.
Yeah.
So, yep.
Exactly.
I keep asking people,
so what are the points equal in hours?
No, we can't talk about that.
Okay.
Do I use powers of two?
What do I do?
Yeah.
Anyway.
Cool.
Well, thanks, Ethan, for coming on the show.
It was fun.
Yeah, this was great.
Thanks for having me.
Yeah, it's been fantastic to have you here.
Thanks for being here.
Brian, thanks as always.
Thanks.
Bye, everyone.
Thanks for listening to Python Bytes.
Follow the show on Twitter via at Python Bytes.
That's Python Bytes as in B-Y-T-E-S.
Get the full show notes over at Pythonbytes.fm.
If you have a news item we should cover,
just visit Pythonbytes.fm and click Submit in the nav bar.
We're always on the lookout for sharing something cool.
If you want to join us for the live recording,
just visit the website and click Livestream
to get notified of when our next episode goes live.
That's usually happening at noon Pacific on Wednesdays over at YouTube.
On behalf of myself and Brian Okken,
this is Michael Kennedy.
Thank you for listening and sharing this podcast
with your friends and colleagues.