Transcript #296: pip: Constrain your excitement
Return to episode page view on github00:00 Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to
00:04 your earbuds. This is episode 296, recorded August 9th, 2022. I'm Michael Kennedy.
00:10 And I'm Brian Okken.
00:12 Hey, Brian. We have a new sponsor. I just want to say thank you to Mozilla and the IRL podcast
00:17 for sponsoring the show. Check them out at pythonbytes.fm/IRL. And more on that later.
00:22 For now, I want to hear what you've discovered to share with us. Can you constrain your excitement?
00:27 Yeah. I want to talk about pip constraints. So there's a, I think I knew about pip constraints,
00:35 but I kind of forgot about them. But there's an article called pip constraints files by somebody
00:41 named Luminisman. So this is what, so they're kind of neat. So one of the things I was just using a
00:50 pip requirements.in file recently in a course that I'm taking. And I like,
00:57 using requirements.in to generate my requirements.txt file. But there's, and then there's,
01:04 there's a, yeah, anyway, that uses pip-tools. So you have to get pip-tools. But so there's that.
01:10 And then there's also pinning. So especially with applications, we see it more in applications,
01:15 less in libraries of pinning the application. But you can, even in libraries, there's regularly
01:23 sort of constraints around stuff to say, Hey, for this library, I need this, this range of versions,
01:29 or it has to be greater than this or something. Cause I'm depending and that's fine. But this is a way to
01:35 say not what libraries I want to want to use, but if I use a library, which version? So, or constraint on the
01:44 version without saying, I want the library. So, and in the, actually in the pip documentation,
01:49 it says constraint files are requirement files that only control which version, not whether or not it's
01:56 installed. So how would you use this? So this, this article talks about it and it basically says you,
02:03 you kind of use it normally pip install requirements.txt, but you might have,
02:09 if you do like a freeze for instance, or something, or you just pin everything, you might have all of
02:13 the versions, but you might only want like constraints on like one of them. Say, let's say
02:20 you want your, your including pandas, but you want a certain version of pandas or, or you want a certain
02:26 version of numpy, even though pandas requires numpy or something like that. You can have a constraints
02:30 file that lists, this just looks like a, a pip freeze file, but you can, you can put like less
02:37 than or less than equal if you want, or, and you don't have to have everything. So you could just pin
02:42 one of the things. And that way, like, let's say you were doing pandas and you wanted to constrain numpy
02:47 to be a certain version of numpy. You can do that with a constraints file and not have it, not have to
02:53 specify everything, just have it be separate. And the kind of the, the article talks about actually just
02:59 sticking the constraints, specifying your constraint file within the requirements file. And that way
03:05 they're separate. And, and I was thinking about that. And that's an interesting thing to say,
03:09 the dependencies of my application don't change, but the constraints might because of testing or
03:14 whatever. And this, this separating of these two files would help with like, you know, when you
03:19 have the two files of version control, you've changed your constraints, but you haven't changed really
03:24 what you're depending on just the versions of those. So it's kind of a neat to have that separate
03:28 possibility. So, yeah. So for people who are listening, literally the first line of the
03:32 requirements.txt file is --constraint constraints.txt, which I had never considered
03:38 doing that. That's interesting. And then one of the things I thought is, but I'm not, and this works
03:43 if you're handwriting your requirements file, but what if you're, what if you're not, what if you're,
03:47 you're using, requirements.in instead, and this article doesn't go into it,
03:53 but I tried to just, instead of putting that constraint thing in a, in a, requirements.txt
04:00 file, putting it in a requirements.in and using, pip compile to generate it. And it, the pip compile
04:07 seems to also watch the look at this. So it, this constraint works for pip compile as well.
04:13 okay. So that's cool. Yeah. So, kind of a neat thing to, to, to check out. the usage of it's
04:20 pretty easy. just, yeah. Anyway, pinning your requirements is good, but don't pin them too
04:25 tight. If, especially for application for, for libraries and then for applications. yeah,
04:31 I kind of like this because there's a lot of times where I, I know there's a bug in something
04:36 or I've heard about it or, or I haven't gotten around to fixing my code to deal with the new
04:41 version yet. So I'm going to pin something and I don't necessarily need to pin everything. I just
04:45 need to pin certain parts of it. So that's kind of neat. So I like this, just also a little bit
04:51 of a sidebar with the pip compile from pip-tools, you know, you give it the end file and it generates
04:57 the TXT file and it basically obliterates the TXT file, whatever's there previously.
05:02 Yeah. And that can be a hassle, especially if you want to have like a requirements dot dash dev
05:07 and then a production requirements. And if you install the dev, the dev one that you want to
05:12 also pick up like a dash R on the main ones and the pip-tools blows that away. So what I ended up
05:18 doing a lot for my workflows is having pip-tools generate some base TXT file and then having like
05:25 requirements dot TXT just have a dash R, you know, requirements production. And then the dev
05:30 have dash R requirements dot TXT, you know, broad and like sort of like put those commands just in
05:36 real simple and have it actually generate a separate file. So it kind of makes it a little bit messy,
05:40 but it, it gives you lots of flexibility.
05:42 Cool. Yeah. I'd like to see that written up. That's neat.
05:45 Yeah. Maybe I should actually, blog something like in the last three years.
05:49 Blog.
05:50 Pam, yeah. What is that? Is that with words?
05:52 Written words, not spoken words.
05:54 Pamphil on the audience says, does it take over requirements? Like if pip would resolve numpy to
05:58 one dot 19 and you say at one 20, it sounds to me like it does, but what do you think Brian?
06:04 Well, like I tried it, with, typer. So I knew, I know typer pulls in a click for instance,
06:11 and they're both command line things.
06:12 Yep. and so then I said, okay, well, the typer has a broad range of click things that it can do.
06:20 And if I constrain click to be a lower number, will it work? And I blew everything away and tried it
06:25 again. And, and sure enough, it, it did it like add those extra constraints on top of even like,
06:31 so I was, I was only declaring typer, but typer was specifying click and I could specify which version
06:37 of click I wanted. So yeah, this is cool. Yeah. it's, I guess what adding one more
06:43 complexity to your packaging, workflow. So, but exactly.
06:48 But useful if you need it.
06:49 But flexibility.
06:49 Yeah.
06:49 Yes. Good flexibility.
06:51 All right. Well, let, I'll cover something simple. Async caching.
06:54 Simple.
06:55 It is simple in a sense. we've had, we have some nice stuff built into Python,
07:02 like async, I'm sorry, with like functools, and the LRU cache and whatnot. But from what I
07:10 understand, those are synchronous only. Basically they're decorators, those decorators wrap
07:16 functions and the decorators themselves are synchronous. And so it only makes sense for
07:21 them to wrap sync functions. Yeah. Okay. And so if you will have an async function, but you want to
07:26 do the LRU cache where you just put the decorator LRU cache. And then if it gets called with the same
07:31 arguments, again, it doesn't even call the function. It just goes, you know what? You already called it
07:35 with that. Here's the answer. So like if you're in a tight loop and you're pulling in some values and
07:40 you've got to compute something with it through a function, but there's a good chance of repeat
07:44 of those values. You can put an LRU cache. And long as that pretty deterministic and you call it again,
07:50 you expect the same output. You can make it fly by just adding one of those caches on it. Right.
07:54 So a short version of this is, this is the same idea, but for, async functions. So I can have some
08:01 function I want to call. And I just say at LRU cache, and this one, you can give it a maximum size
08:07 of results that it's willing, you know, inputs and matched up results. It's willing to cache up.
08:13 And if you call it with the same arguments, it'll give the same response back. So that's pretty cool.
08:18 That's the, sort of last used version. And then you also have time to live a time to live
08:23 an async TTL. So you can say any results. I don't care, how many I've used, but just within the last
08:31 60 seconds. And one thing that's really, really nice about that is it will expire results. So maybe
08:36 you're calling an API and you want to do rate limiting, but you know, you only want to be,
08:41 call it maybe once a minute, right. That'll both make your code faster, but also not overrun your rate
08:47 limiting that you might have with your API key and so on. So here's a real simple way to add rate
08:52 limiting is just say time to live. I guess you got to have the same input arguments, but you know,
08:56 assuming that you have the same arguments, that's, that's one way to do it. And you can also
09:00 specify the max size, which is pretty cool. Yeah. Or if you're grabbing something off of a service,
09:04 like, what's the, like, what's the temperature out? I don't really care if
09:09 it fluctuates every second, but every minute I might check it. sort of thing. Yep. Yep. Precisely.
09:15 And I don't, there's not a T T L on the normal LRE cache. Is there? I don't believe so. Yeah. So
09:24 that's actually cool. I like the time to live part. Yeah. I do too. I like that. That really resonates
09:30 with me. And the other thing that's pretty cool here is you can pass ORM objects and pass request
09:36 objects. You can pass custom classes, even if the classes are not hashable, it will still go through.
09:42 And actually, so one of the problems you can run into is if you pat, say, if you've got a customer
09:47 object or a product object or something, you call it once you've created this object. Maybe you got it
09:52 from the database and you say, call the function with the LRU cache. And it says, well, what object
09:58 is this? Have I seen it before? And maybe yes or no. And then you call it again. it might have the
10:03 same effective value, but it's not actually the same object, right? You might get it from the database
10:08 again. So it has a different pointer, a different ID and so on that. I'm not sure what the behavior
10:14 there is, but this one will actually, look and see, Oh, is it actually a class? Well then let's
10:20 just get the dictionary and use the dictionary, the underlying field dictionary of the class to use
10:26 as the, the match to see if I'm calling it again. So there's some really cool, functionality here,
10:32 simple little class, but if you want to quickly add some performance boost async functions, you can add
10:38 this. Oh, nice. Okay. This is neat. Yeah. Yeah. Yeah. It's fine. Also. Yeah. Thanks. Also it's entirely
10:45 possible. I don't think it does, but it's entirely possible to add, async and synchronous support
10:52 to a single decorator. if, if you need to, right. for example, I have the, what was it called?
10:59 The million templates, FastAPI one that I created. Let's see. Look at that. Number one result.
11:07 What a search search thing. So there's, so there's this FastAPI chameleon framework or library that
11:14 I created that allows you to just do a decorator and say dot template and put a HTML template in the
11:20 chameleon language on a FastAPI response. And it returns a dictionary and that just turns it into an
11:25 HTML response. Okay. This one in FastAPI, you can both have synchronous and asynchronous functions.
11:31 So this thing has to look and see if the inbound thing is a co-routine and async co-routine,
11:36 and it will dynamically generate the right wrapper and async one or a synchronous one based on. So
11:41 it's not super hard. It's, it's also not super easy, but I did it so it can be done. Cool. Anyway,
11:46 that's a little bit of a diversions, but this, this async cache versus a non-async cache,
11:51 I feel like, you know, it could just be, it could be one thing if it really, really wanted to be,
11:55 but I feel like the person who created it probably is just like, I need this for async methods.
11:59 Let's go.
12:00 Yeah. It's almost kind of too bad that the normal oil or your cache doesn't just do that.
12:05 Yeah. And you know, maybe it's been updated too, and I don't know, but I don't believe it does.
12:09 I don't think so. Right. Not currently.
12:11 Yeah. Yeah. Not that I know of people can write us if we're wrong and we'll let people know next time.
12:16 Be great to, great to do it.
12:17 I am never wrong.
12:19 Oh, okay. Sometimes.
12:21 And because like I said, it's because it's a decorator, like you could, you could make it start
12:24 working that way. That's a good featured ad. Cool. All right. Before, yeah. Before we move on,
12:29 Brian, let me tell you about AI in real life. Wow. Yeah. So this week's sponsor, this episode of
12:37 Python Bytes is brought to you by the IRL podcast, an original podcast from Mozilla. So thank you,
12:44 IRL and Mozilla for supporting the show. If you're like us, you care about the ideas behind technology and
12:50 not just the tech itself. Obviously we do a podcast on these things all the time. So we love talking
12:54 about it, thinking about it. And everyone out there knows that tech has an enormous influence on society.
12:59 Many of these effects are hugely beneficial. Just, you know, you think about walking around with your
13:05 cell phone. You have basically the entire sum of human knowledge just constantly with you. Other
13:10 influences can have, you know, negative effects. And I really appreciate that Mozilla is always
13:14 looking out for and working to mitigate these types of negative influences tech has in all of us.
13:19 all of us. So if these ideas resonate with you, you should definitely check out their podcast,
13:23 IRL, the IRL podcast. It's hosted by Bridget Todd. And in this season, IRL looks at AI in real life.
13:31 Who can AI help? Who can it harm? The show features fascinating conversations with people who are
13:36 working to build more trustworthy AI. So just some of the examples of episodes, there's an episode about
13:42 how our world is mapped, like Google Maps style mapped with AI. And what's really interesting is
13:48 the data that's missing from those maps tells as much of the story as the data that's there. So also
13:54 an episode about gig workers who depend on apps for their livelihood. And it looks at how they're pushing
13:58 back against algorithms that control how much they get paid, seeking new ways to gain power and autonomy
14:04 over data and creating better working conditions. And finally, for political junkies, there's an episode on the role that AI plays when it comes to the spread of data.
14:12 This information around elections, a huge concern for democracies. You hear a lot about the US democracies, but more broadly, absolutely across the world. And I just listened to the first episode,
14:24 the tech that we won't build, which explores when developers and data scientists should consider saying no to projects that can be harmful or strongly against their beliefs,
14:32 even though, sure, you could technically build them, you know, just because you can, you know, should, should you? Anyway, if this sounds like an interesting show, try an episode for yourself,
14:41 just search for IRL in your podcast player or visit pythonbytes.fm/IRL links in your podcast blur show notes. And thank you to IRL and Mozilla for supporting our show. Thank you.
14:51 And strong.
14:52 Yes, thanks.
14:53 So I want to talk about organizing your code to actually organizing your Python code kind of structure structuring projects and everything. But there's more than that. So I ran across this article called organized Python code like a pro. And yes, it's got a lot of great advice. And it's opinionated. It's by one person, of course, but but I think it's, it's for the most part, really good stuff.
15:18 And also, a couple of things that I don't normally see in these kinds of articles, and there's not too much weird stuff. So, sometimes it's a little, sometimes it's a little too opinionated, but this is obviously where you can see where some of the opinions are held.
15:33 So, take a look at, it talks about structuring your project. for instance, one of the first things is use a source directory, SRC. and so I try to do this and I used to do it because there was a, there was an article about, about having your tests be seen.
15:52 So basically if I, if I'm doing a pack installable package, I'd like to have my tests, see the installed package, not the local files.
16:00 And, that happens sometimes if you're running like say py test or unit test from the top level directory, and it might, it might see the top level module and you don't want it to.
16:11 So source is a way to hide that, but there's ways to get around that and testing. So, I don't, I don't really, it's not really a solid, solid argument as it used to be.
16:20 This argument really is just, it looks nice, in your, in your code editor that you, if you, if you like, here's an example of a non, a non source project where you have a couple of modules within the project.
16:34 And, but alphabetically they fall below there around your, your, you've got your test directory and your pyproject.toml and your source codes on both top and bottom of that.
16:45 That's confusing. So I actually kind of love this simple argument of just combine all the source in one place. It's nice. so I do like that too.
16:53 I know the, the, the first reaction to this though, is you're going to put a package level directory anyway, and having a package level directory in there instead of your, if you have a package,
17:04 instead of, this, you know, source or something that works too. But anyway, this is kind of interesting.
17:10 The one thing that, that kind of gets me and it shows up here is this, this, this author is considering what I, so we have a problem in Python of what a, what a package is.
17:20 A package is something I install from PyPI, but it's also within this Python documentation. Sometimes it's just a directory with an init file in it. I don't know how you, so Python or Michael, you teach people about that.
17:33 Do you ever like, do you stumble with this part or just.
17:36 Both seems complicated and overly simplistic for me. I think one of the challenges really I often run into is how do I organize my files? If I want like a sub module, I want simple import statements, you know?
17:51 So, okay. So do you think I don't have, yeah, go ahead.
17:54 Do you think of directories with stuff directories within a net as a module or as a package or do you use.
18:01 I do, but often I, I try to dodge that bullet and just not.
18:06 Not talk about it.
18:07 Not really get. Yeah. Well, honestly not talk about it. If you're building a library, this matters very, very much. If you're building an application, a web app or a CLI app or something, it often, it doesn't matter because you're just running the top level, some top level, like main or app.py or something.
18:23 And then it, it'll just pick it up, whether it's a module or, you know, a package or just a directory.
18:29 So I guess, regardless of like what we call directories, whether we call them modules or packages, this, this article calls them modules.
18:37 So then it goes on to talk about some other cool stuff. Let's, let's go down naming things. So it, it talks about that. There's really no files. There's a, there's modules. So, it also, also there's no directories.
18:49 They're all modules, but the, that that's okay. So this is some of the opinion stuff that you can, it's interesting. You can skip over it. But the, the, the thing that I thought was interesting is these module names, they should be, they could be plural names.
19:03 And I never thought about that. And it, it kind of makes sense. like if you have, it gives an example like drivers, drivers would be a module. Yeah. It'd probably be the S on there makes sense. So it's a, you know, keep a, keep config and main as, as single, but, most things that have an S on the end. I never really thought about that before, but it does make sense of like, from crawler storages, import, get storage or something.
19:31 I don't know. Yeah. Yeah. it's, it's just a nice little extra thing. and then talks about naming functions and, and stuff. so functions, I, this is something people get wrong all the time. So it's good to talk about it. Name your functions with verbs. It makes your code a lot clearer if your functions or methods or verbs. And even unless you have to jump through giant hoops to make it work. But if you have to jump through giant hoops to make a verb work, maybe it's not really one function. Maybe it should be two or three, but we'll see. Anyway.
20:00 Yeah. Or property instead of a function or property. Right. and then class names. One of the things I never thought about it also was class names should be, singular. So classes should be singular unless it's a, it's, unless it's really a container. So don't name, don't name a class orders because it's going to describe multiple orders. It's, it's an order. It's an order class, not an orders class. So that's a, I, it's a good thing.
20:27 That the, the, one of the things I loved about this article also is there's two things that we kind of talk about. We use a lot, but nobody, I don't think very many people talk about it too much. And well, it's the dunder init thing. I'm going to hop down the, not the, the dunder name equals dunder main that's used all the time. and so it's good to talk about that of, if you want to execute a module itself, use that. But the, if you, one of the things I tried to do recently that I kind of didn't know how to do right off the bat is a directory with an init.
20:57 But if it also has a dunder main, then you can use the dash M, thing on it. so if you include like dunder main, then you can use, like, Python dash M module name, when you're interesting.
21:12 Okay. and cause I had a, I had a library I was working with and it was like, I'm, I'm using dash M for everything else. I'd like to have the entry point for my application be usable. If I do dash M also, how do I do that? And this is how you do it. So it's kind of neat to have this in right away. Cause I don't, I don't know if it's really a beginner thing, but it's still kind of cool.
21:35 Yeah. I like it a lot. It's like entry points, but simpler.
21:38 Yeah. anyway, so decent, decent article. there's some, some opinions there, but that's okay. We like opinions.
21:45 Absolutely. We do. We do. All right. Well, do you know what else we like, Brian? Follow up.
21:50 Yay. I was going to do this. I'm glad you're doing it.
21:53 Too late. I grabbed it. I grabbed it. Cause this one is a good one. So remember last week you spoke about CLI apps and doing OAuth.
22:01 OAuth and you've got to remember the tokens you get the example you gave us from Twitter, but it could be from all over the place.
22:06 So Trent, we got a, multiple pieces of feedback. One about encrypting the stuff that goes into your user profile.
22:14 I can't remember who, but I apologize about forgetting the name, but someone sent in a message that says, well, the AWS CLI just puts your tokens straight there unencrypted. So there's that.
22:24 I said, maybe you should encrypt them somehow. And I agree with that, still, but Trent sent in this project called key ring and key ring is hearing or vault vaults, those types of things.
22:36 There are ways sort of more, managed central stores of this type of information, right?
22:42 So you can see that on macOS you hear, and it put it in your OS X key chain, right? You probably heard that or the windows credential store or those, those things that the actual operating system is protecting from other apps to go look at it.
22:55 So it's basically just encrypted login password or, or tokens. Yeah. So this key ring thing that suggested was, is something like that, but it works to Python library.
23:07 It works across platform and it works with different backends based on both what platform you're on and other things you might decide.
23:14 So it's, a library that gives you access to system key ring services from Python, which I think is fantastic.
23:22 So on macOS that's key chain on, Linux, it's the secret service or the KDE four and five K wallets.
23:31 And then on windows, it's the windows credential locker. Okay. Right. And so in there you can just call, set password and get password and off it goes.
23:42 And that's pretty much it. Right. But it's stored in a nice encrypted, not just encrypted, but protected access, way for the OS.
23:49 Yeah. So I actually forgot about this. where I actually use this for testing, all the time, but I never thought I didn't think about using it for a command line application.
23:59 so it's okay. How do you use it for testing?
24:02 So we have, so some of the issues are we have, we have, different devices that we're testing against that are password protected devices.
24:11 And so you had, in order to, to access them, you need a, login and password, to run, run commands against them.
24:19 And then, so to be able to do that, we need the, like if you're SSHing into something or something like that, that's part of your process.
24:28 you've got to, you've got to, you have to have those credentials somewhere and we don't want them in our source code.
24:34 that's the gist of it is, is we don't want them.
24:36 We don't want them, just to, to be, yeah, we don't want them in the source code and checked in to get lab and to have the whole company be able to read them.
24:44 it's, it's still protected.
24:46 It's internal thing, but maybe you're on get lab, or github or something.
24:51 And it's, it's a public repo.
24:53 You don't want any passwords right there, but you can have them stored on your local machine and then pull them out with key ring.
24:59 right.
24:59 It's surprised me a little bit that they're just, that get passwords a thing.
25:03 I kind of expected it to be like a, like get the, get the password hash or something.
25:08 But I have to remember this isn't, this isn't verifying passwords.
25:11 It's having them to be able to send them to another system.
25:15 so right.
25:16 Ideally that one is storing the hash, not the real thing.
25:19 Yeah, exactly.
25:20 So, yeah, yeah.
25:21 I don't know if it would want to see.
25:23 So I don't know if this would be, this is still cool and I'm glad we're covering it, but I was,
25:28 my original question was around, is this a re what's a reasonable thing to store passwords for sessions for command line application?
25:35 And I don't know if key ring would work, but I haven't tried it yet.
25:39 And maybe if you have a set password, maybe it will work.
25:42 Maybe it stores something locally.
25:43 So I'll have to try it out.
25:44 Yeah.
25:45 I think that it will.
25:45 Okay.
25:46 The question that I was wondering is what about the get password?
25:49 You know, is that restricted to the process that put it in there?
25:53 Yeah.
25:53 Or is it anything running on the system?
25:55 Yeah.
25:55 Yeah, exactly.
25:56 Okay.
25:57 Can you just start arbitrarily asking for stuff?
25:59 Probably some restrictions there, but I don't know exactly what they are.
26:02 handful out in the audience says, I'm not mistaken.
26:06 Poetry is using the it's, it's installed.
26:08 So that's where your PI PI credentials get installed.
26:11 And you can check out issue 210 from poetry.
26:15 And down here somewhere says, they talk about ways in which you could store.
26:20 And it says, why not just make key ring a dependency?
26:23 Okay.
26:24 Yeah.
26:25 If this approach, why not simply make hearing and so on?
26:28 It talks about, basically using this to store your PI PI credentials and that's a CLI app.
26:35 Perfect.
26:35 Then we have, it sounds like a pretty good match.
26:38 Yeah.
26:38 Nice example.
26:39 Yeah.
26:39 You can just follow along what they're doing there.
26:41 So thank you, Penfield for pointing that out.
26:42 Yeah.
26:43 Yeah.
26:43 Well, anyway, I don't currently have any use for this.
26:46 I think it might be useful even outside of, I have this interactive application, for example,
26:52 storing secrets.
26:53 You know, if you want to have the database connection string to your app, right?
26:57 This might be a good way to do it.
26:59 and one other thing that's interesting is you can have third party backends.
27:02 So you could have just encrypted text files.
27:05 You could have, the D bus API for Linux.
27:09 Google sheets.
27:11 I don't know about this, but.
27:13 It does say for use with IPython secrets.
27:15 So maybe it encrypts them, but more realistically, we've talked about Bitwarden before, open
27:21 source password manager, which is really nice.
27:23 I use that for a few things.
27:25 Okay.
27:26 So that has a CLI aspect.
27:28 You could have Bitwarden as a backend.
27:29 you can write your own as well.
27:31 And one password has a CLI option as well for storing SSH keys even.
27:37 So you could even put your SSH keys in there and whatnot.
27:40 I don't know if this would pull it back correctly, but there's a lot of,
27:43 ways to store things and say one password and then access it with a CLI.
27:47 And maybe you could plug this in.
27:48 So just, it's another provider, which is cool.
27:50 Yeah.
27:50 Yeah.
27:51 Anyway, it seems really nice to me.
27:53 if I have a use for it, I'll definitely look into it more.
27:55 Yeah.
27:56 Cool.
27:56 Nice.
27:57 Yep.
27:57 All right.
27:58 Hey, that might be all of our topics for the day, huh?
28:00 I think so.
28:01 Yeah.
28:01 So you got any extras?
28:03 I just, I just wanted to say that I am, I'm working on a couple of things.
28:08 I'm editing my pytest course, of course, still working on that.
28:13 but the other thing that I just started, which I'm super excited about is I just started
28:18 taking a FastAPI course.
28:19 Oh yeah.
28:20 It's really neat.
28:21 The instructor's awesome.
28:22 Yeah.
28:23 Awesome.
28:24 Yeah.
28:24 Thank you.
28:25 That, yeah.
28:25 That's the FastAPI course.
28:27 This live course that I'm doing this week and next week.
28:29 Right.
28:29 Yeah.
28:30 Yeah.
28:30 So I'm taking it from Michael and, if anybody, if anybody is, you've never taken a
28:35 pick in one of the online courses with Michael or a live course, it's just really excellent.
28:40 He's a good instructor.
28:41 So it's good.
28:42 Thank you very much.
28:43 Yeah.
28:43 I love it.
28:43 We're having a good time just playing with code as a group.
28:46 Yeah.
28:47 How about you?
28:47 I have, I think I have some extras just really quickly here.
28:51 Brian skin, who's been a co-host before sent us a tweet and said, attention, Python
28:57 bytes.
28:57 And that went over to, this message from Jeff, Jeff Huntley.
29:02 And it says, get lab.
29:04 Are you all right?
29:05 And this is a link to an article from the register and says, get lab plans to delete dormant projects
29:12 in free accounts, hoping to save a quarter of the hosting costs by binning repos that haven't
29:16 been touched for a year.
29:17 Thanks.
29:18 Is that, that's a little nerve wracking because just cause it hasn't been changed doesn't
29:21 mean it's not useful.
29:22 Yeah.
29:23 Yes.
29:24 Oh, maybe I keep my recipes up there and I haven't added any recipes.
29:27 Yeah.
29:28 Yeah.
29:28 Maybe nothing's changed or whatever.
29:30 So a couple of things, PSA, if you have a get lab, get lab project, you know, maybe
29:36 just touch, just add a period to some text file or something and check that in.
29:42 Spam your own repo with like, trivial PRs.
29:46 Yeah.
29:46 Exactly.
29:47 Yeah.
29:47 Yeah.
29:47 Exactly.
29:47 I fixed this misspelling here by changing the word and the more, oh, Mario Munoz says
29:53 they may be reverting this.
29:55 Okay.
29:55 So this was just from four or five days ago.
29:58 Yeah.
29:58 Okay.
29:59 And Pamphil says, yes, they did.
30:00 Okay.
30:00 Well, it sounds like they had the same face.
30:03 Many people had the same reaction that we are going, oh boy, this seems like a bad idea.
30:08 I'm glad this was changed.
30:10 Yeah.
30:11 Pamphil says because of the huge backlash I can imagine.
30:14 Yeah.
30:15 All right.
30:16 Well, I guess they'll have to continue to pay their million dollars extra per year
30:19 to host things that people put up on there where they said they would host it.
30:22 Yeah.
30:22 Well, hopefully they, okay.
30:24 Even if you did that, hopefully they would like email people at least.
30:27 Hopefully your current email is there.
30:28 Yeah.
30:29 Kind of like Google voice.
30:30 Please log in with the next, within the next 30 days to keep your phone number or whatever
30:35 it is they always did to me.
30:36 Okay.
30:37 Well, with that, I think, brings us to some jokes.
30:40 You got some jokes to tell and I brought a quick one as well.
30:42 Okay.
30:43 Want to go first?
30:43 sure.
30:44 I'm, I'm not going to read the ones up here, but I got them.
30:47 I got a couple of jokes from a place called, from a GitHub repo.
30:51 That's a dad style programming jokes, which is perfect for me.
30:55 So, I got a couple, how do programming pirates pass method parameters?
31:00 I don't know.
31:01 With varargs.
31:03 Awesome.
31:05 Okay.
31:06 Second one.
31:06 how do you get code?
31:09 How do you get the code of your bank vault?
31:11 Like, so you can break into the bank.
31:13 I don't know.
31:14 You check out their branch.
31:15 This is bad.
31:16 Nice.
31:17 I love it.
31:18 And then, I, one of the things I liked on the top of this, it says, unfortunately,
31:22 these jokes only work if you get them.
31:24 bad.
31:25 Oh, so good.
31:27 And it's a GitHub repo.
31:28 So that's actually fitting.
31:29 So anyway, it's very, self-referential, very meta.
31:32 Okay.
31:32 How about you?
31:33 here's a quick one before I put it up on screen.
31:36 You know how there's this constant not built here syndrome.
31:40 Like, sure.
31:41 This key ring is cool, but did we build it?
31:43 No, I bet we could build a better key ring than that.
31:45 And like, we'll get a team together to build key ring.
31:47 Right.
31:48 So here's a picture of, normal people acting like developers.
31:52 So there's these two construction workers with their hard hats on and there's a screwdriver
31:57 with a $2 tag on it.
31:59 Cause it was just purchase.
31:59 And one guy's outraged.
32:01 What did you buy a screwdriver instead of building your own from scratch?
32:05 Exactly.
32:07 Yeah.
32:07 yeah, pretty good.
32:09 What you're using Hugo.
32:10 Why didn't you build your own blog engine?
32:12 Exactly.
32:14 First, I'm going to build my own markdown parser so I can have better tables.
32:18 Let's go.
32:18 Exactly.
32:19 Yeah.
32:20 Yes, indeed.
32:21 So, all right.
32:22 Well, excellent podcast as always.
32:23 Thanks for being here.
32:24 Thank you.
32:25 Yeah, you bet.
32:25 And thank you everyone for listening, watching, however you've been part of this.
32:29 Yeah.