WEBVTT

00:00:00.001 --> 00:00:05.780
Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds.

00:00:05.780 --> 00:00:11.260
This is episode 374, recorded March 11th, 2024.

00:00:11.260 --> 00:00:12.620
I am Michael Kennedy.

00:00:12.620 --> 00:00:13.760
And I'm Brian Okken.

00:00:13.760 --> 00:00:16.780
And this episode is brought to you by Scout APM.

00:00:16.780 --> 00:00:22.480
Check them out at pythonbytes.fm/scout.

00:00:22.480 --> 00:00:24.000
I'll tell you more about them later.

00:00:24.000 --> 00:00:27.460
If you'd like to connect with us, Mastodon is the main place.

00:00:27.460 --> 00:00:29.100
We're also on X Twitter.

00:00:29.800 --> 00:00:31.740
But primarily on Mastodon.

00:00:31.740 --> 00:00:36.240
And that's at mkennedy, at brianockenden, at pythonbytes, all at fosstodon.org.

00:00:36.240 --> 00:00:40.920
And watch us live, usually Tuesdays at 10 a.m. Pacific time.

00:00:40.920 --> 00:00:42.480
However, different today.

00:00:42.480 --> 00:00:44.860
But check it out at pythonbytes.fm/live.

00:00:44.860 --> 00:00:47.660
You'll be able to get notified about the next upcoming recording.

00:00:47.660 --> 00:00:50.520
I usually put that up right after we're done with this one.

00:00:50.520 --> 00:00:58.920
Brian, before we jump into your first topic, I want to just take a moment and appreciate the beginning of summer.

00:00:59.600 --> 00:01:01.820
First step towards summer coming.

00:01:01.820 --> 00:01:05.400
It is daylight savings switch over here in the U.S.

00:01:05.400 --> 00:01:07.240
And I know it is much maligned by people.

00:01:07.240 --> 00:01:14.880
But I was delighted to see the sun was up past 7 p.m. yesterday after living in dark and rain for months and months.

00:01:14.920 --> 00:01:16.500
I'm feeling the summer.

00:01:16.500 --> 00:01:18.000
I know it's not quite there yet.

00:01:18.000 --> 00:01:21.900
Yeah, I didn't really notice it until after I woke up.

00:01:21.900 --> 00:01:22.700
Yeah.

00:01:22.700 --> 00:01:25.140
I woke up and I'm like, oh, gosh.

00:01:25.140 --> 00:01:28.380
I thought I'd slept into like 10, but it was really 11.

00:01:28.380 --> 00:01:31.680
So sleep the day away.

00:01:32.280 --> 00:01:32.820
Oh, beautiful.

00:01:32.820 --> 00:01:33.720
Beautiful, beautiful.

00:01:33.720 --> 00:01:34.200
All right.

00:01:34.200 --> 00:01:35.800
Well, over to Python.

00:01:35.800 --> 00:01:36.500
What's your first thing?

00:01:36.500 --> 00:01:36.960
Okay.

00:01:36.960 --> 00:01:39.600
Well, I want to talk about spaghetti code a little bit.

00:01:39.600 --> 00:01:41.940
Actually, or how to fix it.

00:01:41.940 --> 00:01:43.440
So there's an article.

00:01:43.440 --> 00:01:44.580
Is that what you get when you're real hungry?

00:01:44.580 --> 00:01:45.640
You're like, what are you going to have for dinner?

00:01:46.080 --> 00:01:47.420
Maybe some spaghetti code.

00:01:47.420 --> 00:01:48.800
A little carbonara.

00:01:48.800 --> 00:01:51.700
Is that how you pronounce it?

00:01:51.700 --> 00:01:53.940
I've never been able to pronounce it.

00:01:53.940 --> 00:01:56.240
I'm probably going to get email that it's not, but that's how I pronounce it.

00:01:56.240 --> 00:01:59.120
Article from somebody that goes by Piggly.

00:01:59.120 --> 00:02:04.040
Six ways to improve the architecture of your Python project using import linter.

00:02:04.040 --> 00:02:08.620
And I kind of like this article, even if you don't want to use import linter.

00:02:08.620 --> 00:02:12.860
So because of the six ways to improve the architecture, I love that.

00:02:12.860 --> 00:02:14.280
I love digging into that.

00:02:14.280 --> 00:02:19.500
So, and I actually have a couple of projects that I'm working on that I would like to maybe

00:02:19.500 --> 00:02:20.820
clean up the architecture a bit.

00:02:20.820 --> 00:02:22.480
So kind of a fun picture.

00:02:22.480 --> 00:02:23.780
Not sure what's going on here.

00:02:23.780 --> 00:02:25.940
Just a whole bunch of boxes pointing at each other.

00:02:25.940 --> 00:02:33.220
I guess just indicating that there's circular dependencies or something going on.

00:02:33.220 --> 00:02:40.040
And anyway, so a little bit of a discussion about why complex architecture might be bad,

00:02:40.040 --> 00:02:42.840
but I don't think any of us need convincing of that.

00:02:43.280 --> 00:02:44.420
Simplifying is a good thing.

00:02:44.420 --> 00:02:49.840
So the first part talks about maybe setting up an idea of like, maybe you could, you have

00:02:49.840 --> 00:02:52.440
an idea of like setting your architecture into layers.

00:02:52.920 --> 00:03:00.480
If that's what you want to do, like a user layer or an application layer plus utilities or something services.

00:03:01.440 --> 00:03:15.020
But there's a tool called the import linter that there's a discussion about how to set it up so that you can use that to both configure what you want your layers to be and then test for it.

00:03:15.020 --> 00:03:18.640
It's like a linting to make sure that you're not importing in the wrong direction.

00:03:19.000 --> 00:03:25.700
So the idea would be like you're not importing, like if you want the top level one to be calling the lower level ones, but not the other way around.

00:03:26.560 --> 00:03:31.040
So the importing is a way to test that, which is because of that.

00:03:31.040 --> 00:03:36.800
I'm not sure what these arrows mean because it doesn't quite make sense if it's not inheritance or calling.

00:03:36.800 --> 00:03:37.360
I don't know.

00:03:37.360 --> 00:03:38.520
Anyway, it's just an error.

00:03:38.520 --> 00:03:40.080
That looks pretty interesting.

00:03:40.300 --> 00:03:45.980
I think that means that something from that layer is importing something from the bottom layer, the lower layer.

00:03:45.980 --> 00:03:47.940
Yeah, but yeah.

00:03:47.940 --> 00:03:48.540
Okay.

00:03:48.540 --> 00:04:01.060
I think the things are with, you can have stuff like import across within, but then it can only, I think it would be an error or a warning if maybe say like the data layer imported the UI layer sort of thing.

00:04:01.060 --> 00:04:02.140
I think that's what it's saying.

00:04:02.140 --> 00:04:02.720
Yeah.

00:04:02.720 --> 00:04:07.320
Oh, and it makes more sense if I would have drawn the top layer at the top.

00:04:07.320 --> 00:04:09.900
I think it makes more sense to me if we do it the other way.

00:04:10.020 --> 00:04:12.420
Anyway, that's a drawing thing.

00:04:12.420 --> 00:04:13.120
It doesn't really matter.

00:04:13.120 --> 00:04:14.080
And also-

00:04:14.080 --> 00:04:17.000
The problem is by somebody in Australia because everything is upside down down there.

00:04:17.000 --> 00:04:17.760
Oh, yeah.

00:04:17.760 --> 00:04:18.760
Yeah, that makes sense.

00:04:18.760 --> 00:04:19.840
Yeah, yeah, that was it.

00:04:19.840 --> 00:04:20.040
Okay.

00:04:20.040 --> 00:04:20.620
Okay.

00:04:20.620 --> 00:04:29.160
So what happens when you run this is the recommendation is you're probably going to get a bunch of lint warnings or errors.

00:04:29.160 --> 00:04:31.580
Or maybe not.

00:04:31.580 --> 00:04:32.700
If not, awesome.

00:04:32.700 --> 00:04:40.960
But if you do, the recommendation here, which I kind of thought was cool, was to kind of exclude all of them.

00:04:41.120 --> 00:04:47.800
Like go through and add these ignore imports and just go through and ignore the ones that failed.

00:04:47.800 --> 00:04:52.080
And I'm like, okay, well, then you're going to pass and it's just going to ignore everything.

00:04:52.080 --> 00:04:55.180
But the idea behind it is to do it one at a time.

00:04:55.180 --> 00:04:57.420
So it's going to be overwhelming to get a bunch of errors.

00:04:57.420 --> 00:04:58.680
So ignore them all.

00:04:58.680 --> 00:05:03.920
And then un-ignore one at a time and then go through and fix them.

00:05:04.240 --> 00:05:10.400
So that's where the reason why I picked out this article isn't really because import lint is cool.

00:05:10.400 --> 00:05:11.100
It might be cool.

00:05:11.100 --> 00:05:19.040
But it's these ways to fix these import dependencies I thought were really great to walk through.

00:05:19.040 --> 00:05:20.540
There's six of them.

00:05:20.540 --> 00:05:23.340
First one is merging and splitting modules.

00:05:23.340 --> 00:05:27.560
And there's an example where you've got resources that calls clusters.

00:05:27.560 --> 00:05:30.520
Clusters calls resources.clusterutils.

00:05:30.520 --> 00:05:32.960
And that's going the wrong direction.

00:05:33.220 --> 00:05:39.540
But to fix it, you maybe move those clusterutils down into the lower, like a lower library, like splitting them off.

00:05:39.540 --> 00:05:45.160
Kind of sort of straightforward, but it's good to like think about this.

00:05:45.160 --> 00:05:47.120
So I like that part of it.

00:05:47.120 --> 00:05:48.300
Dependency injection.

00:05:48.300 --> 00:05:55.540
And if you're the kind of person that's kind of afraid of dependency injection, then don't even think about that term.

00:05:55.540 --> 00:05:57.280
Because it's not actually that scary.

00:05:57.280 --> 00:05:59.520
Just the term was scary to me for a while.

00:05:59.520 --> 00:06:07.960
So anyway, dependency injection might help to be able to pass dependencies down into lower layers from upper layers.

00:06:07.960 --> 00:06:10.360
So that's a good way to get around it.

00:06:11.340 --> 00:06:18.140
The interesting, I'm glad they dug into this, is when you do the inversion of, what is it?

00:06:18.140 --> 00:06:20.040
I forget, the inversion of control.

00:06:20.040 --> 00:06:20.980
Inversion of control, yeah.

00:06:20.980 --> 00:06:21.220
Yeah.

00:06:22.280 --> 00:06:26.820
Sometimes with Python, that works great, except for type hints.

00:06:26.820 --> 00:06:31.260
Sometimes you need to get the type hints, getting those right.

00:06:31.260 --> 00:06:38.020
So talking about how to use the protocol from typing to get that to work right.

00:06:38.020 --> 00:06:40.400
That discussion's in here, which is great.

00:06:40.400 --> 00:06:41.080
I love protocol.

00:06:41.080 --> 00:06:48.360
Then another discussion about using simpler dependency types, and then delaying function implementation.

00:06:48.360 --> 00:06:52.420
And then even, what was the last one?

00:06:52.420 --> 00:06:54.580
Look at 4.6, configuration driven.

00:06:54.580 --> 00:06:55.500
That was interesting.

00:06:55.920 --> 00:06:57.560
I've never really thought about doing this.

00:06:57.560 --> 00:07:08.920
The idea is you'd have a settings file or something, and have that, and then have the string that you would import, like marketing.sendSMS.

00:07:08.920 --> 00:07:14.260
And then later on in your calling thing, you use import string to import it.

00:07:14.260 --> 00:07:22.000
So you still have the backwards dependency, but you don't know it at compile, at write time.

00:07:22.000 --> 00:07:22.920
You know it at run time.

00:07:22.920 --> 00:07:23.380
I don't know.

00:07:23.380 --> 00:07:24.680
I don't know what I think about that.

00:07:24.680 --> 00:07:25.640
But anyway.

00:07:25.640 --> 00:07:27.140
Yeah, that's interesting.

00:07:27.140 --> 00:07:28.800
It's a way to do it.

00:07:28.800 --> 00:07:34.260
And then the last one is replace function calls with event driven approaches.

00:07:34.260 --> 00:07:37.000
So like callbacks and stuff like that.

00:07:37.000 --> 00:07:41.860
So these are great architecture things to think about when you're cleaning up architecture.

00:07:41.860 --> 00:07:45.220
Because it's not always trivial to just say, just don't do that.

00:07:45.220 --> 00:07:46.160
Don't do those imports.

00:07:46.160 --> 00:07:48.820
Well, how do you get around it if you've designed it that way?

00:07:48.820 --> 00:07:52.940
So I think a decent discussion about software architecture here.

00:07:52.940 --> 00:07:54.980
I do think that's pretty interesting.

00:07:54.980 --> 00:07:55.120
Interesting.

00:07:55.120 --> 00:08:01.100
And also, just more broadly, I like the idea of ignoring all the issues you might run into

00:08:01.100 --> 00:08:05.980
with linters and then slowly turning the screws to make it a little tighter is good advice.

00:08:05.980 --> 00:08:11.200
Because if you have existing code of any significant size and you've never done linting on it,

00:08:11.320 --> 00:08:12.400
and then you turn on a linter?

00:08:12.400 --> 00:08:13.000
Yeah.

00:08:13.000 --> 00:08:14.900
You feel bad about yourself.

00:08:14.900 --> 00:08:16.460
You're like, I've done all that wrong?

00:08:17.440 --> 00:08:18.440
93 errors?

00:08:18.440 --> 00:08:18.560
Great.

00:08:18.560 --> 00:08:18.600
Great.

00:08:18.600 --> 00:08:21.300
Well, we'll turn that back off because I got work to do.

00:08:21.300 --> 00:08:21.840
You know what I mean?

00:08:21.840 --> 00:08:22.460
Yeah.

00:08:22.460 --> 00:08:26.420
Well, I'm kind of going through that with the rough right now.

00:08:26.420 --> 00:08:33.340
So I've got some projects where default rough works fine, but the rough has like 800 rules or something you can add.

00:08:33.720 --> 00:08:37.280
And so I'm trying to turn on some of those extra features.

00:08:37.280 --> 00:08:39.300
I have just a few at a time.

00:08:39.300 --> 00:08:40.700
See, testing the waters.

00:08:40.700 --> 00:08:44.160
See how many failures I get and whether I want to clean them up.

00:08:44.160 --> 00:08:44.840
So, yeah.

00:08:44.840 --> 00:08:45.240
Yeah.

00:08:45.240 --> 00:08:45.860
Interesting.

00:08:45.860 --> 00:08:48.820
Just interesting timing.

00:08:48.940 --> 00:08:51.560
I'm going to be speaking with Charlie Marsh on Talk Python tomorrow.

00:08:51.560 --> 00:08:52.460
Oh, awesome.

00:08:52.460 --> 00:08:55.200
About 24 hours from now, whatever that makes it for you.

00:08:55.200 --> 00:08:56.160
Yeah.

00:08:56.160 --> 00:08:56.620
Out there listening.

00:08:56.620 --> 00:08:57.200
Yeah.

00:08:57.200 --> 00:09:00.260
And we're going to talk mostly about uv, but I'm sure we'll talk a bit about rough as well.

00:09:00.260 --> 00:09:00.740
Cool.

00:09:00.740 --> 00:09:04.560
Well, I'm going to release a episode with Charlie Marsh today.

00:09:04.560 --> 00:09:06.400
Well, how about that?

00:09:06.400 --> 00:09:07.460
Awesome.

00:09:07.460 --> 00:09:07.940
Awesome.

00:09:07.940 --> 00:09:09.300
Do you guys talk about uv as well?

00:09:09.300 --> 00:09:10.140
Yeah.

00:09:10.140 --> 00:09:13.100
We talked about Flicate or not Flicate.

00:09:13.580 --> 00:09:21.700
We talked about rough and Astral and uv, most of the conversations around uv and some of the discussion around that.

00:09:21.700 --> 00:09:22.560
Nice.

00:09:22.560 --> 00:09:23.160
Yeah.

00:09:23.160 --> 00:09:23.840
That'll be fun.

00:09:23.840 --> 00:09:24.220
All right.

00:09:24.220 --> 00:09:28.140
On to the next one here by Pierce Freeman.

00:09:28.140 --> 00:09:29.500
That's kind of a cool name, isn't it?

00:09:29.500 --> 00:09:31.940
It could be like a 00 sort of agent.

00:09:31.940 --> 00:09:32.720
Yeah.

00:09:32.720 --> 00:09:33.340
009.

00:09:33.340 --> 00:09:34.560
I don't know what that is.

00:09:34.560 --> 00:09:36.200
Not James, but something like that.

00:09:36.200 --> 00:09:36.500
Anyway.

00:09:36.500 --> 00:09:38.280
Pierce Freeman to the rescue.

00:09:38.280 --> 00:09:39.420
Exactly.

00:09:39.420 --> 00:09:42.980
To bring you React and FastAPI and Python.

00:09:43.220 --> 00:09:45.240
In fact, with this framework called Mountaineer.

00:09:45.240 --> 00:09:50.680
So Mountaineer is a batteries included web framework for Python and React.

00:09:50.680 --> 00:10:00.320
So this, it plays in a similar space as Fast UI from Samuel Colvin and the Pydantic crew.

00:10:00.320 --> 00:10:05.680
I don't know enough about them to know how truly similar they are.

00:10:05.680 --> 00:10:08.160
I think this is coming from a different angle.

00:10:08.160 --> 00:10:12.580
I think you're doing, you know, so Fast UI is more about maybe you don't really have to do the

00:10:12.580 --> 00:10:14.020
React side unless you want.

00:10:14.020 --> 00:10:15.780
And it kind of brings that stuff together.

00:10:15.780 --> 00:10:22.180
Whereas this kind of like you're embracing TypeScript, you're embracing React, but you also get some

00:10:22.180 --> 00:10:23.420
really nice Python integration.

00:10:23.420 --> 00:10:26.600
And so if you look down here, what does it say?

00:10:26.600 --> 00:10:30.000
It says it lets you easily build web apps in Python and React.

00:10:30.560 --> 00:10:36.420
And if you are familiar with this, it should sound familiar to you and should basically seem like what you're used to.

00:10:36.420 --> 00:10:39.360
And if not, then maybe not.

00:10:39.360 --> 00:10:45.240
But it says each framework like Flask or FastAPI or Django or whatever has its trade-offs and features.

00:10:45.840 --> 00:10:51.400
And for this one, it focuses on developer productivity above all else with production speed of close seconds.

00:10:51.400 --> 00:10:54.520
So type hints up and down the stack, front-end, back-end database.

00:10:54.520 --> 00:10:57.540
Trivially easy client-server communication.

00:10:57.540 --> 00:11:07.220
So you don't find yourself creating a bunch of APIs so that your React stuff can talk to the API so it can actually get its data and all that, which is pretty interesting.

00:11:07.220 --> 00:11:09.500
It comes, this is kind of cool.

00:11:09.580 --> 00:11:14.420
So one of the things you can run into, I'm sure you've seen this, Brian, it drives me absolutely bonkers.

00:11:14.420 --> 00:11:23.260
You'll go to a website and it'll have something on the screen and then like half a second later, it'll shift around and stuff will all come into existence.

00:11:23.260 --> 00:11:29.400
You know, you'll be like, it'll have like the footer will be touching the top and then it'll bump out, it'll be a spinner and then stuff.

00:11:29.400 --> 00:11:31.360
You know, it's like, what is it doing?

00:11:31.360 --> 00:11:37.400
Well, especially if you start reading and then a picture pops in and what you read pops off the screen.

00:11:37.400 --> 00:11:38.000
Yeah.

00:11:38.000 --> 00:11:47.160
Another thing that drives me crazy is if you paste something into an input, but you don't type it, sometimes that won't trigger the data binding.

00:11:47.160 --> 00:11:55.140
And, you know, like if it's a password manager type thing or something, or you just paste something, it'll say, oh, this is invalid.

00:11:55.140 --> 00:11:56.060
What is wrong with this?

00:11:56.060 --> 00:11:57.700
Oh, if you put a space and delete the space.

00:11:57.700 --> 00:11:59.340
Oh, oh, it's valid now.

00:11:59.340 --> 00:12:00.560
It's like, uh-huh, I see.

00:12:00.560 --> 00:12:05.260
So something that would be really nice is if you just could ship straight HTML, right?

00:12:05.260 --> 00:12:05.700
Yeah.

00:12:06.020 --> 00:12:08.520
Or the first view of that was normal.

00:12:08.520 --> 00:12:12.480
And so what this comes with is they actually bundle the V8 engine.

00:12:12.740 --> 00:12:19.020
So on the server side, it can render what your browser would do for you as final HTML and it delivers.

00:12:19.020 --> 00:12:24.080
So optimize server side rendering for better accessibility in SEO.

00:12:24.080 --> 00:12:25.040
That's pretty cool.

00:12:25.040 --> 00:12:26.240
Yeah, that is cool.

00:12:26.240 --> 00:12:27.420
As a Python thing.

00:12:27.420 --> 00:12:29.780
Like normally you hear that as a node thing or something, right?

00:12:29.780 --> 00:12:30.200
Yeah.

00:12:30.300 --> 00:12:35.600
It also does static analysis for validations of like links and CSS and so on.

00:12:35.600 --> 00:12:41.100
And like I said, skip the API or Node.js server just for front-end clients.

00:12:41.100 --> 00:12:41.520
Okay.

00:12:41.520 --> 00:12:43.600
So all of these things are pretty cool.

00:12:43.600 --> 00:12:46.240
If, let me give you a warning and a disclaimer.

00:12:46.240 --> 00:12:51.340
One, if you don't know React real well, I don't think you'll really appreciate the benefits here that much.

00:12:51.340 --> 00:12:53.980
Like this is really for React people 100%.

00:12:53.980 --> 00:12:55.360
Second, that's not me.

00:12:55.360 --> 00:12:59.280
So I'm going to do my best to like tell you why you might want this.

00:12:59.280 --> 00:13:00.980
I think I can kind of get there.

00:13:00.980 --> 00:13:06.280
So first of all, it has a scaffolding type thing called Create Mountaineer app.

00:13:06.460 --> 00:13:08.020
And they suggest pipx.

00:13:08.020 --> 00:13:12.600
And I'm loving to see more pipx come along for these kinds of tools, right?

00:13:12.600 --> 00:13:13.940
Like you run this once.

00:13:13.940 --> 00:13:15.120
It's not part of your app.

00:13:15.120 --> 00:13:17.140
You just pipx install it and everything gets going.

00:13:17.140 --> 00:13:17.860
It's great.

00:13:17.860 --> 00:13:19.860
Also uses poetry pretty heavily.

00:13:19.860 --> 00:13:27.220
So what it does is it creates a Python bits and then some TypeScript stuff for your front-end.

00:13:27.220 --> 00:13:29.060
And it comes with a CLI as well, which is nice.

00:13:29.060 --> 00:13:35.480
It has built-in Docker containers for like managing Postgres databases and so on if you want to use that,

00:13:35.560 --> 00:13:36.300
but you don't have to.

00:13:36.300 --> 00:13:37.900
And let's see.

00:13:37.900 --> 00:13:41.760
So another interesting integration is it uses SQL model.

00:13:41.760 --> 00:13:44.380
So that's the typing and the data layer aspect.

00:13:44.380 --> 00:13:49.740
So SQL model is Pydantic plus SQLAlchemy basically by Sebastian Ramirez.

00:13:49.740 --> 00:13:50.560
So that's cool.

00:13:50.560 --> 00:13:54.540
And then you go down here and you create controllers.

00:13:54.540 --> 00:13:56.640
So it's kind of a class-based type of thing.

00:13:56.640 --> 00:14:03.400
First, it seems a little unnecessary, but as you interact with it and expose more features to the React layer,

00:14:03.520 --> 00:14:05.640
you'll see that kind of relevant there.

00:14:05.640 --> 00:14:10.880
So you just say, I'm going to render, say, my database things and some other pieces of data.

00:14:10.880 --> 00:14:18.500
And then down somewhere, you've got your React code and your TSX, your React component there.

00:14:18.760 --> 00:14:22.920
And if you've written React stuff, you should know pretty well how it works.

00:14:22.920 --> 00:14:26.060
But it manages passing all that data over like server state dot to-dos.

00:14:26.060 --> 00:14:28.080
Then you can just work with that, which is interesting.

00:14:28.080 --> 00:14:35.500
But it gets more interesting later if you say, let's add an async function like add one of my to-dos.

00:14:35.500 --> 00:14:36.720
And they have a to-do example, right?

00:14:36.820 --> 00:14:41.880
So if you put this at side effect decorator on it, here's where the React integration comes in.

00:14:41.880 --> 00:14:42.780
That's pretty wild.

00:14:42.780 --> 00:14:46.760
So it automatically generates type typed.

00:14:46.760 --> 00:14:50.860
Let's just say typed TypeScript because, I mean, you can't have non-typed TypeScript.

00:14:50.860 --> 00:14:52.160
But generally, TypeScript is typed.

00:14:52.160 --> 00:14:58.520
You generate TypeScript versions of the functions that you write in Python on the JavaScript side.

00:14:58.520 --> 00:15:02.320
So you immediately can just start calling it and using those features, right?

00:15:02.320 --> 00:15:06.500
So it kind of has this really tight integration with React, like as you would expect.

00:15:06.500 --> 00:15:07.280
What else?

00:15:07.280 --> 00:15:08.280
I think that's pretty much it.

00:15:08.280 --> 00:15:18.480
But if you're a heavy React shop and you want a nice Python backend and you want a tight data integration between those, this is probably worth a look.

00:15:18.480 --> 00:15:18.880
Yeah.

00:15:18.880 --> 00:15:19.340
Neat.

00:15:19.340 --> 00:15:19.720
Yeah.

00:15:19.720 --> 00:15:20.100
Yeah.

00:15:20.100 --> 00:15:21.400
It looks pretty neat to me too.

00:15:21.400 --> 00:15:23.900
I'm not, like I said, I'm not really a React person.

00:15:23.900 --> 00:15:26.980
So I'm not sure that I'm necessarily going to use it.

00:15:26.980 --> 00:15:31.400
But if I were to start adopting React, I may well decide that that's what I want.

00:15:31.400 --> 00:15:36.420
Speaking of cool things, Brian, how about Scout APM?

00:15:36.420 --> 00:15:40.400
Let me tell you real quick about Scout APM.

00:15:40.400 --> 00:15:42.580
They're big supporters of Python Bytes.

00:15:42.580 --> 00:15:44.100
So we appreciate that very much.

00:15:44.100 --> 00:15:53.360
So if you are tired of spending hours trying to find the root cause of issues impacting your performance, then you owe it to yourself to check out Scout APM.

00:15:53.720 --> 00:16:02.640
They're a leading Python application performance monitoring tool, APM, that helps you identify and solve performance abnormalities faster and easier.

00:16:02.640 --> 00:16:12.980
Scout APM ties bottlenecks such as memory leaks, slow database queries, background jobs, and the dreaded N plus one queries that you can end up if you do lazy loading in your ORM.

00:16:12.980 --> 00:16:15.960
And then you say, oh, no, why is it so slow?

00:16:15.960 --> 00:16:18.300
Why are you doing 200 database queries for what should be one?

00:16:18.300 --> 00:16:19.740
So you can find out things like that.

00:16:19.740 --> 00:16:27.140
And it links it back directly to source code so you can spend less time in the debugger and healing logs and just finding the problems and moving on.

00:16:27.140 --> 00:16:30.240
And you'll love it because it's built for developers by developers.

00:16:30.240 --> 00:16:31.900
It makes it easy to get set up.

00:16:31.900 --> 00:16:34.440
Seriously, you can do it in less than four minutes.

00:16:34.440 --> 00:16:35.260
So that's awesome.

00:16:35.260 --> 00:16:38.320
And the best part is the pricing is straightforward.

00:16:38.320 --> 00:16:43.820
You only pay for the data that you use with no hidden overage fees or per seat pricing.

00:16:43.820 --> 00:16:46.340
And I just learned this, Brian.

00:16:46.340 --> 00:16:51.500
They also have they provide the pro version for free to all open source projects.

00:16:51.500 --> 00:16:58.960
So if you're an open source maintainer and you want to have Scout APM for that project, just shoot them a message or something on their pricing page about that.

00:16:58.960 --> 00:17:02.840
So you can start your free trial and get instant insights today.

00:17:02.840 --> 00:17:05.520
Visit pythonbytes.fm/scout.

00:17:05.520 --> 00:17:07.800
The link is in your podcast player show notes as well.

00:17:07.800 --> 00:17:09.220
And please use that link.

00:17:09.220 --> 00:17:13.180
Don't just search for them because otherwise they don't think you came from us.

00:17:13.180 --> 00:17:14.780
And then they'd stop supporting the show.

00:17:14.780 --> 00:17:17.340
So please use our link pythonbytes.fm/scout.

00:17:17.340 --> 00:17:18.280
Check them out.

00:17:18.280 --> 00:17:20.200
It really supports the show.

00:17:20.200 --> 00:17:20.840
Awesome.

00:17:20.840 --> 00:17:21.180
Awesome.

00:17:21.660 --> 00:17:22.380
What's next, Brian?

00:17:22.380 --> 00:17:25.720
Well, what's next is Guido Van Rossum.

00:17:25.720 --> 00:17:26.520
Oh, yeah.

00:17:26.520 --> 00:17:30.300
So he's blogging a little bit lately.

00:17:30.300 --> 00:17:37.940
And he put up a post called Why Python's Integer Division Floors.

00:17:37.940 --> 00:17:43.240
And I think this is just an interesting little bit of history.

00:17:43.240 --> 00:17:47.580
And this was a difference between Python 2 and 3.

00:17:47.580 --> 00:17:51.160
I guess, no, it's integer division always did flooring.

00:17:51.160 --> 00:17:55.780
But we did a kind of a thing of what one slash meant.

00:17:55.780 --> 00:17:59.900
So if you do two slashes, it's always inner division.

00:18:00.400 --> 00:18:09.660
If you do one slash in, if it was both integers in Python 2, it would be integer division and it would possibly not be the floating point result.

00:18:09.980 --> 00:18:11.280
But in Python 3, it will generate a float.

00:18:11.280 --> 00:18:13.260
But in Python 3, it will generate a float if you have it.

00:18:13.260 --> 00:18:18.380
Like, for instance, one third will one divided by three results in a float.

00:18:18.380 --> 00:18:21.480
But if you do integer division, it's not.

00:18:21.480 --> 00:18:22.380
It's something else.

00:18:22.980 --> 00:18:24.960
Is that why the 2 to 3 conversion was so hard?

00:18:24.960 --> 00:18:25.860
I'm just kidding.

00:18:25.860 --> 00:18:26.400
What was that?

00:18:26.400 --> 00:18:27.000
It was strings.

00:18:27.000 --> 00:18:28.060
Everyone knows it's strings.

00:18:28.060 --> 00:18:32.800
So is that why the Python 2 to 3 story was so hard?

00:18:32.800 --> 00:18:35.840
No, I'm just joking.

00:18:37.400 --> 00:18:37.780
Yeah.

00:18:37.780 --> 00:18:46.680
So if you do five to two slashes, so integer division of five divided by two, you get two.

00:18:46.680 --> 00:18:49.720
And which is normal.

00:18:49.720 --> 00:18:51.560
That's everywhere.

00:18:52.020 --> 00:18:57.280
But if you do it, like, say, negative five, you don't get negative two.

00:18:57.280 --> 00:18:58.380
You get negative three.

00:18:58.380 --> 00:19:00.480
So there's a question.

00:19:00.480 --> 00:19:06.320
So Guido said that he had a question about that, of why it's different, why it's like that.

00:19:06.320 --> 00:19:07.880
And so it's going.

00:19:07.880 --> 00:19:09.060
It does a division.

00:19:09.060 --> 00:19:16.140
And then it goes to the closest integer to the negative, closest to negative infinity.

00:19:16.140 --> 00:19:19.680
And there's reasonings behind that.

00:19:19.680 --> 00:19:21.060
But it's different than C.

00:19:21.220 --> 00:19:23.700
Apparently, I completely forgot what C did.

00:19:23.700 --> 00:19:26.120
C does it closer to zero.

00:19:26.120 --> 00:19:31.740
So negative five divided by two, you'd end up with negative two.

00:19:31.740 --> 00:19:37.620
So the history there is that there was a choice to make.

00:19:37.620 --> 00:19:44.700
And it works with the modulo operator as well.

00:19:44.700 --> 00:19:51.200
Modulo will create the remainder where integer division creates the integer division.

00:19:51.200 --> 00:19:52.440
The integer quotient.

00:19:52.440 --> 00:20:00.940
So such that A divided by B equals Q with remainder R such that R is between zero and B.

00:20:00.940 --> 00:20:03.240
There's math here.

00:20:03.840 --> 00:20:14.460
But it just you have a choice as to what you want to do, whether you want R to be possibly negative, positive or negative for the remainder, or if you want R to always be positive.

00:20:14.960 --> 00:20:22.020
And basically, Guido chose the one that looks nicer in math.

00:20:22.020 --> 00:20:27.320
So that we go do a floor division instead.

00:20:27.920 --> 00:20:33.620
The interesting take on this, I thought, was why did C choose the other way?

00:20:34.620 --> 00:20:37.560
And that's the part that I thought was really interesting.

00:20:37.560 --> 00:20:44.780
And his answer is, or his guess is that, well, C was doing it way before Python was.

00:20:44.780 --> 00:20:54.200
And C was doing it on hardware that it may have been easier to do division closer to zero instead of floor division.

00:20:54.580 --> 00:21:05.520
And part of that reason might be because some of the early hardware architectures were using sine plus magnitude rather than two's complement, which is kind of, I didn't know that.

00:21:05.520 --> 00:21:09.000
I must have either if I did know it from CS.

00:21:09.000 --> 00:21:10.040
I forgot it.

00:21:10.040 --> 00:21:11.160
Definitely know.

00:21:11.160 --> 00:21:12.280
Remember two's complement.

00:21:12.540 --> 00:21:14.780
But anyway, some interesting history there.

00:21:14.780 --> 00:21:16.020
It's interesting.

00:21:16.020 --> 00:21:20.640
Also, one of the things I brought up, one of the reasons, it's kind of a silly little article to bring up.

00:21:20.640 --> 00:21:34.080
But one of the things I wanted to bring it up is because a lot of new Python people actually don't remember, will forget about energy division and just assume that division is division.

00:21:34.080 --> 00:21:37.620
But energy division is really handy for a lot of cases.

00:21:37.620 --> 00:21:38.740
So don't forget about it.

00:21:38.740 --> 00:21:39.580
That's true, actually.

00:21:40.100 --> 00:21:43.220
Yeah, I find myself sometimes doing int of some float result.

00:21:43.220 --> 00:21:46.520
Maybe I could just double slash it and not have to.

00:21:46.520 --> 00:21:51.160
So comment from the chat, which I'm not sure how to take this.

00:21:51.160 --> 00:21:53.760
I'm thinking that they're bored with this topic, but.

00:21:53.760 --> 00:21:56.660
I'm not sure either.

00:21:56.660 --> 00:21:58.480
Anyway.

00:21:58.480 --> 00:21:59.860
No comment.

00:21:59.860 --> 00:22:01.120
All right.

00:22:01.120 --> 00:22:03.540
We're going to bring the hatchet out on this one, Ryan.

00:22:03.540 --> 00:22:04.740
Bring in the hatchet.

00:22:04.740 --> 00:22:13.200
So there's this thing I ran across called hatchet, which is a distributed task queue for more resilient web apps.

00:22:13.200 --> 00:22:17.660
Now, I don't recall exactly what it is written in.

00:22:17.660 --> 00:22:19.440
I don't think it's written in Python.

00:22:20.700 --> 00:22:21.520
It's unclear.

00:22:21.520 --> 00:22:24.640
It's primary language is Python, but also as a go.

00:22:24.640 --> 00:22:26.020
Anyway, it doesn't matter.

00:22:26.020 --> 00:22:26.660
It has a Python.

00:22:26.660 --> 00:22:32.980
Its first SDK, its first integration is with Python.

00:22:32.980 --> 00:22:34.980
So here's the idea.

00:22:34.980 --> 00:22:36.300
You've got some work.

00:22:36.300 --> 00:22:39.400
It's going to take a little while to run.

00:22:39.600 --> 00:22:46.040
You know, your web app says, hey, I want you to ship this thing or I want you to run some analytics.

00:22:46.040 --> 00:22:56.060
And if those analytics take 10, 15 seconds to run, maybe they're computational and they should run out on another computer rather than on your main web front end.

00:22:56.060 --> 00:22:58.240
Or they shouldn't block it for 15 seconds or whatever.

00:22:58.300 --> 00:23:09.680
When you're talking about your how do you break up import dependencies across the wrong layers and stuff, maybe one way to fix that is to move some of the compute work completely to its own place.

00:23:09.680 --> 00:23:09.920
Right.

00:23:09.920 --> 00:23:17.480
Like these this whole queuing mechanism is super fascinating for creating like truly scalable, like multi user thing.

00:23:17.480 --> 00:23:17.940
Right.

00:23:17.940 --> 00:23:27.520
So if the majority of your work is in some place and you kind of don't really need the answer to give a response, you can just throw it onto one of these background queues and let it go.

00:23:27.760 --> 00:23:35.060
So one of the problems that you run into, though, is what if something goes wrong or how do I see what is running?

00:23:35.060 --> 00:23:36.020
Something fails.

00:23:36.020 --> 00:23:36.880
Can I resume it?

00:23:36.880 --> 00:23:39.420
Maybe it was really important, like ship this thing to the customer.

00:23:39.420 --> 00:23:48.520
But when I put that on the queue and it finally got around to being run, the API at UPS was down for who knows, whatever reason.

00:23:48.520 --> 00:23:48.800
Right.

00:23:48.800 --> 00:23:49.440
Things like that.

00:23:49.440 --> 00:23:50.160
And you can't ship it.

00:23:50.160 --> 00:23:53.540
And then just go into the ether as an error or you resume it.

00:23:53.540 --> 00:23:56.220
Another problem you run into is fairness.

00:23:56.220 --> 00:23:57.120
Right.

00:23:57.120 --> 00:24:01.460
If there's a ton of work coming in faster than the processor can handle.

00:24:01.460 --> 00:24:07.500
Is there some something where maybe only the new ones get worked on and the older ones get almost abandoned?

00:24:07.500 --> 00:24:07.880
Right.

00:24:07.880 --> 00:24:09.240
There's all these interesting things.

00:24:09.240 --> 00:24:14.780
So this thing called hatchet is in the realm of many different things that attempt to solve this problem.

00:24:14.780 --> 00:24:15.180
Right.

00:24:15.800 --> 00:24:16.300
It's interesting.

00:24:16.300 --> 00:24:16.840
It's interesting.

00:24:16.840 --> 00:24:18.860
It's Y Combinator backed.

00:24:18.860 --> 00:24:22.440
It's a company that presumably will have a price.

00:24:22.960 --> 00:24:29.440
But there's also just an open source self, you know, take it for yourself and run with it version over on GitHub.

00:24:29.440 --> 00:24:30.780
So 100% open source.

00:24:30.780 --> 00:24:33.500
2000 or 2200 GitHub stars.

00:24:33.500 --> 00:24:34.580
Pretty interesting.

00:24:34.720 --> 00:24:37.480
But I think the business model is it says request cloud access.

00:24:37.480 --> 00:24:40.460
Like they can run it for you or you can run your own.

00:24:40.460 --> 00:24:40.680
Right.

00:24:40.680 --> 00:24:41.380
Yeah.

00:24:41.700 --> 00:24:45.260
So the website has a bunch of these little animations, which are kind of cool.

00:24:45.260 --> 00:24:48.340
Talks about fairness, batch processing.

00:24:48.340 --> 00:24:52.000
And like as you click on them, see how it like has these little fun, fun animations.

00:24:52.000 --> 00:24:52.720
Like what does this mean?

00:24:52.720 --> 00:24:53.320
Oh, I see.

00:24:53.320 --> 00:24:54.420
Oh, I love it.

00:24:54.420 --> 00:24:55.200
I do too.

00:24:55.200 --> 00:24:55.860
I do too.

00:24:56.040 --> 00:25:02.660
So talks about fairness, batch processing, workflow and event stuff.

00:25:02.660 --> 00:25:06.240
It's engineered for scaling challenges, which is pretty awesome.

00:25:06.240 --> 00:25:19.240
So low latency, 25 milliseconds on average, which means if you put something into the queue, there's ways in which you can sort of make callbacks to check on the process of the work and it shouldn't take all that long.

00:25:19.240 --> 00:25:21.600
Bunch of rules about rate limiting.

00:25:21.600 --> 00:25:23.240
Also durable.

00:25:23.240 --> 00:25:25.280
So you can replay events.

00:25:25.700 --> 00:25:32.360
You can do cron jobs and say, hey, every every morning, just drop this into the queue and run it at 7 a.m. or whatever.

00:25:32.360 --> 00:25:34.640
You can schedule one time jobs.

00:25:34.640 --> 00:25:38.980
It has ability to avoid being destroyed by spikes.

00:25:38.980 --> 00:25:49.800
Like if for some reason a whole bunch of work comes in all at once, maybe you got IoT things that do a bunch of work when people come into the office and the very first sees a bunch of stuff and then it chills out.

00:25:49.800 --> 00:25:51.080
You could smooth that out.

00:25:51.080 --> 00:25:51.900
All kinds of stuff.

00:25:51.900 --> 00:25:54.640
But like I said, it supports three technologies.

00:25:54.880 --> 00:25:58.060
Python number one, type script number two and go number three.

00:25:58.060 --> 00:26:00.340
And it's really easy to do.

00:26:00.340 --> 00:26:06.200
You just go down here and you just put a, you know, when this event happens, I want you to run this class.

00:26:06.200 --> 00:26:08.700
And then it has a bunch of functions methods.

00:26:08.700 --> 00:26:09.700
You say, here's a step.

00:26:09.700 --> 00:26:11.380
Step one, do this work.

00:26:11.380 --> 00:26:11.820
Step two.

00:26:11.920 --> 00:26:17.060
So you just basically put some decorators on a class and then plug it in and off it goes.

00:26:17.060 --> 00:26:17.800
Super easy.

00:26:17.800 --> 00:26:23.460
And to run it, you just say, push an event, whatever the name it is with the data and it'll go, put it off in the background and run it.

00:26:23.460 --> 00:26:26.160
So, yeah, it also has like nice visualizations.

00:26:26.160 --> 00:26:29.440
Like here you can see there's this on hatchet.run.

00:26:29.700 --> 00:26:35.740
You can see there's this like live view of how is the work running through the system and all kinds of stuff.

00:26:35.860 --> 00:26:37.640
So it looks pretty neat to me.

00:26:37.640 --> 00:26:38.420
Open source.

00:26:38.420 --> 00:26:39.340
People can check it out.

00:26:39.340 --> 00:26:40.680
It's worth knowing about.

00:26:40.680 --> 00:26:41.700
Yeah, it's pretty cool.

00:26:41.700 --> 00:26:42.520
Neat.

00:26:42.520 --> 00:26:42.980
Yep.

00:26:42.980 --> 00:26:43.620
Indeed.

00:26:43.620 --> 00:26:43.960
Indeed.

00:26:44.980 --> 00:26:46.000
That's it for our items.

00:26:46.000 --> 00:26:47.360
How are you feeling?

00:26:47.360 --> 00:26:48.600
How extra are you feeling?

00:26:48.600 --> 00:26:52.760
I have only got one extra that I almost that I pretty much mentioned already.

00:26:52.760 --> 00:26:53.700
So I'll do it quickly.

00:26:53.700 --> 00:26:57.820
So Python test is at 215 right now as we look.

00:26:57.820 --> 00:27:06.900
But the most recent episode that will come out probably today is 216, which will be Charlie Marsh talking about uv.

00:27:06.900 --> 00:27:08.500
So check that out also.

00:27:08.500 --> 00:27:09.320
Awesome.

00:27:09.320 --> 00:27:10.440
Yeah, you did mention that.

00:27:10.440 --> 00:27:11.360
That's really good, though.

00:27:11.360 --> 00:27:12.560
How about you?

00:27:12.560 --> 00:27:13.160
Got any extras?

00:27:13.160 --> 00:27:14.780
I'm feeling somewhat extra.

00:27:14.880 --> 00:27:16.760
I got two exciting announcements.

00:27:16.760 --> 00:27:23.700
One, I have a free new course over at Talk Python Training that covers a bunch of awesome technologies.

00:27:23.700 --> 00:27:31.600
But the core idea, the title is build an audio app with AI, with Python and Assembly AI.

00:27:31.600 --> 00:27:41.020
So the idea is what would you do if you, say, had access to, I don't know, a podcast's worth of data that's been going for many years?

00:27:41.280 --> 00:27:43.160
Like Python Bytes or Talk Python.

00:27:43.160 --> 00:27:48.160
Honestly, the thing we build lets you access a whole library of podcasts.

00:27:48.160 --> 00:27:52.540
And you can go in there and do things like, hey, create a transcript, which seems kind of straightforward.

00:27:52.540 --> 00:28:03.300
But once you have transcript data, you could get really cool search, like building your own custom search engine, not just over the title and the show notes and stuff, but also all the spoken words, which is kind of neat.

00:28:03.540 --> 00:28:07.420
So you could create a summary.

00:28:07.420 --> 00:28:09.300
What are the key moments of this?

00:28:09.300 --> 00:28:15.600
And actually, what if I could just have a Q&A with like you and me around what we said in the show?

00:28:15.600 --> 00:28:23.640
So kind of creating an LLM ChatGPT type of thing, but where it knows about any given episode out on the Internet.

00:28:24.220 --> 00:28:25.660
So really fun.

00:28:25.660 --> 00:28:27.260
People will learn FastAPI.

00:28:27.260 --> 00:28:28.700
They learn Pydantic.

00:28:28.700 --> 00:28:30.420
They learn HTMX.

00:28:30.420 --> 00:28:31.180
They learn Beanie.

00:28:31.180 --> 00:28:34.080
And they learn Assembly AI and build a cool thing.

00:28:34.080 --> 00:28:36.180
And the whole course is like a four-hour free course.

00:28:36.180 --> 00:28:37.300
So they can check that out.

00:28:37.300 --> 00:28:37.960
Wow, neat.

00:28:37.960 --> 00:28:38.660
Sounds fun.

00:28:38.660 --> 00:28:39.660
Thanks.

00:28:39.660 --> 00:28:45.140
And next to another new course, Rock Solid Python with Python Typing.

00:28:45.140 --> 00:28:54.220
So this one is not a free one, but it basically shows you not just the how, but the why and when of Python typing.

00:28:54.220 --> 00:28:56.420
A bunch of different examples.

00:28:56.420 --> 00:29:02.460
Obviously, the language, but things like FastAPI and Pydantic, how do they use it?

00:29:02.460 --> 00:29:05.260
What you talked about protocol before.

00:29:05.260 --> 00:29:05.940
What is protocol?

00:29:05.940 --> 00:29:07.060
Where does it fit?

00:29:07.060 --> 00:29:13.580
A bunch of design patterns and guidance for Python typing and how to think about how you should use it.

00:29:13.580 --> 00:29:15.780
So people should also check this one out.

00:29:15.780 --> 00:29:16.820
I'm really proud of this one.

00:29:16.820 --> 00:29:19.120
And it is also around four hours, 4.4 hours.

00:29:19.120 --> 00:29:22.680
And Pradeep asks out there, are these courses paid or free?

00:29:22.680 --> 00:29:23.280
Yes.

00:29:23.280 --> 00:29:27.780
The Build an Audio app course is 100% free.

00:29:27.780 --> 00:29:28.800
You just have to create an account.

00:29:28.800 --> 00:29:31.300
The Rock Solid Python course is 49 bucks.

00:29:31.300 --> 00:29:33.700
Yeah, but that's like 10 bucks an hour.

00:29:33.700 --> 00:29:34.920
That's almost free.

00:29:34.920 --> 00:29:35.440
Yes.

00:29:36.480 --> 00:29:42.540
It's certainly not a lot of money, you know, compared to other ways you might go learn about things like this.

00:29:42.540 --> 00:29:44.620
So anyway, both of these courses are awesome.

00:29:44.620 --> 00:29:45.880
People should check them out.

00:29:45.880 --> 00:29:48.440
So those are the two big announcements.

00:29:48.440 --> 00:29:51.980
I also have a couple of interesting things I just want to give a quick shout out to.

00:29:51.980 --> 00:29:54.000
Previously, we spoke about Doku.

00:29:54.000 --> 00:29:54.600
Doku?

00:29:54.600 --> 00:29:56.480
I'm going to go with Doku because I think it's based on Docker.

00:29:56.480 --> 00:29:56.920
I don't know.

00:29:56.920 --> 00:29:57.380
Yeah.

00:29:57.820 --> 00:29:58.100
Doku.

00:29:58.100 --> 00:29:58.220
Doku.

00:29:58.220 --> 00:29:58.260
Doku.

00:29:58.260 --> 00:29:58.660
Doku.

00:29:58.660 --> 00:29:59.060
Doku.

00:29:59.060 --> 00:29:59.460
Doku.

00:29:59.460 --> 00:29:59.460
Doku.

00:29:59.460 --> 00:29:59.860
Doku.

00:29:59.860 --> 00:29:59.860
Doku.

00:29:59.860 --> 00:29:59.860
Doku.

00:29:59.860 --> 00:29:59.860
Doku.

00:29:59.860 --> 00:29:59.860
Doku.

00:29:59.860 --> 00:29:59.860
Doku.

00:29:59.860 --> 00:30:00.260
Doku.

00:30:00.260 --> 00:30:00.660
Doku.

00:30:00.660 --> 00:30:00.660
Doku.

00:30:00.660 --> 00:30:00.660
Doku.

00:30:00.660 --> 00:30:00.660
Doku.

00:30:00.660 --> 00:30:00.660
Doku.

00:30:00.660 --> 00:30:04.040
platform as a service alternative to Heroku.

00:30:04.040 --> 00:30:05.120
We already spoke about that.

00:30:05.120 --> 00:30:09.640
But when we did, Ray out there on Mastodon, thank you, Ray,

00:30:09.640 --> 00:30:12.700
said, hey, you guys, love the episode on Doku.

00:30:12.700 --> 00:30:14.080
Haven't tried it myself.

00:30:14.080 --> 00:30:15.580
I'm a big fan of Heroku.

00:30:15.580 --> 00:30:18.620
However, I set up Coolify.

00:30:18.620 --> 00:30:19.680
Coolify.

00:30:19.680 --> 00:30:21.100
I haven't talked about this, have I?

00:30:21.100 --> 00:30:22.060
I don't think so.

00:30:22.060 --> 00:30:23.000
Yeah, I don't think so.

00:30:23.000 --> 00:30:23.620
Okay.

00:30:23.620 --> 00:30:27.240
So Coolify is kind of the same.

00:30:27.240 --> 00:30:29.820
So it's pretty similar, but it has a nice GUI

00:30:29.820 --> 00:30:32.500
to configure everything and keep an eye on the status

00:30:32.500 --> 00:30:33.540
and all those things.

00:30:33.540 --> 00:30:36.900
So Coolify is self-hosting with superpowers.

00:30:36.900 --> 00:30:40.620
It's a self-hosted alternative to not just Heroku,

00:30:40.620 --> 00:30:42.680
but also Netlify and Verisil.

00:30:42.680 --> 00:30:44.680
So Netlify for static sites.

00:30:44.680 --> 00:30:47.800
You basically set this thing up, get it going.

00:30:47.800 --> 00:30:51.280
It'll run any language on basically any server.

00:30:51.280 --> 00:30:54.760
You just push to some Git branch, you deploy it.

00:30:54.760 --> 00:30:57.140
It does automatic SSL certificates.

00:30:57.140 --> 00:30:59.100
So it just had a static site.

00:30:59.100 --> 00:31:01.960
And I just want it to run over SSL on the internet.

00:31:01.960 --> 00:31:02.860
Boom, done.

00:31:02.860 --> 00:31:08.640
It just does, lets encrypt automatically as part of creating the app up there and gets it going.

00:31:08.640 --> 00:31:13.720
So it's probably a little bit of setup to get it going and get it running on Docker and stuff.

00:31:13.720 --> 00:31:19.160
But once you do, it just becomes the substrate for all of your apps that you want to put out there.

00:31:19.160 --> 00:31:21.360
And you don't have to think about anything but Git basically.

00:31:21.360 --> 00:31:22.800
That's pretty cool actually.

00:31:23.180 --> 00:31:24.980
Yeah, it looks really, really nice.

00:31:24.980 --> 00:31:26.960
So people can check this out.

00:31:27.960 --> 00:31:28.440
Yeah.

00:31:28.440 --> 00:31:37.360
It has a paid cloud version and a self-hosted version with 17,000 or more people using it self-hosted.

00:31:37.360 --> 00:31:38.140
So that's pretty cool.

00:31:38.140 --> 00:31:39.760
It's interesting that they give stats there.

00:31:39.760 --> 00:31:41.100
But that's my last one.

00:31:41.100 --> 00:31:42.720
I think this is really neat as well.

00:31:42.720 --> 00:31:45.320
So Ray, thanks for sharing extra details.

00:31:45.320 --> 00:31:46.500
Yeah, nice.

00:31:46.500 --> 00:31:47.000
Cool.

00:31:47.260 --> 00:31:48.980
Shall we close it off with a joke?

00:31:48.980 --> 00:31:50.060
Yeah, let's.

00:31:50.060 --> 00:31:50.760
Yeah.

00:31:50.760 --> 00:31:51.240
Okay.

00:31:51.240 --> 00:31:55.280
So speaking of, I want to run my stuff on production.

00:31:55.280 --> 00:31:56.000
How do I do it?

00:31:56.000 --> 00:31:57.680
This is a great, a great one.

00:31:57.680 --> 00:32:00.060
Back to workchronicles.com.

00:32:00.060 --> 00:32:04.020
And so I don't know how you feel about this, Brian, but I think it's pretty true.

00:32:04.020 --> 00:32:05.820
There's two engineers talking.

00:32:05.820 --> 00:32:07.820
He says, oh no, I broke production.

00:32:07.820 --> 00:32:09.440
Will I get fired?

00:32:09.440 --> 00:32:12.560
The Morrissey and developer looks over.

00:32:12.560 --> 00:32:17.500
If we fire engineers who break production, we will need to fire everyone eventually.

00:32:17.500 --> 00:32:19.140
Yeah.

00:32:19.140 --> 00:32:20.120
Yeah.

00:32:20.120 --> 00:32:25.860
Also, if you fix it, you'll get a promotion or a raise or something.

00:32:25.860 --> 00:32:27.000
So there you go.

00:32:27.000 --> 00:32:27.620
Yeah.

00:32:27.620 --> 00:32:32.700
Maybe you just need to keep your fix rate above your destroy rate.

00:32:32.700 --> 00:32:33.480
Yeah.

00:32:33.480 --> 00:32:33.940
Yeah.

00:32:33.940 --> 00:32:34.440
There you go.

00:32:34.440 --> 00:32:38.140
Well, that's what I brought for us today.

00:32:38.140 --> 00:32:38.640
Cool.

00:32:38.640 --> 00:32:39.420
I like it.

00:32:39.420 --> 00:32:40.120
Yeah.

00:32:40.120 --> 00:32:40.680
Excellent.

00:32:40.680 --> 00:32:41.280
Okay.

00:32:41.280 --> 00:32:45.060
Well, nice to kick off the week with a little Python bites.

00:32:45.060 --> 00:32:46.200
Happy to do it early.

00:32:46.200 --> 00:32:46.700
Yeah.

00:32:46.700 --> 00:32:47.640
Good to see you.

00:32:47.640 --> 00:32:49.340
And thanks to everyone who joined.

