Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds.
This is episode 378, recorded April 9th, 2024.
I'm Michael Kennedy.
And I'm Brian Okken.
And you can follow us over on Mastodon.
We're all on Facedon, at Brian Okken, at M. Kennedy, and at Python Bytes.
We'd love to talk to you over there.
We're also on X Twitter, if you want to be there as well.
But we probably spend a little more time on Mastodon these days.
Support the show by supporting our work.
We have, obviously, a bunch of courses that Talk Python Training, Brian's complete pytest course, and the Patreon as well.
Be part of the live show if you wish.
You can see the video version.
Absolutely not required, but always awesome to have people in the audience to give it a little bit more of multiple perspectives.
We'll get some of that coming on in a second.
And you can check that out at pythonbytes.fm/live.
Live, usually Tuesdays at 10 a.m.
So that's Pacific time.
Finally, if you want an artisanal, handcrafted digest of what we talk about sent to you in email form, even if you don't listen,
well, head over to the website, Python Bytes.fm.
Click newsletter right in the middle and enter your email address.
We will not share it or do other nefarious things.
So we just want to be able to contact you and have a chat if you wish.
So Brian will be sending out something cool to everyone this week, as usual.
Brian, do you have health news or something you've got to share?
What's going on here, man?
Well, I've found a pacemaker.
My ticker's doing good.
No problems with that.
But you can control your heart with Python.
Oh, okay.
Actually, it's not.
You can't control your heart yet.
Actually, I don't know if you can.
But I ran across a project from Brandon Rohr called Pacemaker.
And what this does, it's not controlling your heart.
It's controlling a time per iteration loop.
So with, and I don't know if this has anything to do with uv or not,
but one of the things that uv has brought us is really fast installing of lots of packages.
If you have a lot, why not?
So having, this is a small package.
So this is in Brandon's own words on the readme.
I think I saw this here.
It is, essentially, it's a glorified snippet.
Instead of a snippet, he wrote a package, which I love this.
So I'm taking a look at it.
It's a small package.
Good example, though, for how to do a package.
Like if you take a look at the pyproject.toml, it's pretty concise.
It's using setup tools, which is fine.
But it shows you how easy it is to put a package together, which is pretty fun.
And also with the code, I was taking a look at the code.
So what this does is not terribly earth-shattering, but it just sticks around.
You tell it that you want to, it's kind of like a metronome thing.
So you've got some code that you want to run.
And here's an example.
And you just say pacemaker beat, and it waits.
So it's a busy wait, or it does a sleep or something like that.
Yeah, sleep.
But it sleeps and then comes back alive, does its thing, and then goes back.
So you can have it be, like in this example, it does a beat for 100 times.
And this is important in a lot of different types of code, a lot of monitoring code, a lot
of other things.
And busy waits aren't necessarily always the greatest, but in a lot of cases, it works great.
The thing that I wanted to point out about this, there's a few things that I love about
this project, or just wanted to point out.
Really great documentation, even for a small project.
Also, I had kind of forgot about time monotonic.
So this is using time monotonic when it does the time comparisons.
Instead of normal, there's a couple times of timestamps, types of timestamps, and monotonic,
and then there's a monotonic nanoseconds.
If you really want to do really tight loops, you could modify it for that.
The thing that monotonic does is it makes sure that all time deltas are positive.
So even if something happens, like you change your system clock, during the times, between
timestamps, it'll still do it correctly so that it is monotonically increasing in times.
That's interesting.
Another thing could be, you know, like maybe even you don't change it, but we all have our
clocks set to auto-adjust, right?
And it could come online and auto-adjust or something.
Yeah, and that would be weird if like suddenly, especially with this project where like one
of the things it does, and he warns about this, is, I mean, sleeps aren't exact science.
And this isn't a real-time, especially on non-real-time operating systems, but I don't think Python's
even a real-time thing.
So it's an approximation for how long it's going to sleep, but it tries to correct it.
So if you, if you, if you slept too long, it tries to do more events so to, so that on
average you get the average amount of times you're running be correct.
So it's kind of a cool library.
Check it out.
A couple of things I wanted to point out about it.
One is the cool use of monotonic.
The other one is a good, good read me documentation, even for a small thing.
But there's, there's no tests.
Brandon, come on.
Anyway, I'm not, I actually, there's a couple of things around this.
I don't think that people should stop from putting a code online just because they don't
have tests yet.
It might be that somebody could contribute and add tests.
It also might be that for you, if you're using this all the time, if Brandon uses this all
the time, the tests are covered by the, the calling code.
So you're, you're, you're using this and you're covering it.
And I just want to, I guess I want to point out to everybody for any library you're using,
you probably should have tests that cover the part of the library that you depend on, even
if they do have tests.
So this one doesn't.
So you, you know, buyer beware, but even if they do, you probably should make sure that
it is really working the way you think it's working.
So anyway.
Yeah.
Sometimes it's just hard to have meaningful tests.
Like a while ago, I released that Umami Python event library, right?
For the analytics tracking.
And all it does is serialize the messages that come to it from the Umami API.
I can test what my perception of the API is, right?
But, but the real danger is that that API changes in some way or another, or, you know, it's just
90% of the fragility is outside of, if you mock out all that stuff, then well, you know,
you're just kind of testing your view, which hopefully is already mostly encoded.
And I mean, it's not completely useless, but it's, is there's certain things that are just
tricky to get.
Right.
And, and testing isn't, testing isn't necessarily always automated testing.
It could be like that.
You're using it.
The Umami API they're using, it's you're using it.
So you'll know when it breaks and other things are like your use of it will break or the,
the calling code.
And I just like, I don't think that people should, especially with the internal stuff,
maybe on PyPI, maybe we should have a little bit like things eventually should have tests
probably.
But the, for internal projects where you're sharing code it's better to package and share
code than to not share code.
So if, if writing testers, what's stopping you from putting it in a central repository,
don't let that stop you.
It's, it's better than just, I mean, we, we have snippets, like he said, it's a glorified
snippet.
So why not package it?
So yeah, very nice.
I like the monotonic.
That's news news to me.
I hadn't paid attention to that before.
Yeah, it's cool.
I want to try the nanosecond monotonic.
So yeah.
Other stuff that people might want to pay attention to, and this is not to drum up a bunch of
fear and concern so much.
It's not huge news in that regard to people, but is more to just sort of put on out there
what the PyPI, the Python Packaging Authority folks to deal with, you know, kind of say thanks.
So the news comes to us from bleeping computer, which usually does pretty good news, but this
article is pretty vacuous of information, but the title says a lot.
PyPI suspends new user registrations to block malware campaign.
And so there's some interesting things in here.
So it basically says, look, when was this?
It was like a couple of, this is March 28th, a little bit, a couple weeks ago.
IPI has temporarily suspended user registration in the creation of new projects to deal with
ongoing malware campaign.
Then it proceeds to tell you what, what IPI is basically.
And then it says, oh, look, there was some, some problems.
People are uploading bad stuff, but it doesn't tell you, for example, like what projects,
what did the malware do?
So if you jump over to the status.python.org, actually that tells you about the status of
Python infrastructure, which is kind of cool.
And it says same deal.
This is official reporting.
Did it say how long the event went for?
Nope.
Just that it was a thing.
I guess if I did math, that would be 10 hours, about 10 hours, 30 minutes.
That's a ways.
And this, this is the real article you want to read.
It is over on Medium, IPIs under attack, project creation and user registration.
It's been adhered to the details by Yehuda Gelb.
I hate to link to Medium.
I hate Medium.
I think it's a crummy place.
I don't know.
It just seems gross, but they have really good details.
So basically this was a typo squatting attack.
And what's interesting, it was a multi-stage attack, stealing all sorts of things.
Crypto wallets, obviously, but real sketchy is browser cookies.
So you're logged into your bank for a session that's good for 20 minutes.
You know, if they could grab that and log in as you, that might be less good, you know,
or log into your email and reset stuff and so on.
So what happened is there was a bunch of packages in here somewhere.
There's the package list.
So you can just, you can see these are all about the capturing people who, one, misspelled
things, but also just like didn't quite understand.
Like, for example, Brian, one of the packages is requirements.tx.
requirements.txt without the dot or requirements.
So if you say pip install requirements, right, without the -r or the .txt, you're getting
this.
And there's a bunch of others, you know, TensorFlow and Selenium and like they're all over the
requirements business.
So it's just everywhere.
And the deal was basically each one of these had a malicious setup.py, which is why I think
it's kind of interesting to look at.
And inside the malicious setup.py, it encrypted using the cryptography.fairnet library, which
just listed as a dependency, I imagine.
It then decrypts some kind of URL that it very lightly.
It's funny.
It's like using little analytics.
It'll like passes the query string of like, which one hacked me before you get going.
It downloads some kind of thing that installs and runs and basically installs a backdoor
ongoing thing.
So even if you pip uninstall this, there's this thing running that just monitors your
system, which is not ideal, to be honest.
That's not what you want.
No, one does not want this.
Yeah.
Oh, and Henry out in the audience says, in addition to all the stuff I said, that actually blocked
all uploads for a few hours and couldn't upload build 1.2.1.
You know, what a hassle, huh?
This is why we can't have nice things, you know?
Come on now.
Yeah.
So there's a, I guess there's a lesson here to make sure that you're careful when
you pip install something, because even if you catch it and you're like, oh, that's not
what I meant, you may have already done damage.
Isn't there a way, I don't remember off the top of my head, to say pip install, but don't
run, only use wheels, like don't allow anything to run?
I don't know.
I'm not sure.
I feel like there was.
There were probably some of the audiences going, yes, yes, of course.
How do you not know this?
But it doesn't mean this is not going to happen.
It just means you have to write, use the code.
You know, as opposed to just the act of installing it or sneaking it into a requirements
file somehow.
Yes.
And I knew Henry would come through and say, dash, dash, only dash binary.
Indeed.
That's it.
All right.
Well, you know, they were on top of it.
The fact that this was completely dealt with within 12 hours is pretty awesome.
The fact that it has to happen, not so much.
Yeah.
All right.
Over to you, Brian.
So I want to just, I guess the world has changed a little bit with uv and other rustified things.
So we have, there's an updated doc or an updated blog post from Hinnick.
Python projects, Python project, local virtual env management redo or redux.
And so he's just started really talking about all of the tools that he uses around virtual
environments.
And I kind of just enjoyed it because it matches my own use quite a bit.
So some caveats in here that says this is what works for me.
I'm not necessarily saying you have to use this, of course.
But it's a good list of kind of how you're, how dealing with, dealing, dealing with virtual
environments.
The major thing that happened is uv and it's changed a lot of how we deal with it, but it
makes things a lot faster.
So the, some of the things I thought I want to revisit in here.
So it's pretty great.
So he's using .venv and I in product in each project directory.
And that's, it's close to what I use.
I use the venv.
I just don't use the dot.
I do as well, Brian.
And it's, I know the dot means kind of like, just, it's not real important, put it to the
side, but I love to be able to open up a project in Finder or Explorer and look at it and go,
all right, this one has a virtual environment.
Oh, this one doesn't.
I need to make one.
And I don't want to have to keep like show hidden files, hide hidden files over and over.
So while I appreciate the dot, like I'm a hundred percent with you.
Yeah.
So I think I want to revisit this.
I've tried it a while ago, but I haven't tried it lately.
is a, is a way to, to have an ENVRC file or dot ENVRC file in your directory.
And, and that gets run when you CD into it or, or something.
Anyway, I think this is cool stuff, but I don't use it.
Do you use this Michael?
No, I love the idea of it.
And in practice, I just haven't, I just haven't done it now.
There's some cool tricks in here with it that he's using that I kind of want to get back to
trying it again.
So I guess, thanks, Sinek for bringing this up so I can take a look again.
Using Astral's uv over Rye.
I kind of never went to Rye, but it looks like he switched from Rye to uv.
Python installations.
Now switch to both, just always using python.org downloads because they're now universal builds
mostly.
And it just sort of works.
And that's what I've been using also for installing Python.
Dead snakes for Linux, of course.
And then there's a, a mention of Python build standalone for various other projects that are
needed.
So that's, that's kind of neat.
A discussion about unpinned versus pinned packages and, and then also using a dot Python version
default within a directory.
And the, the, the, the tie in back to during during during this kind of cool is, is he's,
he's got some tricks in here.
So if you, if you drop in a dot Python version default, it would just shows you, tells you
what version to, to use by default that, that in a directory and then you check it in so that
the development environment can be recreated easily.
And he's got some in VRC with that's part of during that he's got a little snippet that will
activate it based on which Python you're using, using you UV, which is kind of a neat little trick to,
to use to Renv and Python versions and, and uv altogether, which, so I'll definitely have to try that.
That's kind of a neat trick.
That is neat.
There's using all of this as well helps with GitHub actions.
He's describing how to do that with, with as input to the setup Python, GitHub action,
which is, I didn't know you could do this.
So you can say the Python version file and you can just give it that Python version default.
So the GitHub actions uses the right default version.
It's this cool trick.
Um, he's also, he's got some, tricks on how to use, use it with the fish shell.
I don't, I don't use fish, but for those fish users, that'd be great.
The, the other part that I wanted to, that I really enjoyed seeing is because of all of this,
the, in which version and stuff you can use, oh, he's using the requires Python and
Python project Toml, which I'm, I'm using for everything now.
So, but the, he's has a way, a little, little sed snippet to parse that out of the
pyproject.toml and pass it into, using the get, get have actions, the animal file,
to pass it to a Docker build, but it's just, it's grabbing this, this version of Python.
So you could use it for other things within your, within your, I guess within get
your, your GitHub action or, or something else, or other tool, if you needed to pass what
Python version to use.
So that's pretty, some pretty clever things in here that I, some, some, something old,
something new, kind of some neat tricks.
Yeah.
Very interesting.
A lot of stuff to explore, interesting comments in the audience about liking or
disliking all the magic, the auto magic.
Well, and it's also another example of like, I kind of like these sort of posts, but even
for different people, just to see this is how I work.
This is the workflow I use.
Um, not, not necessarily just focusing on one tool, but I use all these things together
and this is how they work together.
It's kind of fun to read.
Yeah.
Yeah, absolutely.
Even if you don't adopt it, it's cool to just see the tools and the things you can do.
Yeah.
All right.
On to the next one.
This one is super exciting.
Super exciting.
Okay.
We need to talk for just a second about Cloudflare and edge workers.
Okay.
Now this is just a Cloudflare thing, but I think it's sufficiently interesting that it's
worth calling out.
Okay.
So CDNs like Cloudflare, like bunny.net, the one that we use and stuff like that have a bunch
of what are called pops points of presence.
And traditionally these have been, how do I get my files really close to you?
So they feel immediate no matter where you are in the world.
So for example, I don't know about Cloudflare's details, like their stats, but I know bunny.net
has something like 115 servers that are points of presence throughout the world.
And so if you try to, if you visit the Python by site website, all the static content, like
images and CSS and stuff are delivered from one of those pops, like right by you.
Yeah.
And obviously the MP3s are as well.
Now those things have started to have programmable models where in addition to just having
the content of say a static file near you, they'll have some of the logic of the application
near you.
So if you've got like a React friend in that talks to APIs, maybe it's only talking just
down the street to the point of presence, not halfway around the world to New York where
our server lives.
Right.
And this has traditionally been JavaScript.
So here's the, with that set as the stage, Cloudflare has these things called, I think they
call them web workers.
Yeah.
Something like that.
We'll see in just a second.
And those have been traditionally done in JavaScript.
So there's a whole infrastructure about distributed databases and things like that, that these
workers can work with.
It's pretty interesting.
But the news is Cloudflare announces Python, they're bringing Python to these workers with
Pyodide and WebAssembly.
So now you can start to program these edge devices, these points of presence things like
right near each other with first class Python support.
Based on all the work of Pyodide and WebAssembly and all those things.
Isn't that excellent?
It is excellent.
This is a big announcement.
I got the omnivore page pulled up and the read time is 16 minutes.
We're not going to go through all that.
So let me just pull out some highlights here.
And so one of the things that's really made this possible, made it interesting is they've
put a huge amount of effort into optimizing the runtime for JavaScript to make it work well.
And it's Pyodide's integration with JavaScript for that sort of runtime performance implementation side to make this work really, really well.
So it says beyond just compile to WebAssembly.
So each worker is what's called a V8 isolate.
So it's kind of like a container, but just less, you know, just an isolated version of the V8 runtime,
which is the Chrome's JavaScript engine that also runs WebAssembly.
Okay.
So it says it's not just as easy as copying over the WebAssembly stuff and running it because they have thousands of these things running on one server.
And if each one had to do full on startup for WebAssembly, full on startup for Pyodide, which is six megs and take some delay to get going and so on, it would be, it wouldn't be practical.
So they've done all this work to kind of memory snapshot and almost running pip installed setup version of this and then like deliver it to you upon request.
So there's a lot of shared memory or shared processing.
And here's how you write it, Ryan.
From JavaScript, import response, async def on fetched and do your Python and return some response.
Hmm.
How cool.
Let's see.
There's a cool graph that compares what's VMs versus containers versus these isolate things.
Like I said, it's a lot more sort of put together.
And one of the things that's pretty interesting here is it has support for FastAPI in Langchain.
So there's a bunch of, like I said, this is really long, but let's look at the FastAPI version here.
There's a whole, there's a whole example I'll point people at of code Python worker examples under Cloudflare's GitHub repo.
And so if you go to the FastAPI one here and you go into source and you pull up the worker and you hide the symbol.
So we can all see, basically check this out.
So this is Python code running effectively in a node style like thing in WebAssembly on the edge of one of these workers.
And here's what you write.
From FastAPI, import FastAPI request.
From Pydantic, import base model.
Use app equals FastAPI, app.get.
Here's your document you return.
Here's your async function that you write.
You can go do async things.
Here's your Pydantic model with Python types.
What do you think?
Here's your post, your puts, your gets.
Oh, this is pretty cool.
Yeah, and they've got some sort of database thing that it integrates with so you can have persistent data and so on.
But like I said, I don't do a ton with these things, but I might start paying attention if I can do it in Python.
Yeah, definitely.
Yeah, back in my day, a V8 isolate was just carrots.
Exactly.
It's the part that like sinks to the bottom and then you take it out, right?
No, if people use Cloudflare already and those workers, this is super interesting.
And if you just want to see some cool, unique uses.
And I guess in a way, one of the real first production uses of Pyodide and Python in WebAssembly.
Yeah.
Check this out.
Definitely.
All right.
Is that, that's all of our main topics, right?
That is.
All right.
How extra are you feeling today?
I have zero extras.
Zero.
Zero extras.
Just a bad job.
Zero.
All right.
Well, I got a couple.
I'll go through quickly here for us.
First of all, Brian Skin sent both of us a message and said, look, there's a decent chance the podcast
already is, our audience has already filled you in on this.
But last week, since I talked about L-Python and the related projects are spearheaded by Andre
Sertik.
Brian, you are, Brian Skin, you are the podcast audience who has filled us in.
Thank you.
So he did a, actually Brian did a whole long, hour long interview with him on it.
And so people want to check out L-Python further, which we talked about before.
Check that out.
That's pretty cool.
Next.
I really like this idea.
We talked about just path last time.
Yeah.
And how it sort of helped you diagnose your path, you know, like duplicates, missing directories,
all that kind of stuff.
Listen to last week if you want the whole details.
But the guy behind it said, hey, that was really awesome.
You covered it.
I'm going to create a badge, a Python bytes GitHub badge for the project.
What do you think about that, Brian?
I think that's really cool.
I do too.
And so I'm going to try to set it up so that there's an automatic GitHub badge that
people can put on their readme if their project was featured in Python bytes.
And I'll put that at the top, put the code you can get for that or something at the top
of the show on the episode page.
It's not there yet, but eventually you should be able to get a cool, cool little badge like
this that says my project was featured on the podcast on this episode.
And here's a link to it all within one badge.
Yeah.
And the badge has like the little, like the number shows what episode it was on, which is.
Yeah, exactly.
Instead of saying like Python 312, it says Python bytes and the episode number.
It's excellent.
Yeah, that's pretty cool.
So yeah.
Yeah.
Thanks.
Thanks for that.
I am as well.
Let's see what else.
Oh, Brian, we have a brand new server going strong now.
Did you see?
I did.
That's pretty exciting.
Was that a lot of work?
Yes.
It was a lot of stress, not a lot of work.
So I decided it's time to upgrade the server, get some more RAM.
More CPUs is always nice, but I couldn't reasonably get more RAM without more CPUs.
So I'll just take them.
So we had some downtime for about 20 minutes actually last night.
So if you ran into that, I apologize.
That took out everything because this was not one of the Docker pieces out of the Docker.
This was the host of all the Docker clusters.
So it was gone, gone.
I couldn't even reasonably put up a, we're down page because it was the host thing that
was down, not part of the site.
Right.
Yeah.
Anyway, now is there a, I don't know where the reply went.
Oh, maybe if I were, I guess if I'm not logged in, it doesn't show me, but we now have a sweet
machine running along just like before.
So that worked out pretty well before that.
I was so happy, Brian.
We had for the last 30 days running a 99.98% global uptime.
That was awesome.
That was pretty great.
Yeah.
I know turning off the server for 20 minutes, you know, with like 20 gigs of database records,
it takes a while to copy that from one VM to another.
And so that, that's, that's what took so long.
It's only three nines though.
You need to work on that.
Well, it's three nines and then an eight on the end.
It's almost four nines.
It's so close.
I'm going to try to make it better now.
But it went down to, I think 99.94%, which I think is still pretty darn good for some random
dude in Oregon running a server.
That's pretty awesome.
My Python test went down last week for like 12 hours or something like that.
Oh no.
Was that something that had nothing to do with you?
Just the host of it or something?
It was had to something to do with me, but it was a DNS thing.
A DNS glitch then, or, you know, it wasn't really, it was, it was an accounting thing
on my part.
Like, but I got like, when it, when it got repaired, they didn't repair all the DNS records.
So I had to go recreate all the DNS records.
What a hassle.
Yeah.
That's a huge hassle.
All right.
Cool.
But before we, before we go on for a joke, Henry out there on his points out, what about
rich and textual?
They'll just be overrun with these badges.
Yeah.
These Python bytes badges.
We'll have to do an infinity symbol for the projects.
Exactly.
Oh, maybe some sort of like a sequence like this, you know, 100 dot, dot, dot, 400.
Yeah.
Something like that.
Also, backing up a little bit, the, the worker, the edge workers, we, from Andrew Bayer,
Pyodide works in web workers now too, which is totally different thing, but also cool.
That is very cool.
Okay.
That is very cool.
Thanks, Andrew.
I think web workers are basically like background threads on your web app, which I think there
used to be troubles with that as well.
All right.
This one, I thought of you when I got this joke, Brian.
Okay.
So this makes us a little AI, a little bit of C++.
The graphic kind of is crumbly.
The graphic kind of is crumbly, so it's hard to read.
But Gemini, the Google AI says, this person says, Gemini is apparently told your Google account age and will answer questions with the appropriate caution.
So if you're like a minor, you're like 12 year old kid with a Gmail account.
You don't want this thing to just tell you all the secrets of life.
Like, hey kid, Santa Claus is fake.
No.
All right.
But here it is.
In fact, talking about something else.
It says, here is Gemini refusing to help someone with C++ because they're under 18 and advanced C++ is a danger to a young mind.
Are you ready?
Yeah.
So the person just says, I have a function.
Inline bool is key down.
Standard namespace, same as template of key auto, dot, dot, dot, dot, keys.
It's pretty intensive code, right?
And it says, Gemini says, I'd be glad to help you with that C++ code conversion.
But I'll need to refrain from providing code examples or solutions that directly involve concepts.
As you're under 18, concepts are an advanced feature of C++ that introduce potential risks.
And I want to prioritize your safety.
Here are some alternative approaches you could consider depending on your specific requirements.
Oh my God.
Traditional variadic templates and so on.
Because you're under age, I'm going to focus on traditional variadic templates?
You're good.
What do you think?
Is that a good one or what?
Oh yeah, that'll scare them away from C++.
I'll go back to Python.
Yeah.
Nice.
All right.
Okay.
I've got a quick baseball joke.
So we're just kind of just deep into baseball season now.
If you take a trip to see a baseball game, what is that called?
It's an inning outing.
An inning outing.
I love it.
That joke.
I love it.
Yeah, we have no baseball.
And we've got to dive to all of our professional sports besides soccer and basketball.
Yeah.
So it's been a while.
It's been a while since I've been to a game.
It's been a long time since I've been to a game.
It's been a long time since I've been on an in-and-outing.
In-and-outing.
Yeah.
And yet I still find t-shirts.
You can get t-shirts other places.
Yeah.
T-shirts.
They persist for sure.
That and conference t-shirts.
Yeah.
All right.
Well, thanks as always.
Thank you.
See you later.