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


Transcript #236: Fuzzy wuzzy wazzy fuzzy was faster

Return to episode page view on github
Recorded on Wednesday, Jun 2, 2021.

00:00 Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to

00:04 your earbuds. This is episode 236, recorded June 2nd, 2021. I'm Michael Kennedy.

00:09 And I'm Brian Okken.

00:11 And I'm Anastasia Timosuk.

00:12 Hey, Anastasia. So great to have you here. Nice to have you on the show.

00:17 Thank you for inviting.

00:18 Yeah, absolutely. Why don't you tell people a little bit about yourself before we get into

00:21 the topics?

00:22 So I'm joining from Germany, Berlin remotely right now. And I have a little one, a baby

00:28 doc joining as well. You might hear him on the stream. I am originally from Ukraine. I'm not

00:35 German. I moved to Germany around five years ago, maybe five and a half. And my passion is Python.

00:41 I used to be a C++ developer, game developer, and so many more languages. But the best one,

00:47 I think, for me is Python. So I decided to stick with it for around eight years now.

00:52 Oh, how cool. I started out doing my professional programming in C++. And I

00:57 I know Brian still touches a little bit of C and C++ in his world. So that's cool.

01:01 Yeah, it's half my life.

01:03 Nice. And what kind of games?

01:06 Well, they were adapted first for iPad. They were like two and a half D games. And then later on,

01:15 it was mostly 3D games with Unreal Engine.

01:19 Oh, cool. Yeah, that's awesome. All right. Well, once again, welcome. Welcome. So glad to have you

01:25 here. Brian, do I have the first item this time around? No, you do. Go for it. Okay. What do you got

01:30 for us? Well, accessibility isn't really something I probably should think about accessibility more,

01:36 but I don't really. But I probably should. So I was excited to see there was a tweet recently by Matthew

01:42 Feikert that said, I need to give some serious praise to a fellow scikit hep dev, Hans Deminski,

01:50 on his excellent monolens tool for interactive simulations of color blindness. So I checked this

01:57 out. So monolens is this is a Python package and you can pip install it. And as Matthew said,

02:04 you can pip x install it. So you just always have it around, which is nice. And it just pops up this

02:12 tool, this, this really cool window. And you can just, you just drag it around. And it makes the

02:21 whatever the windows over all over your desktop, it just makes it black and white instead of color.

02:27 So you can see what it looks like in grayscale. So I, one of the things I really liked about this is,

02:34 is the, the, the example showing it with, with Matt plotlib and plots, because plots are really where

02:43 you're using color to distinguish between the two different sets of data. So you really kind of want

02:50 that data to look different, even if people don't see color. So that's, that's an important thing.

02:56 So that was neat. And then somebody that replied to that and said, Hey, I always try to use C,

03:03 C masher smasher. I'm not sure. It is a, to make sure they're colorblind friendly. So I'm like,

03:11 I've never heard of this. So I went and checked out smashers. And what it, what it is, is it's a bunch of

03:19 color maps. So you don't really have to think about it. So you, so there's all these great named color

03:25 maps and they're, they're actually fairly attractive color changes, but the, it shows you what they look

03:33 like in black and white also. So they, this isn't, it's kind of a little demo what the top

03:39 that we're looking at on the stream, but the code that you have to, you just, it's just kind of built

03:44 into Matt plotlib already. Like it's an extent, it's also kind of an extension to Matt plotlib and other

03:50 things that use color maps. So you can just say, when you're plotting, you can just specify a color

03:55 map like rainforest or something. And it, it automatically is a colorblind, friendly

04:01 color map. So you can do your plots and have it still look nice everywhere. So.

04:07 Oh yeah. This is really cool. And Matthew friend of the show. Thanks for sending that in. I never

04:13 really thought about this and I should have, you know, I mean, I feel like maybe I should go over my

04:17 websites and go, do they look terrible for people who have, you know, color vision impairments?

04:24 Yeah. So really cool. And it looks like it's this independent thing that will just go over.

04:30 You just move your mouse around. It works on anything. It doesn't necessarily have to do

04:34 with Jupyter or Matt plotlib or something like that. Right. Right. So the model lens is just a,

04:38 it's just something that works on anything. I could, I drug it over even my desktop, my background,

04:43 and it showed, showed the picture in black and white. So, it is cool.

04:48 The other thing is, wait, there's a color maps. I can just add to, Matt plotlib. That's cool.

04:54 Like rainbows and stuff. How neat. I didn't know you could just do that. So that's a,

04:59 that's kind of a neat thing. And then you can like, for instance, the, the, one of the examples

05:03 that they have on the CMASH or read me, is just, just sort of a simple plot. And when

05:09 you're in Matt plotlib kind of just picks colors for you, unless you specify colors for different

05:16 plot lines. but you can just, you can give it a color map instead of a, a specific,

05:22 list for each item. so, and that just kind of nice.

05:27 That's super neat. Yeah. Why not do it? Anastasia, what do you think?

05:31 Oh, it looks amazing really. And it's super helpful.

05:34 Yeah. when you were doing the video games, but that would be great to use it as well.

05:40 For sure. When you were doing games, did you have to think about this kind of stuff?

05:43 No, actually we were not that far at that time. It was around seven years ago, eight.

05:49 Yeah. So, yeah. The, on the, on the monolens site, one of the examples they show is using,

05:56 having one of the plots use some sort of pattern underneath and not just color. And that's,

06:03 that's, I'm not sure how to do that. So people that are great at Matt plotlib probably know how

06:07 to do that really right away. But that's kind of a neat idea also to have like one of the,

06:11 one of the graphs has hashes versus stars or slant lines or something like that.

06:16 Oh yeah. I have it like some sort of ASCII differentiator. Yeah.

06:20 Yeah.

06:20 Very nice. Yeah. This is super helpful. And Matthew again, thanks for sending in and, joy. Yeah.

06:27 Welcome to the live stream. Thanks for, for being here for the recording.

06:30 So the next one I want to talk about is something called rapid fuzz.

06:35 Yeah. So last time I talked, when we had Vincent on, I saw the fuzzy, fuzzy, fuzzy, fuzzy text matching for that, that chat bot that he was showing off. I thought,

06:47 Oh, fuzzy, fuzzy is cool. So Mikel Honkala sent in a rapid fuzz and it's very much like fuzzy,

06:55 fuzzy, but it turns out to be a whole lot faster and it uses some of the same ideas, but, you know,

07:01 coming back to the, some of the things we were talking about, it is basically written in C++ using

07:06 the Levenstein distance algorithm for words similarities, but obviously has a Python

07:12 API that we all work with. And so, yeah, it's pretty neat. It's really easy to work with. You just,

07:18 again, pip install it. And then you can come down here and do things like

07:21 fuzz.ratio and you can give it two sentences. This is a test or this is a test exclamation mark. And it

07:28 says that's 96.5% the same or, you have fuzzy, fuzzy was a bear. I guess these are, yeah. Fuzzy,

07:36 fuzzy was a bear. I guess those are the same. No, was he fuzzy. Oh, was he fuzzy. Yeah. I got it.

07:41 I got to read better. Was he fuzzy was a bear versus fuzzy. Was he was a bear? Oh my goodness.

07:45 that's 90% the same. Given a bunch of, phrases, you can sort them by similarity. You can say,

07:53 kind of use selection, like, you know, to call in sort of call center type of automation,

07:58 given three choices and given some text, you can say, find which one, you know, like Atlanta Falcons,

08:05 New York Jets, New York Giants, and so on. Somebody says, you know, lowercase New York Jets instead of

08:10 uppercase, it'll say, well, here's the likelihood that that's a match, but here's another possible

08:15 match that's, you know, and it gives you the ratios of how good of a match it is. So if you've got a

08:19 select set of choices and you're asking for input on it, you can just say, well, give me the closest

08:24 match. And if it's anywhere close, you can just run with that. So yeah, pretty neat, right?

08:29 That is pretty cool. Yeah. And the other thing that's interesting is the performance. And before

08:36 people tell me that all, all benchmarks are broken and they don't work, you know, sometimes at least

08:40 they give you a sense. So here's some of the things that, they've got in terms of performance,

08:45 save versus fuzzy wuzzy and the numbers are like 10 or 20 times faster. Definitely broken.

08:50 It's definitely broken. I think it's because it's written in C++ instead of Python, at most of

08:56 its core, you know, probably. But anyway, if you're looking for fuzzy text matching, fuzzy wuzzy is a good

09:02 option. And apparently thanks to Mikko rapid fuzz is as well. So yeah, pretty neat. Yeah. We probably

09:08 should do a segment on benchmarks at some point. No, no, no, no, no, we should do it, but I've

09:15 written blog posts and stuff on it. And it's just an endless battle of you're doing it wrong. Your

09:21 situation is not my situation and my situation. It's not as good or it's worse or it's better or

09:26 you're yeah. No, I, I hear you. It would be interesting, but at the same time. Yeah. Okay.

09:30 There we go. We just had a section on, benchmarks. Yeah. I've already just explained like the emotional

09:35 trauma that I'll go through from receiving all the feedback now. And it's what do you think about

09:40 this, fuzzy text matching? Well, maybe next time we can organize a battle between them.

09:46 That's right. Yeah. We'll bring some in. Yeah, sure. Do you have any use for this fuzzy text

09:51 matching, string matching stuff? Well, actually, yes, at work, we have, lots of, matching

09:57 algorithms, but we're using, different tools and I'm not a data scientist person, but I would love to

10:05 try that actually. It looks super cool. Yeah. We, we use some C++ libraries.

10:09 Yeah. Yeah. Robert out there in the live stream says we would have to benchmark the episode if we had

10:15 an episode about benchmarking. You see, it's like recursion. Save that thought for the end of the

10:20 show, by the way. All right. And Stacia, you're up next. Structured logging. Tell us about it.

10:25 well, a few years ago, I, went to meet up and I heard a talk from my Marcus Holterman about

10:32 struct log. That's the first time when I heard about this and I decided to give it a try. And actually I

10:38 fell in love with it. and I'm using it, since at least two and a half years, maybe two.

10:45 it's awesome way to bring a bit of structure to your logs to make them more visible and more usable because

10:53 usually how we log, it's like just one huge sentence, which is readable by humans, but it's not machine

11:01 readable. And the idea is here, to bring more structure, to build some dashboards based on,

11:09 different keys and then values and then see what's actually happening with the system without

11:15 touching the logs, without scrolling through the whole log. And then just reading all bunch of

11:21 things. and I already used it in production. It looks pretty well. If, you try using JSON format,

11:31 just fantastic. Oh, how cool. Yeah. You can pass it all these like processors and type stuff. So you can

11:37 say render out the print that, you know, stack info, the log level, all those kinds of things. That's neat.

11:45 We added a bunch of, processors like custom made, which were specifically designed for our

11:50 applications, which made a life of our devops parsing the logs way easier because they didn't

11:57 have to write them by hand. And if you use a structured logs for all applications, not just one, but,

12:05 for example, for example, microservices and you pass, the key ID or like trace ID or something

12:12 that will identify the path, which, the log goes through, then you might see what happened before

12:20 the bug happened or maybe because, if you want to see, how the system is working, you also need to be

12:28 either one of the detectives of the system or use the struct log.

12:33 Yeah. It's interesting when you log out stuff, it looks like you can just do key keyword arguments and

12:40 those will add to the log really nicely. So you don't have to create a message that you're going to send

12:46 that embeds, you know, the value equal, you know, variable equals valuable, very equals value. You just pass

12:52 them to the log message and they become part of the message like that. That's cool.

12:56 Yeah. And you can also use, the initial message, which is an event like greeted here,

13:01 as some kind of key, which would give more clues where this message is coming from and what type of

13:08 event happened instead of a usual message. Yeah. Nice. Very cool. The other thing it says is if you have

13:15 Colorama installed, it will automatically render in nice colors and that's very neat. I love Colorama and I love

13:22 having colors in, in the code that we look at, it really makes a nice difference. So yeah, you get things

13:28 like the colored, whether it's an info message or an error and whatnot. Yeah. Very neat. I like it.

13:35 I keep meaning to use this more and I know I'm glad you brought it up because I definitely want to try this.

13:41 Definitely try this. Yeah. Yeah. This is a really good one. This is new to me, but, quite neat.

13:46 All right. Not new to me, but also quite neat is our sponsor for this episode. So this episode is

13:52 brought to you by Sentry. So how would you like to remove a little stress from your life? Do you

13:57 worry that users may be having difficulties and encountering errors with your app right now?

14:02 Would you even know until they send that support email? I mean, yes, maybe using struck log,

14:05 but are you watching the struck log now? You don't know, right? So how much would it,

14:09 how much better would it be if you had that error or performance details immediately sent to you

14:14 with the call stack and local variables and active user and all that stuff. And with Sentry,

14:19 it's not just possible. It's easy. We use Sentry on all of our web apps, Python by set up M talk,

14:24 Python training, all those kinds of things. And we know if there's some kind of problem.

14:28 It's unfortunate if someone hits a problem, but it's better to know and be able to fix it right away.

14:31 In fact, one time somebody ran into a problem over at Talk Python Training, getting a course and

14:37 got the message. I could see who was logged in when they had the problem. And I actually fixed the bug

14:42 and was about to push out the changes. And I got an email. Hey, I'm having a problem with your,

14:46 your site. I'm like, yeah, I know. I just fixed it. Try again, please. And they were quite a surprise.

14:51 So surprise and delight your users today. Create your Sentry account at Python by set up M slash

14:55 Sentry. And please, when you're signing up, click the got a promo code redeem option and enter Python

15:01 bytes. It's not automatic. And they'll make sure that you enter Python bytes as the promo code.

15:06 Otherwise they won't know us from us. You'll get a bunch of cool stuff, two,

15:08 three months of the team plan with many more errors and events and other features as well.

15:12 So check them out at Python bytes set up M slash Sentry. That's pretty awesome.

15:16 Brian, I guess you should probably also test your code maybe before you end up with errors. What do

15:22 you think? Definitely. And actually, before we go on, I think I've mentioned this before,

15:26 but the graphic on that is on the Sentry page is so cool.

15:29 I know. I really like it too. Like, I love the upset console terminal reading a paper.

15:35 Yeah. So this is, this is kind of like inside baseball, maybe, but I don't know, maybe three

15:42 people might care about this. But anyway, I'm one of them. So X fail now works with by test subtests.

15:50 So that's, it's neat. But I got to explain it a little bit. So subtests are kind of this weird

15:57 feature of unit tests that came along in Python three, four, and it's a way it's a context manager

16:03 so that you can have possibly several places where your test might fail, but continue. It doesn't stop

16:11 if it fails. And that's a, that was within unit test. pytest had, well, pytest said pytest check,

16:18 the plugin that I wrote that allows something similar context manager. But then pytest subtests

16:25 came out, which was a plugin in about 2019 that started that, that allowed you to run the unit test

16:33 subtests within from pytest. But there's also a pytest style of doing subtests also.

16:40 They're a bit quirky. So I'm going to, we, I'm linking to, to two resources, an article by Paul

16:48 Gansel and an episode of testing code where he and I talked about subtests. And so they're a little,

16:55 before you jump in and use them right away, you should know some of the quirks about it,

16:58 but they're still cool if they work for you. But one of the quirks that was around for a long time

17:03 was that X fail didn't work. And X fails a way to say, I know my test is going to fail.

17:09 but you know, and then you get to decide whether or not you want to make market as an

17:14 X pass or market as a fail, if it, if it fails. and the, this, anyway, X fail didn't work

17:22 with subtests, but it does now as of like the start of the month. So somebody named maybe Sibber on,

17:29 GitHub, maybe, merged a fix or submitted a fix as a pull request and it got merged and it's

17:37 now in version 0 5 0. So X fail, if you wanted to use subtests, X fail now works with them. So that's

17:44 the good news. Yeah. Yeah. This looks really interesting. So the basic idea is I want to loop

17:49 over a bunch of scenarios or whatever, and maybe test them all and then have the test fail if any of them

17:54 did, but actually just go through them all before. Yeah. So like in, on the, on the subtests,

18:01 site, there's a little example. So like, let's say you're looping through a range and you want to,

18:05 you want to run all of them within, not, not a parameterized, just within the test,

18:09 you're doing like several things and you can, yeah. And if something fails, you want to actually

18:15 report all of the failures. and this is, this is, you know, sort of helpful with loops, but you

18:21 know, why not just use parameterization? but the, the, the one part where it does really help is if

18:27 you really are checking like four or five different things and you really want to know, like, let's say

18:33 you're measuring something or you're checking, several dimensions of something and, and

18:39 having all of the failures together would help you determine what the real problem is. So, so it's,

18:46 it's, it's when you have to have all the information, this is a good idea.

18:49 Very cool. Anastasia, what's the testing story in your world?

18:53 Well, we use mostly parameterized testing because we don't have the subtest need. We don't need to

19:00 test it multiple times, maybe in the future. Yeah.

19:03 Yeah. parameterized works. I'd stick with it. So yeah, it's definitely good. All right. Another

19:10 thing that I think is really neat to talk about, but I feel like it's almost down to the benchmark type

19:17 of situation is what do you do with the secrets in your application? There's to get,

19:23 ssh get, which is always terrifying. If you go here, you can see, oh, here's all the code that

19:31 we found in this branch of this GitHub repository. For example, here's your, you know, database

19:36 connection string with username and password right there. Right. So you can see all kinds of issues.

19:42 If you go over here, like even a live stream, if it doesn't feel bad enough, you like watch the live

19:46 stream of all the things that are coming in. Like right now, apparently there's some username and

19:51 password in a URI and some kind of private key and whatnot. So you don't want that. So what do you

19:56 do? Well, there's all kinds of things you can do. Do you encrypt those secrets and put them in source

20:02 code? Well, then where do you store the encryption key? There's some kind of certain types of vaults

20:07 you can install on your server, kind of like one password, but for servers, you could do that kind of

20:12 thing. There's just leave it in there and hoping for the best. There's putting it in environment

20:19 variables. That's a very, very common one. Right. But still, no matter what you pick, you kind of got to

20:24 get that data back and deal with it. So I want to introduce you to Pydantic. Brian, you've heard of

20:30 Pydantic, right? Yeah. In fact, I didn't know this had anything to do with secrets. Yeah. If you go to

20:37 Pydantic right here at the top, I believe there might be some nice little comment here. Oh, yeah. I thought,

20:45 I thought you were in here, apparently I'm in here right now. I think it toggles between us. Anyway.

20:49 Yeah. So we've known, the point is we really talked about Pydantic a lot. It's a really cool way to

20:55 create these classes that are kind of like data classes, point them at some data source, and then

21:00 they validate it and adapt it. Right. So if I've got like a JSON document and it has a field in it,

21:05 and that field is a list of something I could say in my model, this thing has a list of integers.

21:10 And if it happens to be quote a string or a number that has quotes on it, it'll just, you know,

21:16 automatically do the int pars type of thing to get it fixed. Or it'll tell us that it couldn't figure

21:21 out what to do with the third value, something like that. It's really fantastic. But what I also didn't

21:26 know was that it has a built in support for working with these user secrets. So Dennis Roy pointed this

21:32 out to me. And there's all kinds of things. You can have the .env file. You can have Docker secrets.

21:39 You can have environment variables. And all of these things has your secrets. And if you just derive from,

21:46 instead of base model, you derive from base settings, then this will automatically determine

21:51 any of the fields that are not passed to it from the environment or from .env files. What do you think?

21:58 Well, that's cool. Where do the .env files go?

22:01 Not in GitHub.

22:02 Okay.

22:04 You know, you store them somewhere else, right? You probably, what ideally I think you do is you

22:10 would store like an .env template file that has, you know, put this value and then the real value here,

22:16 this value and the real value there. And then you, of course, ignore, .gitignore the other one,

22:20 the real one, right? So you at least have a structure. But so the idea is you come down here and say,

22:24 I've got these settings and we've got like an API key and off key. We've got a Redis connection,

22:31 all those kinds of things. And you can even say, I'm going to put a prefix on it. So in your environment

22:38 variables is fine if you've got one app in one server, but if you've got 10 apps running or 10 APIs

22:45 running on your server, what is the API key referred to? What is the database connection string with the

22:50 database name in it referred to? Which one of those 10 apps, right? So you can put a prefix. So you

22:55 could have like login app API key or, you know, login app API key. And you put that in there and it

23:03 automatically will just let you access it as if it's API key. So you can sort of configure in the

23:08 environment a little bit better. There's just lots of really neat things that you can do in here to make

23:12 that work. you can say whether it's case sensitive, let's see, let me pull up, I had to take notes,

23:18 some other things that were super cool. So it's a regular Pydantic model, which means it'll do all

23:24 the conversions and the validation. So if something is missing that's required from your environment,

23:28 it'll let you know exactly what's missing. It'll do those conversions. yeah, all sorts of stuff.

23:34 It has support for raw sequence files as well, which is like a slightly different way to do it.

23:40 You can have differently named ENV files, like a prod dot ENV versus U and a D dot ENV or whatever, all sorts of settings. So I've always thought Pydantic is amazing

23:52 and I had no idea it had this built in support for working with this. The other thing that's really

23:57 cool about this is if you go back to the top where it describes it, it says it will try to get these

24:02 values from the environment if you don't pass them over. So if you're in say a testing environment,

24:08 you want to actually pass values that would control it, you could just explicitly pass them along

24:13 instead of, you know, having them come from the environment. So it's really easy to test,

24:16 you know, set the test values instead of trying to configure a test environment.

24:20 Nice. We do use it by the way, base settings, but we didn't use prefixes. Yes. Yeah. Which is a good idea.

24:27 Yeah. The prefixes are cool. If you have a bunch of apps, if you just have one,

24:31 yeah, it doesn't really matter. Right. Yeah. Yeah. Of course. Cool. You like this? It's working well for

24:35 you? Yeah, it's working perfectly well. And we are committing on the development version with some dummy

24:41 keys just to have them around. Of course. Of course. Oh, wow. How neat. Okay. Well, cool. Well,

24:46 that's neat that you're using it. Brian, you got the next one. Is that right? You've already done it.

24:51 No, but I just wanted to mention the, oh, wait. Nevermind. I had the wrong thing. Oh, here we go.

24:59 Yeah. The quote I think you were looking for was from FastAPI. Oh, yes. Yes. Of course. Of course.

25:06 Yeah. It is. I'm over the moon. Yeah. Super excited about it. Yeah. FastAPI. Thanks.

25:12 Yeah. We use it. I love FastAPI as well. And to me, like Pydantic and FastAPI,

25:17 they go together because I learned about them at the same time. I know there are different people

25:21 and different projects, but you know. It works like magic. Yeah. Yeah. Absolutely. It really is. Yeah.

25:26 And if it's not magic, maybe you should document it. Or maybe it is magic. You should document it.

25:31 Definitely. Definitely. Actually, I'm the one who is usually bringing this topic

25:38 to the team, how to write documentation. And first, the question is why to write documentation?

25:44 Everyone knows that we need documentation, but it's hard. It's time consuming. It's annoying. And

25:51 how it usually happens. Someone leaves the team. And then the last days are about handing over

25:58 everything. And... Oh my gosh. I remember I've had this experience twice at least.

26:03 Right? Where it's like, oh, you said, where you said you're going to, you've given me your two weeks.

26:09 So your next two weeks, your two weeks notice that you're going to leave. Your next two weeks will be to

26:13 start writing documentation for everything you've ever worked on and anything that people might need

26:18 to do. So your next two weeks are to begin writing documentation that you should have been doing the

26:22 whole time. In Germany, we have notice period of three months. So like it's three months.

26:27 Oh, that's a lot of documentation writing.

26:28 Yeah.

26:31 Just kidding. But normally, even if you leave the team, like you, for example, move from one team to

26:36 another, you don't, it doesn't mean that you have to leave the company. Still, you have to hand over

26:41 everything that you worked for, let's say, in a year or even half of the year. And for example,

26:49 in my experience, when I started with Python, I didn't know any Python. I had to learn it. And of course,

26:54 I didn't know about Sphinx or Read the Docs or any kind of documentation for Python. And what did I do?

26:59 Nothing. I didn't write it. And half a year later, I was wondering who wrote this code. So I did get

27:06 blame. And of course, it was me. And I was like, what a stupid person. So yeah. And I suggest to start

27:14 writing documentation now, even if you're not leaving the team. The reason why I'm bringing up the Sphinx

27:21 and Read the Docs is that it will allow to have continuous documentation. And with Sphinx,

27:28 you can easily write just some doc screens, which will explain what the function does, what the

27:35 class is doing, add some input output parameters, and then you will automatically generate it. So

27:42 there's no need to write it somewhere on Confluence or any other source. Because if there are too many

27:50 sources, that's where the documentation will die, because no one will go and check it. And

27:55 during the handover, usually it happens like that you write documentation somewhere where nobody knows

27:59 where, and nobody reads it.

28:01 Yeah, you pointed out that you've got it in Jira, and you've got it in GitHub, and you've got it in all

28:06 different places.

28:07 Google Docs, yes.

28:08 Yeah. Especially Google Docs.

28:10 Oh, yes.

28:12 And then you share like 10 Google Docs with different people, and then they lose the links, and people

28:19 are leaving. It's nice when people are leaving the team, but it's not nice to the people who are leaving

28:24 the team to another team, because they are getting all the questions for a year.

28:28 Where to find those? How can I get this function? How to get this data?

28:35 Yeah. Yeah. Very good advice. You know, for a long time, Sphinx was like synonymous with restructured

28:42 text, but now we've also got the Markdown with the missed parser there. So that's very cool as well.

28:48 I'm a fan of Markdown instead, yeah.

28:50 And also it supports the Sphinx itself. It supports different types of documentation. For example, you can

28:58 write code reference, then you can go through all the code, and then you can also write extra

29:04 documentation, like Markdown. Even ReadMe can be included into documentation. And you can also style it.

29:09 Oh, nice. Yeah. Yeah, very cool.

29:12 Yeah, there's lots of great themes to it too now. It really looks attractive.

29:15 Yeah, you did recently cover that, right, Brian, the Sphinx themes?

29:18 Yeah. And actually, when the Markdown, the support came on, that's when I went back and started looking

29:26 at Sphinx. So some of our documentation is done in Sphinx now because it does Markdown. And you can even

29:34 make it do, it's not built in, but you can make it read doc strings and interpret doc strings as Markdown.

29:41 So it's cool.

29:42 Yeah. Very cool. Very cool. Robert out in the live stream has an interesting addition to continuous

29:47 integration and continuous delivery. So can we deploy yet? Only if the documentation is complete.

29:53 Definitely.

29:53 Very cool. All right. Well, that's it for our main topics. Brian, you got anything you want to share?

30:00 Any extra stuff you want to throw out there?

30:02 Mostly, I'm curious about pytest uses. So I'll drop a link in the show notes,

30:08 but basically I've got a pinned tweet on my Twitter, and I'd like to have people tell me where they see

30:15 where they're using pytest. So I've got some examples. And then I kind of went,

30:24 I, my first question was people projects that have switched. But I was looking at just the,

30:30 just the guts of how Python works. And there's some amazing projects that use pytest,

30:35 like wheel, tip, setup tools, warehouse. Those all use pytest. That's pretty cool.

30:40 Wow. How interesting. Yeah. And those are sort of almost inside of Python, which is interesting

30:45 because they're not using unit tests, right?

30:47 Yeah. So, and then I just learned about recently, even if it's proprietary, that'd be interesting. I just

30:52 learned that Stripe and Lyft went through a pytest conversion recently. So that's kind of neat.

30:57 Yeah. That's cool. Yeah. Yeah. Very cool. Anastasia, anything else you want to throw out

31:00 there or let people know about while we're here?

31:02 Yeah. Maybe using exceptions. Don't use space exception.

31:08 Yeah. I agree. Custom exceptions.

31:10 Custom ones that like a four-year app or have certain, absolutely. I definitely second that idea.

31:14 All right. This, Brian, this was in danger of almost being an extra, extra, extra,

31:19 extra, extra hero about it. So I'll just go quick. So Matthew Feikert's getting a couple of shout

31:25 outs on the show. So he also pointed out that, whoa, super cool. PipX, which we've talked about

31:31 on the show before, it lets you install Python tools, kind of like Homebrew or Apt. They're not

31:35 part of a project, but you want to have them managed and installed in their own isolated environment. So

31:40 you pipX instead of pip install the thing, which is great. That is now officially part of PyPA,

31:44 the Python Packaging Authority. Nice.

31:47 So yeah, pretty cool. So pipX is now sort of officially part of Python, not Python, the distribution,

31:53 but the group, you know. Next, I will be presenting-ish. It's recorded, but then there's like a live Q&A

32:00 afterwards. Manning is having a conference on developer productivity. I don't honestly remember

32:06 what my top talk is going to be about. Oh yes, here it is. It's 10 tips and tools you can adopt

32:11 in 15 minutes or less to level up your developer productivity. So I'm going to be speaking on that.

32:15 All sorts of fun things. So if you want to check that out, it's free to register for. It's

32:20 later this month, I guess. Here's just a thought I would throw out there for you. I don't expect an

32:25 answer, but yikes, cloud bills can pile up. Alex Chan, who is teaching, I guess I don't,

32:32 I could figure out exactly the context of this, but put out a tweet that said,

32:37 I have a panicked student in my DMs who accidentally racked up an $8,000 AWS bill.

32:43 My suggestion of talk to support is no good. Apparently they won't issue a billing adjustment.

32:48 Anyone got ideas out there?

32:50 Oh no.

32:50 Could you imagine as a student, I mean, as a professional, it's still a lot of money, but as a student, $8,000 is like a ton of money.

32:59 Yeah. It's like a term of bills. It depends on.

33:03 Yes, exactly. Yeah. Like a semester of studies or something. So, maybe other students and

33:09 basically all people out there put up billing alerts on, on whatever cloud thing you're doing,

33:14 on whatever, whatever places I have, including AWS, I get periodically, I get an announcements like

33:21 you, your bill is now at $50. Your bill is at a hundred dollars.

33:24 Your bill is now at $500. Your bill is now at a thousand dollars. And if it goes beyond that,

33:28 I'm going to have to start paying a lot of attention to what's going on with my AWS account. So just,

33:32 you know, put these alerts on there. It's usually easy with whatever platform you're on. anyway,

33:37 don't be that poor student. All right. What's next? Brian skin, shout it out. Hey, this might not

33:44 be a total new item, but maybe we can mention it. Maybe it's interesting. Developed a flare mentioned,

33:49 a flake. It didn't develop it. I don't believe a flake eight plugin for FastAPI. So if you're doing

33:56 FastAPI, there's different ways to do things like routes and whatnot. And there's like the natural way,

34:01 there's sort of a clumsy way. And so here's a flake eight thing to make sure you're using FastAPI.

34:06 Nice. Interesting. Yep. And I think, yeah, and I think this is my last one. It is my last one here.

34:13 So Sal Shannon Brook tweeted JupyterLab three will have localization. So localization means like the

34:21 menus and the help text and the button hover tips and all that kind of stuff are localized for different

34:27 languages. So JupyterLab three will have localization making it more approachable for

34:32 people who don't want to work in an English UI and their crowdsourcing translations. So if you wanted

34:40 to contribute to Jupyter and you were good at programming and in a language that's not English,

34:44 but it's already done in English, you know, go check that out. That would be kind of cool.

34:48 What if anybody just messes with people and like does wrong translations just for fun?

34:53 I'm so afraid of that. Yeah. I think they do.

34:55 I bet they do. I bet they do. And maybe not really obvious, maybe in real subtle ways.

35:01 Yeah. Yeah. Yeah. Nevermind. Don't, don't, don't, don't have any ideas.

35:05 Brian, don't give people ideas. This is not, that's a good one.

35:08 All right. Well, that's all the extras as well. So how about a joke?

35:14 Yeah. Okay. So imagine you're learning programming, you're learning Python, take one of these computer

35:20 science courses where they talk about weird things like recursion. So cursion is the idea that the

35:26 function calls itself with different parameters, right? Like a really common example would be

35:31 factorial. So if I'm going to calculate a factorial, it's just N times N minus one times N minus two.

35:36 So that's just N times factorial of the smaller number. You can just like work your way back.

35:42 Right. But there should be an exit condition. Like if N equals one return, don't keep recursing.

35:48 So here's a nice little graphic under the banner of only programmers would understand. And it's got

35:54 the four squares. It's kind of like screen sharing. We got that infinite view. So learn to program

35:59 in one corner, next corner, make recursive function, third corner, no exit condition. And then it just

36:04 repeats and repeats and repeats down to smaller and smaller and smaller. I love it.

36:07 This is bad. No, this is good. That's how you learn.

36:12 That's right. No. Yeah, exactly. It's like when you share your screen in zoom or, or maybe Google

36:20 meet, but you've still got the window up or something like that. But it's about recursion. It's beautiful.

36:24 And then you silence basic exceptions and you cannot exit the program.

36:27 Yeah.

36:29 Do you know if, yeah, you know, if Python has a tail recursion optimization,

36:34 sorry.

36:35 I'm thinking, I'm thinking no, like, so the whole point is here, Brian, that we would run out of

36:40 a call stack space really quickly. And that's usually the error stack overflow error. If you

36:44 recurse too deep type of thing. Yeah.

36:46 But with trail recursion, it basically becomes an infinite loop. So you run out of time instead

36:50 of memory. Okay.

36:51 So, but I don't, so that would be the advantage of tail recursion. I have no idea if it is there or not.

36:56 Yeah. I mean, there's some languages that do the optimization, so they don't, they don't

37:00 generate a new call stack because there's nothing to save. So yeah.

37:05 Yeah.

37:05 Anyway.

37:05 Yeah. I don't know. I'm sure we will find out before next week.

37:09 Yeah. One of the reasons why I like asking open-ended questions on the podcast.

37:13 So yeah, that's awesome. Yep.

37:16 Well, Brian, thank you as always. And Anastasia, thank you for being here. It was great to have

37:19 you as a guest.

37:20 Thanks.

37:20 Thank you for inviting. Thank you.

37:22 Yep. Bye.

Back to show page