Transcript #273: Getting dirty with __eq__(self, other)
Return to episode page view on github00:00 Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds.
00:05 This is episode 273, recorded March 1st, 2022.
00:09 And I'm Brian Okken.
00:11 I'm Michael Kennedy.
00:12 Well, welcome, Michael. It's good to have us here.
00:16 It's great to see you as always.
00:18 It feels like spring is almost here. It's March. I can't believe it.
00:22 So pretty awesome.
00:23 Yeah.
00:24 Fun to be talking Python with you.
00:26 Yeah. So should we kick it off with your first item?
00:30 Let's do it. I'm a big fan of science, math and all those things.
00:34 And I came across this article because I was reading about science, not because I was reading about Python.
00:40 But then I thought, oh, there has to be a Python story here.
00:43 Let's get into it and see if I can track it down.
00:45 And wow, is it not easy to find.
00:47 So here's the deal.
00:47 I saw an article over on sciencealert.com called Physics Breakthrough as AI Successfully Controls Plasma in a Nuclear Fusion Experiment.
00:58 That's so cool.
00:59 Let me, that's amazing, right?
01:00 So let me put a few things together here.
01:01 Nuclear fusion, not fission.
01:03 That's the kind of nuclear we want.
01:05 That is harnessing the sun with no negative effects to like turn hydrogen into helium and so on.
01:12 Right?
01:13 If we could harness that, that's like free, super easy energy forever.
01:18 It's incredible, right?
01:19 So people have been working on this for a long time.
01:21 The way that I understand, which is probably pretty piecemeal that it works is you put some kind of thing, some kind of material like hydrogen or something in the middle, and then you blast it with tons of energy.
01:37 But then it creates this plasma.
01:39 And you've got to control with lasers and magnets on how you basically keep the pressure high enough in addition to just the heat to actually make the fusion work.
01:49 Right?
01:50 So there's been some success like, hey, we got fusion to work for a while.
01:55 It just took more energy than it put out.
01:57 So, you know, it's not a super great power plant, but it did do the science thing, right?
02:02 Yeah.
02:02 So here's the deal.
02:04 This article says they've used artificial intelligence to teach it how to make instantaneous or near instantaneous adjustments to the magnetic field and the lasers in order to actually get better results with fusion, right?
02:19 So take it farther along.
02:20 And it says, in a joint effort, the Swiss Plasma Center and artificial intelligence research company DeepMind, they used deep reinforcement learning to study the nuances of plasma behavior and control inside a fusion tokamak.
02:36 That's the donut-shaped thing where the reaction happens.
02:40 And they're able to make a bunch of small adjustments really quickly in order to get better results.
02:48 And it's pretty wild that they did that with AI, isn't it?
02:51 Yeah.
02:51 Yeah.
02:52 There's definitely Python in there somewhere.
02:54 You just know it.
02:54 Exactly.
02:55 So I'm like, all right, where is this?
02:56 So I went through and they talk about the findings being in nature, some of the articles that they're referencing.
03:01 So there's some like deep, as in not super engaging sort of scientific articles, like the traditional academic style of writing that you've got to dive into and then like follow a bunch of links.
03:11 But eventually in there, you will find that there is some cool science stuff going on.
03:18 And Python is at the heart of it.
03:21 So it's probably not worth going into too much of the details of how it's actually happening.
03:27 But it's the Python side of things.
03:30 But I just thought it was super cool that, look, here's one of the most exciting things happening in energy and for the climate and for all sorts of things.
03:37 And AI and Python are pushing it forward.
03:40 That's crazy.
03:41 And that's what we need for a Mr. Fusion so that we can make flying cars and time traveling cars too.
03:47 Exactly.
03:48 I mean, Marty McFly and Doc, they go and they throw their banana peel on the back of the DeLorean, right?
03:54 You've got to have one of these token mucks to make it roll.
03:56 You've got to have Python in the car.
03:57 Come on.
03:58 Obviously.
03:59 So, cool.
04:00 Obviously.
04:01 All right.
04:02 Well, take us back to something more concrete.
04:04 Well, okay.
04:05 So I'm pretty excited about this.
04:06 It's a minor thing, but maybe not too minor.
04:10 PEP 680 has been accepted.
04:13 Standards track for Python 311.
04:15 PEP 680 is TomlLib support.
04:19 So support for parsing Toml in the standard library.
04:22 We haven't had it yet.
04:24 That's awesome.
04:24 So we've got JSON.
04:26 We've got CSV.
04:27 Why not?
04:28 Right.
04:28 We've got XML.
04:29 Well, and one of the, and now that we've, PEP uses Toml for PyProject.Toml, but anyway,
04:39 so we kind of need, I think it'd be cool to have it in the standard library.
04:42 I think it's fine to have other outside supports.
04:45 So what they're doing is, and if people don't, there's some rationale here, but, you know,
04:52 just think it's easier than normal.
04:54 So Toml is, I like Toml for, because it's just, I don't know, it's an easy format to
05:00 read.
05:01 It's better than any and some other stuff.
05:03 And for people who don't know, it feels any like, like the .ini file style where you've
05:09 kind of got like section headers and then key value bits.
05:12 Yeah.
05:13 And it doesn't, and often it doesn't like, you can use, you can use black and write a PyProject.Toml
05:20 file without even really knowing anything about Toml.
05:22 So it's pretty straightforward, but we didn't have a way built into standard library to
05:27 just use it.
05:28 So that's, this is this PEP.
05:30 One of the things there, interesting bits about it is it's only reading.
05:35 So it's only adding support for reading Toml.
05:40 So there's a load and a load, load S.
05:43 So you can load a Toml file or you can load a string and that's it.
05:49 And it outputs a dictionary.
05:50 So, and that, that, that makes sense.
05:54 You're just getting a Toml object and getting, turning it into, to a dictionary so you can use
06:01 it.
06:02 But this is built on top of Toml.ly.
06:05 So Toml.ly is being used as a, as, as the, as the library to basically there's an open source
06:13 project called Toml.ly, which a lot of projects are using.
06:16 I think this is the one that pytest is using and quite a few projects are, have switched to this.
06:21 It's really fast.
06:22 It's nice, but it supports like writing as well.
06:26 But yeah, right.
06:27 And then code and dump S and all those things.
06:29 Yeah.
06:29 Right.
06:30 So, so, but that's, that's not the part that's going to get supported.
06:33 And I think that's, I think that's fine to just have reading built into, to, into.
06:39 Sure.
06:39 Some file formats like text and, and CSV and whatnot, like reading and writing is super common.
06:45 Right.
06:46 But these are way more likely to be used as configuration files that drive app startup
06:52 and like hide secrets.
06:53 You know, you put your secrets in there and don't put in Git or something like that, whatever.
06:56 Right.
06:57 Those are the kinds of UK use cases I would see.
07:00 And so in that case, reading, reading seems fine.
07:02 You could always add writing later.
07:03 You just can't take it away if you add it too soon.
07:05 Right.
07:06 Right.
07:06 But, but also like, I don't, I don't, and I'm sure there are reasons to, to need to write
07:13 it, but I, I don't, you know, it's, it's mostly people write it and computers read it
07:20 sort of thing.
07:20 Yeah, exactly.
07:21 Some kind of editor writes it and then you read it.
07:24 Yeah.
07:24 So.
07:25 Fantastic.
07:26 All right.
07:27 Well, cool.
07:27 Very nice to see that one coming along.
07:29 Alvaro out in the audience.
07:32 Hello there.
07:33 It says, Hummel just reached version 1.0, not so long ago.
07:37 So maybe that also has some kind of impact on the willingness, like, all right, the file
07:42 format is stable.
07:43 Now we can actually start to support it in the library.
07:45 That's true.
07:46 And, and we, we do support Python releases for a long time.
07:50 So that it probably needed to be V1 at least.
07:53 So.
07:54 Yeah.
07:55 And Sam also says there's a lot of stylistic choices for how you write Toml files.
07:59 Like we need a black for Toml, not, not to drive Tom, not to configure black, but something
08:05 that then goes against Toml files and, you know, makes them consistent.
08:09 Yeah.
08:11 Maybe.
08:12 Yeah.
08:13 Yeah.
08:13 But you could, yeah, you could, you could bake that in.
08:14 All right.
08:16 What have I got next here?
08:17 I've got sticking on the internals here.
08:20 I want to talk about thread locals in Python.
08:23 Okay.
08:24 So last time we had Calvin on and I spoke about this crazy async running thing that I had built
08:31 and boy, is it working well.
08:33 I, like I said, it is truly horrifying to think about what it's doing, but it actually works
08:37 perfectly.
08:38 So there it is.
08:39 But one of the challenges that it has is it, it doesn't like it if you call back into it
08:46 again.
08:46 And I talked about the, the nest asyncio project last time, which maybe we'll solve
08:53 it.
08:53 I tried those and it wasn't working, but it could have been like at a different iteration
08:57 before I finally realized like, no, I have to go all in on this threading, like isolate
09:02 all that execution into one place where we can control it.
09:05 So maybe it would work, but I just wanted to talk about thread locals in Python, which I
09:10 thought were pretty easy, and pretty interesting.
09:12 So I've got this stuff running over there.
09:15 And one thing that would be nice is each there's different threads calling into the system to
09:20 say, schedule some work for me.
09:21 Basically puts it on a queue.
09:23 The queue runs it on this like controlled loop, and then it sends back the result.
09:26 The problem is if, if one function calls that to put in work, and then as part of doing
09:31 that work, the function itself somewhere deep down, like wraps that around, it doesn't really
09:36 like the recursion aspect very much.
09:38 So what I thought is, well, how do I figure out, well, this thread has running work.
09:42 And if it calls again, you know, raise an exception and say, like, you need to adjust
09:47 the way you're calling this library.
09:48 It's not working right.
09:49 Instead of just like doing some weird thing.
09:51 So what I think I might do, and I'm not totally sure it will work perfectly, but the idea
09:57 is certainly useful for all sorts of things is to use a thread local variable.
10:02 Now, when I thought about thread local variables, I've used them in other languages, and I had
10:06 no idea how to do them in Python.
10:07 It turns out to be incredibly easy.
10:10 You just say, go to threading, the threading module, and you say local.
10:13 That becomes like a dynamic class that you can just start assigning values to.
10:17 So in the example that I'm linking to, it says you get a my data thing, which is a thread
10:22 local data blob, whatever.
10:25 So you could say like, my data dot x equals one, my data dot list equals whatever.
10:30 And then that will store that data, but it will store it on a per thread basis.
10:35 So each thread sees a different value.
10:37 So for example, what I could do is say thread, you know, at the beginning of the call, like
10:42 I have running work.
10:43 Yes.
10:44 At the end, you know, roll that back.
10:47 And if I ever call in to schedule some work and the thread local says, I'm doing, I have
10:52 active work running.
10:53 Well, there's that error case that I talked about and I don't have to do weird things
10:56 like put different IDs of threads into database into like a dictionary and then like check that
11:01 and then lock it.
11:02 Like all sorts.
11:02 I can just say this thread has like a running state for my little scenario.
11:07 What do you think?
11:08 I think that's great.
11:09 I think it's interesting.
11:10 Yeah, it is.
11:11 Right.
11:11 Yeah.
11:12 And it's right.
11:13 Not too hard.
11:14 Just create one of these little local things, interact with it in a thread and each thread
11:18 will have basically its own view into that data, which I think is pretty fantastic.
11:22 So.
11:22 Like a thread version namespace thing.
11:26 Yeah.
11:27 Yes, exactly.
11:28 Exactly.
11:28 It's a cool little isolation without doing like locks and all sorts of weird stuff that
11:33 can end up in deadlocks or slowdowns or other stuff.
11:36 So anyway, if you're got scenarios where you're doing threading and you're like, oh, it would
11:40 be really great if I could dedicate some data just to this particular run and not like a
11:45 global thing.
11:46 Check this out.
11:47 It's it's incredibly.
11:48 Nice.
11:49 Yeah.
11:49 Oh, let me pull up one more thing before we move on, Brian.
11:54 Okay.
11:54 How about Datadog?
11:57 Yes.
11:58 That's also something else that's extremely easy to use.
12:01 Yep.
12:02 Thank you, Datadog, for sponsoring this episode.
12:05 Datadog is a real time monitoring platform that unifies metrics, traces and logs into one
12:11 tightly integrated platform.
12:13 Datadog APM empowers developer teams to identify anomalies, resolve issues and improve application
12:20 performance.
12:21 Begin collecting stack traces, visualize them as flame graphs and organize them into profile
12:27 types such as CPU, IO and more.
12:29 Teams can search for specific profiles, correlate them with distributed traces and identify slow,
12:35 or underperforming code for analysis and optimization.
12:38 Plus, with Datadog's APM live search, you can perform searches across all across the full
12:45 stream of integrated traces generated by your application over the last 15 minutes.
12:50 That's cool.
12:51 Try Datadog APM free with a 14 day free trial and Datadog will send you a free t-shirt.
12:58 Visit pythonbytes.fm/Datadog or just click the link in your podcast player show notes to get
13:06 started.
13:07 Yes.
13:07 Thank you, Datadog.
13:07 I love all the visibility into what's going on.
13:10 I was just dealing with some crashes and other issues on something I was trying to roll out.
13:15 Some library was conflicting with some other library.
13:17 They were fighting.
13:18 And yeah, it's great to be able to just log in and see what's going on.
13:22 Now, before we move off to Threadlocals, quick audience question.
13:26 Sam out there says, it might be better to use context vars if you're also working with an invent loop.
13:30 As far as I know, context vars are the evolved version of Threadlocals that are aware of async too.
13:36 That's very interesting.
13:38 I haven't done anything with context vars, but the way I think asyncio works is even though there's a bunch of stuff running from different locations, there's one thread.
13:46 So Threadlocal is useless for that.
13:48 So that's why Sam is suggesting context vars.
13:50 The side that schedules the work has nothing to do with asyncio in my world.
13:55 So that's why I was thinking Threadlocal.
13:57 It's a good highlight to say if you're using async, you may need something different.
14:03 Absolutely.
14:04 Yeah.
14:04 So thanks, Sam, for that.
14:06 Yeah, so I'm not sure if we've really talked about it much, but I came across that article from Trey Hunter called, What is a Generator Function?
14:16 And like Python, especially, you know, the two to three switch, even like dictionary, the items keyword, you know, function to get all the dictionary elements out.
14:28 It doesn't return a list anymore.
14:30 It returns a generator.
14:31 And maybe it always did.
14:34 I don't know.
14:34 But there's a whole bunch of stuff that used to return lists that now return generators.
14:38 And it kind of, they work great.
14:41 You stick them in a for loop and you're off to the races.
14:45 But a lot of people are a little timid at first to try to write their own because it's a yield statement instead of a return.
14:53 And how do you do it?
14:56 And so this is a great article by Trey to just say, here's what's going on.
15:01 It's not that complicated.
15:03 Generally, you just have a, you often might have a for loop within your code.
15:08 And instead of returning all the items, you're going to try to write your own.
15:17 And it's pretty interesting.
15:21 It's interesting for people to read through it and understand what kind of what's going on behind the scenes.
15:26 So what happens is your function that has a yield in it, it will not return the item right away.
15:32 When somebody calls it, it returns a generator object.
15:36 And that generator object has things like next.
15:40 And mostly that's what we care about.
15:43 And next returns the next item that you've returned.
15:46 And then once you run out of items, it raises a stop iteration exception.
15:52 And that's how it works.
15:54 But generally, we just don't care about that stuff.
15:57 We just throw them in a for loop.
15:58 But it is interesting to learn some of the details around it.
16:01 Yeah, they do seem mysterious and tricky, but they're super powerful.
16:06 The more data that you have, the way better idea it is to not load it all into memory at once.
16:12 Yeah, and you can do some fun things like chunking.
16:16 You can, like if you're returning, like your caller, like let's say, and these are fun things to do with this.
16:23 So let's say you're reading from an API or from a file or from a device or something.
16:29 And it has, you read like a big chunk of things, like 20 of them or 256 or something like that.
16:37 A whole bunch of data at once.
16:38 But then your caller item, your caller really only wants one at a time.
16:43 Within your function, your generator function, you can do fancy stuff like read a whole bunch and then just meter those out.
16:50 And when then that's empty, you go and read some more and have intermittent reads.
16:55 And this will save time for, especially when you're not reading everything often.
17:00 Sometimes the caller will break and not utilize everything.
17:02 So that's definitely where, and they're very, they're a lot more efficient on memory too.
17:08 So if you're, like you said, if it's huge amounts of things, it might be either for memory reasons or for speed reasons.
17:14 These are great.
17:14 Yeah.
17:14 Even computational, like, so suppose you want a list of Pydantic objects back and you're like reading some massive CSV and picking each row and star star value in there somehow.
17:26 That's the actual creation of the Pydantic object.
17:31 If there was like a million of them, forget memory.
17:33 Like even just the computation is expensive.
17:35 So if you only want the first 20, like you can only pay the price of initializing the first 20.
17:40 So there's, there's all sorts of good reasons.
17:42 Yeah.
17:42 Okay.
17:43 I do want, I do want to just say one thing about generators that I wish there was like a slightly, maybe some kind of behavior could be added, which would be fantastic.
17:53 So generators can't be reused.
17:56 Yeah.
17:57 Right.
17:57 So if I get a result back from a function, I try to, and I want to ask you a question, like, were there any items resolved in here?
18:03 And then loop over them if there were like you, you kind of broke it, right?
18:06 You pulled the first one off and then the next thing you work with is like index one through N rather than zero through N, which is a problem.
18:14 So sometimes you need to turn them to a list.
18:16 It'd be cool if there was like a dot two list on a generator instead of having to call list on it, right?
18:22 Just like a way as an expression to kind of like, I'm calling this and it's sort of a data science flow.
18:27 I want all one expression and turn this generator into this other thing that I need to pass along.
18:32 Yeah.
18:32 It would be fun.
18:33 Yeah.
18:34 So a question out in the audience that maybe they, they returns that the dictionary items and keys return something different.
18:43 But Sam Morley says they, they return special generators, special kinds of generators.
18:50 So yeah.
18:51 Thanks Sam.
18:52 Cool.
18:52 Indeed.
18:53 All right.
18:54 Well, what have I got next?
18:57 I think I just closed it.
18:58 Now, would it really be an episode if we didn't talk about Will McGugan in some way or another?
19:02 So we got him on deck twice, but we're going to start with just something he recommended to us.
19:07 That's actually by Sam Colvin, who is the creator of Pedantic.
19:13 And I'm not sure if you're ready for this, Brian, but this is a little bit dirty.
19:17 It's called dirty equals.
19:19 And the idea is to abuse the Dunder EQ method, mostly around unit testing, to make test cases and assertions and other things you might want to test more declarative and less imperative.
19:36 So it all sounds like fun, but how about an example?
19:39 So it starts out with a trivial example.
19:41 It says, okay, from this library, you can import something called is positive.
19:45 So then you could assert one or like some number and whatever.
19:50 One equal equal is positive.
19:52 That's true.
19:53 That assert passes.
19:54 Negative two equal equal is positive fails.
19:57 Okay.
19:58 How does that strike you, Brian?
20:00 We're building.
20:01 These are building blocks.
20:03 This is like a Lego piece, not the whole X wing fighter.
20:06 But anyway, so that's the building block, right?
20:09 Like take something and instead of saying, yes, it's exactly equal, implement the Dunder equal method in the is positive class to like take the value, make sure it's a number, then check whether it's greater than zero.
20:20 Right.
20:20 That kind of thing.
20:21 I don't know if that includes zero, but anyway.
20:23 But then you can get more interesting things.
20:26 So you could go to a database and if you do a query against the database, you get, I think in the case that's up there, I think you get a tuple back.
20:34 It depends on what you set the row factory to be, I suppose.
20:37 But anyway, you get a tuple back of results.
20:41 It looks like maybe this is a dictionary.
20:43 Anyway, so then you can create a dictionary that has attributes that are like the result you want.
20:50 They can either be equal or they can be things like this is positive.
20:53 So in this case, we're doing a query against the database.
20:58 And then we're, looks like there's maybe needs to be like a first one.
21:04 Anyway, it says, all right, what we're going to do is we're going to do equal, equal that the ID, we'll create a dictionary, ID colon is positive int, username colon, Sam Colvin.
21:15 So that's an actual equality.
21:17 Like the username has to be Samuel here.
21:18 Okay.
21:19 Yeah.
21:20 And then the avatar is a string that matches a regular expression.
21:23 That's like a number slash PNG.
21:26 The settings has to be a JSON thing where inside the settings, it's got some JSON values that you might test for.
21:33 And that is created now, is now with some level of variation, like some level of precision that you're willing to work with.
21:41 Right.
21:42 Because obviously you run the database query and then you get the result, but it's like very near, nearly now.
21:49 Right.
21:49 It's like the almost equals and float type of stuff.
21:52 That's pretty cool.
21:53 Right.
21:53 Do I need to answer?
21:57 I mean, I could see the utility.
21:59 I'm sure your thoughts.
22:00 Yeah.
22:01 But the, I don't know.
22:03 It's the API is a little odd to me, but.
22:06 Okay.
22:07 Yeah.
22:08 I think it's, it's definitely an interesting idea.
22:10 It's definitely different.
22:11 you know, Pydantic is often about, I know it's not Pydantic, but it's by the creator.
22:16 Pydantic is often about, given some data that kind of matches, can it be made into that thing?
22:23 And I feel like this kind of testing is in the same vein as what you might get working with Pydantic and data.
22:30 Yeah.
22:31 Right.
22:31 Well, it's definitely, it's definitely terse and, and, and useful.
22:35 so, and, and I, I could totally get used to it.
22:39 If this is a, this is a pretty, pretty, condensed way to, to compare, to see if everything, matches this protocol.
22:48 Yeah.
22:48 Yeah.
22:49 So Sergey on the audience has like sort of the alternative perspective could be, you could just write multiple assert statements.
22:56 Instead of creating a dictionary that represents everything, you could say like, get the record back and assert that, you know, get the first value out and assert on it.
23:06 Then get the username out and assert and get the avatar and assert on it and so on.
23:10 And it's sort of an intermediate view, a story where you use the testing libraries, the testing classes, but sort of more explosive.
23:19 So, right.
23:20 And one of the reasons why a lot of people, there's, there's a couple of reasons why to not use more than one assert.
23:25 because if you were to have multiple asserts, the first one to fail stops the check.
23:31 It's possible that this will tell you everything that's, that's wrong.
23:34 Not just the first thing that's wrong.
23:36 Yes, exactly.
23:37 and, and then, you know, some people are just opposed to multiple asserts per test.
23:42 It's just for, you know, I don't know.
23:45 I mean, a similar thing.
23:48 So I, I have a, a plugin called py test check, which is, is just, it uses checks
23:56 instead of asserts so that you can have multiple checks per test, but, it does come up.
24:02 So this is interesting.
24:04 I'll definitely check it out and play with it.
24:06 Yeah.
24:07 Another benefit of being able to construct one of these like prototypical documents or, dictionaries
24:14 that then represents the, the declarative behavior or state that you're supposed to be testing
24:18 for is you could create one of these and then use it different locations.
24:22 Like, okay, when I insert a record and then I get it back out, it should be like this.
24:25 But also if I call the API and it gives me something back, it should also still pass the same test.
24:32 Like you could have a different parts of my app.
24:34 They all need to look like this.
24:35 Yeah.
24:36 As opposed to having a bunch of tests over and over that are effectively the same.
24:39 And Will is here who recommended this suggests, one of the benefits of dirty equals is that
24:46 py test will generate, generate useful diffs from it.
24:49 Yeah.
24:49 and definitely, reasons, py test being a reason to use something.
24:54 I'm on board then.
24:56 Yeah, sure.
24:57 Yeah.
24:58 Check it out.
24:59 If you do play with it, give us a report how you feel about it.
25:01 One more question from, Sam, said, Sam Morley, py test already has something
25:07 a bit like this with a prox, except for it's for floats, et cetera, except for a prox
25:13 is not, et cetera.
25:14 It's just for floats.
25:15 So you can only use approximate floats.
25:18 So yeah.
25:18 So we have like approximate now and stuff like that.
25:22 So I'll, I'll try it.
25:25 Especially, you know, if Will likes it, it's gotta be.
25:27 Good.
25:28 Exactly.
25:29 So awesome.
25:31 All right.
25:32 What's the final one you got for us here?
25:34 Okay.
25:34 This is more of a question than a, I'm not like saying this is awesome, but I ran across
25:39 this.
25:39 actually this, I, I, I went, I clicked on a listicle, Mike, I think there's a self
25:46 help group for that.
25:47 yeah.
25:48 well, we're definitely prone to clicking on the top listicles.
25:53 So my name is Brian and I clicked on a listicle.
25:57 so the, the listicle was a top 10 where we at, it was, 10 tools.
26:03 I wish I knew when I started working with Python and actually it's a good list.
26:08 I just knew about most of them as all.
26:10 So it's, it's, it's a little link to it anyway.
26:12 It's, it's got the sound of music.
26:13 It's got Jackie Chan.
26:14 It's got office space.
26:15 Come on.
26:16 This is a pretty solid listicle.
26:18 Then I got down to number seven and eight and I'm like, what are these things?
26:21 I've never heard of them.
26:22 So, committison and semantic release.
26:25 So, the idea.
26:29 So I, I tried to do a commit with this.
26:32 So committison is a thing that you can say, if you install it, you can either brew, install
26:37 it for your everything, or you can put it in a virtual environment.
26:40 So that's cool.
26:41 But it's, you, you, instead of just committing, you use this to commit and it asks you questions.
26:48 Right.
26:48 Instead of typing get space commit, you type CZ space commit.
26:52 Yeah.
26:52 And then instead of like, it, and it asks you a whole bunch of stuff.
26:55 It was this a bug fix.
26:56 Fix.
26:57 Was it a feature?
26:58 Did you, and then it follows on what, depending on what you answered, if you had a, if you had
27:03 a, a bug fix or a feature, is it a breaking feature?
27:06 Did you basically it's trying to, it's, it's doing a whole bunch of things.
27:10 But it's trying to do these, conventional, conventional commits.
27:15 And we've got a link to this too.
27:17 And, and then if you've got all this formatting, so it ends up formatting your commit message
27:23 to a consistent format so that when you're reading the history and stuff, you can do a whole
27:28 bunch of, it's easier, I guess.
27:30 and then, this tool also, this listicle also commented that you've got, semantic release, which is a Python package that I haven't got through this much, but
27:43 it, it can take this, all this information from these and do some better control your semantic
27:50 release notes or release.
27:51 I don't know if it's the release notes or just the release version.
27:54 I haven't got that far into it, but.
27:56 Yeah.
27:56 The commit is an ass.
27:57 Is this a, like a change corresponding to semantic versions such that it should be a major change.
28:03 So it'll like, it looks like it'll increment the version and stuff like that as well.
28:06 Yeah.
28:06 Yeah.
28:07 but so, the, in the about, for commitment says command line utility to create
28:14 commits with your rules.
28:16 And apparently you can, you can specify some special rules, which is good.
28:20 display information about your commits, bump the version automatically and, generate
28:26 a change log.
28:28 That's cool.
28:29 I want, that might be helpful.
28:30 so my questions out to the audience and everybody listening, have you used something
28:36 like this?
28:37 Is it useful?
28:38 is there something different than this that you recommend?
28:41 And also what size of a project would this make sense for a small or medium project?
28:45 That's cool.
28:45 Yeah.
28:46 Let us know on Twitter or at the bottom of the YouTube live stream.
28:48 It's probably the best place.
28:49 Yep.
28:50 So.
28:50 Yeah.
28:51 Very cool.
28:52 Now, before you go on, I also have a question out to you.
28:55 You can be the proxy for the audience here.
28:57 Okay.
28:57 Notice at the bottom it says requirements three, six and above.
28:59 yeah.
29:01 And Python, that's not, I don't feel like that's very controversial as three, six is not even
29:06 supported anymore.
29:07 Right.
29:07 Right.
29:07 So this is like every possibly supported version of Python three, this works for.
29:12 Would, what would you think if I said the requirement is this is Python three, not Python
29:18 three, just, it requires Python three.
29:20 Knowing that like that means, or implying that that means supported shipping, real,
29:27 versions of Python, not Python three, one.
29:29 Right.
29:30 Cause obviously Python three, one is no longer supported, but neither is three, five even
29:34 like, could you say f-strings are just in Python three now without worrying about the version?
29:38 Or do you need to, you still need to say.
29:40 Three, six, three, six, three, seven.
29:42 Like, should this be updated?
29:43 It'd be three, seven.
29:43 You know what I mean?
29:44 Kind of have to.
29:45 You think so?
29:47 I, I don't know.
29:48 I, I know I, when I say, something is on three Python three, actually, I don't even
29:54 say that anymore.
29:55 So yeah.
29:56 What do you think?
29:57 Okay.
29:58 well, I used it in the sense like, yeah, you need Python three for this thinking,
30:02 well, any version that's supported these days and people are like, well, there's older versions
30:06 that don't support this thing.
30:07 Like, well, you know, obviously I'm not talking about the one that was not supported five years
30:12 ago.
30:12 Like at some point, Python three is the supported version of Python.
30:18 I don't know.
30:19 Oh, that's true.
30:19 Yeah.
30:20 Okay.
30:21 So that's a bit of a diversion there, but I went down that route.
30:24 Hold on.
30:24 It's like, I really don't know which way I should go, but I feel like there's, there's a case
30:27 to be made that just like, when you talk about Python three, you're not talking about old
30:31 unsupported versions.
30:32 You're everything that's like modern three, seven and above should be like an, an, an, an alias
30:38 for Python three.
30:39 I don't know.
30:39 When we were just saying Python three, what we meant was like three, one.
30:43 So I know we got to get used to that.
30:45 There's no Python two really to worry about.
30:48 All right.
30:49 Well, that will definitely bring us to our extras in a moment.
30:52 Yeah.
30:53 Yeah.
30:54 All right.
30:54 You want me to kick it off since I got my screen up?
30:57 Yeah, go ahead.
30:58 All right.
30:58 So we'll, like I said, he gets two appearances and also it's comments.
31:02 So thank you for that.
31:03 And this is like in the same vein of what I was just talking about.
31:06 Like what is this convention that we want to have?
31:08 Right.
31:08 So the Walrus operator came out in three eight and it was kind of an interesting big deal,
31:14 right?
31:15 There's a lot of debate around whether or not that should be in the language.
31:18 Honestly, I think it's a pretty minor thing that that's not a, not a huge deal, but the
31:22 idea is you can both test for a variable as well, or you can use the test or use the value
31:29 of the variable in the same place that you create it.
31:32 So instead of saying X equals get user or like you equals get user, if user is not none or
31:38 if user, you could just say, if you colon equals get user do the true thing.
31:43 Otherwise then it's, it's not set.
31:45 Right.
31:46 And so Will is suggesting that we pronounce the Walrus operator as you becomes the value.
31:54 So like X colon equals seven is like X becomes seven.
31:58 What do you think?
31:59 Are you behind this?
32:00 Okay.
32:00 So you'd be like when you're reading your code to yourself, I guess.
32:03 How do you say it?
32:04 Like if you say like the Lambda expression, like how do you like define like the variables
32:09 of the land?
32:10 Like there's, there's terms around there that make it a little bit hard to say without just
32:14 saying syntax.
32:14 Right.
32:15 So he's proposing like becomes is the, the saying, the verbal, the way we verbalize Walrus
32:21 operator.
32:22 I like it.
32:24 I'm going to give it a thumbs up.
32:24 It's interesting.
32:25 But what, how is that different from assignment though?
32:27 Do we, do you say, what do you say with assignment?
32:29 I don't say like X equals, I don't know.
32:33 Yeah.
32:33 Equals, the same become, becomes works.
32:36 all right.
32:38 Well, I'll put it out there.
32:39 People can think about it.
32:40 And there's a, there's a nice Twitter thread here with a, lots of comments.
32:43 so folks can jump in.
32:46 Or you just, walrus, just talk X walrus five.
32:50 oh yeah.
32:51 Well, what do walruses do?
32:53 I mean, is there like a cool action that would, is like particular to walruses?
32:57 Well, there probably is, but it's not, it doesn't apply to this.
33:01 It's not a very colloquial, is it?
33:03 is X.
33:05 Yeah.
33:05 And John, then John Sheehan out of the audience says, in my brain, I use assigned to, and he
33:11 must know what's coming because he's up next.
33:14 Hey John.
33:17 so the other thing I want to talk about is, did you know, I learned through John that
33:22 string starts with, we'll take a, an iterable, it says tuple, but I suspect it might even be
33:28 an iterable of sub strings.
33:31 And if any of them match, it will, it'll test out to be true.
33:35 So like ABCDEF, you say starts with a tuple AB or CD or EF.
33:41 Huh?
33:42 I've never used this.
33:43 I didn't know that that was, I would always just do that as like X starts with AB or X starts
33:48 with CD or X starts with EF.
33:51 No, you can apparently can do that all in one go.
33:53 What's the two for?
33:54 I have no idea.
33:55 I was just thinking that as well.
33:57 There's a two and I don't know where, what is four.
33:58 So yeah.
34:02 Yeah.
34:02 Anyway, that's a super quick one, but I thought, pretty interesting there.
34:06 That's all I got.
34:08 How about you?
34:09 I just have one thing that I, we don't need to put it up, but my extra is this book.
34:15 You have your physical 2.0 book in hand.
34:20 Yes.
34:20 I've got, I've, Oh yeah.
34:22 And for the people not, not watching, my, I've got a stack of, it's funny.
34:28 My, my, my daughter uses my Amazon account too.
34:31 So UPS said, Hey, there's a package arriving yesterday.
34:34 And I said, I didn't, and I didn't order anything.
34:37 So I said, I told my daughter, Hey, you probably have a package showing up.
34:41 She's like, I didn't order anything.
34:43 and then this box arrives with five copies of my book, which is great.
34:49 That's awesome.
34:50 Yeah.
34:51 Yeah.
34:51 Congratulations.
34:52 Thanks.
34:52 Very cool.
34:53 Yeah.
34:53 We abuse our Amazon account badly.
34:56 Like there's a lot of people that log into Amazon.
34:58 We end up getting stuff shipped wrong places.
35:00 Cause somebody shipped it to their house last time.
35:02 And then we just hit reorder again.
35:04 And they're like, why do you have our shampoo?
35:06 I don't know.
35:06 Yeah.
35:07 yeah.
35:08 So John adds that the, two is the starting position.
35:12 Oh, the starting position.
35:14 Yeah.
35:15 Right.
35:15 I figured it had something to do with that.
35:16 I wasn't sure how many characters to compare out, whatever.
35:18 Well, I also didn't know if the, that you could do that.
35:21 It's a good pass.
35:22 The starting position for starts with.
35:23 That's cool.
35:25 Yeah.
35:26 There's a lot going on here.
35:27 Almost starts with.
35:28 all yeah.
35:29 Nearly starts with.
35:30 Yeah.
35:31 What's the, what's the, what's the, what's the right way.
35:33 So I want to close this out with a, a joke as always, but there's the joke we talked about
35:40 a while ago, where, Sebastian Ramirez creator of FastAPI saw an ad hiring a FastAPI developer.
35:48 And he said, Oh, it looks like I can't apply for this job.
35:51 It requires four years of experience with FastAPI, but I can't possibly have that.
35:56 Cause I only created it two years ago.
35:57 Right.
35:58 Yeah.
35:58 So it's a little bit in that vein.
36:00 So here we have, somebody, tweeting and says, here's a conversation with the recruiter
36:06 and them.
36:07 It says, recruiter, do you have a CS background?
36:10 Yes, absolutely.
36:11 My CS background.
36:13 And this is the screenshot from the game counter strike, which is often referred to as just CS.
36:17 Yeah, of course I got a CS background.
36:19 Are you kidding me?
36:19 That's pretty good.
36:23 I love it.
36:24 Yeah.
36:24 yeah, that's a good one.
36:26 Well, just a question though.
36:28 If you, if you did FastAPI instead of eight hours a day, if you did it 16 hours a day for
36:34 two years, would that constitute?
36:36 You know, that probably, that probably is about the same amount of experience.
36:41 Yeah.
36:41 So what a slacker that Sebastian is.
36:44 Does he have to eat or something?
36:46 Does he have family?
36:47 What's going on?
36:48 Come on.
36:48 Well, always fun with, hanging out with you and talking Python.
36:53 So you bet.
36:54 And thanks to everybody on the, that listens to it on, on their podcast player or watches
37:00 us on YouTube.
37:01 Yeah, absolutely.