WEBVTT
00:00:00.020 -->
00:00:04.960Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds.
00:00:05.400 -->
00:00:09.660This is episode 459, recorded November 24th, 2025.
00:00:10.400 -->
00:00:11.240And I am Brian Okken.
00:00:11.480 -->
00:00:12.280And I am Michael Kennedy.
00:00:12.660 -->
00:00:18.960And we want to thank everybody that supports us through the stuff we sell to you guys
00:00:19.260 -->
00:00:23.900and provide services like the courses at Talk Python Training, the Complete pytest course,
00:00:24.960 -->
00:00:26.780our Patreon supporters, of course, we love you.
00:00:26.880 -->
00:00:30.220and also like everybody that buys books and stuff.
00:00:31.600 -->
00:00:33.100Connect with us if you'd like to,
00:00:33.270 -->
00:00:34.680like to send us some topic ideas
00:00:35.000 -->
00:00:36.780or have a comment about what we said on the show.
00:00:37.420 -->
00:00:38.420Feel free to connect with us.
00:00:38.860 -->
00:00:43.459There's a contact us form on pythonbytes.fm,
00:00:45.400 -->
00:00:47.860but you can also reach us on Bluesky or Mastodon
00:00:48.360 -->
00:00:49.620and those links are in the show notes.
00:00:50.000 -->
00:00:51.460If you are listening to us
00:00:51.460 -->
00:00:54.939and occasionally would like to maybe see what we look like
00:00:54.960 -->
00:00:58.220or see the topics that we're putting on the screen,
00:00:58.510 -->
00:01:03.360you can join us on YouTube at pythonbytes.fm/live.
00:01:03.720 -->
00:01:06.920And there you can also subscribe to the show
00:01:07.030 -->
00:01:11.680and also get notified when the upcoming ones are going on.
00:01:12.500 -->
00:01:15.100Usually Monday at, we need to change this,
00:01:15.390 -->
00:01:16.240usually Monday at 11,
00:01:16.640 -->
00:01:18.440but all the older versions are there too.
00:01:18.880 -->
00:01:20.980And if we ever change it for personal reasons,
00:01:20.980 -->
00:01:22.260you can get notified there.
00:01:22.880 -->
00:01:24.800And of course, please sign up for the newsletter.
00:01:24.840 -->
00:01:31.220We love to send you all of the links of the things we talked about in the show are sent to you right to your inbox.
00:01:31.780 -->
00:01:33.040And we don't spam you.
00:01:33.160 -->
00:01:34.500It's just the show notes, really.
00:01:35.220 -->
00:01:36.720What do you got for us up first, Michael?
00:01:36.920 -->
00:01:38.860Actually, we have some pre-topics.
00:01:39.760 -->
00:01:42.180We have a topic zero topic.
00:01:42.420 -->
00:01:43.080How about that?
00:01:43.420 -->
00:01:43.540Yeah.
00:01:43.740 -->
00:01:44.200Topic zero.
00:01:44.440 -->
00:01:45.880So I don't know if people notice.
00:01:46.500 -->
00:01:53.240I mean, if you've read your email or listened to the radio or anything like that, you might know that it is the week of Black Friday.
00:01:53.480 -->
00:01:57.720And I think there's a lot of restraint on our end, Brian, by keeping it to the week.
00:01:57.960 -->
00:02:01.840Like I was getting Black Friday sales in October and this is wrong.
00:02:02.160 -->
00:02:05.060This is disrespecting Halloween amongst other things.
00:02:05.340 -->
00:02:05.580Yeah.
00:02:06.700 -->
00:02:10.479Anyway, Black Friday, I launched the Black Friday sale over at Talk Python.
00:02:10.520 -->
00:02:11.980And this year is different than the last year.
00:02:12.260 -->
00:02:15.380Traditionally, I just sort of done, hey, get the everything bundle, get all the courses
00:02:16.060 -->
00:02:16.840on in forever sort of thing.
00:02:17.280 -->
00:02:19.380But I wanted to do a couple of different deals.
00:02:19.580 -->
00:02:21.900So now there's three options you can pick from.
00:02:21.960 -->
00:02:27.720you can pick i have what's called the ai python bundle so two of our most popular courses agentic
00:02:27.760 -->
00:02:34.300ai programming with python the one that i wrote and that's if you want to use things like water
00:02:34.560 -->
00:02:41.240cursor or junior or whatever to build applications with alongside you and we have llm building blocks
00:02:41.240 -->
00:02:48.559in python by vincent mormonam which is uh basically if i'm going to build something that uses an llm
00:02:48.680 -->
00:02:52.800as an API kind of really cool stuff in both courses they're both really well reviewed and
00:02:53.000 -->
00:02:57.960received you can get that for like half off as a special mini bundle then the whole library thing
00:02:58.060 -->
00:03:02.900is still on you can get it at at super discounts and I'm also offering the talk python in production
00:03:03.080 -->
00:03:08.340book it's doing really well for a while it's been a good while at number one in software engineering
00:03:08.600 -->
00:03:14.960on Amazon which is amazing it's nice it's got pure five star reviews on gumroad at least as of
00:03:14.940 -->
00:03:19.240yesterday. I haven't looked today, but I think that's still true. So really well received.
00:03:19.480 -->
00:03:24.040That's also on sale at a discount. So that's Black Friday at Talk Python. talkpython.fm
00:03:24.240 -->
00:03:31.060slash Black-Friday. Check it out, please. It's, as you said, at the top brain, it's a really
00:03:31.140 -->
00:03:34.280great way to support a show. Make sure that we keep doing what we're doing here on the podcast.
00:03:34.960 -->
00:03:40.320And with that, how about you? Well, I was actually not planning on doing a Black Friday thing,
00:03:40.440 -->
00:03:45.680but I saw your topic in there. So I thought, yeah, why not? I'll do a Black Friday thing too.
00:03:46.280 -->
00:03:51.600So the complete pytest course bundle, I put that on sale. And if you go, so you have to use a coupon
00:03:51.820 -->
00:03:57.820code, the coupon code, if you go to the, if you just say, yeah, I want to get this. If you type
00:03:57.860 -->
00:04:04.759in Black Friday, hit apply, then it's a 20% discount. But yeah, I don't think that looks
00:04:04.780 -->
00:04:10.760big enough um i think i think we'll also do a save 50 so if you do save 50 um and apply that
00:04:11.140 -->
00:04:16.720that's better that's 29 bucks now um so you get half off um 20 off or half off your choice
00:04:18.479 -->
00:04:24.820um so uh doing that it'll be in the show notes uh but i kind of want okay so i was trying to match
00:04:25.100 -->
00:04:29.080michael because he was doing 20 on some of the stuff so i did i did the black friday for 20
00:04:28.980 -->
00:04:39.220But then I read my newsletter from Pragmatic, and Pragmatic is doing a 50% off for Black Friday.
00:04:39.320 -->
00:04:42.980So you can get all Pragmatic books.
00:04:43.320 -->
00:04:45.520If you save 50, you get 50% off.
00:04:45.720 -->
00:04:47.880And that includes Python testing with pytest.
00:04:48.160 -->
00:04:52.160So you can grab the video course or the book or both.
00:04:53.040 -->
00:04:55.440So those are my Black Friday deals.
00:04:55.780 -->
00:04:56.020Awesome.
00:04:56.100 -->
00:05:09.020And yeah, I don't, I mean, I know sometimes it feels overly salesy, but I did not do Black Friday one year and I got a ton of email like, Michael, where's your Black Friday sales? I've been hoping that you would do one. So I know at least a subset of people genuinely look forward to it.
00:05:09.120 -->
00:05:15.980And I personally, if there's something I really want for my learning path, I try to get it whenever I get it.
00:05:16.979 -->
00:05:20.160But there's some things that are like, it depends on your budget.
00:05:20.270 -->
00:05:24.160And there's some things that I don't need to have right away and I'd like to use.
00:05:24.160 -->
00:05:28.120And there's a lot of stuff that I've purchased on Black Friday sales.
00:05:28.420 -->
00:05:35.980And I appreciate that independent retailers and independent people like you and me do the Black Friday thing.
00:05:36.280 -->
00:05:40.980people that the full price is just a smidge out of their price range that's good yeah absolutely
00:05:41.660 -->
00:05:45.360all right let's talk about python stuff i mean that was python stuff but you know other stuff
00:05:45.590 -->
00:05:52.620yeah pure python and i'm talking a language level python okay there's a lot more to python than just
00:05:52.700 -->
00:05:57.900the language i think some people get confused i saw this comment on reddit of all places somebody
00:05:57.950 -->
00:06:02.300said hey what podcast should i listen to to learn python like why would you do that that's stupid
00:06:02.410 -->
00:06:06.240why would you listen to a podcast like just it's a simple language just go here and take the
00:06:06.260 -->
00:06:07.660I was like, a little bit broader.
00:06:07.810 -->
00:06:10.320But today, no, actually, we're talking built-ins.
00:06:10.370 -->
00:06:11.140We're talking runtime.
00:06:13.479 -->
00:06:18.880So PEP 814, this one is a really natural addition now that Python 3.14 came out.
00:06:19.380 -->
00:06:22.480This is add frozen dict as a built-in type.
00:06:22.920 -->
00:06:26.880Comes from Victor Stinner, who does a ton of performance stuff as a core developer.
00:06:27.300 -->
00:06:28.020Thank you for that, Victor.
00:06:28.500 -->
00:06:34.920And the idea is that when you have a frozen type, you get a lot of guarantees that you
00:06:34.860 -->
00:06:40.020can work against that make your life easier, your bugs, et cetera, right? With a regular dictionary,
00:06:40.150 -->
00:06:43.520you might say, oh, I need to return this dictionary to a thing. And you don't do a copy,
00:06:43.640 -->
00:06:47.060you just hand it over. And then somebody changes it. You're like, wait, you aren't supposed to
00:06:47.180 -->
00:06:51.280change it. I'm just trying to give you some data, right? So these frozen types are great for if you
00:06:51.380 -->
00:06:55.480don't want something to change, it's not going to change. Also, in the code that would try to change
00:06:55.490 -->
00:06:58.820it would get an error, right? So you're like, no, you're not supposed to do this. Figure something
00:06:58.910 -->
00:07:02.840else out, right? The intention is sort of conveyed through the exceptions, I guess, of a cause.
00:07:03.560 -->
00:07:07.800But also, it's really good for concurrency, which is the link back to 3.14.
00:07:08.300 -->
00:07:12.880Now that we have true parallelism, we, I don't know how many people are doing this,
00:07:13.060 -->
00:07:17.980but find yourself a re-entered lock and use it in your code if you're writing true parallel code, right?
00:07:18.060 -->
00:07:22.800Because race conditions, deadlocks, well, it starts with race conditions, ends with deadlocks, and hopefully fix.
00:07:23.620 -->
00:07:26.940Anyway, you want to do that, and you've got to lock mutable code.
00:07:26.940 -->
00:07:30.480But if you're reading, two things are reading from the same data structure, and it's not changing,
00:07:30.900 -->
00:07:32.040well, there ain't no problem with that.
00:07:32.180 -->
00:07:35.980You can read with a hundred threads in parallel and they're all going to get the same answers
00:07:36.620 -->
00:07:37.840deterministically, right?
00:07:37.890 -->
00:07:43.680So having frozen dict adds dictionaries in as a type that is basically purely thread safe
00:07:43.790 -->
00:07:45.980if you use a frozen dict instead of a regular one.
00:07:46.180 -->
00:07:46.460Cool, right?
00:07:46.700 -->
00:07:47.240That is cool.
00:07:47.490 -->
00:07:51.200I wonder if this will ripple up into other data types like classes and stuff.
00:07:51.440 -->
00:07:52.740That is a very good question.
00:07:53.000 -->
00:07:54.480So I have an answer for you as well.
00:07:54.860 -->
00:07:55.920So there's some interesting things.
00:07:56.110 -->
00:07:57.660I linked to the discussion, not the PEP.
00:07:57.810 -->
00:08:01.780And there's like a really thoughtful conversation by lots of people that you know from the show.
00:08:01.960 -->
00:08:04.140It's like, well, okay, that's cool.
00:08:04.540 -->
00:08:07.740Can I equate a dictionary with a frozen dict?
00:08:08.120 -->
00:08:13.100Because what you'll see from the PEP is frozen dict actually derives from something that is not a dictionary.
00:08:13.350 -->
00:08:16.740So it's not, if you said, is instance a dictionary frozen dict, it would say no.
00:08:17.400 -->
00:08:20.520I'm not so sure how I feel about that, but that's how it is.
00:08:20.860 -->
00:08:22.760So the question is, well, can you say equal, equal?
00:08:23.560 -->
00:08:25.120And is it ordered and so on?
00:08:25.130 -->
00:08:28.480It is ordered, but is that order dependent and the equals and so on, right?
00:08:28.670 -->
00:08:30.360So there's a lot of stuff coming along.
00:08:30.600 -->
00:08:32.440And here you can go see all the conversation there.
00:08:32.700 -->
00:08:35.520So I also, just like you, Brian, like, well, what else is frozen in Python?
00:08:35.719 -->
00:08:36.860Like, what do we already have?
00:08:37.000 -->
00:08:38.360You know, if we didn't have a frozen dictionary.
00:08:39.200 -->
00:08:43.500So I put together a list of existing frozen types and structures in Python.
00:08:44.300 -->
00:08:45.420Tuple, frozen set.
00:08:45.600 -->
00:08:47.440Frozen set was the motivation for frozen dict.
00:08:47.480 -->
00:08:50.000Like, well, if we got a frozen set, why can't we have a frozen dictionary?
00:08:50.300 -->
00:08:50.700You know what I mean?
00:08:51.200 -->
00:08:53.820String, obviously, bytes, ranges, memory views.
00:08:54.220 -->
00:08:58.140Memory views are interesting to put over like a buffer, but you don't want it to be written to.
00:08:58.540 -->
00:09:05.640but you've also got mapping proxy types you've got a record class in the form of data classes
00:09:05.920 -->
00:09:09.760and then data classes you can say frozen is true so this is as close as you're going to get probably
00:09:09.860 -->
00:09:17.360to what you're asking for right frozen classes you technically could more or less do that if you had
00:09:17.480 -->
00:09:22.260private variables and only read-only properties but that's a lot of work you might as well just
00:09:22.440 -->
00:09:26.240create a frozen data class i don't know but yeah so there's a whole bunch of stuff that i put in
00:09:26.220 -->
00:09:28.080here that people can check out.
00:09:28.120 -->
00:09:31.480I put a little extra data sheet because I'm like, huh,
00:09:31.800 -->
00:09:32.700I also want to know this.
00:09:33.240 -->
00:09:33.640Yeah.
00:09:34.020 -->
00:09:34.860Yeah. All right.
00:09:35.260 -->
00:09:38.080I'm looking forward to Python 3.15 being more frozen.
00:09:38.200 -->
00:09:38.580How about that?
00:09:39.100 -->
00:09:40.040More frozen. Yeah.
00:09:40.340 -->
00:09:41.100More frozen.
00:09:41.360 -->
00:09:42.340Might be faster too.
00:09:42.620 -->
00:09:44.980Yeah. It definitely has a possibility for faster,
00:09:45.300 -->
00:09:46.200safer code more easily.
00:09:46.760 -->
00:09:47.040Yeah.
00:09:47.180 -->
00:09:47.660Document it though.
00:09:48.120 -->
00:09:49.100Yeah, got to document it.
00:09:49.720 -->
00:09:54.880I'm bringing up an interesting topic that this was suggested by John Hagen.
00:09:55.120 -->
00:09:55.420Thanks, John.
00:09:56.640 -->
00:09:57.540Material for MkDocs.
00:09:57.820 -->
00:10:01.320So I use MkDocs and I use Material for MkDocs.
00:10:01.440 -->
00:10:04.460Material for MkDocs is a theme for MkDocs,
00:10:04.460 -->
00:10:07.120but it also adds some cool stuff to it.
00:10:07.270 -->
00:10:09.820So it's like a theme++ or something.
00:10:11.800 -->
00:10:17.080And I use it for both personal projects and for at work
00:10:17.880 -->
00:10:20.140because it's just as easy to work with.
00:10:20.200 -->
00:10:22.020Anyway, there's some news about Material.
00:10:22.360 -->
00:10:26.740So the news that came out is that the team behind it
00:10:26.790 -->
00:10:32.280is putting the Material for MkDocs project in maintenance mode.
00:10:32.720 -->
00:10:38.020So for new updates, I don't know because I didn't really fully read this,
00:10:40.400 -->
00:10:44.700but I'm guessing that they're going to, let's see, changes the issue tracker.
00:10:46.620 -->
00:10:49.160Are they encouraged to open bug reports following?
00:10:49.700 -->
00:10:52.820okay, they'll fix critical bugs and security vulnerabilities.
00:10:53.320 -->
00:10:53.680That's right.
00:10:53.860 -->
00:10:55.160That's a good, that's fair.
00:10:56.200 -->
00:10:58.260Because a lot of people use it, including me.
00:10:58.900 -->
00:10:59.640So I care about that.
00:11:00.020 -->
00:11:02.620But why are they putting it in maintenance mode?
00:11:02.800 -->
00:11:04.820It's because the efforts that they're putting in this,
00:11:04.940 -->
00:11:08.140they're switching over to a new project called Zensical.
00:11:09.600 -->
00:11:10.040Zensical?
00:11:10.380 -->
00:11:11.860Anyway, interesting name.
00:11:12.480 -->
00:11:15.500Modern static site generator built on material for MkDocs team,
00:11:15.780 -->
00:11:17.380built by the material for MkDocs team.
00:11:17.600 -->
00:11:27.380So it's a backwards compatibility, and we're going to link to a post that is actually all the, it's like a four post series talking about the transition because it affects a lot of people.
00:11:27.980 -->
00:11:41.020So they're transforming Material for MkDocs, they're starting Zensical, and they've got a Material for MkDocs insiders program, and they're closing down GitHub discussions on Material for MkDocs.
00:11:41.960 -->
00:11:47.820So it doesn't seem like it's profit-driven
00:11:48.120 -->
00:11:49.700because they were actually making a decent amount
00:11:49.730 -->
00:11:53.240off of GitHub sponsorships for this,
00:11:53.920 -->
00:11:54.960but maybe that's part of it.
00:11:55.180 -->
00:11:57.600But the gist of it is at the top,
00:11:57.740 -->
00:12:00.080they said they want Zensical
00:12:00.340 -->
00:12:03.360to overcome technical limitations of MkDocs.
00:12:03.620 -->
00:12:05.400There's so many people that were using it, though,
00:12:05.580 -->
00:12:07.600and not using any other form of MkDocs,
00:12:07.740 -->
00:12:11.139but in part of this discussion they were talking about
00:12:11.180 -->
00:12:19.960that a lot of the stuff in the forum and a lot of stuff in just GitHub issues were really not their problem.
00:12:20.380 -->
00:12:25.880There were like really issues with MkDocs or issues with some other dependencies that they were using.
00:12:26.010 -->
00:12:28.440So Zensical is going to just wrap up.
00:12:29.080 -->
00:12:33.540It's going to be a replacement for MkDocs and MkDocs, material for MkDocs.
00:12:33.800 -->
00:12:47.080And I think a few of the other plugins that used to work with all of this, they're pulling those in to have a support model so that they can actually support everything that matters to people that use it.
00:12:48.420 -->
00:12:52.100The new website, Zensical.org, is just fun to look at.
00:12:52.680 -->
00:12:54.240There's this cool animation thing.
00:12:56.900 -->
00:12:58.440Yeah, it's really cool.
00:12:58.530 -->
00:13:00.200So for people listening, you got to check it out.
00:13:00.360 -->
00:13:01.120Zensical.org.
00:13:01.380 -->
00:13:08.420It's a black background with this kind of a yellow light laser thing going around in circles.
00:13:09.860 -->
00:13:11.340I don't know what that shape is.
00:13:12.120 -->
00:13:12.600Like a donut.
00:13:15.240 -->
00:13:16.860Thank you, Henry Schreiner.
00:13:17.760 -->
00:13:19.440It's also a...
00:13:20.420 -->
00:13:21.520Henry jumped in the show.
00:13:21.840 -->
00:13:24.500It's also a rust rewrite, and it's five times faster.
00:13:25.000 -->
00:13:25.860So a lot faster.
00:13:26.760 -->
00:13:28.360I'm pretty excited to try that out.
00:13:28.420 -->
00:13:36.020I haven't tried this yet, but since I'm a heavy material for MkDocs user, I'll definitely be checking this out.
00:13:36.800 -->
00:13:44.920So one of the things I was curious about is the whole, like, how does this work for, like, is it going to go away or what's the open source model?
00:13:45.400 -->
00:13:49.760It's still going to be open source and MIT licensed.
00:13:50.400 -->
00:13:52.520And there's a compatibility back.
00:13:52.880 -->
00:13:54.340They're trying to make it backwards compatible.
00:13:54.420 -->
00:13:58.980So when you switch over, you can use your make ducks YAML file just as is.
00:13:59.300 -->
00:14:00.060And hopefully it works.
00:14:00.140 -->
00:14:01.000I haven't tried this yet.
00:14:01.260 -->
00:14:04.000And I, you know, I actually haven't like customized it too much.
00:14:04.120 -->
00:14:05.740So it's probably going to work fine for me.
00:14:06.580 -->
00:14:11.460But I do want to check out this, this compatible backwards compatibility thing to switch it over.
00:14:11.860 -->
00:14:16.740I like some of the cool features that they're, they're trying to build in and faster is great.
00:14:17.860 -->
00:14:22.020The other, the other thing I was, so how are they making money?
00:14:22.160 -->
00:14:24.120is the Zensical Spark model.
00:14:24.620 -->
00:14:25.940So this is going to be,
00:14:26.620 -->
00:14:28.160so what's Zensical Spark?
00:14:29.440 -->
00:14:30.560It's for basically,
00:14:31.260 -->
00:14:33.240actually, I think it's more than this,
00:14:33.280 -->
00:14:36.780but part of it is companies that use it
00:14:37.080 -->
00:14:39.060or groups, teams that use it, even startups.
00:14:39.460 -->
00:14:41.120It's not just for enterprise people,
00:14:41.760 -->
00:14:46.000but groups can go ahead and sign up for this
00:14:46.080 -->
00:14:47.440and have better support model.
00:14:47.760 -->
00:14:50.280So they can prioritize supporting people
00:14:50.460 -->
00:14:52.020that are paying them, which makes sense.
00:14:52.320 -->
00:14:55.280But those fixes will help everybody.
00:14:55.720 -->
00:14:56.120So that's good.
00:14:57.460 -->
00:15:02.180One of the cool things that they're doing also during the transition is material for
00:15:02.260 -->
00:15:08.140MkDocs, one of the ways they made money is they had both an open version that's just
00:15:08.200 -->
00:15:08.760free for everybody.
00:15:09.180 -->
00:15:13.160And then they would release new features to an insiders group.
00:15:13.460 -->
00:15:15.160So you could get new features right away.
00:15:15.620 -->
00:15:19.620And then they would sort of trickle into the general population features.
00:15:19.780 -->
00:15:25.100they're getting um i don't know if there's going to be something similar for the spark thing but
00:15:25.400 -->
00:15:29.740for material for make docs they've just opened up the floodgates anything that was in the insiders
00:15:29.820 -->
00:15:35.120is now part of uh the open source thing so if you want to stick to that you get all the features
00:15:35.640 -->
00:15:43.280so anyway just news for people that use make docs yeah nice i'm i'm optimistic here if their website's
00:15:43.400 -->
00:15:49.040anything to go by no it's i'm optimistic i think it will it's the kind of thing that'll make it
00:15:49.020 -->
00:15:52.560really polished and really nice if they get a decent number of customers.
00:15:52.730 -->
00:15:53.380So good.
00:15:53.660 -->
00:15:59.120And I do like that they're just actually putting the people on the people with their pictures.
00:15:59.470 -->
00:16:01.060She just, these are the people behind it.
00:16:01.270 -->
00:16:07.460It's not something just no faceless people making your money off you.
00:16:07.780 -->
00:16:08.260Exactly.
00:16:08.770 -->
00:16:08.940Cool.
00:16:09.220 -->
00:16:09.600That's right.
00:16:09.980 -->
00:16:10.980Keep Python independent.
00:16:11.110 -->
00:16:11.260Okay.
00:16:11.960 -->
00:16:17.800So I want to talk about something that was sent in to us by Gerber Decken.
00:16:18.340 -->
00:16:21.000And this is sort of the hat trick, if you will, Brian.
00:16:21.400 -->
00:16:26.160Two weeks ago, you talked about pip-dep-tree and UV-pip-tree, right?
00:16:26.520 -->
00:16:29.020And then the last week, you talked about dep-tree.
00:16:29.899 -->
00:16:32.900This time, I want to talk about a couple of things.
00:16:33.000 -->
00:16:34.620I want to talk about uv.
00:16:35.520 -->
00:16:36.740I mean, I got to look at this.
00:16:36.760 -->
00:16:38.980This is a bit of a statement here.
00:16:39.200 -->
00:16:39.960I know it's rough.
00:16:40.560 -->
00:16:42.000Rough, analyze, graph.
00:16:42.500 -->
00:16:47.659And you give it a virtual environment and some place to start or file
00:16:47.700 -->
00:16:52.740or something like that. And it will generate basically an architectural layer diagram.
00:16:53.390 -->
00:16:59.180This portion of your application depends on these other modules, which depend on those modules. And
00:16:59.540 -->
00:17:03.440is there any form of circular weirdness or whatever, right? So if you want to understand
00:17:03.590 -->
00:17:09.180how that works, this is like, it'll give you just a list. So this thing tech, which I'm covering,
00:17:09.250 -->
00:17:14.819he sent in is a Python tool to visualize and enforce dependencies using this architecture.
00:17:14.839 -->
00:17:17.839and it basically takes that output that I described
00:17:18.020 -->
00:17:20.260and then turns it into a UI, okay?
00:17:20.680 -->
00:17:20.880Okay.
00:17:21.199 -->
00:17:25.280So there's a little graph that shows how it works,
00:17:25.329 -->
00:17:27.620but basically you just create a TOML file
00:17:28.060 -->
00:17:30.220and then you run a command and it will scheme your code.
00:17:30.640 -->
00:17:33.440It will generate basically that, more or less, that output.
00:17:33.810 -->
00:17:37.380And then you can upload that, not your code,
00:17:37.640 -->
00:17:40.060just this little TOML file that basically has module names
00:17:40.110 -->
00:17:40.940and nothing else in it,
00:17:41.500 -->
00:17:43.760to this service that will turn that into a graph, okay?
00:17:43.880 -->
00:17:49.940So I did that by creating one for a project that I'm not talking about yet, but I'm working on here.
00:17:50.330 -->
00:17:56.060And you can see we've got this cool little thing and it shows like, how are you, how is it put together?
00:17:56.210 -->
00:17:57.740What pieces depend on what, right?
00:17:57.900 -->
00:17:59.320What depends on services?
00:17:59.450 -->
00:18:02.860And then as you interact with it, you can click on like, I want to see what views depend upon.
00:18:03.100 -->
00:18:03.860Oh, that's a lot.
00:18:04.360 -->
00:18:08.140But if I click on view models, you can see there's a nice layered architecture, right?
00:18:08.280 -->
00:18:15.580view models depend on services infrastructure modules and db models but it doesn't depend on
00:18:15.680 -->
00:18:20.000the stuff above it that depends on it so you don't get these weird cycles and other things and there's
00:18:20.040 -->
00:18:24.820like a little cms component it's used by the views it's used by the services and nothing else so you
00:18:24.880 -->
00:18:29.860can get this like cool little understanding of different parts of your app what do you think
00:18:30.340 -->
00:18:36.299this is cool so this is um maybe because we were talking about pipped up tree before this is not
00:18:36.380 -->
00:18:42.680the third-party stuff is just this is your yeah this is your own code so how does your own code
00:18:42.760 -->
00:18:48.220within itself like a set of sub modules depend upon each other because if you look at this um
00:18:48.540 -->
00:18:53.440you actually look at the code this view model section probably has 30 or 50 classes in it
00:18:53.760 -->
00:18:59.520this infrastructure bit has maybe 20 different things like utilities for web stuff urls and so
00:18:59.520 -->
00:19:04.840on and text parsing and um numeric converting libraries and you know stuff like that this dv
00:19:04.800 -->
00:19:08.700Everything has, I think, five database models and a helper class or something.
00:19:09.180 -->
00:19:10.720But they just show up as these blocks.
00:19:10.880 -->
00:19:13.600So you can kind of get a sense of like, how do these things interact?
00:19:14.180 -->
00:19:17.360The lines are drawn by analyzing all the individual files, I believe,
00:19:17.920 -->
00:19:20.300and seeing which ones point to things from other categories.
00:19:20.900 -->
00:19:22.200Oh, nice. This is cool.
00:19:22.560 -->
00:19:24.940Yeah. So I uploaded this picture.
00:19:25.900 -->
00:19:27.520I shared this. I create these shareable graphs.
00:19:27.620 -->
00:19:29.740So you can actually play with this graph yourself as well.
00:19:30.040 -->
00:19:33.340Yes. And then Christian asks, is this unmaintained?
00:19:33.380 -->
00:19:37.600Yes, I believe TAC has become unmaintained, but you can still run it.
00:19:37.610 -->
00:19:38.540It still looks like it's okay.
00:19:38.820 -->
00:19:39.840So that's a good point.
00:19:39.960 -->
00:19:46.280I did notice after I put this together that somewhere it's got like a, although the GitHub
00:19:46.530 -->
00:19:51.140repo, no, it's not TAC that is at least doesn't have an explicit statement that has gone into
00:19:51.260 -->
00:19:51.880maintenance mode or anything.
00:19:52.640 -->
00:19:56.620But if you look at TAC, it goes to gauge.sh.
00:19:56.640 -->
00:20:06.220And if you go to gauge.sh, this product is changed and it's becoming some AI thing that means nothing to me.
00:20:07.180 -->
00:20:08.160So I don't know.
00:20:08.360 -->
00:20:11.160But I imagine they'll probably keep it running.
00:20:11.500 -->
00:20:13.740And apparently it's also open source.
00:20:14.060 -->
00:20:16.380So you could go and fork it and just run it yourself or whatever.
00:20:16.650 -->
00:20:16.920I don't know.
00:20:17.230 -->
00:20:22.520So there is some component in this whole chain that is, it's the visualization of it, not the parsing.
00:20:22.820 -->
00:20:25.240I think TAC, which does the parsing, still works fine.
00:20:25.340 -->
00:20:26.480but then it uploads the gauge.
00:20:26.570 -->
00:20:28.320And the gauge thing is in question
00:20:28.630 -->
00:20:30.140about whether that will still work.
00:20:30.660 -->
00:20:32.160But, you know, you could always go
00:20:32.210 -->
00:20:33.800and make yourself, you know, fork it.
00:20:34.180 -->
00:20:35.280I mean, how hard would it be to make,
00:20:36.140 -->
00:20:38.500given the file, which I don't have it easy,
00:20:38.560 -->
00:20:39.060I can pull it up,
00:20:39.200 -->
00:20:40.900but given a file that lists these relationships,
00:20:41.420 -->
00:20:42.620how hard is it to graph it, right?
00:20:42.700 -->
00:20:44.420You could AI your way to something
00:20:44.490 -->
00:20:46.340that draws your pictures out of tech
00:20:46.990 -->
00:20:48.600in like an afternoon if you really had to.
00:20:49.400 -->
00:20:51.800This visualization left is an exercise for the reader.
00:20:52.140 -->
00:20:52.460Exactly.
00:20:52.710 -->
00:20:53.799Like you could visualize it
00:20:54.020 -->
00:20:57.020if you knew the right series of prompts, I don't know, or you wanted to write it or something.
00:20:57.340 -->
00:21:00.460No, anyway, that's a good point, Christian. Thank you. Over to you, Brian.
00:21:00.880 -->
00:21:08.400Well, I wanted to talk about upcoming speedups in Python. So there's a couple news articles that
00:21:08.520 -->
00:21:15.280came by that I noticed talking about some efforts to speed up Python in the future. So we're at
00:21:15.460 -->
00:21:22.300Python 3.14 right now. 3.15 is in the works and 3.16 later, right? So one of the things,
00:21:22.400 -->
00:21:30.140This is a post by Ken Jin, a plan for 5% to 10% faster free-threaded JIT by Python 3.16.
00:21:30.560 -->
00:21:36.480And the highlight is 5% faster for 3.15, 10% faster for 3.16.
00:21:37.480 -->
00:21:42.060And some of the names popped out as why I should pay attention to this.
00:21:42.600 -->
00:21:48.100This was brought up during the Python Core Dev Sprint in Cambridge hosted by ARM.
00:21:48.860 -->
00:21:50.160They planned this project.
00:21:50.520 -->
00:22:06.260The planners of the project that were present is Savannah Ostrowski, Mark Shannon, Ken Jen, this person, Diego Russo, and Brent Butcher, accompanied by other CPython core team members as well.
00:22:07.620 -->
00:22:12.060And also, I'm like, well, 5% to 10%, that's not that big of a deal.
00:22:12.400 -->
00:22:15.020It says, you might wonder, 5% seems awfully conservative.
00:22:15.280 -->
00:22:18.520However, note that this figure is a geometric mean.
00:22:18.540 -->
00:22:21.840the number can range from slower to significantly faster.
00:22:22.210 -->
00:22:24.760All numbers are high performance figures.
00:22:26.050 -->
00:22:29.080So I think that means they're optimistically thinking
00:22:29.360 -->
00:22:30.960it's going to be a lot faster.
00:22:32.880 -->
00:22:36.440So it's interesting that the LLM involvement here
00:22:36.560 -->
00:22:37.160is a little interesting.
00:22:37.880 -->
00:22:43.520Plan for 3.15 profiling support via LLVM21.
00:22:43.800 -->
00:22:44.740Oh, not LLVM.
00:22:44.740 -->
00:22:48.340That's probably performance-driven compiler optimization.
00:22:48.400 -->
00:22:50.040stuff. Yeah. Yeah.
00:22:50.350 -->
00:22:51.940Where you profile it and then the
00:22:52.640 -->
00:22:54.260compiler says let me look at the profiler
00:22:54.680 -->
00:22:56.340output and then actually re-optimize
00:22:56.640 -->
00:22:58.340based on how you actually ran. You know, like
00:22:58.350 -->
00:22:59.840that sort of fact. I bet it's something like that.
00:23:00.260 -->
00:23:02.460Yeah, but it's also looking forward to
00:23:03.180 -->
00:23:04.420some support from
00:23:05.280 -->
00:23:06.400LLVM20 and then LLVM21.
00:23:07.780 -->
00:23:08.500So some
00:23:08.950 -->
00:23:10.540of those lower
00:23:10.670 -->
00:23:12.140level parsing improvements
00:23:12.550 -->
00:23:14.240are going to help with the JIT. So
00:23:14.290 -->
00:23:15.980trace recording, better machine code,
00:23:16.360 -->
00:23:18.660Register allocation, top of stack caching,
00:23:19.140 -->
00:23:20.080reference count elimination.
00:23:20.800 -->
00:23:21.660That's an interesting one.
00:23:22.370 -->
00:23:25.380More constant promotion and basic free threading support.
00:23:26.480 -->
00:23:30.180So I'm looking forward to seeing there's some graphs
00:23:30.430 -->
00:23:33.480and some more information that's really above my pay grade.
00:23:35.620 -->
00:23:36.500That just-
00:23:36.500 -->
00:23:37.940Bars and stuff, they must be in things.
00:23:37.940 -->
00:23:39.580We don't know.
00:23:39.580 -->
00:23:41.000Yeah, it looks like,
00:23:41.000 -->
00:23:44.300it's got like those bar graphs with the eyes,
00:23:44.300 -->
00:23:45.240like max admin and stuff.
00:23:45.960 -->
00:23:46.740Oh, wow.
00:23:47.000 -->
00:23:48.540Yeah, so the potential.
00:23:48.940 -->
00:23:49.420Yeah, anyway.
00:23:50.260 -->
00:23:50.620Interesting.
00:23:50.840 -->
00:23:54.220I'm glad that we're getting some JIT speed up.
00:23:54.260 -->
00:23:54.840So this is cool.
00:23:55.360 -->
00:23:58.880Another speed up is, this is from Emma's blog.
00:24:00.540 -->
00:24:04.440I forgot to grab what Emma's last name is, but Emma's blog.
00:24:05.180 -->
00:24:09.920Decompression is up to 30% faster in CPython 3.15.
00:24:11.040 -->
00:24:11.900This is cool.
00:24:12.000 -->
00:24:21.660So, you know, and this is based on the Z standard being added to the standard library.
00:24:22.160 -->
00:24:27.140So really, I didn't really get why we cared about the Z standard before.
00:24:27.390 -->
00:24:30.820But hey, if we can decompress that much faster, that's great.
00:24:31.340 -->
00:24:37.000There's compression and decompression happening all over the place that you don't even really know is going on.
00:24:37.240 -->
00:24:52.920So, you know, I actually ended up for the very first time, I think ever using compression in my Python app for a non, not because I somehow received a zip file or a tarball or something and wanted to process it, but like as a part of operation of the app.
00:24:52.920 -->
00:24:54.760So I'll run this by you, tell me what you think.
00:24:55.340 -->
00:25:06.740So this project that I'm working on that, that shall not be named has to store text and it has to store about 250 K of text per database record for like a certain thing.
00:25:07.040 -->
00:25:08.080But you never search it.
00:25:08.330 -->
00:25:09.280You never index it.
00:25:09.560 -->
00:25:12.300You mean you don't have a database index, like you find it through other
00:25:12.460 -->
00:25:13.700keys and you just want to process it.
00:25:13.700 -->
00:25:17.180And I'm like, well, how long does it take to compress and decompress that?
00:25:17.440 -->
00:25:18.780How much smaller does it get?
00:25:18.990 -->
00:25:23.720So I used XZ, which is also built in a Python and it goes down to about a
00:25:23.900 -->
00:25:24.64010th of the size.
00:25:24.920 -->
00:25:29.900So for caching and database records, it's instead of being 250 K it's like 25 K
00:25:30.300 -->
00:25:32.220and you want to process it as part of a web request.
00:25:32.340 -->
00:25:34.980You're like, yeah, let me just unzip it and send it back to you or whatever.
00:25:35.540 -->
00:25:36.780And yeah, I found it really useful.
00:25:36.880 -->
00:25:40.700So I'm all of a sudden super excited about fast decompression inside the, inside of CPython.
00:25:40.940 -->
00:25:41.320Yeah.
00:25:42.860 -->
00:25:45.080Little, little bits matter if you do the right ones.
00:25:45.620 -->
00:25:46.080So yeah.
00:25:47.300 -->
00:25:51.400And by the way, it's, it's like millisecond level type of time to do that.
00:25:51.600 -->
00:25:54.120So you might think, well, I mean, it's going to make your site slow, right?
00:25:54.360 -->
00:25:57.940You know, but if you can store 10 times as much data without running out of disk space
00:25:57.980 -->
00:26:00.240or cash or whatever, like that also helps a lot, you know?
00:26:00.480 -->
00:26:00.740Yeah.
00:26:00.780 -->
00:26:05.280It helps with your, your, how much you're paying for database services as well.
00:26:05.600 -->
00:26:05.820So yeah.
00:26:06.480 -->
00:26:06.720All right.
00:26:06.880 -->
00:26:09.240Oh, one more thing for Henry on the compression thing.
00:26:10.220 -->
00:26:12.360ZSTD is used by Python build standalone.
00:26:12.510 -->
00:26:14.920So having the ability to handle that without dependencies is great.
00:26:15.240 -->
00:26:16.260And faster next year too.
00:26:16.440 -->
00:26:17.500Yeah, thanks for the background info there.
00:26:17.900 -->
00:26:22.320And, you know, just shout out, like, I'm such a fan of Python build standalone as a way to,
00:26:22.490 -->
00:26:25.820like getting Python on your, a computer, your computer, server, whatever,
00:26:26.100 -->
00:26:29.980is just ridiculous with uv plus Python build standalone now, right?
00:26:30.380 -->
00:26:32.280Seconds, not trouble, right?
00:26:32.380 -->
00:26:34.760You know, uv, make a virtual environment, desperation, Python.
00:26:35.060 -->
00:26:36.600Yeah, it just changed.
00:26:37.000 -->
00:26:39.720It's one of those things that changed everybody's workflow.
00:26:40.820 -->
00:26:45.120And I don't even think about having to install a different version anymore.
00:26:45.410 -->
00:26:46.020It just happens.
00:26:46.610 -->
00:26:47.180And just does.
00:26:47.840 -->
00:26:49.580All right, you got any extras while you got your screen up?
00:26:49.880 -->
00:26:50.200Sure.
00:26:51.210 -->
00:26:55.960The one extra I've got is that the Lean TDD book,
00:26:56.620 -->
00:27:00.500one of the things I'm putting it out while I'm writing it.
00:27:01.030 -->
00:27:02.980This week, I'm doing Thanksgiving prep,
00:27:03.200 -->
00:27:04.860so I'm not going to release a chapter this week.
00:27:04.940 -->
00:27:07.120but there'll probably be one next week.
00:27:08.020 -->
00:27:09.900And that one's on building on lean.
00:27:10.900 -->
00:27:12.720Last one was building on TDD.
00:27:13.820 -->
00:27:15.820What I wanted to talk about though
00:27:15.960 -->
00:27:17.140is I appreciate the issues.
00:27:17.460 -->
00:27:20.620So I decided to just use GitHub repo
00:27:21.120 -->
00:27:22.840as an issue tracker for this.
00:27:23.260 -->
00:27:26.400And I've gotten a couple so far,
00:27:26.640 -->
00:27:28.700not very many, but maybe that's a good thing.
00:27:29.420 -->
00:27:32.400A typo came in and actually it's one that like was,
00:27:32.640 -->
00:27:33.280I was just missing.
00:27:33.330 -->
00:27:34.340I was reading all the time.
00:27:34.440 -->
00:27:35.360And so I appreciate that.
00:27:36.200 -->
00:27:43.000And then one of the ones was, was that I really appreciate is like discussion of extra topics
00:27:43.100 -->
00:27:43.920I should build in.
00:27:43.940 -->
00:27:48.880So I had, one of the things I've done is like release the headings and subheadings
00:27:49.180 -->
00:27:53.400for different chapters and, and, and different parts of the chapter.
00:27:53.820 -->
00:27:58.320And I'm hoping in the hopes of that people will go, oh, you gotta make sure you don't
00:27:58.600 -->
00:27:59.720forget to talk about this.
00:28:00.160 -->
00:28:03.800And that's what I got from looks like Jonah.
00:28:04.600 -->
00:28:06.920I'm not going to try to pronounce that, but I'll say Jonah.
00:28:08.280 -->
00:28:14.000In the chapter on considering considerations for applications for applying Lean TDD,
00:28:14.880 -->
00:28:22.460talked about not just technical considerations, but what we're really doing to social considerations.
00:28:23.220 -->
00:28:24.380And I've faced this too.
00:28:24.540 -->
00:28:26.200I'm like, oh, yeah, I didn't even think about this.
00:28:26.460 -->
00:28:34.400There's a lot of people just meant like just opposed to doing test-driven development or opposed to doing different kinds of tests for various reasons.
00:28:35.100 -->
00:28:38.880And I wasn't planning on talking about that, but I think it's very essential.
00:28:39.140 -->
00:28:41.200I'm glad that I'm getting people's feedback.
00:28:41.780 -->
00:28:42.480Could be the other way.
00:28:42.630 -->
00:28:46.700They only want to do TDD and they want to do integration tests because they're impure.
00:28:47.100 -->
00:28:47.480Yuck.
00:28:47.840 -->
00:28:50.900You know, I mean, there's a whole spectrum of things you probably got to speak to.
00:28:51.240 -->
00:28:51.460Yeah.
00:28:52.360 -->
00:28:52.800Go ahead.
00:28:52.880 -->
00:29:08.960And they even brought up some other things, like we don't have time to test. Testing makes it harder to refactor. Your tests are not compatible with our architecture. I did a release, even though the tests are failing because it's too important to get the code out there. Yeah, these are great things to talk about.
00:29:09.460 -->
00:29:21.900Yeah, for sure. I set up a issue tracker discussion board for the Talk Python in production book too. And it's been pretty active. I really appreciate it. There's a couple of things I could respond to. So if you're waiting on me, I'm forgotten, I'm forgotten.
00:29:21.960 -->
00:29:28.120And I told you that this was a follow-up to the dependency thing, but here's another.
00:29:28.190 -->
00:29:29.320This one's by Bob Belderbus.
00:29:29.330 -->
00:29:32.640I didn't think it was big enough to make its own thing, but check this out.
00:29:32.960 -->
00:29:37.780Bob says, I need to see which packages were pulling in a certain dependency instead of
00:29:38.320 -->
00:29:39.820what packages depend.
00:29:40.140 -->
00:29:45.400So you can actually go and do uv tree and give it a package and say --invert
00:29:45.910 -->
00:29:47.340to answer who depends upon this.
00:29:47.450 -->
00:29:48.220And look at this picture.
00:29:48.560 -->
00:29:49.560I see that's not really helpful.
00:29:50.040 -->
00:29:57.220But you look at it and it actually says six was pulled in by bleach, which was pulled in by Jenga bleach, which was pulled in PyBytes platform.
00:29:57.860 -->
00:29:59.120Also six pulled in Python.
00:29:59.620 -->
00:30:00.780DateUtil, why is that even there?
00:30:00.900 -->
00:30:03.740So it's like a reverse of your depth tree.
00:30:04.480 -->
00:30:10.420So you can focus it on a node and basically filter and restrict it just to the stuff that works with that leaf node, I guess.
00:30:10.740 -->
00:30:11.380So you'd look at it.
00:30:11.640 -->
00:30:11.780Yeah.
00:30:11.900 -->
00:30:16.360So if you're thinking about cleaning up your dependencies and say, well, I don't want to pull in six anymore.
00:30:16.540 -->
00:30:21.040it might not matter because a bunch of your dependencies are already pulling it in.
00:30:21.370 -->
00:30:21.900Right, exactly.
00:30:22.150 -->
00:30:25.520And so you could also ask the question like, well, do I really need that dependency?
00:30:26.260 -->
00:30:26.380Yeah.
00:30:26.640 -->
00:30:29.060Or could I find something else that would allow me to get rid of this thing,
00:30:29.420 -->
00:30:31.780this lower level dependency that's causing a problem?
00:30:32.060 -->
00:30:33.840You know, that's often a question to try and answer.
00:30:34.180 -->
00:30:34.380All right.
00:30:35.000 -->
00:30:37.380Well, that is it for...
00:30:37.380 -->
00:30:42.580Well, now I want an extra feature that says, hey, uv, can you tell me which packages
00:30:43.180 -->
00:30:45.860don't have any transitive, aren't transitive dependencies?
00:30:46.440 -->
00:30:54.020Hmm. Yeah. cool. So, okay. Let's talk a joke. So do you remember Brian last week,
00:30:54.260 -->
00:30:59.360it was like so many things went down. And one of the things that we had, we had AWS go down
00:30:59.960 -->
00:31:04.280two weeks ago and take out a huge chunk of the internet, I think for 14 hours because of DNS,
00:31:04.720 -->
00:31:08.240because of course it was, it was DNS to the database, which was the foundation of all the
00:31:08.260 -->
00:31:13.300other things. And then we had Azure go down in the beginning of the last week. And then was it Friday,
00:31:13.600 -->
00:31:19.240Thursday I don't know GitHub itself went down not the web page but all the git based operations
00:31:19.290 -->
00:31:25.800like git pull git push etc that talked to GitHub over the git CLI and other tools was failing for
00:31:25.940 -->
00:31:32.440hours and so my question or my question my joke is which is a question can GitHub even push fixes
00:31:32.530 -->
00:31:38.360to GitHub when GitHub is down like what do they do how do you fix GitHub if git is surely and I'm
00:31:38.320 -->
00:31:43.780oh my gosh surely there's a lot of ways that you deploy code within GitHub by doing some kind of
00:31:43.940 -->
00:31:48.780git pull or git push with a webhook or something like that might have been a huge portion of the
00:31:48.840 -->
00:31:56.160problem yeah yeah the fix was probably instantaneously known but you can't roll back
00:31:56.660 -->
00:32:02.080or you know get rollbacks can't do that um exactly they're like how who is going to log in here and
00:32:01.920 -->
00:32:08.380fix this i cannot fix this oh no i'm curious how they did it then i mean this is this funny but
00:32:08.540 -->
00:32:14.640also it probably was an issue exactly so i thought we might have a um an educational joke this week
00:32:14.800 -->
00:32:20.960can GitHub even push to GitHub when GitHub is down this looks like uh um who is the guy in the
00:32:21.040 -->
00:32:26.880matrix neo who's that actor keanu reeves yeah this looks like a young keanu reeves i'm not sure who
00:32:26.720 -->
00:32:33.700this actually is but from like bill and ted days yeah exactly whoa man how'd they even fix it
00:32:34.120 -->
00:32:38.420anyway i don't know how they fixed it but when it came back i was very excited that it was back
00:32:38.660 -->
00:32:45.380awesome all right well uh fun episode and i hope everybody everybody in the u.s or anybody that
00:32:45.580 -->
00:32:50.260celebrates turkey day outside of the u.s i hope you have a wonderful exgiving and um and everybody
00:32:50.400 -->
00:32:53.979else hope you have a great week also yeah thanks to you next week bye everyone bye