WEBVTT

00:00:00.001 --> 00:00:04.500
Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to

00:00:04.500 --> 00:00:10.820
your earbuds. This is episode 296, recorded August 9th, 2022. I'm Michael Kennedy.

00:00:10.820 --> 00:00:12.160
And I'm Brian Okken.

00:00:12.160 --> 00:00:17.420
Hey, Brian. We have a new sponsor. I just want to say thank you to Mozilla and the IRL podcast

00:00:17.420 --> 00:00:22.960
for sponsoring the show. Check them out at pythonbytes.fm/IRL. And more on that later.

00:00:22.960 --> 00:00:27.320
For now, I want to hear what you've discovered to share with us. Can you constrain your excitement?

00:00:27.960 --> 00:00:35.100
Yeah. I want to talk about pip constraints. So there's a, I think I knew about pip constraints,

00:00:35.100 --> 00:00:41.440
but I kind of forgot about them. But there's an article called pip constraints files by somebody

00:00:41.440 --> 00:00:50.120
named Luminisman. So this is what, so they're kind of neat. So one of the things I was just using a

00:00:50.120 --> 00:00:57.660
pip requirements.in file recently in a course that I'm taking. And I like,

00:00:57.660 --> 00:01:04.260
using requirements.in to generate my requirements.txt file. But there's, and then there's,

00:01:04.260 --> 00:01:10.340
there's a, yeah, anyway, that uses pip-tools. So you have to get pip-tools. But so there's that.

00:01:10.340 --> 00:01:15.800
And then there's also pinning. So especially with applications, we see it more in applications,

00:01:15.800 --> 00:01:23.520
less in libraries of pinning the application. But you can, even in libraries, there's regularly

00:01:23.520 --> 00:01:29.980
sort of constraints around stuff to say, Hey, for this library, I need this, this range of versions,

00:01:29.980 --> 00:01:35.260
or it has to be greater than this or something. Cause I'm depending and that's fine. But this is a way to

00:01:35.260 --> 00:01:44.780
say not what libraries I want to want to use, but if I use a library, which version? So, or constraint on the

00:01:44.780 --> 00:01:49.760
version without saying, I want the library. So, and in the, actually in the pip documentation,

00:01:49.760 --> 00:01:56.480
it says constraint files are requirement files that only control which version, not whether or not it's

00:01:56.480 --> 00:02:03.260
installed. So how would you use this? So this, this article talks about it and it basically says you,

00:02:03.260 --> 00:02:09.260
you kind of use it normally pip install requirements.txt, but you might have,

00:02:09.680 --> 00:02:13.860
if you do like a freeze for instance, or something, or you just pin everything, you might have all of

00:02:13.860 --> 00:02:20.000
the versions, but you might only want like constraints on like one of them. Say, let's say

00:02:20.000 --> 00:02:26.680
you want your, your including pandas, but you want a certain version of pandas or, or you want a certain

00:02:26.680 --> 00:02:30.920
version of numpy, even though pandas requires numpy or something like that. You can have a constraints

00:02:30.920 --> 00:02:37.600
file that lists, this just looks like a, a pip freeze file, but you can, you can put like less

00:02:37.600 --> 00:02:42.060
than or less than equal if you want, or, and you don't have to have everything. So you could just pin

00:02:42.060 --> 00:02:47.700
one of the things. And that way, like, let's say you were doing pandas and you wanted to constrain numpy

00:02:47.700 --> 00:02:53.740
to be a certain version of numpy. You can do that with a constraints file and not have it, not have to

00:02:53.740 --> 00:02:59.340
specify everything, just have it be separate. And the kind of the article talks about actually just

00:02:59.340 --> 00:03:05.020
sticking the constraints, specifying your constraint file within the requirements file. And that way

00:03:05.020 --> 00:03:09.140
they're separate. And, and I was thinking about that. And that's an interesting thing to say,

00:03:09.140 --> 00:03:14.720
the dependencies of my application don't change, but the constraints might because of testing or

00:03:14.720 --> 00:03:19.980
whatever. And this, this separating of these two files would help with like, you know, when you

00:03:19.980 --> 00:03:24.200
have the two files of version control, you've changed your constraints, but you haven't changed really

00:03:24.200 --> 00:03:28.380
what you're depending on just the versions of those. So it's kind of a neat to have that separate

00:03:28.380 --> 00:03:32.920
possibility. So, yeah. So for people who are listening, literally the first line of the

00:03:32.920 --> 00:03:38.760
requirements.txt file is --constraint constraints.txt, which I had never considered

00:03:38.760 --> 00:03:43.440
doing that. That's interesting. And then one of the things I thought is, but I'm not, and this works

00:03:43.440 --> 00:03:47.840
if you're handwriting your requirements file, but what if you're, what if you're not, what if you're,

00:03:47.840 --> 00:03:53.900
you're using, requirements.in instead, and this article doesn't go into it,

00:03:53.900 --> 00:04:00.440
but I tried to just, instead of putting that constraint thing in a, in a, requirements.txt

00:04:00.440 --> 00:04:07.000
file, putting it in a requirements.in and using, pip compile to generate it. And it, the pip compile

00:04:07.000 --> 00:04:13.280
seems to also watch the look at this. So it, this constraint works for pip compile as well.

00:04:13.520 --> 00:04:20.000
okay. So that's cool. Yeah. So, kind of a neat thing to, to, to check out. the usage of it's

00:04:20.000 --> 00:04:25.300
pretty easy. just, yeah. Anyway, pinning your requirements is good, but don't pin them too

00:04:25.300 --> 00:04:31.620
tight. If, especially for application for, for libraries and then for applications. yeah,

00:04:31.620 --> 00:04:36.020
I kind of like this because there's a lot of times where I know there's a bug in something

00:04:36.020 --> 00:04:41.640
or I've heard about it or, or I haven't gotten around to fixing my code to deal with the new

00:04:41.640 --> 00:04:45.760
version yet. So I'm going to pin something and I don't necessarily need to pin everything. I just

00:04:45.760 --> 00:04:51.680
need to pin certain parts of it. So that's kind of neat. So I like this, just also a little bit

00:04:51.680 --> 00:04:57.000
of a sidebar with the pip compile from pip-tools, you know, you give it the end file and it generates

00:04:57.000 --> 00:05:02.180
the TXT file and it basically obliterates the TXT file, whatever's there previously.

00:05:02.180 --> 00:05:07.600
Yeah. And that can be a hassle, especially if you want to have like a requirements dot dash dev

00:05:07.600 --> 00:05:12.720
and then a production requirements. And if you install the dev, the dev one that you want to

00:05:12.720 --> 00:05:18.740
also pick up like a -r on the main ones and the pip-tools blows that away. So what I ended up

00:05:18.740 --> 00:05:25.040
doing a lot for my workflows is having pip-tools generate some base TXT file and then having like

00:05:25.040 --> 00:05:30.120
requirements.txt just have a dash R, you know, requirements production. And then the dev

00:05:30.120 --> 00:05:36.780
have -r requirements.txt, you know, broad and like sort of like put those commands just in

00:05:36.780 --> 00:05:40.820
real simple and have it actually generate a separate file. So it kind of makes it a little bit messy,

00:05:40.820 --> 00:05:42.340
but it, it gives you lots of flexibility.

00:05:42.340 --> 00:05:45.120
Cool. Yeah. I'd like to see that written up. That's neat.

00:05:45.120 --> 00:05:49.440
Yeah. Maybe I should actually, blog something like in the last three years.

00:05:49.440 --> 00:05:50.040
Blog.

00:05:50.040 --> 00:05:52.640
Pam, yeah. What is that? Is that with words?

00:05:52.640 --> 00:05:54.020
Written words, not spoken words.

00:05:54.200 --> 00:05:58.920
Pamphil on the audience says, does it take over requirements? Like if pip would resolve numpy to

00:05:58.920 --> 00:06:04.260
one dot 19 and you say at one 20, it sounds to me like it does, but what do you think Brian?

00:06:04.260 --> 00:06:11.520
Well, like I tried it, with, typer. So I knew, I know typer pulls in a click for instance,

00:06:11.520 --> 00:06:12.820
and they're both command line things.

00:06:12.820 --> 00:06:20.220
Yep. and so then I said, okay, well, the typer has a broad range of click things that it can do.

00:06:20.220 --> 00:06:25.740
And if I constrain click to be a lower number, will it work? And I blew everything away and tried it

00:06:25.740 --> 00:06:31.520
again. And, and sure enough, it, it did it like add those extra constraints on top of even like,

00:06:31.520 --> 00:06:37.320
so I was, I was only declaring typer, but typer was specifying click and I could specify which version

00:06:37.320 --> 00:06:43.560
of click I wanted. So yeah, this is cool. Yeah. it's, I guess what adding one more

00:06:43.560 --> 00:06:48.320
complexity to your packaging, workflow. So, but exactly.

00:06:48.320 --> 00:06:49.160
But useful if you need it.

00:06:49.160 --> 00:06:49.440
But flexibility.

00:06:49.440 --> 00:06:49.980
Yeah.

00:06:49.980 --> 00:06:51.120
Yes. Good flexibility.

00:06:51.120 --> 00:06:54.580
All right. Well, let, I'll cover something simple. Async caching.

00:06:54.580 --> 00:06:55.520
Simple.

00:06:55.520 --> 00:07:02.920
It is simple in a sense. we've had, we have some nice stuff built into Python,

00:07:02.920 --> 00:07:10.080
like async, I'm sorry, with like functools, and the LRU cache and whatnot. But from what I

00:07:10.080 --> 00:07:16.080
understand, those are synchronous only. Basically they're decorators, those decorators wrap

00:07:16.080 --> 00:07:21.360
functions and the decorators themselves are synchronous. And so it only makes sense for

00:07:21.360 --> 00:07:26.880
them to wrap sync functions. Yeah. Okay. And so if you will have an async function, but you want to

00:07:26.880 --> 00:07:31.400
do the LRU cache where you just put the decorator LRU cache. And then if it gets called with the same

00:07:31.400 --> 00:07:35.940
arguments, again, it doesn't even call the function. It just goes, you know what? You already called it

00:07:35.940 --> 00:07:40.560
with that. Here's the answer. So like if you're in a tight loop and you're pulling in some values and

00:07:40.560 --> 00:07:44.960
you've got to compute something with it through a function, but there's a good chance of repeat

00:07:44.960 --> 00:07:50.620
of those values. You can put an LRU cache. And long as that pretty deterministic and you call it again,

00:07:50.620 --> 00:07:54.480
you expect the same output. You can make it fly by just adding one of those caches on it. Right.

00:07:54.480 --> 00:08:01.980
So a short version of this is, this is the same idea, but for, async functions. So I can have some

00:08:01.980 --> 00:08:07.560
function I want to call. And I just say at LRU cache, and this one, you can give it a maximum size

00:08:07.560 --> 00:08:12.760
of results that it's willing, you know, inputs and matched up results. It's willing to cache up.

00:08:13.220 --> 00:08:18.240
And if you call it with the same arguments, it'll give the same response back. So that's pretty cool.

00:08:18.240 --> 00:08:23.560
That's the, sort of last used version. And then you also have time to live a time to live

00:08:23.560 --> 00:08:31.360
an async TTL. So you can say any results. I don't care, how many I've used, but just within the last

00:08:31.360 --> 00:08:36.940
60 seconds. And one thing that's really, really nice about that is it will expire results. So maybe

00:08:36.940 --> 00:08:41.880
you're calling an API and you want to do rate limiting, but you know, you only want to be,

00:08:41.880 --> 00:08:47.760
call it maybe once a minute, right. That'll both make your code faster, but also not overrun your rate

00:08:47.760 --> 00:08:52.560
limiting that you might have with your API key and so on. So here's a real simple way to add rate

00:08:52.560 --> 00:08:56.800
limiting is just say time to live. I guess you got to have the same input arguments, but you know,

00:08:56.800 --> 00:09:00.320
assuming that you have the same arguments, that's, that's one way to do it. And you can also

00:09:00.320 --> 00:09:04.960
specify the max size, which is pretty cool. Yeah. Or if you're grabbing something off of a service,

00:09:04.960 --> 00:09:09.740
like, what's the, like, what's the temperature out? I don't really care if

00:09:09.740 --> 00:09:15.600
it fluctuates every second, but every minute I might check it. sort of thing. Yep. Yep. Precisely.

00:09:15.600 --> 00:09:24.520
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

00:09:24.520 --> 00:09:30.300
that's actually cool. I like the time to live part. Yeah. I do too. I like that. That really resonates

00:09:30.300 --> 00:09:36.560
with me. And the other thing that's pretty cool here is you can pass ORM objects and pass request

00:09:36.560 --> 00:09:42.700
objects. You can pass custom classes, even if the classes are not hashable, it will still go through.

00:09:42.700 --> 00:09:47.840
And actually, so one of the problems you can run into is if you pat, say, if you've got a customer

00:09:47.840 --> 00:09:52.880
object or a product object or something, you call it once you've created this object. Maybe you got it

00:09:52.880 --> 00:09:58.400
from the database and you say, call the function with the LRU cache. And it says, well, what object

00:09:58.400 --> 00:10:03.940
is this? Have I seen it before? And maybe yes or no. And then you call it again. it might have the

00:10:03.940 --> 00:10:08.800
same effective value, but it's not actually the same object, right? You might get it from the database

00:10:08.800 --> 00:10:14.820
again. So it has a different pointer, a different ID and so on that. I'm not sure what the behavior

00:10:14.820 --> 00:10:20.040
there is, but this one will actually, look and see, Oh, is it actually a class? Well then let's

00:10:20.040 --> 00:10:26.200
just get the dictionary and use the dictionary, the underlying field dictionary of the class to use

00:10:26.200 --> 00:10:32.040
as the match to see if I'm calling it again. So there's some really cool, functionality here,

00:10:32.040 --> 00:10:38.220
simple little class, but if you want to quickly add some performance boost async functions, you can add

00:10:38.220 --> 00:10:45.340
this. Oh, nice. Okay. This is neat. Yeah. Yeah. Yeah. It's fine. Also. Yeah. Thanks. Also it's entirely

00:10:45.340 --> 00:10:52.120
possible. I don't think it does, but it's entirely possible to add, async and synchronous support

00:10:52.120 --> 00:10:59.080
to a single decorator. if, if you need to, right. for example, I have the, what was it called?

00:10:59.080 --> 00:11:07.320
The million templates, FastAPI one that I created. Let's see. Look at that. Number one result.

00:11:07.440 --> 00:11:14.120
What a search search thing. So there's, so there's this FastAPI chameleon framework or library that

00:11:14.120 --> 00:11:20.000
I created that allows you to just do a decorator and say dot template and put a HTML template in the

00:11:20.000 --> 00:11:25.500
chameleon language on a FastAPI response. And it returns a dictionary and that just turns it into an

00:11:25.500 --> 00:11:31.280
HTML response. Okay. This one in FastAPI, you can both have synchronous and asynchronous functions.

00:11:31.280 --> 00:11:36.480
So this thing has to look and see if the inbound thing is a co-routine and async co-routine,

00:11:36.660 --> 00:11:41.620
and it will dynamically generate the right wrapper and async one or a synchronous one based on. So

00:11:41.620 --> 00:11:46.860
it's not super hard. It's, it's also not super easy, but I did it so it can be done. Cool. Anyway,

00:11:46.860 --> 00:11:51.500
uh, that's a little bit of a diversions, but this, this async cache versus a non-async cache,

00:11:51.500 --> 00:11:55.600
I feel like, you know, it could just be, it could be one thing if it really, really wanted to be,

00:11:55.600 --> 00:11:59.500
but I feel like the person who created it probably is just like, I need this for async methods.

00:11:59.500 --> 00:12:00.140
Let's go.

00:12:00.140 --> 00:12:04.780
Yeah. It's almost kind of too bad that the normal oil or your cache doesn't just do that.

00:12:05.100 --> 00:12:09.620
Yeah. And you know, maybe it's been updated too, and I don't know, but I don't believe it does.

00:12:09.620 --> 00:12:11.180
I don't think so. Right. Not currently.

00:12:11.180 --> 00:12:16.460
Yeah. Yeah. Not that I know of people can write us if we're wrong and we'll let people know next time.

00:12:16.460 --> 00:12:17.800
Be great to, great to do it.

00:12:17.800 --> 00:12:19.120
I am never wrong.

00:12:19.120 --> 00:12:20.320
Oh, okay. Sometimes.

00:12:21.020 --> 00:12:24.860
And because like I said, it's because it's a decorator, like you could, you could make it start

00:12:24.860 --> 00:12:29.020
working that way. That's a good featured ad. Cool. All right. Before, yeah. Before we move on,

00:12:29.020 --> 00:12:37.120
Brian, let me tell you about AI in real life. Wow. Yeah. So this week's sponsor, this episode of

00:12:37.120 --> 00:12:44.360
Python Bytes is brought to you by the IRL podcast, an original podcast from Mozilla. So thank you,

00:12:44.360 --> 00:12:50.000
IRL and Mozilla for supporting the show. If you're like us, you care about the ideas behind technology and

00:12:50.000 --> 00:12:54.880
not just the tech itself. Obviously we do a podcast on these things all the time. So we love talking

00:12:54.880 --> 00:12:59.680
about it, thinking about it. And everyone out there knows that tech has an enormous influence on society.

00:12:59.680 --> 00:13:05.060
Many of these effects are hugely beneficial. Just, you know, you think about walking around with your

00:13:05.060 --> 00:13:10.460
cell phone. You have basically the entire sum of human knowledge just constantly with you. Other

00:13:10.460 --> 00:13:14.720
influences can have, you know, negative effects. And I really appreciate that Mozilla is always

00:13:14.720 --> 00:13:19.500
looking out for and working to mitigate these types of negative influences tech has in all of us.

00:13:19.500 --> 00:13:23.980
all of us. So if these ideas resonate with you, you should definitely check out their podcast,

00:13:23.980 --> 00:13:31.140
IRL, the IRL podcast. It's hosted by Bridget Todd. And in this season, IRL looks at AI in real life.

00:13:31.140 --> 00:13:36.500
Who can AI help? Who can it harm? The show features fascinating conversations with people who are

00:13:36.500 --> 00:13:42.400
working to build more trustworthy AI. So just some of the examples of episodes, there's an episode about

00:13:42.400 --> 00:13:48.180
how our world is mapped, like Google Maps style mapped with AI. And what's really interesting is

00:13:48.180 --> 00:13:54.040
the data that's missing from those maps tells as much of the story as the data that's there. So also

00:13:54.040 --> 00:13:58.880
an episode about gig workers who depend on apps for their livelihood. And it looks at how they're pushing

00:13:58.880 --> 00:14:04.380
back against algorithms that control how much they get paid, seeking new ways to gain power and autonomy

00:14:04.380 --> 00:14:12.380
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.

00:14:12.380 --> 00:14:24.080
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,

00:14:24.080 --> 00:14:32.980
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,

00:14:32.980 --> 00:14:41.100
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,

00:14:41.100 --> 00:14:51.640
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.

00:14:51.640 --> 00:14:52.100
And strong.

00:14:52.100 --> 00:14:53.100
Yes, thanks.

00:14:53.100 --> 00:15:18.640
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.

00:15:18.640 --> 00:15:33.500
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.

00:15:33.500 --> 00:15:52.340
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.

00:15:52.500 --> 00:16:00.580
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.

00:16:00.580 --> 00:16:11.320
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.

00:16:11.320 --> 00:16:20.260
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.

00:16:20.260 --> 00:16:34.280
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.

00:16:34.280 --> 00:16:45.000
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.

00:16:45.000 --> 00:16:53.720
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.

00:16:53.720 --> 00:17:03.760
I know 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,

00:17:04.080 --> 00:17:10.120
instead of, this, you know, source or something that works too. But anyway, this is kind of interesting.

00:17:10.120 --> 00:17:20.740
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.

00:17:20.740 --> 00:17:33.720
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.

00:17:33.760 --> 00:17:36.840
Do you ever like, do you stumble with this part or just.

00:17:36.840 --> 00:17:51.720
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?

00:17:51.720 --> 00:17:54.720
So, okay. So do you think I don't have, yeah, go ahead.

00:17:54.920 --> 00:18:01.360
Do you think of directories with stuff directories within a net as a module or as a package or do you use.

00:18:01.760 --> 00:18:06.640
I do, but often I try to dodge that bullet and just not.

00:18:06.640 --> 00:18:07.600
Not talk about it.

00:18:07.600 --> 00:18:23.920
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.

00:18:23.920 --> 00:18:29.340
And then it, it'll just pick it up, whether it's a module or, you know, a package or just a directory.

00:18:29.800 --> 00:18:37.160
So I guess, regardless of like what we call directories, whether we call them modules or packages, this, this article calls them modules.

00:18:37.160 --> 00:18:49.480
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.

00:18:49.540 --> 00:19:03.580
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 thing that I thought was interesting is these module names, they should be, they could be plural names.

00:19:03.580 --> 00:19:31.600
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.

00:19:31.600 --> 00:20:00.280
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.

00:20:00.280 --> 00:20:27.980
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.

00:20:27.980 --> 00:20:57.960
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 __init__() thing. I'm going to hop down the, not 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.

00:20:57.960 --> 00:21:12.440
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.

00:21:12.440 --> 00:21:35.360
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.

00:21:35.360 --> 00:21:38.180
Yeah. I like it a lot. It's like entry points, but simpler.

00:21:38.180 --> 00:21:45.460
Yeah. anyway, so decent, decent article. there's some, some opinions there, but that's okay. We like opinions.

00:21:45.460 --> 00:21:50.680
Absolutely. We do. We do. All right. Well, do you know what else we like, Brian? Follow up.

00:21:50.680 --> 00:21:53.300
Yay. I was going to do this. I'm glad you're doing it.

00:21:53.300 --> 00:22:01.360
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.

00:22:01.360 --> 00:22:06.720
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.

00:22:06.720 --> 00:22:14.080
So Trent, we got a, multiple pieces of feedback. One about encrypting the stuff that goes into your user profile.

00:22:14.080 --> 00:22:23.260
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.

00:22:24.040 --> 00:22:36.380
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.

00:22:36.380 --> 00:22:42.760
There are ways sort of more, managed central stores of this type of information, right?

00:22:42.820 --> 00:22:55.900
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.

00:22:55.900 --> 00:23:07.660
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.

00:23:07.660 --> 00:23:14.880
It works across platform and it works with different backends based on both what platform you're on and other things you might decide.

00:23:14.880 --> 00:23:22.660
So it's, a library that gives you access to system key ring services from Python, which I think is fantastic.

00:23:22.660 --> 00:23:31.840
So on macOS that's key chain on, Linux, it's the secret service or the KDE four and five K wallets.

00:23:31.840 --> 00:23:42.100
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.

00:23:42.100 --> 00:23:49.840
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.

00:23:49.840 --> 00:23:59.720
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.

00:23:59.720 --> 00:24:02.620
so it's okay. How do you use it for testing?

00:24:02.620 --> 00:24:11.760
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.

00:24:11.760 --> 00:24:19.580
And so you had, in order to, to access them, you need a, login and password, to run, run commands against them.

00:24:19.580 --> 00:24:28.860
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.

00:24:28.860 --> 00:24:34.260
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.

00:24:34.460 --> 00:24:36.860
that's the gist of it is, is we don't want them.

00:24:36.860 --> 00:24:44.580
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.

00:24:44.880 --> 00:24:46.480
it's, it's still protected.

00:24:46.480 --> 00:24:51.860
It's internal thing, but maybe you're on get lab, or github or something.

00:24:51.860 --> 00:24:53.200
And it's, it's a public repo.

00:24:53.200 --> 00:24:58.900
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.

00:24:59.140 --> 00:24:59.840
right.

00:24:59.840 --> 00:25:03.300
It's surprised me a little bit that they're just, that get passwords a thing.

00:25:03.300 --> 00:25:08.060
I kind of expected it to be like a, like get the, get the password hash or something.

00:25:08.060 --> 00:25:11.800
But I have to remember this isn't, this isn't verifying passwords.

00:25:11.800 --> 00:25:15.620
It's having them to be able to send them to another system.

00:25:15.620 --> 00:25:16.540
so right.

00:25:16.540 --> 00:25:19.520
Ideally that one is storing the hash, not the real thing.

00:25:19.520 --> 00:25:20.300
Yeah, exactly.

00:25:20.300 --> 00:25:21.820
So, yeah, yeah.

00:25:21.820 --> 00:25:23.600
I don't know if it would want to see.

00:25:23.600 --> 00:25:28.520
So I don't know if this would be, this is still cool and I'm glad we're covering it, but I was,

00:25:28.520 --> 00:25:35.920
my original question was around, is this a re what's a reasonable thing to store passwords for sessions for command line application?

00:25:35.920 --> 00:25:39.700
And I don't know if key ring would work, but I haven't tried it yet.

00:25:39.700 --> 00:25:42.080
And maybe if you have a set password, maybe it will work.

00:25:42.080 --> 00:25:43.520
Maybe it stores something locally.

00:25:43.520 --> 00:25:44.680
So I'll have to try it out.

00:25:44.680 --> 00:25:45.020
Yeah.

00:25:45.020 --> 00:25:45.980
I think that it will.

00:25:45.980 --> 00:25:46.500
Okay.

00:25:46.500 --> 00:25:49.640
The question that I was wondering is what about the get password?

00:25:49.640 --> 00:25:53.220
You know, is that restricted to the process that put it in there?

00:25:53.220 --> 00:25:53.860
Yeah.

00:25:53.860 --> 00:25:55.560
Or is it anything running on the system?

00:25:55.560 --> 00:25:55.920
Yeah.

00:25:55.920 --> 00:25:56.860
Yeah, exactly.

00:25:56.860 --> 00:25:57.240
Okay.

00:25:57.260 --> 00:25:59.220
Can you just start arbitrarily asking for stuff?

00:25:59.220 --> 00:26:02.320
Probably some restrictions there, but I don't know exactly what they are.

00:26:02.320 --> 00:26:06.060
handful out in the audience says, I'm not mistaken.

00:26:06.060 --> 00:26:08.880
Poetry is using the it's, it's installed.

00:26:08.880 --> 00:26:11.400
So that's where your PI PI credentials get installed.

00:26:11.400 --> 00:26:15.080
And you can check out issue 210 from poetry.

00:26:15.300 --> 00:26:20.820
And down here somewhere says, they talk about ways in which you could store.

00:26:20.820 --> 00:26:23.900
And it says, why not just make key ring a dependency?

00:26:23.900 --> 00:26:24.680
Okay.

00:26:24.680 --> 00:26:25.300
Yeah.

00:26:25.300 --> 00:26:28.600
If this approach, why not simply make hearing and so on?

00:26:28.600 --> 00:26:35.180
It talks about, basically using this to store your PI PI credentials and that's a CLI app.

00:26:35.180 --> 00:26:35.740
Perfect.

00:26:35.740 --> 00:26:38.000
Then we have, it sounds like a pretty good match.

00:26:38.000 --> 00:26:38.560
Yeah.

00:26:38.560 --> 00:26:39.440
Nice example.

00:26:39.440 --> 00:26:39.680
Yeah.

00:26:39.680 --> 00:26:41.160
You can just follow along what they're doing there.

00:26:41.160 --> 00:26:42.980
So thank you, Penfield for pointing that out.

00:26:42.980 --> 00:26:43.300
Yeah.

00:26:43.300 --> 00:26:43.740
Yeah.

00:26:43.940 --> 00:26:46.620
Well, anyway, I don't currently have any use for this.

00:26:46.620 --> 00:26:52.380
I think it might be useful even outside of, I have this interactive application, for example,

00:26:52.380 --> 00:26:53.660
storing secrets.

00:26:53.660 --> 00:26:57.800
You know, if you want to have the database connection string to your app, right?

00:26:57.800 --> 00:26:59.000
This might be a good way to do it.

00:26:59.000 --> 00:27:02.580
and one other thing that's interesting is you can have third party backends.

00:27:02.580 --> 00:27:05.040
So you could have just encrypted text files.

00:27:05.040 --> 00:27:09.400
You could have, the D bus API for Linux.

00:27:09.400 --> 00:27:11.200
Google sheets.

00:27:11.200 --> 00:27:12.800
I don't know about this, but.

00:27:13.660 --> 00:27:15.700
It does say for use with IPython secrets.

00:27:15.700 --> 00:27:21.100
So maybe it encrypts them, but more realistically, we've talked about Bitwarden before, open

00:27:21.100 --> 00:27:23.920
source password manager, which is really nice.

00:27:23.920 --> 00:27:25.760
I use that for a few things.

00:27:25.760 --> 00:27:26.300
Okay.

00:27:26.300 --> 00:27:28.060
So that has a CLI aspect.

00:27:28.060 --> 00:27:29.860
You could have Bitwarden as a backend.

00:27:29.860 --> 00:27:31.980
you can write your own as well.

00:27:31.980 --> 00:27:37.820
And one password has a CLI option as well for storing SSH keys even.

00:27:37.820 --> 00:27:40.080
So you could even put your SSH keys in there and whatnot.

00:27:40.080 --> 00:27:43.460
I don't know if this would pull it back correctly, but there's a lot of,

00:27:43.460 --> 00:27:47.040
ways to store things and say one password and then access it with a CLI.

00:27:47.040 --> 00:27:48.480
And maybe you could plug this in.

00:27:48.480 --> 00:27:50.740
So just, it's another provider, which is cool.

00:27:50.740 --> 00:27:50.980
Yeah.

00:27:50.980 --> 00:27:51.380
Yeah.

00:27:51.380 --> 00:27:53.100
Anyway, it seems really nice to me.

00:27:53.100 --> 00:27:55.860
if I have a use for it, I'll definitely look into it more.

00:27:55.860 --> 00:27:56.320
Yeah.

00:27:56.320 --> 00:27:56.680
Cool.

00:27:56.680 --> 00:27:57.160
Nice.

00:27:57.160 --> 00:27:57.620
Yep.

00:27:57.740 --> 00:27:58.180
All right.

00:27:58.180 --> 00:28:00.360
Hey, that might be all of our topics for the day, huh?

00:28:00.360 --> 00:28:01.200
I think so.

00:28:01.200 --> 00:28:01.600
Yeah.

00:28:01.600 --> 00:28:03.440
So you got any extras?

00:28:03.440 --> 00:28:08.960
I just, I just wanted to say that I am, I'm working on a couple of things.

00:28:08.960 --> 00:28:13.520
I'm editing my pytest course, of course, still working on that.

00:28:13.760 --> 00:28:18.240
but the other thing that I just started, which I'm super excited about is I just started

00:28:18.240 --> 00:28:19.860
taking a FastAPI course.

00:28:19.860 --> 00:28:20.460
Oh yeah.

00:28:20.460 --> 00:28:21.520
It's really neat.

00:28:21.520 --> 00:28:22.620
The instructor's awesome.

00:28:22.620 --> 00:28:23.120
Yeah.

00:28:23.120 --> 00:28:24.660
Awesome.

00:28:24.660 --> 00:28:24.960
Yeah.

00:28:24.960 --> 00:28:25.320
Thank you.

00:28:25.320 --> 00:28:25.920
That, yeah.

00:28:25.920 --> 00:28:27.620
That's the FastAPI course.

00:28:27.620 --> 00:28:29.640
This live course that I'm doing this week and next week.

00:28:29.640 --> 00:28:29.840
Right.

00:28:29.840 --> 00:28:30.320
Yeah.

00:28:30.320 --> 00:28:30.840
Yeah.

00:28:30.840 --> 00:28:35.660
So I'm taking it from Michael and, if anybody, if anybody is, you've never taken a

00:28:35.660 --> 00:28:40.600
pick in one of the online courses with Michael or a live course, it's just really excellent.

00:28:40.600 --> 00:28:41.400
He's a good instructor.

00:28:41.400 --> 00:28:42.200
So it's good.

00:28:42.200 --> 00:28:43.000
Thank you very much.

00:28:43.000 --> 00:28:43.360
Yeah.

00:28:43.360 --> 00:28:43.900
I love it.

00:28:43.900 --> 00:28:46.780
We're having a good time just playing with code as a group.

00:28:46.780 --> 00:28:47.040
Yeah.

00:28:47.040 --> 00:28:47.620
How about you?

00:28:47.620 --> 00:28:51.420
I have, I think I have some extras just really quickly here.

00:28:51.420 --> 00:28:57.200
Brian skin, who's been a co-host before sent us a tweet and said, attention, Python

00:28:57.200 --> 00:28:57.560
bytes.

00:28:57.560 --> 00:29:02.440
And that went over to, this message from Jeff, Jeff Huntley.

00:29:02.440 --> 00:29:04.600
And it says, get lab.

00:29:04.600 --> 00:29:05.600
Are you all right?

00:29:05.600 --> 00:29:12.300
And this is a link to an article from the register and says, get lab plans to delete dormant projects

00:29:12.300 --> 00:29:16.840
in free accounts, hoping to save a quarter of the hosting costs by binning repos that haven't

00:29:16.840 --> 00:29:17.740
been touched for a year.

00:29:17.740 --> 00:29:18.320
Thanks.

00:29:18.320 --> 00:29:21.800
Is that, that's a little nerve wracking because just cause it hasn't been changed doesn't

00:29:21.800 --> 00:29:22.980
mean it's not useful.

00:29:22.980 --> 00:29:23.760
Yeah.

00:29:23.760 --> 00:29:24.320
Yes.

00:29:24.320 --> 00:29:27.540
Oh, maybe I keep my recipes up there and I haven't added any recipes.

00:29:27.540 --> 00:29:28.540
Yeah.

00:29:28.540 --> 00:29:28.980
Yeah.

00:29:28.980 --> 00:29:30.380
Maybe nothing's changed or whatever.

00:29:30.380 --> 00:29:36.540
So a couple of things, PSA, if you have a get lab, get lab project, you know, maybe

00:29:36.540 --> 00:29:42.060
just touch, just add a period to some text file or something and check that in.

00:29:42.060 --> 00:29:45.540
Spam your own repo with like, trivial PRs.

00:29:46.260 --> 00:29:46.380
Yeah.

00:29:46.380 --> 00:29:47.220
Exactly.

00:29:47.220 --> 00:29:47.260
Yeah.

00:29:47.260 --> 00:29:47.260
Yeah.

00:29:47.260 --> 00:29:47.260
Exactly.

00:29:47.260 --> 00:29:53.820
I fixed this misspelling here by changing the word and the more, oh, Mario Munoz says

00:29:53.820 --> 00:29:55.120
they may be reverting this.

00:29:55.260 --> 00:29:55.380
Okay.

00:29:55.380 --> 00:29:58.300
So this was just from four or five days ago.

00:29:58.300 --> 00:29:58.840
Yeah.

00:29:58.840 --> 00:29:59.140
Okay.

00:29:59.140 --> 00:30:00.300
And Pamphil says, yes, they did.

00:30:00.300 --> 00:30:00.560
Okay.

00:30:00.560 --> 00:30:03.720
Well, it sounds like they had the same face.

00:30:03.720 --> 00:30:08.540
Many people had the same reaction that we are going, oh boy, this seems like a bad idea.

00:30:08.540 --> 00:30:10.560
I'm glad this was changed.

00:30:10.560 --> 00:30:11.260
Yeah.

00:30:11.260 --> 00:30:14.440
Pamphil says because of the huge backlash I can imagine.

00:30:14.440 --> 00:30:14.900
Yeah.

00:30:15.760 --> 00:30:16.100
All right.

00:30:16.100 --> 00:30:19.160
Well, I guess they'll have to continue to pay their million dollars extra per year

00:30:19.160 --> 00:30:22.280
to host things that people put up on there where they said they would host it.

00:30:22.280 --> 00:30:22.680
Yeah.

00:30:22.680 --> 00:30:24.040
Well, hopefully they, okay.

00:30:24.040 --> 00:30:27.360
Even if you did that, hopefully they would like email people at least.

00:30:27.360 --> 00:30:28.840
Hopefully your current email is there.

00:30:28.840 --> 00:30:29.160
Yeah.

00:30:29.160 --> 00:30:30.720
Kind of like Google voice.

00:30:30.720 --> 00:30:35.200
Please log in with the next, within the next 30 days to keep your phone number or whatever

00:30:35.200 --> 00:30:36.400
it is they always did to me.

00:30:36.400 --> 00:30:37.540
Okay.

00:30:37.540 --> 00:30:40.360
Well, with that, I think, brings us to some jokes.

00:30:40.360 --> 00:30:42.900
You got some jokes to tell and I brought a quick one as well.

00:30:42.900 --> 00:30:43.500
Okay.

00:30:43.500 --> 00:30:43.980
Want to go first?

00:30:43.980 --> 00:30:44.820
sure.

00:30:44.980 --> 00:30:47.940
I'm, I'm not going to read the ones up here, but I got them.

00:30:47.940 --> 00:30:51.860
I got a couple of jokes from a place called, from a GitHub repo.

00:30:51.860 --> 00:30:55.580
That's a dad style programming jokes, which is perfect for me.

00:30:55.580 --> 00:31:00.940
So, I got a couple, how do programming pirates pass method parameters?

00:31:00.940 --> 00:31:01.760
I don't know.

00:31:01.760 --> 00:31:03.220
With varargs.

00:31:03.220 --> 00:31:05.420
Awesome.

00:31:05.420 --> 00:31:06.060
Okay.

00:31:06.060 --> 00:31:06.820
Second one.

00:31:06.820 --> 00:31:09.380
how do you get code?

00:31:09.380 --> 00:31:11.600
How do you get the code of your bank vault?

00:31:11.600 --> 00:31:13.280
Like, so you can break into the bank.

00:31:13.280 --> 00:31:13.580
I don't know.

00:31:14.200 --> 00:31:15.440
You check out their branch.

00:31:15.440 --> 00:31:16.920
This is bad.

00:31:16.920 --> 00:31:17.780
Nice.

00:31:17.780 --> 00:31:18.220
I love it.

00:31:18.220 --> 00:31:22.420
And then, I, one of the things I liked on the top of this, it says, unfortunately,

00:31:22.420 --> 00:31:24.760
these jokes only work if you get them.

00:31:24.760 --> 00:31:25.620
bad.

00:31:25.620 --> 00:31:27.300
Oh, so good.

00:31:27.400 --> 00:31:28.360
And it's a GitHub repo.

00:31:28.360 --> 00:31:29.740
So that's actually fitting.

00:31:29.740 --> 00:31:32.440
So anyway, it's very, self-referential, very meta.

00:31:32.440 --> 00:31:32.960
Okay.

00:31:32.960 --> 00:31:33.580
How about you?

00:31:33.580 --> 00:31:36.640
here's a quick one before I put it up on screen.

00:31:36.640 --> 00:31:40.560
You know how there's this constant not built here syndrome.

00:31:40.560 --> 00:31:41.280
Like, sure.

00:31:41.280 --> 00:31:43.320
This key ring is cool, but did we build it?

00:31:43.320 --> 00:31:45.680
No, I bet we could build a better key ring than that.

00:31:45.680 --> 00:31:47.800
And like, we'll get a team together to build key ring.

00:31:47.800 --> 00:31:48.240
Right.

00:31:48.460 --> 00:31:52.900
So here's a picture of, normal people acting like developers.

00:31:52.900 --> 00:31:57.080
So there's these two construction workers with their hard hats on and there's a screwdriver

00:31:57.080 --> 00:31:59.100
with a $2 tag on it.

00:31:59.100 --> 00:31:59.960
Cause it was just purchase.

00:31:59.960 --> 00:32:01.620
And one guy's outraged.

00:32:01.720 --> 00:32:05.560
What did you buy a screwdriver instead of building your own from scratch?

00:32:05.560 --> 00:32:07.060
Exactly.

00:32:07.060 --> 00:32:07.840
Yeah.

00:32:07.840 --> 00:32:09.420
yeah, pretty good.

00:32:09.420 --> 00:32:10.940
What you're using Hugo.

00:32:10.940 --> 00:32:12.980
Why didn't you build your own blog engine?

00:32:12.980 --> 00:32:14.200
Exactly.

00:32:14.200 --> 00:32:18.220
First, I'm going to build my own markdown parser so I can have better tables.

00:32:18.220 --> 00:32:18.760
Let's go.

00:32:18.760 --> 00:32:19.760
Exactly.

00:32:19.760 --> 00:32:20.340
Yeah.

00:32:20.340 --> 00:32:21.160
Yes, indeed.

00:32:21.160 --> 00:32:22.160
So, all right.

00:32:22.160 --> 00:32:23.880
Well, excellent podcast as always.

00:32:23.880 --> 00:32:24.640
Thanks for being here.

00:32:24.640 --> 00:32:25.220
Thank you.

00:32:25.220 --> 00:32:25.980
Yeah, you bet.

00:32:25.980 --> 00:32:29.960
And thank you everyone for listening, watching, however you've been part of this.

00:32:29.960 --> 00:32:30.420
Yeah.

