Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds.
This is episode 412, recorded Monday, December 2nd, 2024.
I am Michael Kennedy.
And I am Brian Okken.
This episode is brought to you by us, especially our Black Friday things.
Visit our website for the Black Friday things.
You have 14 hours, so make haste.
Make haste. Hopefully you listen straight away.
And if not, thanks for supporting our work and check out our courses and things like that.
Links are in the show notes.
You can also get the summary of every episode delivered directly to you.
Handcrafted, artisanal newsletter by Brian Okken here.
So check that out.
And we mentioned this last time, but we are now Blue Skyians.
We now live in the sky, the blue sky.
In particular, Python Bytes is over there with the handle Python, you know, at pythonbytes.fm.
And both Brian and I are linked directly from there.
So come follow us.
I have a little extra, extra, extra to follow up on Blue Sky and Mastodon and Twitter, X Twitter, whatever.
All of these things.
So I think you will find that interesting.
But right now, I would like to know, Brian, what you find interesting.
I find interesting that there's a controversy over loop targets.
This is so inside baseball, I think.
But okay.
So Ned Batchelder wrote a blog post and apparently a social media post on Blue Sky, actually.
But about what loop targets are.
So what I'm talking about is a for loop.
So if you say for, like for X in range 10 or something like that, then X gets assigned 10, like 0 through 9, right?
So what's the controversy?
The controversy is what you should put in for X.
So in his little code example, he's got for param, he's got a parameter dictionary.
And there's a query and a page size.
There's no page element, but we're going to fill that in later.
So what he's doing is he has coded for params, quote, page in iter tools count.
And what that's going to do is it's just going to go through and get 100 things at a time and put them in a page dictionary until it's empty.
And there's a break to get out of the loop once there are no results left.
I think this is kind of clever and I don't see the problem here.
So the problem is this kind of this params, this index into the dictionary.
And that's where you're putting the loop parameters.
Yeah, this is wild because I've seen exploding or expanding tuples into multiple things like for thing in dictionary, the items,
it's a maybe key comma value in the loop target.
And that's perfectly normal.
But assigning a key in the dictionary, this is new to me.
Really?
OK.
Yeah.
I'm not necessarily I'm neutral on it, whether or not it should be done, but I'm just learning about it now.
OK.
So in the discussion, so really what's happening is there's in the discussion, he talks about it, that you could have like an extra variable.
You could say page num.
So for page num in iter tools count, it makes it more clear.
And then you assign the page num to the, you assign that to the dictionary.
But really, you're just using this page num just as a temporary variable just to stuff it in there.
So I say, why not just put just to just assign it where you're going to use it.
And because this extra line of code, I don't know, I'm kind of on the fence because this is more clear.
I think it's more clear to use a temporary variable.
It's more readable.
However, there's an extra line of code.
So it is like that much more.
It's not that much more readable, I don't think.
And it's not.
And there's that.
If this in this short code snippet, not a big deal.
But in a larger for loop, you may have more reason to possibly have something break because somebody like, you know, commented that line out or something and it suddenly doesn't work.
So anyway, I'm like, this is weird.
This is controversy.
But even so he wrote this up just to talk about it and ask what people think.
And most of the responses are like, no.
Or one, I think it's a cool idea.
And I think it's a terrible idea.
Anyway, I guess I'm bringing this up because I just want to point out that with for loops, there's an implicit assignment.
And so you can use that assignment to assign to wherever you want to use the variable.
So I'm going to make an observation here.
You tell me what you think.
I believe the people who are for this are also fans of the walrus operator.
And people who are against this are anti-walrus.
Oh, that might be true.
Right.
It's kind of the same thing.
It's in a for loop, you're assigning to a variable and kind of sort of defining and assigning in a sense.
Whereas, you know, the walrus operator does it for if statements.
But it's like not assign the variable, then test it.
It's like all at once do the assign and test or assign and loop.
But there is already an assign in the for loop.
It's always assignment.
But is it colon equals?
No, I'm just kidding.
Is it colon in?
Yeah.
No, it's interesting.
It does.
Yeah.
It's for loop, the original walrus operator.
All right.
I'm actually going to come back to loops, but not yet.
I want to talk about the standard library.
No, no.
Not the one that you know.
Not the one that comes with CPython.
The async standard library.
It's the missing toolbox for an async world.
Did you know we're living in an async world?
I feel like a little Madonna is rocking in my back.
Is that Madonna?
I don't know.
Yeah.
So one of the problems is if you go and look at many of the things that you know and love,
say, iter tools or functools, those things have not been kind of blowing my mind because
they could be, have not been updated to support async.
Okay.
So when you do like functools, you know, say a decorator at functools.lrucache, that is
perfect for a synchronous function.
It doesn't work for an async one.
And why do I think that it should work for it?
Because just a couple of weeks ago, I covered my chameleon flask decorator for templates.
And I, in a hundred lines of code, I wrote something that decorates and operates on both
sync and async functions.
So surely the people who create async.io could probably like write a multi-operator decorator
deal, but they don't.
And I have no idea if there's any intention ever for them to do so.
So what this is, is it's kind of like a clone of those things.
Not totally.
It also has some other nice features, but it's like an async version of those.
So if you have an async function, you want to apply an LRU cache to it.
Well, go grab this bad boy.
So it's got a bunch of built-ins for things like asynchronous zip sum, or even converting
the list.
It has functools that supports things like I talked about LRU cache.
And if you look at it, it's looks a whole lot like you would imagine.
It has a max size.
It has typed and so on, but it operates on a waitable.
And it returns an LRU async callable, something you can await like you should the function,
rather than just a coroutine that is, I don't know, where you cache the coroutine.
I don't know.
It doesn't make a lot of sense.
So this is what this is about.
It's got a bunch of things like that.
It has the built-ins.
It's got a functools libraries for iterators, async caches, attributes, the context lib and
async context lib.
So I can do things like add async decorator in context that derives from a context decorator.
And you can basically a short circuit, the implementation, a simple implementation of a
enter and a exit.
So on.
It has a heap queue, which implements Python's heap queue, but for async, which is pretty cool.
So you want to merge and stuff.
And then it has some extra tools.
And I don't really, I haven't done enough with this to know whether this is useful, how I
would use it.
So stick with it.
Anyway, it has things like borrow, where you can borrow an async iterator to prevent it from
closing.
Okay.
I don't know about that.
You got scoped ones, but this one is really nice.
I've written this code before and it's not easy to get completely right.
It has a thing that you can just call async standard lib dot sync, giving it a async function
and it'll just, sorry, the way around, given async function, it will turn it into an async
function that you can await if you need to.
Or, yeah, or you can give it an async one as well.
And it doesn't really care.
I think it adapts.
But so a bunch of stuff going on here.
If you're like, ah, there's a bunch of these cool built-ins that I'm used to and they don't
work with async.
Well, check out the async standard lib.
Very cool.
I think it seems like we have a typed Python and non-typed Python.
And now we have async Python and synchronous Python.
And then we're going to have free-threaded and non-free-threaded.
We're going to have typed async free-threaded Python.
Yeah.
And every other combinatorial possibility there.
It's going to be nuts.
Yeah.
But I think this is a cool one.
It's not super popular.
Let me go back to it and see what its GitHub stars are.
But it's kind of one of those things that's like, yeah, this is definitely worth it.
I don't know.
So it has some.
Oh, here we go.
No, don't say.
240.
So it's starting to pick up some speed.
But I think it's real simple.
It's like the kind of thing that's either going to work or not work.
So if it's useful for you, go for it.
Nice.
Yeah.
It's cool.
I was going to talk about.
I haven't had breakfast yet.
So I was going to talk about some.
Maybe getting a bagel.
You want a bagel?
Okay.
Yeah.
I love bagels.
As long as it got everything, we're good.
Everything bagel.
Let's go.
Well, I am taking a look at a project called Enhanced Jack.
It's called Bagels from Enhanced Jack.
Who's Enhanced Jack's?
It's Jack's Tam.
Cool.
Aspiring student studying.
Oh, no.
University student.
Cool.
Anyway, why am I bringing up bagels?
Well, bagels is kind of a fun little expense tracker.
But I think it's a great example of using Textual for something that, you know, people probably
could sink their teeth into pretty easy.
So it's an expense tracker with multiple accounts using Textual.
I've tried it out.
It's really pretty easy.
There's a bunch of stuff I like about this.
And I'm bringing it up.
Not really because I think everybody needs an expense tracker.
But I think a lot of people look for a starter, like a starter project to possibly tweak and make
their own.
And I think this might be kind of a fun thing for people to look at.
A few things about it.
I like it that it's in the command line.
It's a textual app.
But it's also the install instructions.
I love seeing this.
It's starting to use the uv tool install so that you can just run bagels from anywhere.
It's the way.
This is the way.
And it's so fast to get started.
I also like that the project is pretty new.
But it's just a few weeks started.
But there's already some features included.
Features included is great.
And then also how to development setup is listed.
And it doesn't talk about how to run tests.
But that's all right.
It's running pytest, of course.
But then a roadmap of sort of things that they'd like to add to it.
It's heavily inspired by posting.
So anyway, just a fun little project.
The tests are in place.
It's not a complete coverage yet.
But it's a new project.
So if you want to help out, I think it's a good thing for people to check out.
Also, I've always wanted to write my own little expense tracker.
And so this is a good start for even if it doesn't do everything I wanted to do,
to take up the code base and maybe play with it, learn some stuff.
It's also, it's written, it's using, I can't remember.
It was using a PostgreSQL, like a SQLAlchemy.
Also, if you want to have a simple, small project that uses SQLAlchemy to learn that,
be a good one to take a look at.
Awesome.
Yeah, that's really cool.
And we've covered Postling?
What was it called?
You covered it.
The Posting.
Yeah.
A little app that was written in.
Posting, what was that?
Remember?
That was the Postman alternative for the terminal written in textual, which is cool.
Yeah, which is like a dream to work with.
It's a fun one.
Yeah, very nice.
I want to, since you brought this up, I'll throw this out here.
Not super necessarily relevant.
But I recently ran across maybe.co.
Okay.
It's almost a company, but it lost the M along the way.
Anyway, it's a fully open source OS for your personal finances running on Docker.
If you want to do self-hosting, keep all of your data private instead of like sending off
to Intuit or somewhere that it probably doesn't belong.
So anyway, people can check that out.
That's kind of cool.
Cool.
Not an endorsement.
Haven't used it, but kind of thinking about it.
I would rather bring it full circle.
We began with loops.
Let us end with loops.
Isn't that perfect for a full circle?
They go in circles, don't they?
Yeah.
So this is the early days sort of thing, but Giovanni, who is the creator of the Emmet framework
and more relevant to us, the Grannion AsyncSync Rust-based web server that powers Python bytes
and other things that we have, is creating this thing that is an alternative to uv loop.
So uv loop is a, I think it's based on LibUV.
I can't remember exactly the origins of it, but it's a loop that you can plug in as an alternative
for the AsyncIO event loop implementation.
Okay.
So why would you do that?
Well, it turns out that you can optimize some of the juggling of the little tasks.
So if you have like three tasks, one is call the website, one is talk to the database,
one is write a file or whatever, don't do anything.
The built-in one's fine.
But if you have a million tasks and you're breaking them into little tiny pieces and they're jumping
all over, like that juggling could be faster with uv loop.
And I think that's where we're going to see it go with our loop.
So our loop is an Async event loop implemented in Rust and it's coming along.
It is a work in progress and not ready.
But the reason I bring it up early in its life here is it's a really cool option.
We've seen how significant the improvements for other Rust things like Pydantic and uv have
been.
And so if you're passionate about this and you want to have maybe a little influence
before it gets fully baked as this thing's coming to life, you know, jump in.
The way you use it is just like uv.
It's super easy.
Just before you do Async things, you just say AsyncIO.setEventLoopPolicy, which is a factory,
I'm thinking.
Kind of a factory method more.
I don't know, whatever.
And you just give it Rloop.EventLoopPolicy.
And that means anytime code creates a new event loop, it's going to be using the factory
method from Rloop rather than the built-in one.
Off you go.
Cool.
Yeah.
Well, cool.
Well, that's it for our items, right?
I think so.
Yeah.
I think it is.
Extras?
What do you think?
Extras?
Yeah, I have a few.
You want me to jump in?
Jump in.
I am, I've had a lot of stuff going on in personal life lately and trying to fit everything into
my life is sometimes difficult.
So I've been reading, reading, reading in quotes, listening to the audio book for 4,000
weeks, a time management, time management for mortals.
It's a book by Oliver Berkman.
And I'm listening to it for the second time now in the last couple of weeks.
I just picked it up a week or so ago, but I'm really enjoying it.
And it's more of a, you can't get everything done, but that's okay.
Just how to be okay with the limitations of life.
So very refreshing time management book.
It's also got some practical advice too, but it's great.
So highly, highly recommend that.
It's advent of, advent of code time.
And I've heard of the, so I've definitely heard of the advent of code, but the advent of
code.com.
Very cool.
A lot of people do that every year for in December to do little code snippets every year.
But today I came across Adrian Roselli's development advent calendars for 2024.
So if advent of code isn't quite what up your alley, there's a whole bunch here.
There's HTML hell advent calendar.
There's a whole bunch of code and code-based advent calendars here.
So none of them Python specific.
There's a Perl specific, but C# advent of cyber.
Just quite a, quite a few fun, different calendars.
CSS.
If you wanted to learn CSS, maybe there's just CSS.
The Joomla advent calendar.
You too can host it.
So yeah.
And apparently it's gone, it's gone back.
He's got links back to 2010.
So it's fun.
Wow.
Yeah.
If you get your homework done early, you can do more advent of calendars.
Yeah.
I don't, so I tried, I tried advent of code a couple of years ago.
And then I just realized that like in my free time, I've, I'm doing so much code coding at
work, side hustles and everything that I kind of want to do things like draw and paint and
cook and things like that when, when I'm doing other stuff.
So anyway, I hear you.
I'm the same.
I already do a lot of programming.
Even in my spare time, I do more programming.
Yeah.
And so I don't need extra ones, but I know it helps people, especially people are trying
to learn a topic.
It can kind of force you if you don't have a way to apply it.
And today is December 2nd, Monday, traditionally a cyber Monday.
And it is the last day for the black Friday sale, turkey sale for the python test.com courses,
however.
And so I'll take, I'll take off the automatic.
But if you, if you hit me, if you're listening to this later, you know, close in it, close
ish to December 2nd, direct message me on, on blue sky and I'll hook you up.
So anyway, that's it.
Blue sky.
That's a good transition.
All right.
Also black Friday at talk python.
So talkpython.fm/ black Friday, 20 to 50% off the course library.
Nice logo there.
The image is great.
Thanks.
That's pure CSS, by the way.
That's some mad glow in CSS.
Yeah, it's cool.
Yeah.
Awesome.
All right.
So we'd talk blue sky.
So I just, you know, last week when I finished producing the show and I published it onto the
internet, typically go to the social networks and I'll do a quick post.
Hey, new episodes out.
Enjoy it.
If you want it.
This one had a little guitar solo at the end, which was super fun.
And so it said latest episode out for 11 TLS client.
Hello.
Guitar solo was the name.
And I published that and I published it at the same time with the same text to X,
Fostadon, Mastadon and blue sky.
And I just thought, huh, I wonder what the engagement looks like, because I don't know how you've been
feeling, Brian, but I feel like people, I tried and tried to get folks to go to Mastadon
and like some, some people came, came along, but a bunch just didn't, you know, they were
just, you would go back to X and you would just see them all talking there.
I'm like, man, I don't know.
And I'm not necessarily super against X.
I'm a little bit against it, but I'm not a lot, but it's just, it's become not very practical
as you'll see in just a second.
Not very useful.
So, you know, you want to go talk to yourself in a closet.
It's awesome.
You want to talk to other people?
Well, that's so.
Anyway, so my, my test here, this is a non-scientific test that I put out there.
What is the interaction level per platform?
And what you have to keep in mind before I tell you guys this, there's a dramatic difference
in number of followers, subscribers, whatever they're called at that particular location.
Okay.
So basically take the numbers, divide by the number of followers and consider that like
the amount of interaction.
The reason I tell you this is you may want to come follow us and join us on blue sky, but
that's, that's a bit of a get in the head.
So check this out.
So over on X, we have 27,000 followers.
Okay.
Posting this exact message one week ago, we got eight likes and two retweets, reposts,
boost, name it, whatever.
Yeah.
So I don't know what that is.
Two divided by 27,000, but it's a small percentage.
Okay.
Fostadon, Mastodon, right?
It's not Fostadon, Mastodon, because it's across all, all the Fediverse.
Same posts, identical.
Here we have 3,000.
Let me see.
3,100 followers.
Okay.
So yeah, that's great.
But this is almost nine times less.
Something like that, right?
It's many, many less times, but four boosts, which is not out of control, honestly, but
it's in two favorites, two likes.
But as a ratio, it's still a lot more because multiply by nine, right?
Yeah.
Blue sky, which we've been there a couple of days.
We have something like that.
We only have a, somebody hover, different hover targets, 750 followers.
Yeah.
Follow us on blue sky.
Get over there.
Yeah.
Anyway, we have 16 likes and two reposts and a quote posts and then some conversation
about it.
And that's 30 times less followers and more engagement than both platforms.
So anyway, I, y'all take that for what it is.
I just thought that was an interesting experiment.
What do you think, Brian?
Yeah, I'm finding, I'm finding blue sky more interactive.
I've got about this approximate same numbers on a fostered on or mastodon and, and blue sky
and, and I'll, I'll get like twice as much interaction on, I mean, approximate gut feel twice as
much interaction on blue skies.
I do on, on mastodon.
Yeah.
And I'm not saying this to bag on some social network or try to promote other too much.
I was like, people are trying to find their community.
I think right now this is where the community is.
And if you go here, you can go to my account and go to the starter pack and there's the
Python personalities and you can follow a bunch of us.
The onboarding experience is way better.
The, the onboarding experience for mastodon still feels like it's too many decisions right
at once.
And then it's like, if you wanted to play games on Linux, you probably could.
Yeah.
And I'm a, by the way, I'm, I'm no longer on X.
So don't notify me there.
Yeah.
Sounds good.
All right.
A couple of other real quick things on episode 277, I believe.
I don't have my show notes up, but I'm pretty sure that was the number.
Way back when I talked about certain string enumeration, which is a thing that basically
backports the string enum from Python 3.11.
So it can be used in other places.
It's super cool.
It's even better than the built-in one, by the way.
So I can have, I can say, give me a string enum and derive a class from that.
That becomes an enumeration where you say that thing dot, but then you have the fields and
just say equals auto, auto, auto, auto.
And it'll actually set it to the text of whatever the variable is.
If you refactor, rename it, it will apply that refactoring to the string version and the variable
version of it.
And you can even do things like use a lowercase or an uppercase one as the base class, a lowercase
string enum.
And that will make the string version lowercase.
Even if you have a different, a different representation for the variable names.
Anyway, the re why did I do this?
Because on my list monk little client, somebody came and said, why doesn't this work on anything
less than 3.11?
I'm like, because it uses string enum from 3.11.
So I'm like, you know what?
I'll just, I'll just derive from the other class.
Add that as a dependency.
I already had dependencies.
That's one more small one.
And guess what?
Now it supports older versions of Python.
I stopped it at 3.10 because I want nice type-ins.
I don't want ugly type-ins.
You're nicer than me, man.
I'm like, it doesn't support it.
It doesn't, because I don't want to support it.
Yeah.
But then I was curious, like, well, why doesn't it?
And I remember we talked about this thing.
And if I literally just change a base class and don't do anything else, that was pretty
low effort.
So, you know, it took like five minutes, right?
All right.
Yeah.
So anyway.
All right.
That's it for my extras.
Shall we close it out with a joke?
Yeah.
Let's do something funny.
Man.
I know we were just talking, we just experienced a food holiday in the United States last week
with Thanksgiving and all.
And I hope everyone's was good.
If you celebrate it.
However, sometimes there's a lot of food prep and it can be, it can be hard, right?
It can be hard.
Like you're shopping, you're chopping all of these things.
So here is a programmer or just a computer user really who has a grocery list.
And the grocery list says eggs, corn, tomatoes, onions, rice, milk.
They decide they don't want the onions.
So they highlight it and they hit control X and a tear forms in their eye because of course
it does when you cut onions.
That's really funny.
It's pretty good, right?
I mean, yeah, it's good.
I don't know why.
It's cheesy.
It's a little cheesy.
A little cheesy.
Yeah.
I'll do one more for us.
That's straight out of the comments because Cohen did a pretty good one.
When we were talking about the loop targets, it says, how about this?
We're putting two controversial ideas together.
Sum of sum of numbers plus X for numbers of zero in numbers.
If X colon equal numbers squared is such and such.
Like, oh my goodness.
This is a lot of stuff going.
I said, here's a job interview for you.
Job interview question.
If you answer with a straight face, you fail.
No, it's good.
Yeah.
If you think that's all right.
Nope.
You're out.
I don't know.
Not seriously, but as a joke, it's pretty good.
Yeah.
Job interview stuff.
Job interviews are tough.
I know a lot of people are going through that now.
Yeah.
Well, you know, the control X part and also the job interview might bring a tear to the
heights.
I don't know.
I haven't, I haven't applied for a job in, well, since the nineties, however, which is
insane.
That is insane, man.
It's actually insane.
Um, but because all my job transitions have been like, Hey, you'd be awesome.
Like, why don't you consider working for, it was more of the other way around, you know,
which is pretty fortunate, but it sounds like your resume has like, like a lawn mowing
on it still or something.
Exactly.
I work for companies.
They just reached out to me and said, would you consider working for us?
I know, but you probably didn't have to, you haven't probably had to update your resume
for a long time.
Yeah.
My LinkedIn is like, I'm, I've had some experience at a pizza place and I've done lawn mowing.
So that was good.
No, but I do.
I was just going to say, I think it's probably pretty brutal.
You've got to, you know, pass the AI gauntlets and all sorts of weird business and take home
quizzes.
And I can see why there would be tears.
But not for this in the show.
Thank you everyone for coming.
Thank you, Brian.
See y'all later.