WEBVTT
00:00:00.040 -->
00:00:04.880Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to
00:00:04.920 -->
00:00:13.380your earbuds. This is episode 444, recorded August 11th, 2025. I am Michael Kennedy.
00:00:13.680 -->
00:00:14.480And I'm Brian Okken.
00:00:14.760 -->
00:00:21.460And this episode is brought to you by DigitalOcean and their generative AI features and tools,
00:00:22.080 -->
00:00:26.000and DigitalOcean more generally, but specifically by their gen AI tools,
00:00:26.140 -->
00:00:28.460which we're going to talk about. Brian's going to tell you about them.
00:00:28.760 -->
00:00:38.740So 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.440So 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.980Also connect with us on the socials, Mastodon, Bluesky, YouTube, all of those things.
00:00:49.100 -->
00:00:51.040Links are in the show notes at the top.
00:00:51.380 -->
00:00:58.420And 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.180is out. Diving further into the stuff that we talked about, maybe some additional resources
00:01:03.380 -->
00:01:07.560and 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.340It's really cool. I enjoy getting it as well. Thanks, Ryan. I enjoy putting it together.
00:01:11.710 -->
00:01:17.900I 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.180Speaking of coverage, let's talk about coverage. Ned Batchelder released,
00:01:24.660 -->
00:01:27.580I guess this was in July, but just recently,
00:01:27.900 -->
00:01:32.400a blog post called coverage.py regex pragmas.
00:01:32.940 -->
00:01:34.480So that seems like a mouthful.
00:01:35.940 -->
00:01:38.640And probably, please don't run away because this is powerful.
00:01:39.360 -->
00:01:43.500I know that pragmas and regex isn't everybody's favorite topic.
00:01:43.680 -->
00:01:46.080I'm feeling like C++ is back again.
00:01:47.860 -->
00:01:48.760So what does pragma mean?
00:01:49.020 -->
00:01:50.820It's the pound thing.
00:01:50.880 -->
00:02:03.780So 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.260However, 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.180So, coverage uses regexes to define pragma syntax.
00:02:16.500 -->
00:02:22.440And 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.760And there is a way to say particular files, just ignore the whole file.
00:02:28.060 -->
00:02:29.640However, this is pretty cool.
00:02:29.740 -->
00:02:30.720So, what is he talking about?
00:02:30.920 -->
00:02:37.600He's talking about a couple things around it that allow you can extend it using regular expressions.
00:02:38.160 -->
00:02:40.380And you don't necessarily have to figure this out.
00:02:40.480 -->
00:02:45.820other people have figured it out for you. For instance, there are plugins for coverage that do
00:02:46.030 -->
00:02:53.340a 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.920So 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.160things like exclude your dundermain.py file. Because if you're distributing a package,
00:03:07.360 -->
00:03:09.100that might be just so you can test things.
00:03:09.700 -->
00:03:10.800You're probably not going,
00:03:11.080 -->
00:03:13.180it's okay if coverage doesn't hit it.
00:03:13.680 -->
00:03:14.740A lot of stuff like that.
00:03:14.820 -->
00:03:16.520And then a whole bunch of regular expressions
00:03:16.880 -->
00:03:18.220for things like type relating,
00:03:19.040 -->
00:03:21.080typing relating code and excluding that.
00:03:21.300 -->
00:03:21.780That's pretty cool.
00:03:21.800 -->
00:03:22.660I didn't know that was there.
00:03:22.820 -->
00:03:23.020That's neat.
00:03:23.520 -->
00:03:26.240Another one is coverage conditional plugin,
00:03:26.760 -->
00:03:29.820which does things like if you've got certain,
00:03:30.280 -->
00:03:30.980what does it do?
00:03:31.100 -->
00:03:31.860He talks about it.
00:03:32.140 -->
00:03:34.979It gives you a way to create common syntaxes
00:03:35.000 -->
00:03:37.880for entire files or entire packages,
00:03:38.260 -->
00:03:39.580whether a package is installed
00:03:39.660 -->
00:03:41.640or different operating systems, things like that.
00:03:42.000 -->
00:03:42.740That's pretty neat also.
00:03:43.680 -->
00:03:46.320But a change happened apparently recently,
00:03:46.840 -->
00:03:49.780this was, well, recently for me, last year,
00:03:50.160 -->
00:03:54.200but a change to coverage that allowed multi-line,
00:03:54.440 -->
00:03:56.480and this was contributed by Daniel Diniz,
00:03:57.680 -->
00:04:00.660multi-line fragments or multi-line regular expressions
00:04:01.180 -->
00:04:04.080so that it like compares it for the whole file.
00:04:04.500 -->
00:04:07.240So one of the neat things about this is you can do things like,
00:04:08.680 -->
00:04:13.520with this regular expression that you can put in your no coverage stuff,
00:04:14.220 -->
00:04:19.920you can pop in pragma exclude file and define a file there.
00:04:20.090 -->
00:04:24.620Instead of trying to figure out how to find the file in your directory structure,
00:04:24.840 -->
00:04:26.020you can just pop this in and say,
00:04:26.230 -->
00:04:28.720this particular file, I don't want to delete it yet,
00:04:28.770 -->
00:04:31.300but don't worry about this for testing.
00:04:31.700 -->
00:04:32.240That's pretty cool.
00:04:32.580 -->
00:04:36.140Right. My boss has been on me about getting that code coverage percentage up.
00:04:36.380 -->
00:04:39.900So I wouldn't do it for that.
00:04:40.380 -->
00:04:44.400And 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.880I 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.900isn't worthwhile, but I think it is because coverage is so powerful. You can, with all of
00:04:55.920 -->
00:05:01.019this 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.020stuff 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.880can 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.860so 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.860start 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.159a 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.580during 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.560they'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.580placeholder 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.159more 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.840because it has to for some structural reason,
00:06:00.000 -->
00:06:01.320but it's never going to run.
00:06:01.560 -->
00:06:03.400So don't worry about trying to cover it.
00:06:03.540 -->
00:06:04.200So that's pretty neat.
00:06:04.240 -->
00:06:04.720Yeah, that's cool.
00:06:04.960 -->
00:06:05.440Yeah, very cool.
00:06:05.940 -->
00:06:07.160Anyway, thanks, Ned,
00:06:07.320 -->
00:06:10.980for teaching us how to use regular expressions for coverage.
00:06:11.620 -->
00:06:12.760Yeah, that's very neat.
00:06:13.140 -->
00:06:13.420All right.
00:06:14.100 -->
00:06:18.600I want to take you back to the times of knights, maidens,
00:06:19.040 -->
00:06:19.980to the land of yore.
00:06:20.100 -->
00:06:20.880No, this is totally different.
00:06:21.000 -->
00:06:22.260This comes to us from Matthias.
00:06:22.360 -->
00:06:23.940It is a package called yore, however.
00:06:24.480 -->
00:06:24.660Okay.
00:06:24.800 -->
00:06:27.180It's quite new.
00:06:27.440 -->
00:06:29.380It's like an undiscovered gem sort of thing.
00:06:29.720 -->
00:06:32.460So when I first saw this, I'm like, huh, do I care about this?
00:06:32.530 -->
00:06:33.520I don't know if I care about this.
00:06:34.040 -->
00:06:34.800And then I looked more carefully.
00:06:35.020 -->
00:06:36.020That is kind of interesting.
00:06:36.380 -->
00:06:39.880It starts with a quote from ChatGPT, the sage, which is always good.
00:06:40.240 -->
00:06:43.360But it's more productive to just jump down to some examples.
00:06:43.860 -->
00:06:48.220So basically what this is, is it is a tool a little bit like Ruff or Flint
00:06:48.360 -->
00:06:50.920or one of those things that works on--
00:06:51.240 -->
00:06:53.660basically, it looks at your code, tells you if there are issues.
00:06:54.200 -->
00:07:12.320But 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.000I don't know what that is.
00:07:13.210 -->
00:07:14.420Or the AST parser.
00:07:14.420 -->
00:07:15.460Yeah, abstracts and text tree.
00:07:16.000 -->
00:07:23.840If 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.960Or if you're in 3.9 or above, you can use AST from unparse.
00:07:29.240 -->
00:07:35.460So, 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.860Otherwise, I'm going to do the other.
00:07:37.220 -->
00:07:41.280And so what you do here is you still write that code because that's how it is.
00:07:41.620 -->
00:07:49.100However, 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.740to-do colon as a comment, I don't know if you've noticed this, but probably.
00:07:53.340 -->
00:07:58.220If you say capital to-do colon and you write something, that shows up in a separate window,
00:07:58.520 -->
00:08:00.140at least in PyCharm, you say, show me my to-dos.
00:08:00.250 -->
00:08:03.400And 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.800done.
00:08:04.130 -->
00:08:04.920You sure you want to commit?
00:08:05.280 -->
00:08:07.480There's a whole integration with the tooling like that.
00:08:07.710 -->
00:08:09.080So this is the same type of deal.
00:08:09.140 -->
00:08:17.360So 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.180Oh.
00:08:18.560 -->
00:08:22.140And then a thing like replace block with line four.
00:08:22.660 -->
00:08:22.920Okay.
00:08:23.340 -->
00:08:23.520Okay.
00:08:23.690 -->
00:08:28.560So you say, once 3.8 is gone and we stop supporting it, just do the straight import.
00:08:29.060 -->
00:08:30.260We don't have to do this test.
00:08:30.550 -->
00:08:31.260We don't have to do anything.
00:08:31.710 -->
00:08:37.180And then later, you can run in your code, you say, your check EOL within five months.
00:08:37.740 -->
00:08:39.680And it says, whenever you run it at the right time,
00:08:39.909 -->
00:08:42.500Python 3, it will reach its end of life approximately four months.
00:08:42.849 -->
00:08:44.560So it uses the comments to say,
00:08:45.000 -->
00:08:47.380you've got sections of your code that depend,
00:08:47.620 -->
00:08:50.700are complicated because of Python versioning breaking changes.
00:08:51.120 -->
00:08:51.480Oh, cool.
00:08:51.560 -->
00:08:52.280Here they are, right?
00:08:52.310 -->
00:08:55.600And you can look for them much like you can use ruff check to say,
00:08:55.800 -->
00:08:57.360show me issues with my code.
00:08:57.720 -->
00:09:00.300But what's even better, ruff check has a --fix.
00:09:00.480 -->
00:09:01.140And so does yours.
00:09:01.210 -->
00:09:04.280You can say your fix, EOL, within five months,
00:09:04.660 -->
00:09:09.940It'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.560Remove the your comment, remove the version checks, all that.
00:09:14.800 -->
00:09:15.020Hmm.
00:09:15.440 -->
00:09:15.780What do you think?
00:09:15.840 -->
00:09:16.760Okay, I like it.
00:09:16.920 -->
00:09:19.080For such a simple idea, I like it too.
00:09:19.280 -->
00:09:29.200Now, 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.220And 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.520So you're getting started cleaning those up.
00:09:42.800 -->
00:09:44.880But that might be your own stuff.
00:09:44.880 -->
00:09:47.380You might be like you might be deprecating your own features.
00:09:47.560 -->
00:09:55.060So 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.060Yeah, that's what I've been thinking about as well.
00:09:57.200 -->
00:10:00.760I was like, I would like it not just necessarily for my features, but hey,
00:10:00.940 -->
00:10:05.580Pydantic went from V1 to V2 and that had super big deprecations for
00:10:05.770 -->
00:10:07.840certain really common functions, right?
00:10:07.940 -->
00:10:09.480Like dumping to JSON and so on.
00:10:09.820 -->
00:10:09.920Yeah.
00:10:10.280 -->
00:10:13.220Is it just the Python release cycle?
00:10:13.370 -->
00:10:14.520I don't know, I'll have to look into that.
00:10:14.800 -->
00:10:18.200Yeah, I think it's just Python version itself, but who knows?
00:10:18.480 -->
00:10:18.680Okay.
00:10:19.680 -->
00:10:21.560Neat, yeah, very, very neat.
00:10:21.960 -->
00:10:25.340All right, also neat is DigitalOcean.
00:10:25.800 -->
00:10:27.080Yeah, let me tell you about DigitalOcean.
00:10:27.330 -->
00:10:30.440This episode of Python Bytes is brought to you by DigitalOcean.
00:10:30.860 -->
00:10:33.360DigitalOcean is a comprehensive cloud infrastructure
00:10:33.620 -->
00:10:36.320that's simple to spin up even for the most complex workloads.
00:10:36.760 -->
00:10:39.960And it's a way better value than most cloud providers.
00:10:40.420 -->
00:10:44.100At DigitalOcean, companies can save up to 30% off their cloud bill.
00:10:44.460 -->
00:10:49.100DigitalOcean boasts 99.99% uptime SLAs
00:10:49.500 -->
00:10:51.580and industry-leading pricing on bandwidth.
00:10:51.660 -->
00:10:55.980It's built to be the cloud backbone of businesses small and large.
00:10:56.360 -->
00:11:02.020And with GPU-powered virtual machines plus storage databases and network capabilities
00:11:02.440 -->
00:11:10.600all in one platform, AI developers can confidently create apps using a platform that the users love.
00:11:10.880 -->
00:11:16.580Devs have access to the complete set of infrastructure tools they need for both training and inference
00:11:17.100 -->
00:11:19.120so they can build anything they dream up.
00:11:19.340 -->
00:11:28.940DigitalOcean 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.560VMs start at just $4 a month and GPUs under $1 per hour.
00:11:33.790 -->
00:11:33.940Wow.
00:11:34.280 -->
00:11:39.020Easy to spin up infrastructure built to simplify even the most intense business demands.
00:11:39.420 -->
00:11:40.220That's DigitalOcean.
00:11:40.580 -->
00:11:50.440And 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.100DigitalOcean is the cloud that's got you covered.
00:11:53.620 -->
00:11:56.360Please use our link when checking out their offer.
00:11:56.820 -->
00:11:59.080You'll find it in the podcast player show notes.
00:11:59.500 -->
00:12:03.020And it's a clickable chapter URL as you're hearing this segment.
00:12:03.170 -->
00:12:06.500And it's also at the top of the episode page in pythonbytes.fm.
00:12:06.800 -->
00:12:07.740And why wouldn't you?
00:12:07.920 -->
00:12:08.880It's $200 credit.
00:12:09.180 -->
00:12:11.580Thank you to DigitalOcean for supporting Python Bytes.
00:12:12.070 -->
00:12:12.600Indeed, indeed.
00:12:13.230 -->
00:12:13.520Thank you.
00:12:14.280 -->
00:12:14.660Over to you.
00:12:14.980 -->
00:12:15.300What's next?
00:12:15.700 -->
00:12:16.360Wait, no, over to me.
00:12:16.840 -->
00:12:17.420Over to me.
00:12:17.600 -->
00:12:19.620Sorry, I'm retracting that statement.
00:12:19.650 -->
00:12:20.700I got the order wrong, Brian.
00:12:21.060 -->
00:12:23.780So we've talked about Nox before, right?
00:12:24.240 -->
00:12:24.300Yeah.
00:12:24.340 -->
00:12:25.140You're a fan of Nox, aren't you?
00:12:25.540 -->
00:12:25.640Yeah.
00:12:25.940 -->
00:12:32.360So Nox is a command line tool like pytest or Tox that allows you to test against multiple
00:12:32.780 -->
00:12:34.280versions of Python, right?
00:12:34.580 -->
00:12:35.480So super cool.
00:12:35.530 -->
00:12:36.120You can run it.
00:12:36.160 -->
00:12:42.740You can say like this might depend on whatever particular version of Python or whatever, right?
00:12:42.990 -->
00:12:47.020So the thing I want to tell you about is something called uv.
00:12:47.900 -->
00:12:49.520No, sorry, Knox-UV.
00:12:49.650 -->
00:12:50.920And this comes to us from John Hagen.
00:12:51.270 -->
00:12:56.560And this facilitates Knox integration with uv for Python projects.
00:12:56.810 -->
00:13:02.040So remember, uv is awesome at installing different versions of Python rapidly.
00:13:02.480 -->
00:13:19.080Like 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.340Right.
00:13:19.630 -->
00:13:19.780Yeah.
00:13:19.900 -->
00:13:20.760So that's really awesome.
00:13:21.060 -->
00:13:27.060And 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.180So there's huge advantages to speeding up testing and CI with uv.
00:13:32.760 -->
00:13:36.080And if you're using Knox to create a combinatorial matrix
00:13:36.520 -->
00:13:38.720of all the different versions of Python you might work with,
00:13:39.040 -->
00:13:41.880well, then uv speed is only going to multiply across that, right?
00:13:42.380 -->
00:13:42.520Yeah.
00:13:42.800 -->
00:13:43.880Yeah, so super cool.
00:13:43.900 -->
00:13:47.080So you can just say uv add group Knox and Knox uv,
00:13:47.620 -->
00:13:48.400and it'll add that in there.
00:13:48.500 -->
00:13:50.780And then within your Knox file, you import the session.
00:13:51.200 -->
00:13:53.480Instead of from Knox, you do it from Knox uv,
00:13:54.280 -->
00:13:55.440set the backend to be uv.
00:13:55.780 -->
00:14:00.300And then for your session, you specify which versions of Python, which groups, et cetera.
00:14:00.880 -->
00:14:01.220Off it goes.
00:14:01.300 -->
00:14:03.460I feel like this should be your topic, honestly, Brian.
00:14:03.480 -->
00:14:05.640I think I stole it from you somehow, effectively.
00:14:06.100 -->
00:14:06.760Why is that?
00:14:07.060 -->
00:14:09.140Just because you're so into testing.
00:14:09.320 -->
00:14:10.420And this is like right at the heart of it.
00:14:11.080 -->
00:14:11.480Okay.
00:14:12.100 -->
00:14:12.460What do you think?
00:14:12.740 -->
00:14:12.800Cool?
00:14:13.060 -->
00:14:13.980I think this is neat.
00:14:14.140 -->
00:14:16.640Yeah, I'm using like uv almost everywhere now.
00:14:16.900 -->
00:14:23.679And I actually, I used to recommend people like just average folks that are just starting Python
00:14:23.700 -->
00:14:25.620or they just need it for work,
00:14:25.830 -->
00:14:29.920I would recommend them just go to python.org and download it.
00:14:30.260 -->
00:14:31.720And I'm still kind of doing that,
00:14:31.790 -->
00:14:34.860but I'm leaning towards trying to teach people
00:14:34.890 -->
00:14:36.500how to use uv in virtual environments
00:14:36.850 -->
00:14:38.920because it's not going to be that long
00:14:39.250 -->
00:14:40.700after they start using Python
00:14:40.920 -->
00:14:42.200that they're going to want to use that anyway.
00:14:42.520 -->
00:14:43.260So, yeah.
00:14:44.180 -->
00:14:46.240Yeah, and recently we just covered this,
00:14:46.320 -->
00:14:47.840that one of the main things uv did
00:14:48.100 -->
00:14:52.259is now there's a Python version in your path
00:14:52.280 -->
00:14:54.700if you install a Python via uv,
00:14:54.970 -->
00:14:57.340which it used to just be in like some obscure place
00:14:57.570 -->
00:14:59.600hidden in like your user profile sort of thing.
00:14:59.600 -->
00:15:01.940It was hard to run it outside of a virtual environment.
00:15:02.300 -->
00:15:02.400Yeah.
00:15:02.940 -->
00:15:03.040Yeah.
00:15:04.160 -->
00:15:04.340Yeah.
00:15:04.720 -->
00:15:04.780Anyway.
00:15:05.190 -->
00:15:05.280Okay.
00:15:05.720 -->
00:15:05.780Cool.
00:15:05.960 -->
00:15:06.080Yeah.
00:15:06.360 -->
00:15:06.600Very cool.
00:15:06.860 -->
00:15:07.720Thanks, John, for sending that in.
00:15:08.400 -->
00:15:09.140Now over to you, Brian.
00:15:09.920 -->
00:15:10.260All right.
00:15:10.640 -->
00:15:12.520So let's take a look.
00:15:12.640 -->
00:15:16.020I've got a couple short-ish Django items.
00:15:16.090 -->
00:15:18.200So I thought I'd cover them together.
00:15:18.600 -->
00:15:21.440So the first comes from Johnny Metz.
00:15:22.240 -->
00:15:25.800And it's stop using Django's squash migrations.
00:15:26.220 -->
00:15:27.040There's a better way.
00:15:27.280 -->
00:15:29.260And actually, I didn't know about squash migrations.
00:15:29.380 -->
00:15:32.260I'm kind of new to Django, the Django world, new-ish.
00:15:33.360 -->
00:15:38.720But I like this article because I watched a pro, kind of an old hat,
00:15:39.380 -->
00:15:45.180when I was doing a session with somebody that knows Django way better than I do.
00:15:45.760 -->
00:15:50.299And I had a whole bunch of migrations because I was fiddling with
00:15:50.320 -->
00:15:53.080the database structure and everything.
00:15:53.200 -->
00:15:54.780And I was going back and forth, changing things.
00:15:54.940 -->
00:15:56.220And I had a bunch of migrations.
00:15:56.980 -->
00:15:59.060And he said, wait a second, just a second.
00:15:59.220 -->
00:16:00.040Let me do something.
00:16:00.100 -->
00:16:01.760And he just like, he did this.
00:16:01.860 -->
00:16:02.720So what am I doing?
00:16:02.900 -->
00:16:03.680What am I talking about?
00:16:05.019 -->
00:16:06.980So this is Johnny Metz.
00:16:07.080 -->
00:16:09.580He was recommending doing a clean reset.
00:16:10.260 -->
00:16:13.060So you fully migrate all your environments,
00:16:13.440 -->
00:16:14.620make sure everything's running well.
00:16:14.900 -->
00:16:17.360And then you delete all your migration files.
00:16:17.780 -->
00:16:18.380Seems crazy.
00:16:18.800 -->
00:16:22.260but you delete them all and generate a fresh migrations.
00:16:22.840 -->
00:16:25.720And then you've got just a new one.
00:16:26.320 -->
00:16:31.500So this creates a new 0001 initial for each app,
00:16:31.820 -->
00:16:37.800and then some apps might get a 002 or higher.
00:16:37.900 -->
00:16:41.300So you do this on different, it's going to do it on different apps.
00:16:41.600 -->
00:16:44.340But then you, so, okay, I'll just walk through it.
00:16:44.580 -->
00:16:47.460Fully migrate all your environments, delete all your migrations,
00:16:47.840 -->
00:16:52.420generate fresh migrations, then add data migrations,
00:16:53.080 -->
00:16:57.100temporarily disable automatic migrations during deployment,
00:16:57.540 -->
00:16:58.220reset migrations.
00:16:58.620 -->
00:16:59.500Okay, so it's not trivial.
00:16:59.700 -->
00:17:01.360Then re-enable automatic migrations.
00:17:01.900 -->
00:17:04.199So why would you do all of this?
00:17:04.199 -->
00:17:05.780This seems more complicated.
00:17:06.120 -->
00:17:10.800However, you end up with a really clean set.
00:17:11.020 -->
00:17:14.939So you've got a very clean migrations set at the end.
00:17:15.780 -->
00:17:31.480And 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.580So interesting Django article.
00:17:33.840 -->
00:17:34.920It is an interesting idea.
00:17:35.140 -->
00:17:40.180And certainly, I think if you've not pushed it to production, you know, you just like,
00:17:40.630 -->
00:17:44.640instead of having the 100 migrations you may have built over time as you built up the app
00:17:44.860 -->
00:17:49.280before you push it out live, like just get that down to a single migration, get the database
00:17:49.520 -->
00:17:50.480up and running, go from there.
00:17:50.840 -->
00:17:50.940Yeah.
00:17:52.000 -->
00:17:57.600I'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.660it up in here, but having migrations per application.
00:18:00.940 -->
00:18:01.040Anyway.
00:18:02.180 -->
00:18:06.840The other one is this comes from Adam Hill is DJ light.
00:18:06.840 -->
00:18:08.700And this is a fairly new project.
00:18:09.760 -->
00:18:14.740And it is how to use SQLite in production with Django.
00:18:15.140 -->
00:18:19.280So yes, you can use SQLite with Django, but there's some tricks.
00:18:19.440 -->
00:18:27.120So he wrote an article called the definitive guide to using Django with SQLite in production.
00:18:27.560 -->
00:18:33.000And then he decided to go ahead and he's still recommending that,
00:18:33.320 -->
00:18:35.180but there's this plugin to make it easier.
00:18:35.580 -->
00:18:39.820So with this plugin, you got a couple settings that you can change,
00:18:39.860 -->
00:18:41.020and it just runs with it.
00:18:41.200 -->
00:18:45.860So it's way easier setup if you want to use SQLite with Django.
00:18:47.239 -->
00:18:50.980And this little blurb here at the top says that
00:18:52.820 -->
00:18:55.540simplify deploying and maintaining production Django websites
00:18:56.000 -->
00:18:57.280using SQLite in production.
00:18:57.680 -->
00:19:03.280DJ Lite helps enable the best performance for SQLite for small to medium-sized projects.
00:19:03.680 -->
00:19:11.900It requires Django 5.1 or above, but I think SQLite is appropriate for a lot of Django.
00:19:12.180 -->
00:19:15.400A lot of people just start with Postgres, but anyway.
00:19:15.690 -->
00:19:16.500Yeah, definitely.
00:19:17.030 -->
00:19:24.100I 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.000especially with concurrent read-write sort of things.
00:19:27.320 -->
00:19:27.440Yeah.
00:19:27.540 -->
00:19:28.600So, yeah, very cool.
00:19:29.100 -->
00:19:32.820And following up on the squash migrations,
00:19:33.320 -->
00:19:33.960Pat Decker says,
00:19:34.330 -->
00:19:36.400sounds like a similar familiar to Git Rebase maybe.
00:19:36.740 -->
00:19:37.780Yeah, it does to me for sure.
00:19:38.120 -->
00:19:38.280Yeah.
00:19:38.420 -->
00:19:38.820Squashing.
00:19:39.130 -->
00:19:39.960Yeah, very similar.
00:19:40.740 -->
00:19:40.900Okay.
00:19:41.320 -->
00:19:42.080While you have the stage,
00:19:42.260 -->
00:19:43.060how extra do you feel?
00:19:43.700 -->
00:19:44.560I got a couple extras,
00:19:44.980 -->
00:19:46.040so we can just cover them.
00:19:46.360 -->
00:19:51.060So the first up is I've got a testing code episode
00:19:51.290 -->
00:19:51.760in the queue.
00:19:52.020 -->
00:19:53.200It's in draft mode currently.
00:19:53.940 -->
00:19:56.620FastAPI cloud with Sebastian Ramirez.
00:19:57.080 -->
00:19:59.260and it was a real fun talk with Sebastian.
00:19:59.390 -->
00:20:00.280This was recorded.
00:20:00.540 -->
00:20:01.740I can't even remember when it was recorded.
00:20:01.940 -->
00:20:03.520Maybe it was a few weeks ago at least.
00:20:04.090 -->
00:20:06.300I feel bad getting so slow to get it out.
00:20:06.560 -->
00:20:10.000But a really interesting article about FastAPI
00:20:10.140 -->
00:20:11.880and about FastAPI Cloud.
00:20:12.100 -->
00:20:14.380And Sebastian's just a joy to talk with.
00:20:14.560 -->
00:20:16.140So that'll be out later today.
00:20:16.580 -->
00:20:18.880I only have to rerecord the ad for it,
00:20:19.060 -->
00:20:20.720but not much left to do.
00:20:21.800 -->
00:20:25.060And then next up, pythontest.com,
00:20:25.090 -->
00:20:25.740a couple things.
00:20:26.320 -->
00:20:29.360I released a, I had a fixture.
00:20:29.980 -->
00:20:30.360When was this?
00:20:30.500 -->
00:20:31.9802013 that I started.
00:20:32.520 -->
00:20:34.240So this is what, over 10 years ago?
00:20:34.960 -->
00:20:37.980That I wrote a four-part series on pytest fixtures.
00:20:38.640 -->
00:20:43.980And I had been talking that I was looking at analytics.
00:20:44.560 -->
00:20:46.180And some of this stuff is still getting hit.
00:20:46.400 -->
00:20:47.960So I went and reviewed it.
00:20:48.180 -->
00:20:50.000And this series was a mess.
00:20:50.300 -->
00:20:54.580And I went ahead and like re, I didn't rewrite it,
00:20:54.880 -->
00:20:59.860But I went through everything and split it up into a more multi-part series.
00:21:00.050 -->
00:21:01.100A lot of these are really short.
00:21:01.270 -->
00:21:06.600I just wanted to keep one topic per blog post and make sure that it runs.
00:21:06.800 -->
00:21:09.820A lot of the stuff didn't even run on current pytest and current Python.
00:21:10.180 -->
00:21:12.120Now it all runs with current pytest and Python.
00:21:12.440 -->
00:21:14.740So there's a nice fixture tutorial there.
00:21:15.440 -->
00:21:20.920The other thing I wanted to bring up with Python Test is there is a bunch of stuff.
00:21:21.380 -->
00:21:26.100So 2013 up through this year, there was a bunch of stuff that was like formatted badly.
00:21:26.500 -->
00:21:30.480And I have gone through and made sure everything is mostly correct.
00:21:31.000 -->
00:21:33.300So if you see any, I think everything's working now.
00:21:33.660 -->
00:21:35.360So if you see anything weird, let me know.
00:21:35.570 -->
00:21:40.660I just, as I was reviewing this morning, I realized that in this particular post, I
00:21:40.850 -->
00:21:45.380refer to a fixture as fixture B and it's really resource B.
00:21:45.600 -->
00:21:46.380So I'll have to fix that.
00:21:46.590 -->
00:21:48.640But, you know, things like that shouldn't be too bad.
00:21:48.860 -->
00:21:49.920Anyway, that's all up to date.
00:21:50.110 -->
00:21:50.700Do you have any updates?
00:21:51.260 -->
00:21:54.720I have three extras, and I think they're really exciting.
00:21:54.880 -->
00:21:56.180They're going to be really cool for people.
00:21:56.480 -->
00:21:57.380So let me tell you about it.
00:21:57.480 -->
00:21:59.520First, brand new course over at Talk Python.
00:21:59.760 -->
00:22:01.180I'm really excited about this one.
00:22:01.340 -->
00:22:05.840Some of the most impactful courses that we create there are ones that take people from
00:22:06.000 -->
00:22:11.780like zero to one or one and 1.5 to two, like the first sort of steps, right?
00:22:12.180 -->
00:22:15.980And so this new course is called Just Enough Python for Data Scientists.
00:22:16.460 -->
00:22:16.740Oh, nice.
00:22:16.940 -->
00:22:20.200Python is kind of a stand-in for software engineering with Python, right?
00:22:20.240 -->
00:22:33.400So 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.060But I don't really know Git very well.
00:22:36.400 -->
00:22:38.220I don't know refactoring super well.
00:22:38.500 -->
00:22:39.880Reproducibility is still an issue.
00:22:40.490 -->
00:22:41.200Those kinds of things.
00:22:41.660 -->
00:22:47.660So 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.120And what can you safely ignore?
00:22:49.680 -->
00:22:49.760Right.
00:22:49.940 -->
00:22:52.320Like don't try to boil the ocean when you're getting started.
00:22:52.560 -->
00:22:54.040What can you just not pay attention to?
00:22:54.890 -->
00:22:55.880How do you write functions?
00:22:56.340 -->
00:22:59.820Create importable modules and packages to split up notebooks
00:23:00.300 -->
00:23:05.080from like one large notebook cell into a bunch of usable, testable, more readable pieces.
00:23:06.160 -->
00:23:08.380Debugging, reproducibility with like Docker and uv,
00:23:08.590 -->
00:23:13.060and even a little bit of agentic AI for like data analysis to like jumpstart your work.
00:23:13.200 -->
00:23:16.880So if people are interested in this, I highly recommend it.
00:23:16.920 -->
00:23:19.680It's an awesome course that I wrote over the last three or four weeks.
00:23:20.040 -->
00:23:21.320and I'm really happy to have it out.
00:23:21.700 -->
00:23:22.480That's pretty exciting.
00:23:22.840 -->
00:23:23.480I like the topic.
00:23:23.920 -->
00:23:24.260Yeah, thanks.
00:23:24.720 -->
00:23:24.780Yeah.
00:23:25.340 -->
00:23:25.580All right.
00:23:26.200 -->
00:23:26.780Speaking of uv,
00:23:27.000 -->
00:23:29.880I was just on with Will Vincent from Django Chat.
00:23:30.920 -->
00:23:31.420When was this?
00:23:31.600 -->
00:23:34.240This was live streamed four days ago.
00:23:34.660 -->
00:23:40.220And we did a whole one hour paired presenting sort of thing on uv,
00:23:40.480 -->
00:23:43.020why people might use it, compatibility, what's new.
00:23:44.020 -->
00:23:45.860I even did a thing like how to make your Docker builds
00:23:46.140 -->
00:23:47.620five times faster sort of thing,
00:23:47.900 -->
00:23:49.900or 30 times faster, depending on what you're using.
00:23:49.950 -->
00:23:51.720If you're using pip, it'll be 30 times faster.
00:23:52.070 -->
00:23:55.320So super neat, super neat stuff that people can check out.
00:23:55.370 -->
00:23:56.060And that's just on YouTube.
00:23:56.190 -->
00:23:56.820So I'm going to link to that.
00:23:57.340 -->
00:24:00.400And then last is I'm a fan of cursor
00:24:00.720 -->
00:24:03.380when I'm doing like super heavy AI programming.
00:24:04.060 -->
00:24:05.160Obviously a big fan of PyCharm
00:24:05.280 -->
00:24:07.400when I'm doing like focused development work, right?
00:24:07.560 -->
00:24:10.600But if I'm just like, I just need some heavy duty AI tools,
00:24:11.160 -->
00:24:14.840cursor and Claude Code has been getting a lot of traction lately
00:24:14.990 -->
00:24:16.560because it's like this terminal based thing.
00:24:16.590 -->
00:24:17.240You can use it anywhere.
00:24:17.700 -->
00:24:22.460Well, Cursor just came out with a Cursor CLI that you could set up.
00:24:22.580 -->
00:24:23.540That's pretty neat.
00:24:23.680 -->
00:24:25.620So use it in your IDE or any terminal.
00:24:25.920 -->
00:24:28.960Cursor, JetBrains, Android Studio, Xcode, whatever.
00:24:29.420 -->
00:24:30.260So pretty neat.
00:24:31.530 -->
00:24:36.840If 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.160It's in beta, but so far it seems pretty neat.
00:24:39.210 -->
00:24:41.620If you have a subscription, it just integrates with that.
00:24:41.800 -->
00:24:42.020Neat.
00:24:42.290 -->
00:24:43.260Yeah, those are my extras.
00:24:43.660 -->
00:24:44.760I have a joke for us as well.
00:24:45.280 -->
00:24:45.700Oh, good.
00:24:45.960 -->
00:24:46.060Yes.
00:24:46.580 -->
00:24:51.480And I think this AI thing I just gave a shout out to perfectly, perfectly blends into this.
00:24:51.630 -->
00:24:51.740Okay.
00:24:52.400 -->
00:24:54.300Control C, Control V remains eternal.
00:24:54.600 -->
00:24:56.680But what kind of dev are you?
00:24:56.800 -->
00:24:57.860This means something different, Brian.
00:24:58.320 -->
00:25:01.620If you're a new school developer, you copy and paste from ChatGPT.
00:25:01.960 -->
00:25:06.160If you're old school, you copy and paste from Stack Overflow.
00:25:06.660 -->
00:25:10.060And if you're ancient like you and me, you copy and paste from the documentation.
00:25:11.460 -->
00:25:13.900Wait, how do I copy and paste from a book?
00:25:14.260 -->
00:25:17.060Okay, I guess I'm so ancient that I'm not even on the chart.
00:25:17.260 -->
00:25:20.620Oh, that one takes a while because that's when you remember people talk about,
00:25:20.880 -->
00:25:24.480oh, I saw that code in the magazine that I typed it in.
00:25:24.800 -->
00:25:25.660Yeah, that was me.
00:25:26.120 -->
00:25:26.900That's how you do it.
00:25:27.120 -->
00:25:27.740That's how you do it.
00:25:28.520 -->
00:25:31.120You copy and paste with the fingers one character at a time.
00:25:32.100 -->
00:25:32.300Yeah.
00:25:32.780 -->
00:25:32.920Yeah.
00:25:33.260 -->
00:25:37.400Anyway, copy, control Z, control V, still important, but changing over time.
00:25:37.780 -->
00:25:37.960Yeah.
00:25:38.700 -->
00:25:38.980All right.
00:25:39.140 -->
00:25:40.740Well, thanks for the episode.
00:25:41.120 -->
00:25:41.700Thanks for being here.
00:25:41.900 -->
00:25:43.180And thanks everyone else for listening.
00:25:43.500 -->
00:25:43.700Thanks.
00:25:43.820 -->
00:25:43.960Bye.