Brought to you by Michael and Brian - take a Talk Python course or get Brian's pytest book


Transcript #374: Climbing the Python Web Mountain

Return to episode page view on github
Recorded on Monday, Mar 11, 2024.

00:00 Hello and welcome to Python Bytes where we deliver Python news and headlines directly to your earbuds.

00:06 This is episode 374 recorded March 11th, 2024.

00:11 I am Michael Kennedy.

00:12 And I'm Brian Okken.

00:14 And this episode is brought to you by Scout APM.

00:17 Check them out at pythonbytes.fm/scout.

00:22 I'll tell you more about them later.

00:24 If you'd like to connect with us, Mastodon is the main place.

00:27 We're also on X Twitter.

00:29 But primarily on Mastodon.

00:32 And that's @mkennedy, @brianocken, and @pythonbytes all at mastodon.org.

00:36 And watch us live, usually Tuesdays at 10 a.m. Pacific time.

00:41 However, different today.

00:42 But check it out at pythonbytes.fm/live.

00:44 You'll be able to like get notified about the next upcoming recording.

00:48 I usually put that up right after we're done with this one.

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

00:59 The first step towards summer coming.

01:01 It is daylight savings switch over here in the U.S.

01:05 And I know it is much maligned by people, but I was delighted to see the sun was up past 7 p.m. yesterday.

01:11 After living in dark and rain for months and months, I'm feeling the summer.

01:16 I know it's not quite there yet, but...

01:18 Yeah, I didn't really notice it until after I woke up.

01:22 Yeah.

01:22 I woke up and I'm like, "Oh, gosh, I thought I'd slept in until like 10,

01:27 but it was really 11. So, sleep the day away." Beautiful. Beautiful, beautiful.

01:33 All right. Well, over to Python.

01:35 What's your first thing?

01:36 Okay. Well, I want to talk about spaghetti code a little bit.

01:40 Actually, or how to fix it.

01:42 So, there's an article...

01:43 Is that what you get when you're real hungry?

01:44 You're like, "What are you gonna have for dinner?

01:46 Maybe some spaghetti code.

01:47 A little carbonara?" Is that how you pronounce it?

01:52 I've never been able to pronounce it.

01:53 I'm probably gonna get emailed that it's not, but that's how I pronounce it.

01:56 Article from somebody that goes by Piggly.

01:59 "Six ways to improve the architecture of your Python project using import linter."

02:04 And I kind of like this article, even if you don't want to use import linter.

02:08 So, because of the six ways to improve the architecture, I love that.

02:12 I love digging into that.

02:14 So, and I actually have a couple projects that I'm working on that I would like to maybe clean up the architecture a bit.

02:20 So, kind of a fun picture.

02:22 Not sure what's going on here.

02:23 Just a whole bunch of boxes pointing at each other.

02:26 I guess just indicating that there's circular dependencies or something going on.

02:33 And anyway, so a little bit of a discussion about why complex architecture might be bad,

02:40 but I don't think any of us need convincing of that.

02:43 Simplifying is a good thing.

02:44 So, the first part talks about maybe setting up an idea of like, maybe you could, you have an idea of like setting your architecture into layers.

02:52 If that's what you want to do, like a user layer or an application layer,

02:58 plus a utilities or something services.

03:01 But there's a tool called the import linter that there's a discussion about how to set it up

03:06 so that you can use that to both configure what you want your layers to be and then test for it.

03:15 It's like a linting to make sure that you're not importing in the wrong direction.

03:18 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,

03:24 but not the other way around.

03:25 So, the importing is a way to test that.

03:29 Because of that, I'm not sure what these arrows mean.

03:32 Because it doesn't quite make sense if it's not an inheritance or calling.

03:36 I don't know. Anyway, it's just an error.

03:38 That looks pretty interesting.

03:40 I think that means that something from that layer is importing something from the bottom layer,

03:45 the lower layer.

03:46 Yeah, but yeah.

03:48 I think 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,

03:57 say like the data layer imported the UI layer sort of thing.

04:01 I think that's what it's saying.

04:02 Yeah. Oh, and it makes more sense if I would have drawn the top layer at the top.

04:07 I think it makes more sense to me if you do it the other way.

04:10 Anyway, that's a drawing thing.

04:12 It doesn't really matter.

04:13 And also-

04:13 It's probably by somebody in Australia because everything is upside down down there.

04:17 Oh, yeah.

04:18 That's probably it.

04:19 Yeah, yeah. That was it.

04:19 Okay.

04:20 So what happens when you run this is you're probably-

04:24 the recommendation is you're probably going to get a bunch of lint warnings or errors.

04:29 And or maybe not, if not, awesome.

04:32 But if you do, the recommendation here, which I kind of thought was cool,

04:37 was to kind of exclude all of them.

04:41 Like go through and add these ignore imports and just go through and ignore the ones that failed.

04:48 And I'm like, okay, well, then you're going to pass and it's just going to ignore everything.

04:52 But the idea behind it is to do it one at a time.

04:55 So it's going to be overwhelming to get a bunch of errors.

04:57 So ignore them all and then unignore one at a time and then go through and fix them.

05:04 So that's where the really- the reason why I picked out this article isn't really because import linter is cool.

05:10 It might be cool, but it's that these ways to fix these import dependencies,

05:17 I thought were really great to walk through.

05:19 There's six of them. First one is merging and splitting modules.

05:23 And like there's an example where you've got resources that calls clusters,

05:27 clusters calls resources dot cluster utils, and that's going the wrong direction.

05:33 But to fix it, you maybe move those cluster utils down into the lower, like a lower library, like splitting them off.

05:40 Kind of sort of straightforward, but it's good to like think about this.

05:45 So I like that that part of it. Dependency injection.

05:48 And if you're the kind of person that's kind of afraid of dependency injection,

05:53 then don't even think about that term because it's not actually that scary.

05:57 Just the term was scary to me for a while.

05:59 So anyway, dependency injection might help to be able to pass a pass dependencies down into lower layers from upper layers.

06:08 So that's a good way to get around it.

06:11 The interesting, I'm glad they dug into this, is when you do the inversion of, what is it?

06:18 I forget, the inversion of control.

06:19 Inversion of control, yeah.

06:21 Yeah. Sometimes if with Python, that works great, except for type hints.

06:27 Sometimes you need to get the type hints, getting those right.

06:31 So talking about how to use the protocol from typing to get that to work right.

06:38 That discussion's in here, which is great. I love protocol.

06:41 Then another discussion about using simpler dependency types and then delaying function implementation.

06:48 And then even, what was the last one?

06:52 Look at for six, configuration driven.

06:54 That was interesting.

06:56 I never really thought about doing this.

06:57 The idea is you'd have a settings file or something and have that have, and then have the string that you would import, like marketing.sendSMS.

07:09 And then later on in your calling thing, you use import string to import it.

07:14 So you're still have the backwards dependency, but you don't know it at run, at compile, at write time, you know it at run time.

07:23 I don't know.

07:23 I don't know what I think about that.

07:24 But anyway.

07:25 Yeah.

07:26 Yeah, that's interesting.

07:27 It's a way to do it.

07:28 So and then the last one is a replace function calls with event driven and purchase.

07:34 So like callbacks and stuff like that.

07:37 So these are a great architecture things to think about when you're cleaning up architecture, because it's not always trivial to just say, just don't do that.

07:45 Don't do those imports.

07:46 Well, how do you get around it if you've designed it that way?

07:48 So I think a decent discussion about software architecture here.

07:53 So I do think that's pretty interesting.

07:55 And also just more broadly, I like the idea of ignoring all the issues you might run into with linters and then slowly turning the screws to make it a little tighter is good advice.

08:06 Because if you have existing code of any significant size and you've never done linting on it, and then you turn on a linter, you feel bad about yourself.

08:14 You're like, I've done all that wrong.

08:16 593 errors.

08:18 Great.

08:19 Well, we'll turn that back off because I got work to do.

08:21 You know what I mean?

08:22 Yeah.

08:22 Well, I'm kind of going through that with rough right now.

08:26 So got some projects where default rough works fine, but the rough has like 800 rules or something you can add.

08:33 And so I'm trying to turn on some of those extra features.

08:37 I have just a few at a time.

08:39 See, testing the waters, see how many failures I get and whether I want to clean them up.

08:44 So yeah.

08:45 Yeah.

08:45 Interesting.

08:46 Just interesting timing.

08:48 I'm going to be speaking with Charlie Marshall on Talk Python tomorrow.

08:51 Oh, awesome.

08:52 About 24 hours from now, whatever that makes it for you.

08:55 Yeah.

08:55 Out there listening.

08:56 Yeah.

08:57 And we're going to talk mostly about UV, but I'm sure we'll talk a bit about rough as well.

09:00 Cool.

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

09:04 So.

09:05 Well, how about that?

09:07 Awesome.

09:07 Awesome.

09:08 Do you guys talk about UV as well?

09:09 Yeah, we talked about Flickate, or not Flickate.

09:14 We talked about rough and Astral and UV, most of the conversations around UV and some of the discussion around that.

09:21 So.

09:22 Nice.

09:22 Yeah.

09:23 That'll be fun.

09:23 All right.

09:24 On to the next one here by Pierce Freeman.

09:28 That's kind of a cool name, isn't it?

09:29 It could be like a double O sort of agent.

09:32 Yeah.

09:32 009.

09:33 I don't know what that is.

09:35 Not James, but something like that.

09:36 Anyway.

09:36 Pierce Freeman to the rescue.

09:38 Exactly.

09:39 To bring you React and FastAPI and Python.

09:43 In fact, with this framework called Mountaineer.

09:45 So Mountaineer is a batteries included web framework for Python and React.

09:51 So this, it plays in a similar space as FastUI from Samuel Colvin and the Pydantic crew.

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

10:05 I think this is coming from a different angle.

10:08 I think you're doing, you know, so FastUI is more about maybe you don't really have to do the React side unless you want.

10:14 And it kind of brings that stuff together.

10:15 Whereas this kind of like you're embracing TypeScript, you're embracing React, but you also get some really nice Python integration.

10:23 And so if you look down here, what does it say?

10:26 It says it lets you easily build web apps in Python and React.

10:30 And if you are familiar with this, it should sound familiar to you.

10:34 It should basically seem like what you're used to.

10:37 And if not, then maybe not.

10:39 But it says each framework like Flask or FastAPI or Django or whatever has its tradeoffs and features.

10:45 And for this one, it focuses on developer productivity above all else with production speed of close seconds.

10:51 So type hints up and down the stack front end, back end database, trivially easy client server communication.

10:57 So you don't find yourself creating a bunch of APIs so that your React stuff can talk to the API.

11:03 So it can actually get its data and all that, which is pretty interesting.

11:07 It comes, this is kind of cool.

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

11:14 You'll go to a website and it'll have something on the screen.

11:17 And then like half a second later, it'll shift around and stuff will like all come into existence.

11:23 You know, you'll be like, it'll have like the footer will be touching the top and then it'll bump out.

11:28 It'll be a spinner and then stuff, you know, it's like, what is it?

11:30 What is it doing?

11:31 Well, especially if you start reading and then a picture pops in and what you read pops off the screen.

11:37 Yeah. Another thing that drives me crazy is if you paste something into an input, but you don't type it,

11:45 sometimes that won't trigger the data binding.

11:47 And you know, like if he's a password manager type thing or something, or you just paste something,

11:53 it'll say, oh, this is invalid.

11:55 What is wrong with this?

11:56 Oh, if you put a space and delete the space.

11:57 Oh, oh, it's valid now.

11:59 It's like, oh, I see.

12:01 So something that would be really nice is if you just could ship straight HTML, right?

12:05 Yeah.

12:05 Or the first view of that was.

12:08 And so what this comes with is they actually bundle the V8 engine.

12:12 So on the server side, it can, it can render what your browser would do for you as final HTML.

12:18 And it delivers with so optimized server side rendering for better accessibility and SEO.

12:24 That's pretty cool.

12:25 I think.

12:25 Yeah, that's cool.

12:26 As a Python thing, like normally you hear that as a node thing or something, right?

12:29 Yeah.

12:30 It also does static analysis for validations of like links and CSS and so on.

12:35 And like I said, skip the API or Node.js server just for front end clients.

12:41 Okay.

12:41 So all of these things are pretty cool.

12:43 If let me give you a warning and a disclaimer.

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

12:51 Like this is really for React people 100%.

12:54 Second, that's not me.

12:55 So I'm going to do my best to like tell you why you might want this.

12:59 I think I can, can I get there?

13:00 So first of all, it has a scaffolding type thing called create Mountaineer app and they suggest pipx.

13:08 And I'm loving to see more pipx come along for these kinds of tools, right?

13:12 Like you run this once, it's not part of your app.

13:15 You just pipx install it and everything gets going.

13:17 It's great.

13:18 Also uses poetry pretty heavily.

13:20 So what it does is it creates a Python bits and then some TypeScript stuff for your front end.

13:27 And it comes with a CLI as well, which is nice.

13:29 It has a built-in Docker containers for like managing Postgres databases and so on if you want to use that, but you don't have to.

13:36 And let's see.

13:37 So another interesting integration is it uses SQL model.

13:42 So that's the typing in the data layer aspect.

13:44 So SQL model is Pydantic plus SQLAlchemy basically by Sebastian Ramirez.

13:49 So that's cool.

13:50 And then you go down here and you create controllers.

13:54 So it's kind of a class-based type of thing.

13:56 First, it seems a little unnecessary, but as you interact with it and expose more features to the React layer, you'll see that kind of relevant there.

14:05 So you just say, I'm going to render, say, my database things and some other pieces of data.

14:11 And then down somewhere, you've got your React code and your TSX, your React component there.

14:18 And if you've written React stuff, you should know pretty well how it works.

14:22 But it manages passing all that data over like serverstate.todo's.

14:26 And then you can just work with that, which is interesting.

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

14:35 And I have a to-do example, right?

14:36 So if you put this @sideeffect decorator on it, here's where the React integration comes in.

14:41 That's pretty wild.

14:43 So it automatically generates typed, let's just say typed TypeScript because, I mean, you can't have non-typed TypeScript.

14:50 But generally, TypeScript is typed.

14:52 You generate TypeScript versions of the functions that you write in Python on the JavaScript side.

14:58 So you immediately can just start calling it and using those features.

15:02 All right, so it kind of has this really tight integration with React, like as you would expect.

15:06 What else?

15:07 I think that's pretty much it.

15:08 But if you're a heavy React shop and you want a nice Python back end and you want a tight data integration between those, this is probably worth a look.

15:18 - Yeah, neat.

15:19 - Yeah, yeah.

15:20 It looks pretty neat to me too.

15:21 I'm not, like I said, I'm not really a React person.

15:24 So I'm not sure that I'm necessarily going to use it.

15:27 But if I were to start adopting React, I may well decide that that's what I want.

15:32 Speaking of cool things, Brian, how about Scout APM?

15:36 Let me tell you real quick about Scout APM.

15:40 They're big supporters of Python Bytes, so we appreciate that very much.

15:44 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.

15:53 They're a leading Python application performance monitoring tool, APM, that helps you identify and solve performance abnormalities faster and easier.

16:03 Scout APM ties bottlenecks such as memory leaks, slow database queries, background jobs, and the dreaded N+1 queries that you can end up if you do lazy loading in your ORM, and then you say, "Oh no, why is it so slow?

16:16 Why are you doing 200 database queries for what should be one?" So you can find out things like that.

16:19 And it links it back directly to source code, so you can spend less time in the debugger and peeling logs and just finding the problems and moving on.

16:27 And you'll love it because it's built for developers by developers.

16:30 It makes it easy to get set up.

16:32 Seriously, you can do it in less than four minutes.

16:34 So that's awesome.

16:35 And the best part is the pricing is straightforward.

16:39 You only pay for the data that you use with no hidden overage fees or per seat pricing.

16:44 And I just learned this, Brian, they also have, they provide the pro version for free to all open source projects.

16:51 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.

16:59 So you can start your free trial and get instant insights today.

17:03 Visit pythonbytes.fm/scout.

17:05 The link is in your podcast player show notes as well.

17:08 And please use that link.

17:09 Don't just search for them because otherwise they don't think you came from us.

17:13 And then they'd stop supporting the show.

17:14 So please use our link pythonbytes.fm/scout.

17:17 Check them out.

17:18 It really supports the show.

17:20 Awesome.

17:20 Awesome.

17:21 What's next, Brian?

17:22 Well, what's next is Guido van Rossum.

17:26 Oh, yeah.

17:27 So he's blogging a little bit lately.

17:30 And he put up a post called "Why Python's Integer Division Floors".

17:38 And I think this is just an interesting little bit of history.

17:43 There's some, so, and this was a difference between Python 2 and 3.

17:47 I guess, no, it, integer division always did flooring.

17:51 But the, you know, we did a kind of a thing of what one slash meant.

17:55 So if you do two slashes, it's always integer division.

18:00 If you do one slash in, if it was both integers in Python 2, it would be integer division.

18:06 And it would possibly not be the floating point result.

18:09 But in Python 3, it will generate a float if you have it.

18:13 Like, for instance, one third will, one divided by three results in a float.

18:18 But if you do integer division, it's not.

18:21 It's something else.

18:22 Is that why the two to three conversion was so hard?

18:25 I'm just kidding.

18:26 What was that?

18:26 It was strings. Everyone knows it's strings.

18:28 So is that why the integer, the Python 2 to 3 story was so hard?

18:33 [laughs]

18:34 No, I'm just joking.

18:36 [laughs]

18:37 Yeah.

18:38 So, yeah, so if you do five to two slashes, so integer division of five divided by two,

18:45 you get two.

18:47 And, which is normal, that's everywhere.

18:51 But if you do it, like, say, negative five, you don't get negative two, you get negative three.

18:58 So that's the, there's a question.

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

19:06 And so it's going, it does a division, and then it goes to the closest integer to the negative, closest to negative infinity.

19:16 So, and there's reasonings behind that.

19:19 But it's different than C.

19:21 Apparently, I completely forgot what C did.

19:24 C does it closer to zero.

19:26 So you'd both, so negative five divided by two would, you'd end up with two, negative two.

19:31 So the history there is that there was a choice to make.

19:37 And you could either, with, it works with the modulo operator as well.

19:45 Modulo will create the remainder, where integer division creates the integer division, the integer quotient.

19:52 So, such that A divided by B equals Q, with remainder R, such that R is between zero and B.

20:01 There's math here.

20:03 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.

20:12 Or if you want R to always be positive.

20:14 And basically, Guido chose the one that looks nicer in math.

20:22 So that we go, we go do a floor division instead.

20:27 The interesting, the interesting take on this, I thought, was, well, why did C choose the other way?

20:33 And that's, that's the part that I thought was really interesting.

20:37 And his answer, or his guess, is that, well, C was doing it way before Python was.

20:44 And C was doing it on hardware that it may have been easier to do, to do division closer to zero instead of floor division.

20:54 And part of that reason might be because some of the early hardware architectures were using sine plus magnitude, rather than twos complement.

21:03 Which is kind of, I didn't know that.

21:06 I must have, either if I did know it from CS, I forgot it.

21:10 Definitely no remember twos complement.

21:12 But anyway, it's an interesting history there.

21:15 Also, one of the things I brought up, one of the reasons, it's kind of a silly little article to bring up.

21:20 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 integer division.

21:31 And just assume that division is division.

21:34 But integer division is really handy for a lot of cases.

21:37 So don't forget about it.

21:38 That's true, actually.

21:39 Yeah, I find myself sometimes doing int of some float result.

21:43 Maybe, maybe I could just double slash it and not have to.

21:46 So comment from the chat, which I'm not sure how to take this.

21:51 I'm thinking that they're bored with this topic, but...

21:53 I'm not sure either.

21:56 Anyway.

21:58 No comment.

21:59 All right.

22:01 You know what, we're going to bring the hatchet out on this one, Ryan.

22:03 Bring in the hatchet.

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

22:13 Now, I don't recall exactly what it is written in.

22:17 I don't think it's written in Python.

22:19 It's unclear.

22:21 It's primary language is Python, but also has a go.

22:24 Anyway, it doesn't matter.

22:25 It has a Python.

22:26 It's first SDK, its first integration is with Python.

22:33 So here's the idea.

22:35 You've got some work.

22:36 It's going to take a little while to run.

22:39 You know, your web app says, "Hey, I want you to ship this thing." Or, "I want you to run some analytics."

22:46 And if those analytics take 10, 15 seconds to run, maybe they're computational.

22:50 And they should run out on another computer rather than on your main web front end.

22:56 Or they shouldn't block it for 15 seconds or whatever.

22:58 When you're talking about your, how do you break up import dependencies across the wrong layers and stuff,

23:04 maybe one way to fix that is to move some of the compute work completely to its own place, right?

23:09 Like this whole queuing mechanism is super fascinating for creating like truly scalable, like multi-user thing, right?

23:17 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,

23:23 you can just throw it onto one of these background queues and let it go.

23:27 So one of the problems that you run into though is what if something goes wrong?

23:32 Or how do I see what is running?

23:35 Something fails, can I resume it?

23:36 Maybe it was really important, like ship this thing to the customer.

23:39 But when I put that on the queue and it finally got around to being run,

23:43 the API at UPS was down for who knows, whatever reason, right?

23:48 Things like that and you can't ship it.

23:50 And then just go into the ether as an error or you resume it.

23:53 Another problem you run into is fairness, right?

23:57 If there's a ton of work coming in faster than the processor can handle,

24:01 is there some thing where maybe only the new ones get worked on and the older ones get almost abandoned, right?

24:07 There's all these interesting things.

24:09 So this thing called Hatchet is in the realm of many different things that attempt to solve this problem, right?

24:15 It's interesting, it's Y Combinator backed.

24:19 It's a company that presumably will have a price, but there's also just an open source, take it for yourself and run with it,

24:28 version over on GitHub, so 100% open source, 2,200 GitHub stars.

24:33 Pretty interesting.

24:34 But I think the business model is it says request cloud access, like they can run it for you or you can run your own, right?

24:40 - Yeah.

24:41 - So the website has a bunch of these little animations, which are kind of cool.

24:45 It talks about fairness, batch processing.

24:48 And as you click on them, see how it has these little fun animations.

24:52 Like, what does this mean? Oh, I see.

24:53 - Oh, I love it.

24:54 - I do too. I do too.

24:56 So it talks about fairness, batch processing, workflow, and event stuff.

25:02 It's engineered for scaling challenges, which is pretty awesome.

25:06 So low latency, 25 milliseconds on average, which means if you put something into the queue,

25:12 there's ways in which you can sort of make callbacks to check on the process of the work

25:17 and it shouldn't take all that long.

25:19 A bunch of rules about rate limiting.

25:21 Also durable, so you can replay events.

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

25:32 You can schedule one-time jobs.

25:34 It has ability to avoid being destroyed by spikes.

25:38 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

25:45 and people come into the office and at very first sees a bunch of stuff and then it chills out, right?

25:49 You could smooth that out, all kinds of stuff.

25:51 But like I said, it supports three technologies, Python number one, TypeScript number two, and Go number three.

25:58 And it's really easy to do.

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

26:05 And then it has a bunch of functions, methods.

26:08 You say, here's a step, step one, do this work, step two.

26:11 So you just basically put some decorators on a class and then plug it in and off it goes.

26:17 Super easy. And to run it, you just say, push an event, whatever the name it is with the data,

26:21 and it'll go, put it off in the background and run it.

26:23 So yeah, it also has like nice visualizations.

26:26 Like here you can see there's this on hatchet.run.

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

26:35 So it looks pretty neat to me.

26:37 Open source, people can check it out.

26:39 It's worth knowing about.

26:40 Yeah, it's pretty cool.

26:42 Indeed, indeed.

26:44 That's it for items.

26:46 How are you feeling? How extra are you feeling?

26:48 I've only got one extra that I almost, that I pretty much mentioned already.

26:52 So I'll do it quickly.

26:54 So Python test is at 2.15 right now as we look, but the most recent episode that will come out probably today

27:02 is 2.16, which will be Charlie Marsh talking about UV.

27:06 So check that out also.

27:08 Awesome. Yeah, you did mention that.

27:10 That's really good though.

27:11 How about you? Got any extras?

27:13 I'm feeling somewhat extra.

27:14 I got two exciting announcements.

27:16 One, I have a free new course over at Talk Python Training that covers a bunch of awesome technologies,

27:23 but the core idea, the title is Build an Audio App with AI, with Python and Assembly AI.

27:31 So the idea is what would you do if you say had access to, I don't know, a podcast's worth of data

27:39 that's been going for many years, like Python Bytes or Talk Python, or honestly,

27:43 the thing we built lets you access a whole library of podcasts.

27:48 And you can go in there and do things like, hey, create me a transcript, which seems kind of straightforward.

27:52 But once you have transcript data, you could get really cool search, like building your own custom search engine,

27:57 not just over the title and the show notes and stuff, but also all the spoken words, which is kind of neat.

28:03 Then you also bring more of the AI stuff in.

28:05 You could create a summary. What are the key moments of this?

28:09 And actually, what if I could just have a Q&A with you and me around what we said in the show?

28:15 So kind of creating an LLM ChatGPT type of thing, but where it knows about any given episode out on the internet.

28:23 So really fun. People will learn FastAPI.

28:26 They learn Pydantic. They learn HTMX.

28:29 They learn Beanie, and they learn Assembly AI and build a cool thing.

28:33 And the whole course is like a four-hour free course, so they can check that out.

28:36 - Wow, neat. Sounds fun.

28:38 - Thanks. And next to it, another new course, Rock Solid Python with Python Typing.

28:44 So this one is not a free one, but it basically shows you not just the how,

28:50 but the why and when of Python typing.

28:53 A bunch of different examples.

28:56 Obviously the language, but things like FastAPI and Pydantic, how do they use it?

29:02 What you talked about protocol before.

29:04 What is protocol? Where does it fit?

29:06 A bunch of design patterns and guidance for Python typing and how to think about how you should use it.

29:12 So people should also check this one out.

29:14 I'm really proud of this one.

29:15 And it is also around four hours, 4.4 hours.

29:18 And Pradeep asks out there, are these courses paid or free?

29:22 Yes. The Build an Audio App course is 100% free.

29:27 You just have to create an account.

29:28 The Rock Solid Python course is 49 bucks.

29:30 Yeah, but that's like 10 bucks an hour.

29:33 That's almost free.

29:34 Yes. It's certainly not a lot of money, you know, compared to other ways you might go learn about things like this.

29:41 So anyway, both of these courses are awesome.

29:44 People should check them out.

29:45 So those are the two big announcements.

29:47 I also have a couple of interesting things.

29:49 I just want to give a quick shout out to, previously we spoke about Doku.

29:53 I'm going to go with Doku because I think it's based on Docker.

29:55 I don't know.

29:56 Yes.

29:57 Doku. And this is an open source platform as a service alternative to Heroku.

30:03 We already spoke about that.

30:04 But when we did, Ray out there on Mastodon, thank you, Ray, said, hey, you guys, love the episode on Doku.

30:12 Haven't tried it myself.

30:13 Big fan of Heroku.

30:15 However, I set up Coolify.

30:18 Coolify.

30:19 I haven't talked about this, have I?

30:20 I don't think so.

30:21 Yeah, I don't think so.

30:22 Okay. So Coolify is kind of the same.

30:26 So this is pretty similar, but it has a nice GUI to configure everything and keep an eye on the status and all those things.

30:32 So Coolify is self-hosting with superpowers.

30:36 It's a self-hosted alternative to not just Heroku, but also Netlify and Verisign.

30:42 So Netlify for static sites.

30:44 You basically set this thing up, get it going.

30:47 It'll run any language on basically any server.

30:51 You just push to some Git branch, you deploy it.

30:54 It does automatic SSL certificates.

30:56 So if you just had a static site and I just want it to run over SSL on the internet, boom, done.

31:02 It just does deluxe encrypt automatically as part of creating the app up there and gets it going.

31:08 So it's probably a little bit of setup to get it going and get it running on Docker and stuff.

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

31:18 And you don't have to think about anything but Git basically.

31:21 - That's pretty cool, actually.

31:22 - Yeah, it looks really, really nice.

31:24 So people can check this out.

31:27 Yeah, it has a paid cloud version and a self-hosted version with 17,000 or more people using it self-hosted.

31:36 So that's pretty cool.

31:37 It's interesting that they give stats there.

31:39 But that's my last one.

31:40 I think this is really neat as well.

31:42 So Ray, thanks for sharing extra details.

31:45 - Yeah, nice.

31:46 - Shall we close it off with a joke?

31:48 - Yeah, let's.

31:49 - Yeah, okay.

31:51 So speaking of I want to run my stuff on production, how do I do it?

31:55 This is a great, great one.

31:57 Back to workchronicles.com.

31:59 And so I don't know how you feel about this, Brian, but I think it's pretty true.

32:03 There's two engineers talking.

32:05 It says, "Oh, no, I broke production.

32:07 Will I get fired?" The more seasoned developer looks over.

32:12 If we fire engineers who break production, we will need to fire everyone eventually.

32:18 - Yeah, yeah.

32:20 Also, if you fix it, you'll get a promotion or a raise or something.

32:25 - There you go.

32:26 Yeah.

32:27 Maybe you just need to keep your fix rate above your destroy rate.

32:32 - Yeah.

32:33 - Yeah, there you go.

32:34 - So, yeah.

32:35 - Well, that's what I brought for us today.

32:37 - Cool.

32:38 I like it.

32:39 - Yeah, excellent.

32:40 - Okay, well, nice to kick off the week with a little Python Bytes.

32:44 Happy to do it early.

32:45 - Yeah, thank you.

32:46 - Yeah.

32:47 Good to see you, and thanks to everyone who joined.

32:48 - Bye.

Back to show page