#447: Going down a rat hole
About the show
Sponsored by DigitalOcean: pythonbytes.fm/digitalocean-gen-ai Use code DO4BYTES and get $200 in free credit
Connect with the hosts
- Michael: @mkennedy@fosstodon.org / @mkennedy.codes (bsky)
- Brian: @brianokken@fosstodon.org / @brianokken.bsky.social
- Show: @pythonbytes@fosstodon.org / @pythonbytes.fm (bsky)
Join us on YouTube at pythonbytes.fm/live to be part of the audience. Usually Monday at 10am PT. Older video versions available there too.
Finally, if you want an artisanal, hand-crafted digest of every week of the show notes in email form? Add your name and email to our friends of the show list, we'll never share it.
Michael #1: rathole
- A lightweight and high-performance reverse proxy for NAT traversal, written in Rust. An alternative to frp and ngrok.
- Features
- High Performance Much higher throughput can be achieved than frp, and more stable when handling a large volume of connections.
- Low Resource Consumption Consumes much fewer memory than similar tools. See Benchmark. The binary can be as small as ~500KiB to fit the constraints of devices, like embedded devices as routers.
- On my server, it’s currently using about 2.7MB in Docker (wow!)
- Security Tokens of services are mandatory and service-wise. The server and clients are responsible for their own configs. With the optional Noise Protocol, encryption can be configured at ease. No need to create a self-signed certificate! TLS is also supported.
- Hot Reload Services can be added or removed dynamically by hot-reloading the configuration file. HTTP API is WIP.
Brian #2: pre-commit: install with uv
- Adam Johnson
- pre-commit doesn’t natively support uv, but you can get around that with
pre-commit-uv
$ uv tool install pre-commit --with pre-commit-uv
- Installing pre-commit like this
- Installs it globally
- Installs with uv
- adds an extra plugin “pre-commit-uv” to pre-commit, so that any Python based tool installed via pre-commit also uses uv
- Very cool. Nice speedup
Brian #3: A good example of what functools.Placeholder from Python 3.14 allows
- Rodrigo Girão Serrão
- Remove punctuation functionally
- Also How to use functools.Placeholder, a blog post about it.
- functools.partial is cool way to create a new function that partially binds some parameters to another function.
- It doesn’t always work for functions that take positional arguments.
- functools.Placeholder fixes that with the ability to put in placeholders for spots where you want to be able to pass that in from the outer partial binding.
- And all of this sounds totally obscure without a good example, so thank you to Rodgrigo for coming up with the punctuation removal example (and writeup)
Michael #4: Converted 160 old blog posts with AI
They were held-hostage at wordpress.com to markdown and integrated them into my Hugo site at mkennedy.codes
Here is the chat conversation with Claude Opus/Sonnet.
- Had to juggle this a bit because the RSS feed only held the last 50. So we had to go back in and web scrape. That resulted in oddies like comments on wordpress that had to be cleaned etc.
- Whole process took 3-4 hours from idea to “production”duction”.
- The chat transcript is just the first round getting the RSS → Hugo done. The fixes occurred in other chats.
This article is timely and noteworthy: Blogging service TypePad is shutting down and taking all blog content with it
This highlights why your domain name needs to be legit, not just tied to the host. I’m looking at you pyfound.blogspot.com. I just redirected blog.michaelckennedy.net to mkennedy.codes
Carefully mapping old posts to a new archived area using NGINX config. This is just the HTTP portion, but note the
/sitemap.xml
andlocation ~ "^/([0-9]{4})/([0-9]{2})/([0-9]{2})/(.+?)/?$" {
portions. The latter maps posts such as https://blog.michaelckennedy.net/2018/01/08/a-bunch-of-online-python-courses/ to https://mkennedy.codes/posts/r/a-bunch-of-online-python-courses/server { listen 80; server_name blog.michaelckennedy.net; # Redirect sitemap.xml to new domain location = /sitemap.xml { return 301 <https://mkennedy.codes/sitemap.xml>; } # Handle blog post redirects for HTTP -> HTTPS with URL transformation # Pattern: /YYYY/MM/DD/post-slug/ -> <https://mkennedy.codes/posts/r/post-slug/> location ~ "^/([0-9]{4})/([0-9]{2})/([0-9]{2})/(.+?)/?$" { return 301 <https://mkennedy.codes/posts/r/$4/>; } # Redirect all other HTTP URLs to mkennedy.codes homepage location / { return 301 <https://mkennedy.codes/>; } }
Extras
Brian:
- SMS URLs and Draft SMS and iMessage from any computer keyboard from Seth Larson
- Test and Code Archive is now up, see announcement
Michael:
Joke: Do you know him? He is me.
Episode Transcript
Collapse transcript
00:00 Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds.
00:05 This is episode 447, recorded September 1st, 2025.
00:10 And I'm Brian Okken.
00:11 And I'm Michael Kennedy.
00:12 And this episode is sponsored by DigitalOcean.
00:15 Thank you, DigitalOcean.
00:17 And you can get a $200 free credit, and there's a link in the show notes,
00:21 but we're going to talk about that more later in the episode.
00:24 Of course, follow us or send us info on the socials on Blue Sky or Mastodon.
00:30 Links are in the show notes as well.
00:32 And if you'd like to listen, watch the show live, head over to pythonbytes.fm/live.
00:37 And that's the link also if you just want to see it after the fact.
00:41 If you want to look at the video, look and see what we're looking at.
00:44 And finally, please sign up for our email newsletter list.
00:49 Go over to pythonbytes.fm and hit the newsletter link, and we send you all the links that we talk about in every episode in an email and a bunch of background information, too.
01:02 All right, Michael, what are we starting with today?
01:04 You know, I'm afraid.
01:06 I'm really afraid, Brian.
01:06 I'm sorry, but I might be taking us down a rat hole.
01:10 I really might.
01:12 Oh, no.
01:12 I want to talk about Rathole, this tool.
01:15 So Rathole is a, you probably have heard of ngrok.
01:19 right? Yeah, we've talked about it. Yeah, we've talked about it before and it's super useful.
01:24 One of the things that is a real big challenge a lot of times is I need to let somebody or something
01:30 access an API. Let me give you two really big examples that are useful for this. One is web
01:38 hooks. You want to do e-commerce or it doesn't really matter. Anything that has to do with a web
01:43 hook where you're on the receiving end, you're creating the web hook. That's a public website
01:48 or service that's going to call your webhook.
01:50 It needs a public page to access that.
01:53 Well, do you want to like try to open up all the different firewalls on your machine
01:59 and your NAT router and then map an IP address and then give that to that thing?
02:03 No, just don't do that.
02:05 But you need somewhere where you can type in a URL and say, here's my URL for the webhook
02:11 when a signup happens or a thing, whatever, right?
02:14 Whatever the webhook's triggering.
02:15 Yeah.
02:16 So you need a public thing.
02:17 So with Ingrok and Rathole and other tools, what you can do is you can say, create me
02:22 based on this domain, basically an SSH tunnel or something to that equivalent that goes back
02:28 into my machine so that then you can share that URL and basically say, I want that port
02:35 to map over to my web app.
02:37 And you can literally run PyCharm, set a breakpoint, go to the external service, make
02:43 it do a thing, and then boom, you're debugging through and you're checking it out.
02:47 It's really, really nice.
02:48 So Ngrok is great, but people may have noticed I'm on this self-hosting Rathole itself, if you will.
02:55 So I don't know, there's just something about Ngrok.
02:58 They've changed their services a bunch and I'm not super psyched about it.
03:01 So I'm like, well, what else is out there?
03:03 And Chat and I had a little conversation about it and we decided that this is one of the really
03:08 nice high-parity features, also written in Rust, more high performance than some of the other ones
03:14 like FRP and Ngrok, it calls out.
03:17 Okay.
03:18 So what I did is I set this up onto my machine, onto my server, and someone runs Python Bytes, and just said,
03:25 they just run in the background.
03:27 And I've set up the certificates so that I can just type Rathole with a port number.
03:32 You know, on my terminal, I just open up and say Rathole like 3,000 or let's say Rathole 5,000.
03:38 And then I have a port, port map, URL map, automatically over to like say any Flask app that I run.
03:46 How cool is that?
03:47 And it's completely self-hosted.
03:49 And here's the thing.
03:49 You might think, oh, self-hosted, all the stuff you got to deal with.
03:52 It's a single Rust binary that runs in Docker.
03:55 And let me see.
03:56 I'll give you up to the date stats if I can find them, if it's not going to take too long.
04:01 The last time I checked, it was about three megabytes of memory usage.
04:06 What is the rat hole doing right now?
04:08 Oh, my God.
04:09 The rat hole is out of control.
04:10 It's up to 11 megabytes of memory usage on a 16 gigabyte machine.
04:14 I think it's going to be okay.
04:17 isn't that cool though so it's it's just got like um you know a docker container that i didn't even
04:22 have to do any docker stuff i just set up like a little compose file to map all the settings over
04:26 so that i don't have to deal with like passing them every time i run it you know and just set
04:30 it up as an auto start daemon but yeah i just set that up and off it goes cool no so when you're not
04:38 so when you're not using it do you turn it off or is it just always sort of running if it took a lot
04:43 of memory or resources or something, I would turn it off, but it's 11 megabytes.
04:48 Okay.
04:49 And so it's really, like, let me give you a sense of, like, other stuff that's running
04:55 on the server.
04:56 So right now we have MongoDB, which is using 1.3 gigabytes.
05:01 We have Talk Python, which is using 927 megabytes, so a gigabyte.
05:08 What's Python Bytes is running at 590 megabytes.
05:11 So, you know, like 11 out of these is like, it doesn't even show up on the radar, right?
05:16 Like you couldn't even notice if it's running or not.
05:18 And so because of that, no, I just leave it running.
05:21 Okay.
05:22 And then like, but on your, okay, so it's running something on your server and then something on your laptop also?
05:27 Yeah.
05:28 So there's a command that you can run locally.
05:31 And I think I don't have it set up on my streaming computer.
05:34 I have it on my dev one.
05:35 So I can't look at it real quick, but I'm pretty sure I just set it up to run the Docker.
05:41 image just sharing ports in the right way so i just do a docker run command to say share that
05:47 port to this port when i when i do the map command and so i don't even really have it installed but
05:52 yeah it's just a super small binary that runs okay this sounds really neat i like it yeah it's a tiny
05:58 bit of a pain to set up but it's not it's not too bad all right yeah well i want to shift gears
06:04 completely i guess something that something else that sometimes is a pain um maybe i'm trying to
06:10 do a transition here. Let's talk about pre-commit. So we have, we, I know we've talked about pre-commit,
06:15 but I don't think we've brought it up lately. And one of the, one of the things is I used to use
06:21 it a ton and then I moved a lot of my tooling to the, to CI and don't run it as much anymore.
06:28 However, I'm going back to using it a lot. So pre-commit just as a reminder, it's a tool. Well,
06:34 there's this notion of pre-commit, which is a pre-commit hook for Git, so that whenever you
06:41 commit something, you can assign pre-commit hooks. There's a project called pre-commit,
06:45 which is something that's written in Python, but it allows you to easily set up a whole bunch of
06:56 these pre-commit GitHub hooks. So Python project and the hook thing. Okay, so why am I bringing
07:03 And you can do things like hook up linters and you can run tests and stuff, but I generally don't do that as a pre-commit hook.
07:10 I'll do linters and other stuff like that.
07:13 Yeah, I don't think I would ever set up tests as a pre-commit hook.
07:19 I mean, I guess you'd say disable the hooks to check in the fix for the hook and they're slow and there's just a lot to it.
07:26 But yeah, I agree with the stuff you're running.
07:29 So one of the things is pre-commit doesn't by default have an official way to use uv.
07:37 It doesn't natively support uv.
07:39 And I, like a lot of people, are using uv to install stuff because it's just so fast.
07:45 Instead of pip install, I do a uv pip install.
07:50 So what we're talking about is an article from Adam Johnson talking about pre-commit install with uv.
07:57 as he puts it, the installation guide for pre-commit isn't obvious.
08:03 It's not terrible, but it's not obvious how to get things set up.
08:06 But he's recommending using uv tool install pre-commit with pre-commit uv.
08:12 So this is another project called pre-commit-uv.
08:17 And this is a couple things.
08:19 This is both an extra thing for pre-commit, but yeah, I guess that's it.
08:24 It's a plug-in for pre-commit.
08:26 But what, so what you're getting with this is you're installed with, if you do uv tool install,
08:33 you're installing pre-commit with uv, but then you're also all the extra things. So these extra
08:39 tools, like, like hooks for linters and all this sort of stuff that gets installed with pre-commit
08:45 with pip normally, but this extra pre-commit uv will allow it so that all of your tools are
08:50 installed. If they're Python based tools get installed with uv as well. So essentially just
08:55 speeding up this whole tool chain.
08:57 And if you switch it around with a bunch of projects, it makes sense to be able to update that stuff quickly
09:05 and install it quickly.
09:06 So there we go.
09:07 I love it.
09:08 uv for the win.
09:10 I'm actually talking with Charlie Marsh tomorrow, but talking about PYX, the server-side equivalent of uv.
09:16 So that's cool.
09:17 I'll be looking forward to listening to that one.
09:22 Another thing that is pretty awesome is our sponsor, DigitalOcean.
09:26 Absolutely.
09:27 Let me tell you about DigitalOcean.
09:30 Definitely a big fan of theirs.
09:31 And this episode is brought to you by DigitalOcean.
09:35 They're a comprehensive cloud infrastructure service that's simple to spin up, even for the most complex workload.
09:42 And it's a way better value than most cloud providers.
09:46 If you're using AWS, because everyone uses AWS, you might seriously consider using DigitalOcean.
09:52 It will save you so much money.
09:54 And you don't get to in the headlights.
09:57 There's 300 services.
09:59 How do I put them together?
10:01 It's nice and simple and powerful.
10:02 So at DigitalOcean, companies can save up to 30% off their cloud bill.
10:07 DigitalOcean boasts 99.99% uptime SLA as an industry leading pricing on bandwidth.
10:13 It's built to be the cloud backbone of businesses, small and large, and GPU-powered virtual machines
10:22 are available, plus storage, database, networking capabilities all on one platform.
10:26 So if you're doing AI, AI developers can confidently create apps that their users are going to love.
10:32 Devs have access to a complete set of infrastructure tools that they need for both training and
10:37 inference so that they can build anything they dream up.
10:40 DigitalOcean provides full-service cloud infrastructure that's simple to use, reliable no matter what the use case,
10:47 scalable to any size business, and affordable on a budget.
10:51 What does affordable mean?
10:52 VMs start at $4 a month.
10:55 $4.
10:56 This might be relevant to my next topic, actually, Brian.
10:59 And GPUs start under $1 an hour.
11:01 So you can easily spin up infrastructure built to simplify even the most intense business demands.
11:07 That's DigitalOcean.
11:07 If you're going to join, please use DO4bytes, DO the number 4 bytes, and get a $200 in free
11:16 credit to get started.
11:18 That code is in our show notes.
11:21 You can definitely check it out there.
11:22 DigitalOcean is the cloud that's got you covered.
11:24 Please use our link with the offer.
11:27 You'll find it in the podcast player show notes.
11:29 It's a clickable chapter URL as you're hearing the segment, and it's at the top of the episode
11:34 page at pythonbytes.fm.
11:36 Thank you to DigitalOcean for supporting Python Bytes.
11:40 Love it.
11:41 Definitely love it.
11:43 Also, I love that Python 3.14 is going to come out here pretty soon.
11:50 I guess soon in the relative sense.
11:53 We had a couple months left, I guess.
11:55 It's almost Christmas for Python.
11:56 Python Christmas.
11:57 So I can't remember the timing.
11:59 We've done this a few years in a row on the yearly, but I still don't remember.
12:03 But anyway, I'm already starting to use 3.14, and I'm excited about it.
12:08 But one of the new things that's coming up with Python, with the new one version, is functools placeholder.
12:17 And honestly, I saw something about it, and I was like, huh?
12:21 And so let's go look at it.
12:24 Is this when you just, I don't really want to write a function.
12:27 I'll just put a little functools placeholder on it.
12:30 No.
12:32 I thought of it as a stand-in for the dot, dot, dot, or pass or whatever,
12:36 when you just write a function.
12:37 Then I read it more and I'm like, "Oh no, this is something else." Tell us about it.
12:41 I am a fan of functools partial.
12:45 Again, it's a little obscure.
12:48 A little rabbit hole or rat hole here.
12:52 Partial is a cool way to create a new function by partially binding some parameters of another function.
12:59 Let's say we've got a function that takes six parameters, and you want to have everybody use it,
13:04 but fill in the same thing for the four of the parameters.
13:07 You can fill those in with partial and return a function that only takes two parameters.
13:11 And then your users can, or the users of your API can use a cleaner interface with just a couple.
13:16 Now, it's so cool.
13:18 However, it's got some limitations that sometimes positional parameters,
13:25 it works great for keywords, but for positional parameters, that's hard to decide which one to fill it in.
13:31 So it doesn't work on all functions.
13:33 Enter placeholder.
13:35 So placeholder is the ability to just say, this is where I want it to go.
13:39 And if I've got a partial, like if I want to pass print, like bind the print function,
13:47 I want the first two to be placeholder, and I want the last one to be world so that I can
13:53 pass in hello, dear, and have that come out.
13:55 Okay, that seems a little trivial.
13:57 So I was still trying to get a good example.
14:01 And the good example came from Rodrigo from MathsPP.com.
14:06 And his example, which is perfect, is to remove punctuation with a function.
14:13 And he's got a little example.
14:15 I've got his Blue Sky post to use placeholder and partial to use translate and make trans
14:23 to fill in this partial thing to create a partial function that removes punctuation.
14:29 and then you just have a function that you say, hey, remove the punctuation from Hello World,
14:33 and it takes out the comma and the exclamation point.
14:35 Something like that is great because this whole removing punctuation thing,
14:39 that comes up.
14:40 Or removing, you know, I've got, I'm doing Markdown episodes for my podcast.
14:47 I'm converting to Markdown.
14:48 But the Hugo doesn't like colons in your title, so you got to remove the colons, that sort of thing.
14:54 This is great.
14:55 And then he also has an article to go with it, how to use functools placeholder where he kind of walks through basically what i just talked about
15:02 is um partial is great but it doesn't always work so placeholder comes to the rescue so awesome
15:08 write up about the new uh placeholder functionality so thanks rodrigo interesting yeah thanks for
15:14 helping me understand that a little better i don't use i don't use functools dot partial
15:19 really very much so placeholder which enhances that doesn't give me a lot of uh clarity on it so
15:24 Oh, I use it a lot.
15:25 I mean, not a lot, a lot, but there's a lot of times where a built-in function
15:30 does almost everything I need, except for that I need to pass in a bunch of preset stuff.
15:36 And I want to expose that as an API.
15:38 And you can wrap it, but you can also just do a partial.
15:41 It's cool.
15:41 Yeah.
15:42 All right.
15:43 All right.
15:44 This was going to be a little extra, just a tiny thing I threw at the end.
15:47 Okay.
15:48 And then it grew and it grew and it grew and it became more and more.
15:53 So let me, so here's the headline.
15:57 I converted the other night, 160 old blog posts from WordPress.com to Hugo using AI in a couple of hours.
16:08 Oh, okay, good.
16:09 Okay.
16:10 And this is something that has been absolutely driving me nuts for years.
16:13 I've had all these posts over on blog.michaelckennedy.net, which is the domain I happened to be able to get at the time.
16:19 and they were on WordPress with this custom theme and so on.
16:23 And I was just done with WordPress.
16:26 Every time I went there, it was just like an antidote against writing.
16:30 Like I just don't want to write here.
16:32 Like why am I doing it?
16:33 I would much rather write markdown and just have simple and clean code like my current website.
16:38 We've talked a lot about using Hugo.
16:39 Like you use Hugo, I use Hugo.
16:41 My mkennedy.code site is Hugo, right?
16:44 But how do I get stuff from WordPress.com over to Hugo?
16:48 Well, guess what? There's an export feature in WordPress.
16:52 If you have the paid WordPress account, which is what you need to have your own domain and not your, just your username.wordpress.com.
17:00 There's different tiers. Well, it's, you have to pay the $200 version to get the export feature turned on.
17:07 What?
17:08 Yes. That's like multiple levels up. I'm like, oh, these guys are holding my stuff hostage. Screw them.
17:14 I'm just going to just put my last blog post over there was we've moved to this place.
17:19 Please join me there.
17:20 You know what I mean?
17:21 Yeah.
17:21 I'm like, but then I got a renewal for 50 bucks or 48 bucks.
17:24 I really don't want to just keep paying for the rest of my life.
17:27 $48 to this thing, you know?
17:31 So I'm like, but it's just too much work to move it over.
17:34 Without an export, I could have paid that as well.
17:36 But then I'd still have to migrate it from HTML and WordPress export format to Markdown.
17:42 So I'm like, I don't really.
17:43 But then I'm like, you know what, let me just fire up cursor and just say cursor over there.
17:47 I want this stuff.
17:48 I want it over here into Hugo.
17:49 And I showed it my, I like opened the Hugo page in cursor or the Hugo site in cursor.
17:54 And I said, here's the URL, go get it.
17:56 And it said, I'm on it.
17:57 And within like five minutes, it had all the posts move over.
18:00 I'm like, this is amazing.
18:02 But it only, it based it off the RSS feed, which is totally reasonable.
18:06 But the WordPress site limits the amount of content in the RSS feed to 50.
18:11 Not all my posts.
18:13 I'm like, oh, where are they?
18:14 Rats.
18:16 I got some of them, but not all of them.
18:18 And so then I just said, hey, go back after it and give me, just start scraping the thing,
18:25 right?
18:25 And so it just started web scraping the other pieces.
18:28 I told it to download all the images, all those kinds of things.
18:31 And it did it.
18:32 It took a couple of iterations.
18:33 Like it downloaded the comments.
18:35 I'm like, no, I don't want the comments.
18:36 I'm sorry.
18:36 I should have told you no comments.
18:38 But eventually it took it out.
18:39 And so now if you go to posts, I've got like 200 posts over here going back to 2006.
18:46 But like here, let me see if I can find one like this.
18:50 Let's just do something that'll call this.
18:52 This is definitely going to come up.
18:53 Let's search.
18:54 Let's search this.
18:55 Okay.
18:56 And I also put the domain.
18:58 I put the URL path.
19:00 So normally for all my real posts, I wrote on Hugo, they're like slash post slash whatever.
19:05 but I put all the archived ones in slash post slash r slash whatever so that I can just look
19:11 at oh that's an archive post if for whatever reason okay but if we go over here and search
19:16 you can see somewhere in here I'm sure that oh maybe it's if I search for that and can you oh
19:22 gosh that's really bad um I'm about to search for something else but if I find one of these you'll
19:28 see that oh this one's definitely gonna come up surely this is there's no way that I can't remember
19:33 why I wrote this article. Doesn't really matter. There we go. So notice it's a blog,
19:38 michaelckinnity.net, 2011-01-19. You know, the date, this is like WordPress style,
19:44 and then the name. But if I hit it, boom, instantly mapped over. So I even gave people
19:50 in the show notes the NGINX configuration to rewrite all of those things. So now I'm just
19:57 hosting my old domain, and I just have a really complicated regular expression route match
20:03 that then pulls off that little last piece and then sticks it on slash post
20:07 slash R slash slug.
20:08 Okay.
20:09 Well, a different little tip.
20:11 I went with a little different technique, but okay.
20:13 Yeah.
20:14 Okay.
20:14 I'm interested to hear what you did, but I got these all over there.
20:18 They're all integrated into the search engine.
20:21 So like you hit new get or whatever, boom, get all these old things that I really don't care super tons about,
20:27 but you know, I wrote it.
20:28 I don't want it to go, go away.
20:29 Right.
20:30 So a couple other noteworthy things, It's like, I did not put this in.
20:35 Let me pull this up for us.
20:36 There's an article on Ars Technica that just came out.
20:39 This is one of the things that got me going just like a couple days ago.
20:42 It says, blogging service TypePad is shutting down, taking all content from all users, from all time away with it.
20:49 What? Wow.
20:51 It's like, ah.
20:52 There were a bunch of artists that I followed that used TypePad for a long time.
20:56 Yeah.
20:56 Yeah.
20:57 And that's, this is not good, is it?
21:00 If that was you.
21:01 And so this points out, like, if you don't have your own domain, if I was, I don't really remember what my username was,
21:08 mkennedy.wordpress.com.
21:10 I don't think that's what it was, but whatever it is, if that was what your domain was, your content is gone
21:15 and you have no choice whatsoever if the server shuts down forever.
21:19 Because you can't remap that domain.
21:21 You don't own wordpress.com or typepad.com.
21:24 And I'm just, you know, looking around.
21:26 There's some other places that might want to, oh, hold on, that didn't copy.
21:31 There are some other places that might want to take that to heart.
21:34 For example, the PSF.
21:36 Blogspot, I know.
21:38 It's pyfound.blogspot.com.
21:40 I know we have some people who are full-time employees making an amazing impact at the PSF.
21:47 We have Luca Schlinger, developer-in-residence, South Michael Larson, Mike Fiedler.
21:52 There's an opportunity for somebody to go, let's get our own custom domain here and just leave it on Blogspot.
21:58 But if for some reason Blogspot shuts down just like TypePad did, it's going to be quite the bad time.
22:06 So anyway, yeah.
22:08 What else do I have to add to this?
22:10 Nothing.
22:11 I don't have anything to add.
22:12 I just think if you feel like your stuff has been out there trapped and been hostage, you can not only get it out,
22:19 but you can really carefully decide.
22:20 I want it to appear in my new setup exactly like this.
22:24 I want it under slash R for archived.
22:27 And also, if you go to my RSS feed, the older posts don't show up in RSS,
22:31 but the newer ones do.
22:32 Because I don't want people to just go, whoa, where did 160 new posts come from
22:35 and why are they 10 years old?
22:37 You know what I mean?
22:39 So I think there's a lot of flexibility here.
22:41 And it used to be like it was not worth it, but if you just fire up an agentic AI
22:46 and let it go on it, like it might be worth it.
22:48 Because it's not there.
22:49 I think I wrote down in the notes, it took me three to four hours to do this.
22:52 And to me, that felt like, okay, I've, I've, my coat, my content has been held hostage by WordPress.com.
22:58 And I finally, you know, I sent in like seal team six and we got it out without actually paying the
23:03 ransom sort of, it's kind of how I feel about it. Anyway, what did you do for yours? Cause you moved yours around as well, right?
23:11 Yeah. So I, let me, I'll pop over and show you, well, are we into extras now? I guess we'll just,
23:19 we are into extras. I'm done with this topic anyway. How's that?
23:22 Okay, well, I'll show you at least this little bit.
23:28 So over at pythontest.com, so not that one, I have a, under the extras, I got test and code archive.
23:36 So I took, I did an archive of all of test and code, 200 and, well, I'm missing episode one,
23:42 so it's 237 episodes off by one error.
23:45 I kind of like that anyway.
23:48 So in each of these is, of course, it's a markdown file.
23:52 And how to get all this.
23:56 So this is like the same similar URL.
24:02 The old testing code is still up.
24:04 And if I go to that episode, that episode's so long and thanks for all the fish.
24:10 That's there.
24:11 And then over at the archive, it's sort of the same URL for that episodes.
24:20 But if I want to redirect it, like if somebody just types in 237 or 238, that's supposed to work also.
24:27 So I've got it set up to do that.
24:30 I think 238 works.
24:34 And also, even if they just go to the top level of that, I think that works.
24:40 And that's done with aliases.
24:42 So I didn't do it.
24:42 I did it with Markdown or Hugo aliases.
24:45 I didn't do it with something else.
24:49 And then eventually, probably next week, I'm going to redirect the top-level testing code to the archive page.
24:59 Yeah, what are the archive pages?
25:01 This top-level pythontest.com slash testing code.
25:04 Yeah, perfect.
25:06 And then anything after that will just redirect to wherever.
25:09 So that's how I'm doing that.
25:11 Yeah, that's really cool.
25:12 I didn't do the people thing yet, and I don't know if I will.
25:16 So I had like all of the different people had their own little page, but there's not much there other than social links and stuff.
25:25 So I might just do that.
25:27 Yeah, that's not it worked.
25:29 But I also had, I almost had it working, but I had a hard time finding all of these original links because the feed XML that I downloaded was incorrect.
25:41 and i i i popped open uh what uh copilot with using claude sonnet for something like that
25:49 and and said hey um um i'm trying to import this can i get you write a python script to
25:56 to grab all the links and and it it said oh i'm trying to but the feed the xml is corrupted
26:04 um and and then um uh but it like worked around it and did it anyway with like just like parsing
26:12 the file um which was kind of ugly but i'm like hey i just need to get this done like five minutes so
26:18 yeah yeah you don't ever need to keep that code once it's done it's done yeah a lot of people
26:22 will say things like oh i can't believe you would use ai for this you know those things make up stuff
26:27 and whatever and it's like it when it wrote the program it's either going to migrate it over
26:31 successfully or not you can look at the article and see is the content there and is it all out
26:36 of whack or does it look fine and if it's fine who cares there's no tech debt there's none none of
26:41 that because i'm never going to run that again i literally map the remap the dns and it's gone
26:46 i deleted my paid account and it's gone yeah and it and i needed to update like 237 markdown files
26:53 and i just i'm probably gonna if i have to make modifications to them later i'll do it one off
26:59 Like I'll just do a search and replace for everything.
27:02 And which that's what I did also.
27:03 So I had these like link to the episode archive and also the feed URL.
27:07 I'm like, oh, I should have added those in.
27:09 Well, I just did a search and replace on all the files and did that.
27:11 I didn't add, ask Claude to do that for me.
27:15 But so there's all sorts of fun stuff.
27:18 And thanks to DigitalOcean, the new episodes are hosted.
27:23 Sorry about that.
27:24 The new episodes are hosted on DigitalOcean Spaces.
27:28 Oh, is that where you put them?
27:29 Yeah, I have a ton of stuff hosted on DigitalOcean Spaces.
27:32 And anytime you see something like blobs.pythonbytes.fm, that's DigitalOcean Spaces as well.
27:37 So that went down from like, what, 20 bucks a month, which isn't terrible that I was paying before,
27:44 down to a whopping $5 a month with DigitalOcean Spaces.
27:48 So that's great.
27:49 And you have the freedom.
27:50 Now it's in Hugo.
27:51 You can do whatever you want.
27:52 Exactly.
27:53 All right.
27:54 So that was one of my extras was, hey, the testing code is finally archived over.
27:59 Yeah, I'm glad you decided to keep that around.
28:01 That's a ton of work, and having that around for historical reasons is good.
28:04 And I probably am going to do, to get off Transistor altogether, Python people.
28:11 I got to do pythonpeople.fm, but I don't remember how many.
28:14 Oops, Python people.
28:17 It's like, what, 15, 14 episodes.
28:20 I could do that by hand if I had to.
28:22 So that's not going to be bad.
28:23 Okay, the other extra that I wanted to talk about was just a really fun thing that Seth Larson brought up.
28:29 So Seth Larson put a post up for SMS URLs, and he said, did you know that you can like the mail to URL?
28:38 You can do SMS.
28:40 And I'm not going to click on this because it won't do anything on my laptop,
28:45 I don't think.
28:46 Also the Hollywood.
28:47 No, yeah.
28:49 But if you do it on your phone, it'll open up an SMS.
28:53 like it'll open up your SMS app, your text messaging app, and fill it in with Hello World,
28:59 which is cool. So this whole fill-in thing, why is this neat? Well, so it's fun anyway. It's just
29:06 fun for one, but also wouldn't it be cool if you could just type in, one of the things you can do
29:12 with URLs is you can create QR codes. So Seth also wrote this draft an SMS message from any keyboard,
29:21 computer keyboard because you can just go to a computer and type stuff in here and it generates
29:26 a uh qr code and the fun thing is as you're typing the qr changes because that is wild i love it yeah
29:34 watch this so if you take like a bunch of lorem ipsum um and drop it in there you get like this
29:40 oh my gosh you need a high-res print out of that yeah but then so what you do is you just point your so you you don't even have to have sms you
29:54 could anywhere you can be at a work computer and even just type this in it doesn't save it
29:58 anywhere and then you just um uh snap the qr code with your phone and it opens up your um your text
30:06 messages so um it's pretty fun yeah yeah i just thought that was neat also uh i still use laura
30:13 ipsum all the time so shout out to lauramipsum.com anyway yeah um i prefer the um the hipster ipsum
30:21 hipster ipsum have you seen it oh i don't know hipster ipsum me um yeah hit it give that give
30:27 that a little bit of a read oh yeah i'm baby post ironic green juice cornhole norm core actually
30:35 heirloom beard quinoa cronut put a bird on it mutt but put a bird on it man fun oh this is good
30:43 Yeah.
30:44 Off to do this.
30:46 I don't know.
30:46 I just get tired of looking at Laura Mipsum all the time.
30:48 I'm like, ah, let's just throw some cupping kinfolk.
30:54 Butcher next level plus one waistcoat.
30:56 Venmo, same Franzen microdosing.
30:59 Cred.
31:00 Microdosing.
31:01 Farm to table.
31:01 Farm to table microdosing.
31:04 Vaporware.
31:05 Yeah, this is good.
31:06 It's pretty good, yeah.
31:07 But same basic ideas, Laura Mipsum.
31:09 8-bit literally.
31:10 Yeah, nice.
31:11 All right.
31:12 You got any more extras or is that it?
31:13 No, that's my extras, but we've got one big extra, right?
31:17 Oh, yeah.
31:17 We do.
31:18 This is the big one.
31:19 So the Python, the documentary, an origin story is out.
31:25 And it's a one hour, 24 minute, highly produced, very entertaining documentary with many friends
31:33 of the show.
31:34 People have been on your other shows, Brian, like your Python people.
31:37 A lot of them are here, right?
31:39 Yeah.
31:40 you know same for talk python as well and i am really looking forward to watching this it came
31:45 out a couple days ago and i'm like oh i could watch it but i actually think what would be really fun
31:49 i would love to just hear your first impression of this i think it would be fun to do a group
31:55 watch through and set up some kind of chat like a discord chat or something for whoever wants to
32:01 watch it all together and hasn't seen it yet i think that'd be kind of cool and just have like
32:04 a chat going in parallel to watching it something like that so kind of like people do with keynotes
32:10 now and then and so on so i don't know i'm contemplating the logistics of that if i can
32:15 come up with a good idea on the next day or two then i'll do that otherwise i'll just watch it
32:18 well i mean there was when it first came out they did like a chat thing yeah it came out as a premiere
32:24 i believe and you can see the chat replay but like how many people who would want to watch this
32:29 actually watched it during its premiere you know probably not that many yeah so i just got rid of
32:34 my inflatable screen too we could have done it in like a cul-de-sac or something oh you had one
32:38 of those big oh that's awesome yeah during the pandemic we had like this what 20 foot 23 foot
32:44 screen or something like that um so yeah that's actually a really good idea we didn't have that
32:49 well you suck i guess i don't know actually um we have a covered outdoor area in the back now and
32:55 i ended up long story ended up with an extra 50 inch flat screen tv and bought it for my dad and
33:02 it turns out he didn't need it anymore so i got it back i'm like what am i gonna do this i'm like
33:05 We're sticking this outside.
33:06 So we've got a little area, but it's not a 20-foot screen.
33:10 That's the next level business right there.
33:12 I don't remember how big it was.
33:13 It was probably that.
33:14 It was a big inflatable thing.
33:16 It's bigger than a regular TV.
33:18 That's awesome.
33:19 Anyway, I recommend people watch this.
33:21 We talked about the trailer when it came out, and it was really good, wasn't it?
33:24 Yeah.
33:25 So I was hoping to get this watched before we recorded.
33:28 Did you happen to watch any of this?
33:30 No, I'm waiting.
33:31 I'm just like, I'm delaying it because I want to try to figure out something fun for...
33:35 That'd be fun.
33:36 Cool.
33:37 Now I don't feel bad about not watching it yet.
33:38 I watched like a few minutes and I was like, oh, it's an hour and a half.
33:41 I'm going to have to set aside some time to do this.
33:43 Yeah.
33:43 Yeah.
33:44 And looking up, I think I've got like, you probably have all of these interviewed on your,
33:49 on Talk Python.
33:50 I think I've got half of the people shown on like the opening screen.
33:53 Yeah.
33:54 There's maybe eight or nine people.
33:56 I think almost everyone.
33:58 I think there's one person I don't necessarily recognize through the little thin slice.
34:02 But yeah, I would say other than that, yeah, everyone's been on the show.
34:04 It's cool.
34:05 Cool.
34:06 Well, cool.
34:07 Can't wait to watch it.
34:08 All right.
34:09 Are you ready to laugh?
34:10 Yeah.
34:10 Let the hilarity ensue.
34:12 We'll see.
34:12 I can't remember what I came up with.
34:13 Oh, yeah.
34:14 So this one is like a Jedi.
34:17 Think.
34:18 I want to just put you in the mindset before we get to it.
34:21 Okay, Brian?
34:22 Okay.
34:22 You're on Tatooine.
34:23 You've been told of this Obi-Wan Kenobi who you must find.
34:27 You know the old wizard man out past the cantina.
34:31 So it says, the joke is, it has Obi-Wan, Obi-Wan Kenobi.
34:36 And it says, when you read some incredibly bad code thinking, what moron wrote this?
34:40 But halfway through, it starts to become familiar.
34:43 Well, of course I know him.
34:45 He is me.
34:46 Yeah.
34:47 Do you know this Obi-Wan?
34:49 Yes, of course I know him.
34:51 Do you know the bad wizard who wrote the bad code?
34:53 Of course I know him.
34:54 He is me.
34:55 Yeah.
34:55 Actually, yeah, it's usually that.
34:57 I really love it when it's not me, but it's usually me.
35:01 You pull up get blamed because you're like, I'm going to, oh no.
35:06 Oh no.
35:07 Yeah.
35:07 I really like that.
35:08 Yeah.
35:09 It's, it's addictive, but I like have, I have blame on every line turned on VS Code so
35:14 that whatever, whatever I'm working on, I'm like, who did this?
35:18 Oh yeah.
35:19 Yeah.
35:20 Yeah.
35:20 It's kind of nice.
35:21 It's kind of nice.
35:21 But I'm, it's also just the last person that touched that line as well.
35:25 So sometimes it's me, even though, even if I didn't write the logic.
35:29 Right.
35:29 It could be something so simple as you ran Ruff format and then committed the change.
35:33 Yeah, exactly.
35:34 Yeah.
35:34 Yeah.
35:35 All right.
35:35 Anyway, of course I know him.
35:36 He is me.
35:38 Of course I know.
35:39 All right.
35:40 Cool.
35:40 Well, wonderful episode again.
35:42 Thanks everybody for showing up and listening.
35:44 We'll talk to you next week.
35:45 Bye-bye.