Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds. This is episode 419, recorded February 4th, 2025, and I am Brian Aukin. And I'm Michael Kennedy. And this episode is sponsored by us. Check out our courses at either pythontest.com or talkpython.com. No, wait, that's right, isn't it? Talkpython.com will work. Yeah, that's right.
Also, thank you to our Patreon supporters. We don't thank them very much, but they do help with the show. So thanks. If you'd like to connect with the show, please hop on Blue Sky or Mastodon. And the links to both Michael and myself and the show are in the show notes. And if you'd like to join us live, it's Tuesday today, but normally it's Monday. Normally Monday at 10 at Pacific time. Go to pythonbytes.fm slash live.
And finally, we are getting some great feedback about our updated Beefy or Show Notes with deep dives. So in the email list, so if you'd like to get some background around all the topics we cover and a little more info than what we have in the show notes, join the newsletter. Just go to PythonBytes.fm, and it's really easy to figure out. Definitely is. You should check it out. And there's a lot of great content there.
And it's an email type, content type. I was trying to go into the first topic there. We'll get there. We'll get there. So yeah, if you're going to attach something, maybe we'd have a MIME type, like a graphic or zip file or something. So last week, this is like Groundhog Day, MIME types, mimetype.io. Remember I talked about that? Well, got some nice feedback from folks, including Rafe Guns, who
who said, "Hey, you mentioned MimeType.0. That reminds me of something that happened just last week. I need to map file names to this." And I thought, surely someone's already done this. And it turns out that the standard library already has a built-in MimeTypes. And you can ask it, "Hey, what is given this file name? What do you think its extension is?" So even better, right? Well, well, well, no, not so fast.
this sent me down such a rabbit hole okay so there are weird things that this mime types library does like there's not that many and especially for the common ones they it's a list of like a hundred or something you know but if you look at the implementation in c python for mime types what it does is it looks at a set of files that come with each different operating system raspberry pi ubuntu mac
Mac OS, Windows 7, whatever. It doesn't have a single built-in MIME type. Like it won't tell you what they are. It doesn't know what text.txt is. It doesn't know what HTML is. It just looks at these files, which is really weird to me because that means you get different answers for MIME types based on your operating system. Like Docker might, if you run Linux in a Docker container, it might give you different output than say desktop Linux and stuff. Yeah.
Just thinking for like 30 seconds around this, it seems like maybe you should build in all the known ones. And then if it overrides it, like something special about the machine configuration says this MIME type is something different, maybe consider overriding it with a local file definition, but just omitting them all, very weird. Plus it'll tell you things that are wrong, like that XML should be text/XML, not application/XML.
Okay. So that sent me looking. I'm like, well, that's not great. Surely there's something on PyPI. So I looked at for like Python magic and Python magic is awesome. What it does is you give it a file. It's based on lib magic because there's some kind of C library or something. So you got to install that with brew, which is kind of weird, but okay, fine. So you got that. And then what it does is you say, Hey, given this, uh,
this file, like this PDF, tell me what kind it is. And it says, hey, this is application.pdf. But the way it knows this is it goes and it actually reads the file. It doesn't just look at the extension. It goes, ah, you said it's a .jpg.
But when I looked at it, I inspected the binary header for the image and it looks like it's a PNG. So we're going to tell you it's PNG. Super helpful when you're talking about the file system. Super duper unhelpful when you're building web applications. You know, like when you need to specify the MIME type. Because what if your image lives in S3 storage?
How are you going to ask what I should return if I want to link, just redirect someone to it? Got to download it from S3, feed it to the thing, throw away the temporary file, and send it back. And all these other ones, they all look at the files. If you don't look at the file, how are you going to know? It's like, OK, if you want to be super thorough, yes. But what if the file's in a database, the file's in remote storage? You don't want to go get the file. You want to do your best guess, right?
So Brian, this has led me to create github.com slash Mike C. Kennedy slash content dash types available on PyPI as content types. So it does exactly what you would think. It tells you given an extension, what is the MIME types? It even includes a CLI. So you can say like after UV tool install it, you can just say type content types anywhere in your terminal, give it any form of file name, and it will tell you what comes out.
That's kind of handy. So if you're curious, it has way more content types than the MIME types. And they're correct. That's always good. We'll talk about that in a second. But you just say content types, get content type. You give it some kind of file name, as long as it has an extension. It doesn't matter if it's a HTTPS to some file or it's just a file path on your hard drive. If it has an extension--
we'll be able to tell you what its MIME type is. So is this just like a big lookup of extension to type or something? Pretty much, yeah. It's like a massive, massive lookup of those things. But the thing is gathering them all up, right? So for example, if you look at the built-in MIME types, like, well, why don't you just have MIME types and use that? One, it varies. But two, it's wrong about things like if you ask MDN, Mozilla Developer Networks, what .xml should be, it says it's application.xml.
It used to be this older text XML. It's not anymore. But the built-in Python one says it's the old style. It's also missing things like TGZ and GZ zip and FLAC and EPUB and all these types you would expect. So anyway, I didn't spend that long. I spent a few hours building this thing. But I'm like, there, I fixed it. It doesn't depend on the operating system. It doesn't have to read the file. You don't have to download it from S3 storage to tell you what it is.
It just given a file name. It'll tell you what the content type is or MIME type. Somebody asked, why don't you name it MIME types? I'm like, I don't know really how to import something that overrides a built-in as a third-party package and make that useful experience. You know what I mean? So anyway, that's what it's called. So hopefully this helps people. It's built in Python. It has something like 180 different types and it has,
31 types that are not known to the built-in library. Common stuff, like I said, like fonts or M4As, audio files, or WebAs for other audio files, or W, a lot of stuff, right? RARs, TTF, it seems like you should know what that is.
Anyway, I present to the world this project I worked on over the weekend. Nice. I like it. Yeah. Thanks. It always threw me that M4As were audio MP4s. Yeah, I know. It's M4A. It's not MP4. Anyway, but...
Since I work with audio as well. Hey, good job, I think. And let's talk about Django a little bit. So Wagtail, Wagtail 6.4 is here. There's an announcement. Enjoy a smoother content experience with Wagtail 6.4. I don't actually use Wagtail 6.4 or Wagtail, but I play one on TV. No, but there's...
I'm glad Wagtail's here. It's a really cool platform, content management system built on top of Django. Why am I bringing this up? It's great that they've got a release and there's some cool stuff. But the thing that I really am excited about is if we go down, it says this version incorporates Django Tasks library. And that's the cool bit, according to me.
So the Django task library, and there's a release notes too that we'll link to. It also is pretty excited about the Django tasks. So what are Django tasks? Let's see. Oh, yeah. Oh, by the way, some of the cool things about Wagtail, it's used by NASA and Google and NHS. And some of those are still operating.
So Django tasks is a is a if we look at it, it says it's a backport. But it's, it's really the it's really the implementation that you can play with right now of a thing defined in depth 14. And that's a Django enhancement proposal for background workers. And this is accepted. And
One of the things, whether you love or hate it, Django enhancement proposals don't happen quickly. Partly it's because we really they do LTS support and they really don't want to break things in the end and they just don't happen fast. But that's okay. We love you Django.
but the so django tasks is background workers um around um yeah but just background workers so like you're not in the normal loop um there's a cool i was following this this this rabbit hole and there's this cool um on the uh django tasks uh forum bringing background workers into django core um there's a talk um that was given at django con europe 2024
And this is a great talk. Listen to this talking about how really the normal, the cycle of a web page of like you do a request and a response that doesn't work for a lot of stuff and you need background tasks and other tasks to run at different times or even just later. Like, you know, you don't have to wait. We'll work on it.
So that's cool. And so now the implementation of this is being done in the Django test application, and you can use it. And since Wagtail is using it, I think it's pretty stable, and I think people should feel free to use it and provide feedback if you run into any issues. So they're really ramping up trying to get all the kinks out. So pretty cool. Yeah.
Yeah, that's really cool. I think a lot of times people overthink how much infrastructure you need to say, run something in the background. Like, oh, this thing takes five seconds. And if we do it on the view call, then it's going to slow down the website all bunch. So let's set up Celery and Redis and a queue and like, whoa, it was running all on its own until just a second ago.
And things like this, where it's kind of just a background thread. Like, OK, well, we just kick it to the thread, and maybe you want to log it to a database or send an email, but you're going to take a second. So just let that happen. It's great. And also, for people that are thinking about using this Django Tasks project to put something in place,
I think that's where I would lean, partly because that's where Django eventually is going. But also, you've got Wagtail as an open source project. You can look to see how they're doing it. So you can look to see how the project's implemented. Yeah, excellent.
Excellent. Excellent. And by the way, Brian, are you familiar with all the WordPress drama? Have you been tracking this? Yeah. Oh, it's so insane. People, if you haven't been tracking this, WordPress has gone off the rails. So maybe if you're out looking for, I don't know, a different CMS instead of WordPress, Wagtail, check it out. Less drama, less drama. Or if you didn't want to do that, you could build it yourself, right? Definitely. So there's a really nice article from Armin Roeneker and he
And he's doing a lot of great writing lately. So I'm really, really enjoying it. Basically, this is something of a rant and a call to arms, if you will, to depend less, depend less. Saying, look, there's a lot of pressure and encouragement to say, if there's anything that you can use as a third-party dependency, rather than building it into your own code, do that. That's how you...
stay agile unless it's not, unless it just becomes a drag. You know, if you have one function that you need and
there's some library that has a hundred functions and it does a whole bunch of stuff but it has that one thing you need you could depend upon it but then what if you want to go to python 3 14 and it doesn't upgrade in time and you're stuck right and you know one library that's one thing but then you multiply that times 100 and it gets real complicated real quick so he pulls out an example and says look what about terminal size this these mostly speaking in rust terms but it equally applies to python so that's why i'm covering it it says i
Terminal size is a package that you can use and it tells you the size of the terminal, like 80 by 25 or 47 by 100 or whatever the rows, columns of the terminal is. It tells you that, right? Well, that thing has been pretty much unchanged for a long, long time, but it's had 26 releases because the stuff that it depends upon has been changed.
has been turning and has to be, you gotta use a newer dependency of this library so that your thing will build on the new version of the runtime, right? Instead of just being basic, right? If terminal size itself hasn't changed,
Why do you have to keep rebuilding it, re-releasing it? Here's a funny term, but big supply chain will tell you you must do it this way. Big supply chain. Yeah, exactly. It's like big tobacco, big supply chain, as well as open source people, right? They're like, oh, you know, why are you putting this in here? You could just use this library and this pull requests or similarly for code reviews at enterprise places. And there's one quote I want to read to you all about it and then kind of leave it there. It says,
It's time to have a new perspective. We should give kudos to engineers who write a small function themselves instead of hooking in a transitive web of packages. We should be suspicious of big dependency graphs. Celebrated are the minimal dependencies, the humble function that just quietly does the job and the code doesn't need to be touched for years because it was done right.
What do you think, Brian? I take issue with this. Okay. Okay. I get the idea, and I agree with, for some things, like something like terminal size, I don't know how to determine a terminal size, but I imagine that I would probably pull in a library or something to do that, but I wouldn't expect that it would have to pull in a lot of stuff. So if, like...
I really, you know, there's a lot of like, um, there's a lot of stuff I depend on because I don't want to figure it out. Um, but I also don't really want those things to be too deep, you know, for instance. Um, but that's our, that, and that, that's the, that's the trade-off you, you either, either, you know, they, so what's the problem. So what's the problem writing yourself is because you don't, you're not, if you're not the expert in this field, why would you think you got it right? Um, uh, it
I wouldn't necessarily think it was right just because there's a package for it, but I know I'm not an expert at it, so that's why I grabbed a package. And also, I don't want to think about security problems and other things in the future if there's an issue with certain packages. Like, why do people use stuff like Redis? I'm sure you could just write a caching system on your own.
There's reasons why we use these packages. Yeah. And to be fair, Armin says, look, it's not black and white. There are important libraries that solve hard problems like web frameworks and graphics libraries and things like that. But I think it's more like left pad. Yeah. Do we really need a library with three dependencies to just pad a string? Probably not.
I don't think we do that that much in Python, though. Or maybe we do. Not as much. Not as much. But I'll give you an example. So I started working with Postmark. I'm trying to move away from SendGrid. Not going as good as it could, I suppose. So I'm like, oh, Postmark. Awesome. This is similarly priced. Seems to be pretty reputable. They really cracked down on spammers, which is the problem with
Syngrid, from what I can tell, at least my personal experience. So it says, okay, look, if you want to use it, there's official libraries. You just go over here and grab one. Like, boom, there's a Rails gem. There's a .NET Postmark library. There's a Java one. There's a PHP one. There's a Craft. What the heck is Craft? But anyway, there's one of them. There's a Node.js one. There's a CLI one. There's one for WordPress. There's one for Grunt and one for Zapier. The most popular programming language in the world is missing, but you know,
I don't know, whatever it is, whatever. So probably PyPI, probably PyPI has one, right? Postmark email. Sure, that's cool. Okay, so there's this one called Postmarks, the top one, updated 2017. It has a single sentence, no documentation.
If I go to it, I guess I could download it. Let's see. Let me try another one. So what about this Postmarker one? What versions of Python? Oh, this actually pretty-- this works pretty well. But you start looking through these, and a lot of them are like, oh, man, I don't know. It's OK. Like, here's one something for Django from 2011, one from Flash from 2020, right? But I wanted one for Cort, right? Async. It doesn't really matter. It's Cort. I want one that supports Async.
OK, here we go again. So I could try to work with one of those libraries and go, hey, guys, can we think about adding an async API to this? Or you can go to ChatGPT Pro. Do you know what the Postmark API is? Yes. Create me one that does async and an async IO-based one that uses HTTP x-rays implementation. Bam. Got it. It works fine. You can stick that in your code and off the races you go. Right? And I don't have to worry about whether their library supports Python 3.14 when it comes out.
or not. And there's no security things because it's just me and Postmark having a little chat and things like that. So I think, and I'm not saying like, don't use packages, don't contribute packages. I mean, literally I opened the show with like, here's my new package. But I think there are also, it's easier than ever these days to go, I need one function that does this thing. I like call this one API endpoint, like give me that function. Boom, here it is. So I don't know. I think there's some balance to be had.
Yeah. Also, good API docs. It might be that Postmark just has pretty decent API docs and you can just build it yourself anyway. I was going to build it myself and then I'm like, "Well, let me ask Chad." Yeah, sure. See if it gets it close and I'll tweak it if needed. I'm like, "No, it got it exactly right."
- Well, that's cool. - It even made the client not just use HTTPX, but it even made the async client an async context manager. So I can say async with Postmark client, da, da, da, da, da, off it goes. I mean, it was sweet. - Yeah, what I hope, I hope that people like Postmark and other services that have APIs that we're using, I hope they keep the documentation good.
and not think that people are just going to use ai to generate the stuff anyway so you don't need the documentation we still need the documentation because sometimes it's wrong or we have bugs or something has to be debugged so
anyway yeah and by the way if there was an official python one that had async support i would have more than gladly used it i didn't want to create my own it just doesn't exist right and so maybe we could turn this around a little bit and say if you're out there listening and you work for a company like postmark that has an api and you're like well it's too much to create an api uh client in python i bet it's not if you ask yeah well
- Yeah, but then you have people in-house to review it and say, yeah, that's probably what we want. - Right, then open source it and people can contribute to it. Yeah, but I think the zero to one, like, oh, we're not gonna create it for this. We'll just give people the docs and let them rewrite it like a million times across all the developers. I don't think that makes as much sense as it used to 'cause it's not that hard to create one these days. - Yeah, yeah, agreed, cool. - Yeah, anyway.
Thanks, Armin, for the cool article. Talking about building packages, though, I was curious what back end, build back end you used.
Do you use setup tools or Hatch or Hatchling? I use Hatchling for the build backend on my pyproject.toml, and I use uvbuild uvpublish as the workflow. Okay, cool. I haven't done the uv... I've done uvbuild, but I haven't done the publish bit before. However, so pyproject.toml, we've been following it on...
the rise of PyProject.toml on the show. And there's this, I'm cracking up, there's a blog from Bastion Venther. Sorry, Bastion. The title of the blog still don't have a title, which is an awesome title for a blog. Just saying.
uh he did this investigation both last year and this year and uh it's about how with the popularity of build back ends for projects using project.toml so this is the second second version um kind of a fun just little data set um
He actually uses dataset, nice. But the results are interesting, I think. I'm gonna pull up from last year and this year, so we get the same graph. Okay, so last year, we had Setup Tools was definitely in the lead, Poetry, Next, Hatchling, and then Flit, and then Other was about the same as Flit, maybe a little bit bigger. And then this year, looking at the graph,
Again, sub tools, poetry, but there's not as much growth in poetry. Hatchling is growing a lot more now.
And then that's a good job with that one. Let's down. And, and then the other is actually bigger than flip. I don't know what all the others are. But anyway, the what takeaway there's some, and then there's some, the plot shows a relative distribution over the quarters. And you can really see there that hatchling is really growing and, and flits actually on the decline. Looks like, looks like poetry is kind of on the decline as well. A little bit. I,
I think I would see, I think there's just a lot more projects now. But, but I think hatchling is sort of taking some lead. I, in this, this, this isn't really that surprising to me because I, I, I think that set up what a big decline in setup tools for a while was because flit and hatchling were working so much better, but setup tools had some updates with being able to use it with a pipe project at Tomo better. And, and those updates, I think have improved.
things. So I use both now. I'm using hatchling for some projects, especially when I want fine control. But if it's really just a really simple thing, especially if I'm doing it in a corporate setting, I'll probably use setup tools because it's more mainstream. People know about it more. I don't have to explain anything. So...
Just interesting looking at the trends for backends. Yeah, that's interesting. I wonder what the default behavior for different projects. If there's certain projects that will create like popular cookie cutter templates or other things that make an outsized impact on this.
I'm not sure, nothing comes to mind, but there could be something like, oh, this thing would be way lower except for it's used in this project that's used by so many people or something. - Yeah. - It would be interesting to know. - What is, when you say, like, I can't remember, oh, UV has its own, right? So if you say, does UVA have its own build backend? Is it a build backend? - Not that I know of.
It just will build any PyProject.toml using the specified build backend, as far as I know. So for mine, I put hatchling in my PyProject.toml. Then I just say uv build, and it
it does it. Yeah. I'm just like, you UV has a UV in it. So you can initialize that pipe project. Tom was curious what back end it is. Oh, I have no idea. I have to play with that. You do your extras and I'll, I'll tell you the answer. Okay. Um, I'll go to the, I've got a couple extras. Um, first off I'll jump ahead. Uh,
So one of the things that we've got with Python bytes, and I think you do this with Talk Python to Me as well, is there's a episodes page that lists all the episodes. I mean, it's one line each, so why not? Just list them all. So if you're curious about an old episode, you can take a look. I wanted this for testing code. So testing code used to be something like this. If you go to all episodes,
It'll show the title of the episode and the information. And then you see 30 of them. And then if you want to see more, you go to the next page. But I've got 225 episodes still.
why, um, you have to, that's a lot of clicking to go through all of them. So the, the update I've got is that I, um, I'm, I'm handwriting this, but it's not that hard. Um, I've got an archive page now that has all episodes. So you can see all episodes of testing code. Um, they're reverse ordered, uh,
And I think that's right for season one because there's a lot here. Season one was long. Yeah, I know. Nine years, 223 episodes. Yeah, whatever. Time for season two. And it'll probably be shorter than nine years for season two. We'll see. Probably.
but I might reverse these and have them one, two, three instead of three, two, one. We'll see. Anyway, uh, that's my first extra. The second extra is something completely different. It has nothing to do with, uh, with, uh, Python. I just came across this thing called name grapher. And, um, uh, and I think it's, it's around about like us names. And, uh, cause I was curious why we did where there weren't any Brian's around anymore, but the peak of Brian was 1970. Uh,
And I looked up Michael also. Yeah.
Michael's been popular. I got a little broader distribution, but still extremely 70s kids. But it was the number one name in the 60s, 70s, and 80s and 90s, I think, or something like that. It's been number one for a long time. So you're popular. There's a lot of money. My wife always jokes that if she yells my name in a supermarket, like three guys will turn around. Yeah. Yeah.
Anyway, it's kind of fun to look up some names. Anyway, that's my answer. Interesting to apply to yourself. And if you're going to have a kid, you can think about, you can put your considered names into there and see what you get. Yeah, we thought we were being clever with a name and it was not clever. Hey, I...
I think the reason, if you look at your daughter's name, it was spiked right around her age, right? When she was born. But I imagine that parents, we think of other parents that we know to a large degree, right? When you're having a younger kid, you're like,
Okay, well, I don't know a lot of people with such and such names, so that must be kind of unique. I'll do that. But it's unique for your generation, but not for the coming one or something, right? Exactly. So you got to look for something that's unique for both. So like my recommendation for a girl's name, Esther. Like no Esther's around. Well, there's some, but not very many. And it may be featured in a Jane Austen novel.
given that it's popular in the 1800s. Okay, there you go, ethyl. There's not going to be any other ethyls at the school. Oh, yeah, the long tail of ethyl is thin. Okay, do you have anything extras for us? Nothing other than real-time follow-up. So here's what I got for you. I did a quick UV init video
And I got a very simple thing, pyproject.tomahawk, that just says a readme. It requires Python 3.13 and empty dependencies. And so I added requests, uvadd. And then it added-- did it add-- that made it add a new version. That's funky. Anyway, it added a version because of that.
oh nice and it added uh the dependencies to just add requests or whatever but it does not specify a build backend weird because maybe you're not going to publish it maybe it's just i don't know right yeah right maybe it's just for you just want a little local package like a mono repo sort of deal i don't know yeah also you can i think you can just push those up anyway uh
I wonder what happens. Anyway, this is what I found. This is what I've discovered by using the latest, nearly latest UV. Yeah. I'm having fun with UV. Yeah, me too. Definitely, definitely. You know what else is fun? A joke. Yeah, let's do a joke.
All right. This one celebrates, in quotes, getting a job or not getting a job. And it's entitled The Long Path to Rejection, in parentheses, for software developers. So for a normal person, this might be really short. Send a CV. Get rejected. And it has this graphic of stepping on a rake. Whack. And you're like, oh!
And then for the software engineer, you got to do more. It shows him like kind of, this is free Brian, like kind of grinding a rail on a rake instead of a skateboard. Send us a CV, interview with HR, interview with the developers, technical interview, whack, get rejected. This is great. He's doing a kickflip all the way down the stairs with a rake. And then gets rejected. And then get rejected. I think that would be enough, wouldn't you? Yeah. But somehow, somehow it is not.
Yeah, I never mastered the kickflip, but I did master trying the kickflip and falling down and getting lots of blood from that.
I mastered the amazing back landing when you go on the skateboard and it shoots out in frontwards, you just land flat on your back. Like, Oh, there yourself. Uh, last, last thought of the show, Christian Letterman says the default is set up tools for a project tunnel, which, you know, defaults are powerful in terms of keeping people doing that. Yeah. That might be the 50% maintain, maintainings people. And you know, to be honest, since UV came around, I don't really think about backends much anymore. Um, uh,
I just kind of use UV. Yeah. All right. And Marco out there says, maybe this is a podcast you could start instead of testing code, skating code, Brian. Skating code. Yeah. Skater go and code. Skatership. Skatership. All right. Cool. Bye. Bye.