WEBVTT

00:00:00.040 --> 00:00:04.880
Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to

00:00:04.920 --> 00:00:13.380
your earbuds. This is episode 444, recorded August 11th, 2025. I am Michael Kennedy.

00:00:13.680 --> 00:00:14.480
And I'm Brian Okken.

00:00:14.760 --> 00:00:21.460
And this episode is brought to you by DigitalOcean and their generative AI features and tools,

00:00:22.080 --> 00:00:26.000
and DigitalOcean more generally, but specifically by their gen AI tools,

00:00:26.140 --> 00:00:28.460
which we're going to talk about. Brian's going to tell you about them.

00:00:28.760 --> 00:00:38.740
So check that out at pythonbytes.fm/digitalocean-gen-ai and use the code DO4bytes, all caps, and get a $200 credit.

00:00:38.960 --> 00:00:43.440
So if you're looking to try out Digital Ocean, you might as well use our code and get plenty of credits.

00:00:43.900 --> 00:00:48.980
Also connect with us on the socials, Mastodon, Bluesky, YouTube, all of those things.

00:00:49.100 --> 00:00:51.040
Links are in the show notes at the top.

00:00:51.380 --> 00:00:58.420
And I highly recommend that you subscribe to our newsletter, which Brian sends out a really nice email pretty soon after the show.

00:00:58.840 --> 00:01:03.180
is out. Diving further into the stuff that we talked about, maybe some additional resources

00:01:03.380 --> 00:01:07.560
and links and insights and tools and all that. It's not just a email version of the show notes.

00:01:07.680 --> 00:01:11.340
It's really cool. I enjoy getting it as well. Thanks, Ryan. I enjoy putting it together.

00:01:11.710 --> 00:01:17.900
I enjoy hearing about whatever you've got to cover first. So let's, yeah, let's jump in there.

00:01:18.300 --> 00:01:23.180
Speaking of coverage, let's talk about coverage. Ned Batchelder released,

00:01:24.660 --> 00:01:27.580
I guess this was in July, but just recently,

00:01:27.900 --> 00:01:32.400
a blog post called coverage.py regex pragmas.

00:01:32.940 --> 00:01:34.480
So that seems like a mouthful.

00:01:35.940 --> 00:01:38.640
And probably, please don't run away because this is powerful.

00:01:39.360 --> 00:01:43.500
I know that pragmas and regex isn't everybody's favorite topic.

00:01:43.680 --> 00:01:46.080
I'm feeling like C++ is back again.

00:01:47.860 --> 00:01:48.760
So what does pragma mean?

00:01:49.020 --> 00:01:50.820
It's the pound thing.

00:01:50.880 --> 00:02:03.780
So let's say if you say like pragma exclude or something like that to say or no cov to say, hey, for coverage for this particular line of code, don't worry about measuring the coverage on that.

00:02:04.760 --> 00:02:11.260
However, so this is a great article and I did not realize I've been using coverage for years and I did not realize it was this powerful.

00:02:11.660 --> 00:02:16.180
So, coverage uses regexes to define pragma syntax.

00:02:16.500 --> 00:02:22.440
And you don't really have to care about it if you just want to just for each individual thing you want to pop in.

00:02:22.680 --> 00:02:27.760
And there is a way to say particular files, just ignore the whole file.

00:02:28.060 --> 00:02:29.640
However, this is pretty cool.

00:02:29.740 --> 00:02:30.720
So, what is he talking about?

00:02:30.920 --> 00:02:37.600
He's talking about a couple things around it that allow you can extend it using regular expressions.

00:02:38.160 --> 00:02:40.380
And you don't necessarily have to figure this out.

00:02:40.480 --> 00:02:45.820
other people have figured it out for you. For instance, there are plugins for coverage that do

00:02:46.030 --> 00:02:53.340
a lot of this. So there's cov defaults. And this one's brought to us by, oh, Anthony Satili. Cool.

00:02:54.300 --> 00:03:00.920
So Anthony has cov defaults. And so there's a whole bunch of defaults already in there to do

00:03:01.100 --> 00:03:07.160
things like exclude your dundermain.py file. Because if you're distributing a package,

00:03:07.360 --> 00:03:09.100
that might be just so you can test things.

00:03:09.700 --> 00:03:10.800
You're probably not going,

00:03:11.080 --> 00:03:13.180
it's okay if coverage doesn't hit it.

00:03:13.680 --> 00:03:14.740
A lot of stuff like that.

00:03:14.820 --> 00:03:16.520
And then a whole bunch of regular expressions

00:03:16.880 --> 00:03:18.220
for things like type relating,

00:03:19.040 --> 00:03:21.080
typing relating code and excluding that.

00:03:21.300 --> 00:03:21.780
That's pretty cool.

00:03:21.800 --> 00:03:22.660
I didn't know that was there.

00:03:22.820 --> 00:03:23.020
That's neat.

00:03:23.520 --> 00:03:26.240
Another one is coverage conditional plugin,

00:03:26.760 --> 00:03:29.820
which does things like if you've got certain,

00:03:30.280 --> 00:03:30.980
what does it do?

00:03:31.100 --> 00:03:31.860
He talks about it.

00:03:32.140 --> 00:03:34.979
It gives you a way to create common syntaxes

00:03:35.000 --> 00:03:37.880
for entire files or entire packages,

00:03:38.260 --> 00:03:39.580
whether a package is installed

00:03:39.660 --> 00:03:41.640
or different operating systems, things like that.

00:03:42.000 --> 00:03:42.740
That's pretty neat also.

00:03:43.680 --> 00:03:46.320
But a change happened apparently recently,

00:03:46.840 --> 00:03:49.780
this was, well, recently for me, last year,

00:03:50.160 --> 00:03:54.200
but a change to coverage that allowed multi-line,

00:03:54.440 --> 00:03:56.480
and this was contributed by Daniel Diniz,

00:03:57.680 --> 00:04:00.660
multi-line fragments or multi-line regular expressions

00:04:01.180 --> 00:04:04.080
so that it like compares it for the whole file.

00:04:04.500 --> 00:04:07.240
So one of the neat things about this is you can do things like,

00:04:08.680 --> 00:04:13.520
with this regular expression that you can put in your no coverage stuff,

00:04:14.220 --> 00:04:19.920
you can pop in pragma exclude file and define a file there.

00:04:20.090 --> 00:04:24.620
Instead of trying to figure out how to find the file in your directory structure,

00:04:24.840 --> 00:04:26.020
you can just pop this in and say,

00:04:26.230 --> 00:04:28.720
this particular file, I don't want to delete it yet,

00:04:28.770 --> 00:04:31.300
but don't worry about this for testing.

00:04:31.700 --> 00:04:32.240
That's pretty cool.

00:04:32.580 --> 00:04:36.140
Right. My boss has been on me about getting that code coverage percentage up.

00:04:36.380 --> 00:04:39.900
So I wouldn't do it for that.

00:04:40.380 --> 00:04:44.400
And that's not what it's for. Okay. No, I like that. I'm just teasing. I like the idea.

00:04:44.780 --> 00:04:49.880
I actually like, I mean, I've heard a lot of people say hitting a hundred percent isn't,

00:04:50.500 --> 00:04:55.900
isn't worthwhile, but I think it is because coverage is so powerful. You can, with all of

00:04:55.920 --> 00:05:01.019
this stuff, you can say, I want to hit a hundred percent of the code that I care about, not the

00:05:01.040 --> 00:05:06.020
stuff I don't care about but the things that the problem area is you can define this so that you

00:05:06.070 --> 00:05:11.880
can just focus on the files and areas where you really want coverage and that needs to be 100%

00:05:12.090 --> 00:05:17.860
so that's where that's where that's my caveat for why I like 100% a couple other cool pragmas

00:05:18.410 --> 00:05:23.860
start and stop so you can just say at the start and stop like add a comment to the top of

00:05:23.860 --> 00:05:30.159
a code block to say yeah this junk we're not I'm leaving it in here but it's not it's not running

00:05:30.220 --> 00:05:36.580
during testing so don't cover it um so really powerful i really love a couple all of these um

00:05:37.120 --> 00:05:43.560
they're pretty great oh this is a neat one so have you ever had like um these uh uh default like a

00:05:43.740 --> 00:05:49.580
placeholder method where you just uh use three dots or something i'm using three dots a lot better

00:05:49.900 --> 00:05:56.159
more than pass because um it kind of does the same thing um and you can just say yeah this is here

00:05:56.180 --> 00:05:58.840
because it has to for some structural reason,

00:06:00.000 --> 00:06:01.320
but it's never going to run.

00:06:01.560 --> 00:06:03.400
So don't worry about trying to cover it.

00:06:03.540 --> 00:06:04.200
So that's pretty neat.

00:06:04.240 --> 00:06:04.720
Yeah, that's cool.

00:06:04.960 --> 00:06:05.440
Yeah, very cool.

00:06:05.940 --> 00:06:07.160
Anyway, thanks, Ned,

00:06:07.320 --> 00:06:10.980
for teaching us how to use regular expressions for coverage.

00:06:11.620 --> 00:06:12.760
Yeah, that's very neat.

00:06:13.140 --> 00:06:13.420
All right.

00:06:14.100 --> 00:06:18.600
I want to take you back to the times of knights, maidens,

00:06:19.040 --> 00:06:19.980
to the land of yore.

00:06:20.100 --> 00:06:20.880
No, this is totally different.

00:06:21.000 --> 00:06:22.260
This comes to us from Matthias.

00:06:22.360 --> 00:06:23.940
It is a package called yore, however.

00:06:24.480 --> 00:06:24.660
Okay.

00:06:24.800 --> 00:06:27.180
It's quite new.

00:06:27.440 --> 00:06:29.380
It's like an undiscovered gem sort of thing.

00:06:29.720 --> 00:06:32.460
So when I first saw this, I'm like, huh, do I care about this?

00:06:32.530 --> 00:06:33.520
I don't know if I care about this.

00:06:34.040 --> 00:06:34.800
And then I looked more carefully.

00:06:35.020 --> 00:06:36.020
That is kind of interesting.

00:06:36.380 --> 00:06:39.880
It starts with a quote from ChatGPT, the sage, which is always good.

00:06:40.240 --> 00:06:43.360
But it's more productive to just jump down to some examples.

00:06:43.860 --> 00:06:48.220
So basically what this is, is it is a tool a little bit like Ruff or Flint

00:06:48.360 --> 00:06:50.920
or one of those things that works on--

00:06:51.240 --> 00:06:53.660
basically, it looks at your code, tells you if there are issues.

00:06:54.200 --> 00:07:12.320
But this one is focused specifically on have you previously supported unsupported versions of Python by doing stuff the old way, you know, be that typing or example is the abstract, the ASTune parser.

00:07:12.320 --> 00:07:13.000
I don't know what that is.

00:07:13.210 --> 00:07:14.420
Or the AST parser.

00:07:14.420 --> 00:07:15.460
Yeah, abstracts and text tree.

00:07:16.000 --> 00:07:23.840
If you want to use that and you're using 3.8 or before, you had to use the astune parse, I guess, from unparse.

00:07:24.120 --> 00:07:28.960
Or if you're in 3.9 or above, you can use AST from unparse.

00:07:29.240 --> 00:07:35.460
So, right, you probably have this comment, like, if the version of Python that I'm running on is less than this, I'm going to do this one thing.

00:07:35.880 --> 00:07:36.860
Otherwise, I'm going to do the other.

00:07:37.220 --> 00:07:41.280
And so what you do here is you still write that code because that's how it is.

00:07:41.620 --> 00:07:49.100
However, you put a comment kind of like, you know, PyCharm and VS Code, if you put a capital

00:07:49.400 --> 00:07:52.740
to-do colon as a comment, I don't know if you've noticed this, but probably.

00:07:53.340 --> 00:07:58.220
If you say capital to-do colon and you write something, that shows up in a separate window,

00:07:58.520 --> 00:08:00.140
at least in PyCharm, you say, show me my to-dos.

00:08:00.250 --> 00:08:03.400
And when you try to do a commit, it'll say, hey, you added some new to-dos that are not

00:08:03.660 --> 00:08:03.800
done.

00:08:04.130 --> 00:08:04.920
You sure you want to commit?

00:08:05.280 --> 00:08:07.480
There's a whole integration with the tooling like that.

00:08:07.710 --> 00:08:09.080
So this is the same type of deal.

00:08:09.140 --> 00:08:17.360
So you say, put a comment that is capital your colon, and then you say EOL, in this case, EOL 3.8, and you put a comment.

00:08:17.760 --> 00:08:18.180
Oh.

00:08:18.560 --> 00:08:22.140
And then a thing like replace block with line four.

00:08:22.660 --> 00:08:22.920
Okay.

00:08:23.340 --> 00:08:23.520
Okay.

00:08:23.690 --> 00:08:28.560
So you say, once 3.8 is gone and we stop supporting it, just do the straight import.

00:08:29.060 --> 00:08:30.260
We don't have to do this test.

00:08:30.550 --> 00:08:31.260
We don't have to do anything.

00:08:31.710 --> 00:08:37.180
And then later, you can run in your code, you say, your check EOL within five months.

00:08:37.740 --> 00:08:39.680
And it says, whenever you run it at the right time,

00:08:39.909 --> 00:08:42.500
Python 3, it will reach its end of life approximately four months.

00:08:42.849 --> 00:08:44.560
So it uses the comments to say,

00:08:45.000 --> 00:08:47.380
you've got sections of your code that depend,

00:08:47.620 --> 00:08:50.700
are complicated because of Python versioning breaking changes.

00:08:51.120 --> 00:08:51.480
Oh, cool.

00:08:51.560 --> 00:08:52.280
Here they are, right?

00:08:52.310 --> 00:08:55.600
And you can look for them much like you can use rough check to say,

00:08:55.800 --> 00:08:57.360
show me issues with my code.

00:08:57.720 --> 00:09:00.300
But what's even better, rough check has a --fix.

00:09:00.480 --> 00:09:01.140
And so does yours.

00:09:01.210 --> 00:09:04.280
You can say your fix, EOL, within five months,

00:09:04.660 --> 00:09:09.940
It'll actually rewrite that code and replace the block with line four and just go back to the straight import.

00:09:10.420 --> 00:09:14.560
Remove the your comment, remove the version checks, all that.

00:09:14.800 --> 00:09:15.020
Hmm.

00:09:15.440 --> 00:09:15.780
What do you think?

00:09:15.840 --> 00:09:16.760
Okay, I like it.

00:09:16.920 --> 00:09:19.080
For such a simple idea, I like it too.

00:09:19.280 --> 00:09:29.200
Now, I'll have to play with this a little bit because it totally makes sense for Python deprecating Python versions and stuff.

00:09:30.160 --> 00:09:39.220
And the reason one of the cool things about like looking into the future is you might be working on a you might be working on a release that you're not planning on releasing for another month.

00:09:39.460 --> 00:09:41.520
So you're getting started cleaning those up.

00:09:42.800 --> 00:09:44.880
But that might be your own stuff.

00:09:44.880 --> 00:09:47.380
You might be like you might be deprecating your own features.

00:09:47.560 --> 00:09:55.060
So you might I'm wondering if you can put like your for your own features or is it just a Python EOL thing?

00:09:55.440 --> 00:09:57.060
Yeah, that's what I've been thinking about as well.

00:09:57.200 --> 00:10:00.760
I was like, I would like it not just necessarily for my features, but hey,

00:10:00.940 --> 00:10:05.580
Pydantic went from V1 to V2 and that had super big deprecations for

00:10:05.770 --> 00:10:07.840
certain really common functions, right?

00:10:07.940 --> 00:10:09.480
Like dumping to JSON and so on.

00:10:09.820 --> 00:10:09.920
Yeah.

00:10:10.280 --> 00:10:13.220
Is it just the Python release cycle?

00:10:13.370 --> 00:10:14.520
I don't know, I'll have to look into that.

00:10:14.800 --> 00:10:18.200
Yeah, I think it's just Python version itself, but who knows?

00:10:18.480 --> 00:10:18.680
Okay.

00:10:19.680 --> 00:10:21.560
Neat, yeah, very, very neat.

00:10:21.960 --> 00:10:25.340
All right, also neat is DigitalOcean.

00:10:25.800 --> 00:10:27.080
Yeah, let me tell you about DigitalOcean.

00:10:27.330 --> 00:10:30.440
This episode of Python Bytes is brought to you by DigitalOcean.

00:10:30.860 --> 00:10:33.360
DigitalOcean is a comprehensive cloud infrastructure

00:10:33.620 --> 00:10:36.320
that's simple to spin up even for the most complex workloads.

00:10:36.760 --> 00:10:39.960
And it's a way better value than most cloud providers.

00:10:40.420 --> 00:10:44.100
At DigitalOcean, companies can save up to 30% off their cloud bill.

00:10:44.460 --> 00:10:49.100
DigitalOcean boasts 99.99% uptime SLAs

00:10:49.500 --> 00:10:51.580
and industry-leading pricing on bandwidth.

00:10:51.660 --> 00:10:55.980
It's built to be the cloud backbone of businesses small and large.

00:10:56.360 --> 00:11:02.020
And with GPU-powered virtual machines plus storage databases and network capabilities

00:11:02.440 --> 00:11:10.600
all in one platform, AI developers can confidently create apps using a platform that the users love.

00:11:10.880 --> 00:11:16.580
Devs have access to the complete set of infrastructure tools they need for both training and inference

00:11:17.100 --> 00:11:19.120
so they can build anything they dream up.

00:11:19.340 --> 00:11:28.940
DigitalOcean provides full-service cloud infrastructure that's simple to use, reliable, no matter the use case, scalable for any size business, and affordable at any budget.

00:11:29.400 --> 00:11:33.560
VMs start at just $4 a month and GPUs under $1 per hour.

00:11:33.790 --> 00:11:33.940
Wow.

00:11:34.280 --> 00:11:39.020
Easy to spin up infrastructure built to simplify even the most intense business demands.

00:11:39.420 --> 00:11:40.220
That's DigitalOcean.

00:11:40.580 --> 00:11:50.440
And if you use DO4bytes, DO the number four and BYTES, you get $200 in free credit to get started.

00:11:50.860 --> 00:11:53.100
DigitalOcean is the cloud that's got you covered.

00:11:53.620 --> 00:11:56.360
Please use our link when checking out their offer.

00:11:56.820 --> 00:11:59.080
You'll find it in the podcast player show notes.

00:11:59.500 --> 00:12:03.020
And it's a clickable chapter URL as you're hearing this segment.

00:12:03.170 --> 00:12:06.500
And it's also at the top of the episode page in pythonbytes.fm.

00:12:06.800 --> 00:12:07.740
And why wouldn't you?

00:12:07.920 --> 00:12:08.880
It's $200 credit.

00:12:09.180 --> 00:12:11.580
Thank you to DigitalOcean for supporting Python Bytes.

00:12:12.070 --> 00:12:12.600
Indeed, indeed.

00:12:13.230 --> 00:12:13.520
Thank you.

00:12:14.280 --> 00:12:14.660
Over to you.

00:12:14.980 --> 00:12:15.300
What's next?

00:12:15.700 --> 00:12:16.360
Wait, no, over to me.

00:12:16.840 --> 00:12:17.420
Over to me.

00:12:17.600 --> 00:12:19.620
Sorry, I'm retracting that statement.

00:12:19.650 --> 00:12:20.700
I got the order wrong, Brian.

00:12:21.060 --> 00:12:23.780
So we've talked about Nox before, right?

00:12:24.240 --> 00:12:24.300
Yeah.

00:12:24.340 --> 00:12:25.140
You're a fan of Nox, aren't you?

00:12:25.540 --> 00:12:25.640
Yeah.

00:12:25.940 --> 00:12:32.360
So Nox is a command line tool like pytest or Tox that allows you to test against multiple

00:12:32.780 --> 00:12:34.280
versions of Python, right?

00:12:34.580 --> 00:12:35.480
So super cool.

00:12:35.530 --> 00:12:36.120
You can run it.

00:12:36.160 --> 00:12:42.740
You can say like this might depend on whatever particular version of Python or whatever, right?

00:12:42.990 --> 00:12:47.020
So the thing I want to tell you about is something called uv.

00:12:47.900 --> 00:12:49.520
No, sorry, Knox-UV.

00:12:49.650 --> 00:12:50.920
And this comes to us from John Hagen.

00:12:51.270 --> 00:12:56.560
And this facilitates Knox integration with uv for Python projects.

00:12:56.810 --> 00:13:02.040
So remember, uv is awesome at installing different versions of Python rapidly.

00:13:02.480 --> 00:13:19.080
Like you can install, go to a machine that has no Python whatsoever, and you can pick your version of Python and have it installed and ready to use in under two seconds versus PyMV, which builds it and takes minutes or downloading the installer and making sure you have all the versions you're going to test with or whatever.

00:13:19.210 --> 00:13:19.340
Right.

00:13:19.630 --> 00:13:19.780
Yeah.

00:13:19.900 --> 00:13:20.760
So that's really awesome.

00:13:21.060 --> 00:13:27.060
And then also installing the dependencies for these different versions of Python, uv is ultra fast at that as well.

00:13:27.160 --> 00:13:32.180
So there's huge advantages to speeding up testing and CI with uv.

00:13:32.760 --> 00:13:36.080
And if you're using Knox to create a combinatorial matrix

00:13:36.520 --> 00:13:38.720
of all the different versions of Python you might work with,

00:13:39.040 --> 00:13:41.880
well, then uv speed is only going to multiply across that, right?

00:13:42.380 --> 00:13:42.520
Yeah.

00:13:42.800 --> 00:13:43.880
Yeah, so super cool.

00:13:43.900 --> 00:13:47.080
So you can just say uv add group Knox and Knox uv,

00:13:47.620 --> 00:13:48.400
and it'll add that in there.

00:13:48.500 --> 00:13:50.780
And then within your Knox file, you import the session.

00:13:51.200 --> 00:13:53.480
Instead of from Knox, you do it from Knox uv,

00:13:54.280 --> 00:13:55.440
set the backend to be uv.

00:13:55.780 --> 00:14:00.300
And then for your session, you specify which versions of Python, which groups, et cetera.

00:14:00.880 --> 00:14:01.220
Off it goes.

00:14:01.300 --> 00:14:03.460
I feel like this should be your topic, honestly, Brian.

00:14:03.480 --> 00:14:05.640
I think I stole it from you somehow, effectively.

00:14:06.100 --> 00:14:06.760
Why is that?

00:14:07.060 --> 00:14:09.140
Just because you're so into testing.

00:14:09.320 --> 00:14:10.420
And this is like right at the heart of it.

00:14:11.080 --> 00:14:11.480
Okay.

00:14:12.100 --> 00:14:12.460
What do you think?

00:14:12.740 --> 00:14:12.800
Cool?

00:14:13.060 --> 00:14:13.980
I think this is neat.

00:14:14.140 --> 00:14:16.640
Yeah, I'm using like uv almost everywhere now.

00:14:16.900 --> 00:14:23.679
And I actually, I used to recommend people like just average folks that are just starting Python

00:14:23.700 --> 00:14:25.620
or they just need it for work,

00:14:25.830 --> 00:14:29.920
I would recommend them just go to python.org and download it.

00:14:30.260 --> 00:14:31.720
And I'm still kind of doing that,

00:14:31.790 --> 00:14:34.860
but I'm leaning towards trying to teach people

00:14:34.890 --> 00:14:36.500
how to use uv in virtual environments

00:14:36.850 --> 00:14:38.920
because it's not going to be that long

00:14:39.250 --> 00:14:40.700
after they start using Python

00:14:40.920 --> 00:14:42.200
that they're going to want to use that anyway.

00:14:42.520 --> 00:14:43.260
So, yeah.

00:14:44.180 --> 00:14:46.240
Yeah, and recently we just covered this,

00:14:46.320 --> 00:14:47.840
that one of the main things uv did

00:14:48.100 --> 00:14:52.259
is now there's a Python version in your path

00:14:52.280 --> 00:14:54.700
if you install a Python via uv,

00:14:54.970 --> 00:14:57.340
which it used to just be in like some obscure place

00:14:57.570 --> 00:14:59.600
hidden in like your user profile sort of thing.

00:14:59.600 --> 00:15:01.940
It was hard to run it outside of a virtual environment.

00:15:02.300 --> 00:15:02.400
Yeah.

00:15:02.940 --> 00:15:03.040
Yeah.

00:15:04.160 --> 00:15:04.340
Yeah.

00:15:04.720 --> 00:15:04.780
Anyway.

00:15:05.190 --> 00:15:05.280
Okay.

00:15:05.720 --> 00:15:05.780
Cool.

00:15:05.960 --> 00:15:06.080
Yeah.

00:15:06.360 --> 00:15:06.600
Very cool.

00:15:06.860 --> 00:15:07.720
Thanks, John, for sending that in.

00:15:08.400 --> 00:15:09.140
Now over to you, Brian.

00:15:09.920 --> 00:15:10.260
All right.

00:15:10.640 --> 00:15:12.520
So let's take a look.

00:15:12.640 --> 00:15:16.020
I've got a couple short-ish Django items.

00:15:16.090 --> 00:15:18.200
So I thought I'd cover them together.

00:15:18.600 --> 00:15:21.440
So the first comes from Johnny Metz.

00:15:22.240 --> 00:15:25.800
And it's stop using Django's squash migrations.

00:15:26.220 --> 00:15:27.040
There's a better way.

00:15:27.280 --> 00:15:29.260
And actually, I didn't know about squash migrations.

00:15:29.380 --> 00:15:32.260
I'm kind of new to Django, the Django world, new-ish.

00:15:33.360 --> 00:15:38.720
But I like this article because I watched a pro, kind of an old hat,

00:15:39.380 --> 00:15:45.180
when I was doing a session with somebody that knows Django way better than I do.

00:15:45.760 --> 00:15:50.299
And I had a whole bunch of migrations because I was fiddling with

00:15:50.320 --> 00:15:53.080
the database structure and everything.

00:15:53.200 --> 00:15:54.780
And I was going back and forth, changing things.

00:15:54.940 --> 00:15:56.220
And I had a bunch of migrations.

00:15:56.980 --> 00:15:59.060
And he said, wait a second, just a second.

00:15:59.220 --> 00:16:00.040
Let me do something.

00:16:00.100 --> 00:16:01.760
And he just like, he did this.

00:16:01.860 --> 00:16:02.720
So what am I doing?

00:16:02.900 --> 00:16:03.680
What am I talking about?

00:16:05.019 --> 00:16:06.980
So this is Johnny Metz.

00:16:07.080 --> 00:16:09.580
He was recommending doing a clean reset.

00:16:10.260 --> 00:16:13.060
So you fully migrate all your environments,

00:16:13.440 --> 00:16:14.620
make sure everything's running well.

00:16:14.900 --> 00:16:17.360
And then you delete all your migration files.

00:16:17.780 --> 00:16:18.380
Seems crazy.

00:16:18.800 --> 00:16:22.260
but you delete them all and generate a fresh migrations.

00:16:22.840 --> 00:16:25.720
And then you've got just a new one.

00:16:26.320 --> 00:16:31.500
So this creates a new 0001 initial for each app,

00:16:31.820 --> 00:16:37.800
and then some apps might get a 002 or higher.

00:16:37.900 --> 00:16:41.300
So you do this on different, it's going to do it on different apps.

00:16:41.600 --> 00:16:44.340
But then you, so, okay, I'll just walk through it.

00:16:44.580 --> 00:16:47.460
Fully migrate all your environments, delete all your migrations,

00:16:47.840 --> 00:16:52.420
generate fresh migrations, then add data migrations,

00:16:53.080 --> 00:16:57.100
temporarily disable automatic migrations during deployment,

00:16:57.540 --> 00:16:58.220
reset migrations.

00:16:58.620 --> 00:16:59.500
Okay, so it's not trivial.

00:16:59.700 --> 00:17:01.360
Then re-enable automatic migrations.

00:17:01.900 --> 00:17:04.199
So why would you do all of this?

00:17:04.199 --> 00:17:05.780
This seems more complicated.

00:17:06.120 --> 00:17:10.800
However, you end up with a really clean set.

00:17:11.020 --> 00:17:14.939
So you've got a very clean migrations set at the end.

00:17:15.780 --> 00:17:31.480
And I think, I don't know if this is, I'm not a Django pro, but so I'm not, I'm not sure if this is appropriate later on, but especially after you've like hashed through the initial development, this is a great time to start clean and then, and then work from there.

00:17:31.690 --> 00:17:33.580
So interesting Django article.

00:17:33.840 --> 00:17:34.920
It is an interesting idea.

00:17:35.140 --> 00:17:40.180
And certainly, I think if you've not pushed it to production, you know, you just like,

00:17:40.630 --> 00:17:44.640
instead of having the 100 migrations you may have built over time as you built up the app

00:17:44.860 --> 00:17:49.280
before you push it out live, like just get that down to a single migration, get the database

00:17:49.520 --> 00:17:50.480
up and running, go from there.

00:17:50.840 --> 00:17:50.940
Yeah.

00:17:52.000 --> 00:17:57.600
I'm not sure if it mentions it in here too, but I have been, guess, yeah, I think it sets

00:17:57.680 --> 00:18:00.660
it up in here, but having migrations per application.

00:18:00.940 --> 00:18:01.040
Anyway.

00:18:02.180 --> 00:18:06.840
The other one is this comes from Adam Hill is DJ light.

00:18:06.840 --> 00:18:08.700
And this is a fairly new project.

00:18:09.760 --> 00:18:14.740
And it is how to use SQLite in production with Django.

00:18:15.140 --> 00:18:19.280
So yes, you can use SQLite with Django, but there's some tricks.

00:18:19.440 --> 00:18:27.120
So he wrote an article called the definitive guide to using Django with SQLite in production.

00:18:27.560 --> 00:18:33.000
And then he decided to go ahead and he's still recommending that,

00:18:33.320 --> 00:18:35.180
but there's this plugin to make it easier.

00:18:35.580 --> 00:18:39.820
So with this plugin, you got a couple settings that you can change,

00:18:39.860 --> 00:18:41.020
and it just runs with it.

00:18:41.200 --> 00:18:45.860
So it's way easier setup if you want to use SQLite with Django.

00:18:47.239 --> 00:18:50.980
And this little blurb here at the top says that

00:18:52.820 --> 00:18:55.540
simplify deploying and maintaining production Django websites

00:18:56.000 --> 00:18:57.280
using SQLite in production.

00:18:57.680 --> 00:19:03.280
DJ Lite helps enable the best performance for SQLite for small to medium-sized projects.

00:19:03.680 --> 00:19:11.900
It requires Django 5.1 or above, but I think SQLite is appropriate for a lot of Django.

00:19:12.180 --> 00:19:15.400
A lot of people just start with Postgres, but anyway.

00:19:15.690 --> 00:19:16.500
Yeah, definitely.

00:19:17.030 --> 00:19:24.100
I think there's certainly defaults you can change or behaviors you can change about SQLite to make it way more high performance,

00:19:24.760 --> 00:19:27.000
especially with concurrent read-write sort of things.

00:19:27.320 --> 00:19:27.440
Yeah.

00:19:27.540 --> 00:19:28.600
So, yeah, very cool.

00:19:29.100 --> 00:19:32.820
And following up on the squash migrations,

00:19:33.320 --> 00:19:33.960
Pat Decker says,

00:19:34.330 --> 00:19:36.400
sounds like a similar familiar to Git Rebase maybe.

00:19:36.740 --> 00:19:37.780
Yeah, it does to me for sure.

00:19:38.120 --> 00:19:38.280
Yeah.

00:19:38.420 --> 00:19:38.820
Squashing.

00:19:39.130 --> 00:19:39.960
Yeah, very similar.

00:19:40.740 --> 00:19:40.900
Okay.

00:19:41.320 --> 00:19:42.080
While you have the stage,

00:19:42.260 --> 00:19:43.060
how extra do you feel?

00:19:43.700 --> 00:19:44.560
I got a couple extras,

00:19:44.980 --> 00:19:46.040
so we can just cover them.

00:19:46.360 --> 00:19:51.060
So the first up is I've got a testing code episode

00:19:51.290 --> 00:19:51.760
in the queue.

00:19:52.020 --> 00:19:53.200
It's in draft mode currently.

00:19:53.940 --> 00:19:56.620
FastAPI cloud with Sebastian Ramirez.

00:19:57.080 --> 00:19:59.260
and it was a real fun talk with Sebastian.

00:19:59.390 --> 00:20:00.280
This was recorded.

00:20:00.540 --> 00:20:01.740
I can't even remember when it was recorded.

00:20:01.940 --> 00:20:03.520
Maybe it was a few weeks ago at least.

00:20:04.090 --> 00:20:06.300
I feel bad getting so slow to get it out.

00:20:06.560 --> 00:20:10.000
But a really interesting article about FastAPI

00:20:10.140 --> 00:20:11.880
and about FastAPI Cloud.

00:20:12.100 --> 00:20:14.380
And Sebastian's just a joy to talk with.

00:20:14.560 --> 00:20:16.140
So that'll be out later today.

00:20:16.580 --> 00:20:18.880
I only have to rerecord the ad for it,

00:20:19.060 --> 00:20:20.720
but not much left to do.

00:20:21.800 --> 00:20:25.060
And then next up, pythontest.com,

00:20:25.090 --> 00:20:25.740
a couple things.

00:20:26.320 --> 00:20:29.360
I released a, I had a fixture.

00:20:29.980 --> 00:20:30.360
When was this?

00:20:30.500 --> 00:20:31.980
2013 that I started.

00:20:32.520 --> 00:20:34.240
So this is what, over 10 years ago?

00:20:34.960 --> 00:20:37.980
That I wrote a four-part series on pytest fixtures.

00:20:38.640 --> 00:20:43.980
And I had been talking that I was looking at analytics.

00:20:44.560 --> 00:20:46.180
And some of this stuff is still getting hit.

00:20:46.400 --> 00:20:47.960
So I went and reviewed it.

00:20:48.180 --> 00:20:50.000
And this series was a mess.

00:20:50.300 --> 00:20:54.580
And I went ahead and like re, I didn't rewrite it,

00:20:54.880 --> 00:20:59.860
But I went through everything and split it up into a more multi-part series.

00:21:00.050 --> 00:21:01.100
A lot of these are really short.

00:21:01.270 --> 00:21:06.600
I just wanted to keep one topic per blog post and make sure that it runs.

00:21:06.800 --> 00:21:09.820
A lot of the stuff didn't even run on current pytest and current Python.

00:21:10.180 --> 00:21:12.120
Now it all runs with current pytest and Python.

00:21:12.440 --> 00:21:14.740
So there's a nice fixture tutorial there.

00:21:15.440 --> 00:21:20.920
The other thing I wanted to bring up with Python Test is there is a bunch of stuff.

00:21:21.380 --> 00:21:26.100
So 2013 up through this year, there was a bunch of stuff that was like formatted badly.

00:21:26.500 --> 00:21:30.480
And I have gone through and made sure everything is mostly correct.

00:21:31.000 --> 00:21:33.300
So if you see any, I think everything's working now.

00:21:33.660 --> 00:21:35.360
So if you see anything weird, let me know.

00:21:35.570 --> 00:21:40.660
I just, as I was reviewing this morning, I realized that in this particular post, I

00:21:40.850 --> 00:21:45.380
refer to a fixture as fixture B and it's really resource B.

00:21:45.600 --> 00:21:46.380
So I'll have to fix that.

00:21:46.590 --> 00:21:48.640
But, you know, things like that shouldn't be too bad.

00:21:48.860 --> 00:21:49.920
Anyway, that's all up to date.

00:21:50.110 --> 00:21:50.700
Do you have any updates?

00:21:51.260 --> 00:21:54.720
I have three extras, and I think they're really exciting.

00:21:54.880 --> 00:21:56.180
They're going to be really cool for people.

00:21:56.480 --> 00:21:57.380
So let me tell you about it.

00:21:57.480 --> 00:21:59.520
First, brand new course over at Talk Python.

00:21:59.760 --> 00:22:01.180
I'm really excited about this one.

00:22:01.340 --> 00:22:05.840
Some of the most impactful courses that we create there are ones that take people from

00:22:06.000 --> 00:22:11.780
like zero to one or one and 1.5 to two, like the first sort of steps, right?

00:22:12.180 --> 00:22:15.980
And so this new course is called Just Enough Python for Data Scientists.

00:22:16.460 --> 00:22:16.740
Oh, nice.

00:22:16.940 --> 00:22:20.200
Python is kind of a stand-in for software engineering with Python, right?

00:22:20.240 --> 00:22:33.400
So the idea of this course is if you've done work in Jupyter notebooks, but you kind of feel like, well, I just learned notebooks and a little bit of Python because I was at this research lab or in this course I took.

00:22:33.510 --> 00:22:36.060
But I don't really know Git very well.

00:22:36.400 --> 00:22:38.220
I don't know refactoring super well.

00:22:38.500 --> 00:22:39.880
Reproducibility is still an issue.

00:22:40.490 --> 00:22:41.200
Those kinds of things.

00:22:41.660 --> 00:22:47.660
So it covers like what do you need to pay attention to in the dev world or the software world?

00:22:47.730 --> 00:22:49.120
And what can you safely ignore?

00:22:49.680 --> 00:22:49.760
Right.

00:22:49.940 --> 00:22:52.320
Like don't try to boil the ocean when you're getting started.

00:22:52.560 --> 00:22:54.040
What can you just not pay attention to?

00:22:54.890 --> 00:22:55.880
How do you write functions?

00:22:56.340 --> 00:22:59.820
Create importable modules and packages to split up notebooks

00:23:00.300 --> 00:23:05.080
from like one large notebook cell into a bunch of usable, testable, more readable pieces.

00:23:06.160 --> 00:23:08.380
Debugging, reproducibility with like Docker and uv,

00:23:08.590 --> 00:23:13.060
and even a little bit of agentic AI for like data analysis to like jumpstart your work.

00:23:13.200 --> 00:23:16.880
So if people are interested in this, I highly recommend it.

00:23:16.920 --> 00:23:19.680
It's an awesome course that I wrote over the last three or four weeks.

00:23:20.040 --> 00:23:21.320
and I'm really happy to have it out.

00:23:21.700 --> 00:23:22.480
That's pretty exciting.

00:23:22.840 --> 00:23:23.480
I like the topic.

00:23:23.920 --> 00:23:24.260
Yeah, thanks.

00:23:24.720 --> 00:23:24.780
Yeah.

00:23:25.340 --> 00:23:25.580
All right.

00:23:26.200 --> 00:23:26.780
Speaking of uv,

00:23:27.000 --> 00:23:29.880
I was just on with Will Vincent from Django Chat.

00:23:30.920 --> 00:23:31.420
When was this?

00:23:31.600 --> 00:23:34.240
This was live streamed four days ago.

00:23:34.660 --> 00:23:40.220
And we did a whole one hour paired presenting sort of thing on uv,

00:23:40.480 --> 00:23:43.020
why people might use it, compatibility, what's new.

00:23:44.020 --> 00:23:45.860
I even did a thing like how to make your Docker builds

00:23:46.140 --> 00:23:47.620
five times faster sort of thing,

00:23:47.900 --> 00:23:49.900
or 30 times faster, depending on what you're using.

00:23:49.950 --> 00:23:51.720
If you're using pip, it'll be 30 times faster.

00:23:52.070 --> 00:23:55.320
So super neat, super neat stuff that people can check out.

00:23:55.370 --> 00:23:56.060
And that's just on YouTube.

00:23:56.190 --> 00:23:56.820
So I'm going to link to that.

00:23:57.340 --> 00:24:00.400
And then last is I'm a fan of cursor

00:24:00.720 --> 00:24:03.380
when I'm doing like super heavy AI programming.

00:24:04.060 --> 00:24:05.160
Obviously a big fan of PyCharm

00:24:05.280 --> 00:24:07.400
when I'm doing like focused development work, right?

00:24:07.560 --> 00:24:10.600
But if I'm just like, I just need some heavy duty AI tools,

00:24:11.160 --> 00:24:14.840
cursor and Claude Code has been getting a lot of traction lately

00:24:14.990 --> 00:24:16.560
because it's like this terminal based thing.

00:24:16.590 --> 00:24:17.240
You can use it anywhere.

00:24:17.700 --> 00:24:22.460
Well, Cursor just came out with a Cursor CLI that you could set up.

00:24:22.580 --> 00:24:23.540
That's pretty neat.

00:24:23.680 --> 00:24:25.620
So use it in your IDE or any terminal.

00:24:25.920 --> 00:24:28.960
Cursor, JetBrains, Android Studio, Xcode, whatever.

00:24:29.420 --> 00:24:30.260
So pretty neat.

00:24:31.530 --> 00:24:36.840
If you kind of like Cursor, but you also kind of prefer the terminal side of things, check this out.

00:24:36.890 --> 00:24:39.160
It's in beta, but so far it seems pretty neat.

00:24:39.210 --> 00:24:41.620
If you have a subscription, it just integrates with that.

00:24:41.800 --> 00:24:42.020
Neat.

00:24:42.290 --> 00:24:43.260
Yeah, those are my extras.

00:24:43.660 --> 00:24:44.760
I have a joke for us as well.

00:24:45.280 --> 00:24:45.700
Oh, good.

00:24:45.960 --> 00:24:46.060
Yes.

00:24:46.580 --> 00:24:51.480
And I think this AI thing I just gave a shout out to perfectly, perfectly blends into this.

00:24:51.630 --> 00:24:51.740
Okay.

00:24:52.400 --> 00:24:54.300
Control C, Control V remains eternal.

00:24:54.600 --> 00:24:56.680
But what kind of dev are you?

00:24:56.800 --> 00:24:57.860
This means something different, Brian.

00:24:58.320 --> 00:25:01.620
If you're a new school developer, you copy and paste from ChatGPT.

00:25:01.960 --> 00:25:06.160
If you're old school, you copy and paste from Stack Overflow.

00:25:06.660 --> 00:25:10.060
And if you're ancient like you and me, you copy and paste from the documentation.

00:25:11.460 --> 00:25:13.900
Wait, how do I copy and paste from a book?

00:25:14.260 --> 00:25:17.060
Okay, I guess I'm so ancient that I'm not even on the chart.

00:25:17.260 --> 00:25:20.620
Oh, that one takes a while because that's when you remember people talk about,

00:25:20.880 --> 00:25:24.480
oh, I saw that code in the magazine that I typed it in.

00:25:24.800 --> 00:25:25.660
Yeah, that was me.

00:25:26.120 --> 00:25:26.900
That's how you do it.

00:25:27.120 --> 00:25:27.740
That's how you do it.

00:25:28.520 --> 00:25:31.120
You copy and paste with the fingers one character at a time.

00:25:32.100 --> 00:25:32.300
Yeah.

00:25:32.780 --> 00:25:32.920
Yeah.

00:25:33.260 --> 00:25:37.400
Anyway, copy, control Z, control V, still important, but changing over time.

00:25:37.780 --> 00:25:37.960
Yeah.

00:25:38.700 --> 00:25:38.980
All right.

00:25:39.140 --> 00:25:40.740
Well, thanks for the episode.

00:25:41.120 --> 00:25:41.700
Thanks for being here.

00:25:41.900 --> 00:25:43.180
And thanks everyone else for listening.

00:25:43.500 --> 00:25:43.700
Thanks.

00:25:43.820 --> 00:25:43.960
Bye.

