Transcript #337: Backtracking For a PackageReturn to episode page view on github
00:00 Hello and welcome to Python bites where we deliver Python news and headlines directly to your earbuds. This is episode 337 recorded May 23 2023 and I am Brian Akin and I'm Michael Kennedy.
00:13 I wanna thank everybody that's watching but anybody that's listening. I encourage you to at least once in a while drop by YouTube and see the upcoming list of events at pythonbytes.fm/live to be part of the audience.
00:28 It's usually fun. It's usually Tuesdays at 11 Pacific time.
00:33 Occasionally we switch.
00:35 If you'd like to connect with us, we're all on Fosted On, at least the three of us, Michael and I on the show.
00:43 It's mkennedy@fostedon, @brianokken, and @pythonbytes.
00:48 And with that, let's jump into our first topic.
00:52 Let's jump into it.
00:54 It's not going to be a Ruff one.
00:56 What is it? The first topic is Ruff, which is obviously Charlie Marsh's project.
01:04 It's very successful. People know that.
01:06 It's not exactly Ruff.
01:07 It's a way to use Ruff.
01:09 This one comes to us from John Hagan.
01:14 John runs this project called Python Blueprint.
01:19 So he's been playing around a lot with that project and PyCharm and Ruff, and realized that now there's a plug-in for all the JetBrains IDEs, most notably PyCharm, called just Ruff.
01:35 The idea is that PyCharm has all these little squigglies and warnings, and maybe even more importantly, the auto-corrections.
01:44 So it'll do things like if you wanted to replace double quotes or single quotes, you can just hit Alt Enter, and it'll suggest, hey, why don't we just do that for you?
01:55 Things like that.
01:57 And so this integrates all the Ruff functionality into that same basic UI system.
02:04 You get little warnings or errors on the screen based on Ruff output.
02:09 So it has inspection and highlighting.
02:11 It can set it up so it runs Ruff on your code when you run reformat code or just hit the hotkey, Command Alt L, Control Alt L.
02:18 It has the quick fixes that I was just talking about, and it will actually run, you can run Ruff --fix as an action, and you can even run that when a file is saved just automatically.
02:29 If there's stuff wrong with it, just fix it Ruff, just do that for me.
02:32 You can configure which version of Ruff is running.
02:35 So basically, the plugin lets you specify, do you use a global one, maybe managed by pipx, do you use a local one in a virtual environment, I sort of feel like isolating that to a per project basis is the right thing.
02:47 So that's what I'm doing, playing with this.
02:49 And yeah, you can run it as a new process.
02:51 You can specify a config option, like a set YAML.
02:55 I'm not sure what the format that is, but whatever the Ruff config file format is so that you can say, you know what?
03:01 I don't really care about the line length for this thing.
03:04 So just ignore that and don't ever run that and so on.
03:08 So yeah, you can even run it out of a WSL Windows subsystem for Linux.
03:12 And there's some nice screenshots as all UI things should have in there.
03:17 You can even see some of the settings if you want to try it out.
03:19 So it has 4.8 out of five ratings and it looks pretty new, but yeah.
03:25 Anyway, I think it looks like a good option.
03:28 So people can check that out also.
03:30 - That's pretty cool.
03:31 - Yeah, I'm really excited about it.
03:32 I've installed it and gonna give it a try.
03:34 You can go check out the, it's open source, obviously.
03:36 So you can go check out basically the repo for the plugin And John sent over to us, and I'm linking to this thing where it says you can add additional PyCharm specific instructions for both black and Ruff.
03:54 So he's got this section that shows you basically how to integrate both black and Ruff at the same time as automatic code formatters in PyCharm using the file watchers plugin.
04:04 So just follow along with the steps there.
04:07 It even has knock support, but yeah, cool.
04:09 So if that sounds interesting to you, So if you want to have kind of auto-Ruff, just built into PyCharm and you use PyCharm, then check this out.
04:17 It looks cool.
04:17 Thanks, John.
04:18 Yeah, that's nice.
04:18 And Ruff, of course, is written in Rust.
04:24 And I'd like to talk a little bit more about Rust.
04:28 So there was an article I ran across called--
04:31 it's from Koblo's blog.
04:34 Don't know if that's a first name or last name, but thanks, Koblo's.
04:38 Writing Python like it's Rust.
04:40 And what I, I haven't written Rust yet, but a little bit, anyway.
04:47 The thing I liked about this article was really, basically, he's going from Rust back to Python, programming in both, and one of the things he misses is some of the safety that types give you.
04:59 So he's discovered that he's changing, or they're changing how they're using types within Python.
05:08 and I kind of liked some of the suggestions.
05:10 I think these are some of the things I didn't even think of before.
05:13 The obvious one, of course, is for function signatures.
05:17 So we really want to, if it's not obvious, like there's an example with a find item with records in check, but what is that?
05:26 What are those types of those things?
05:28 So it's really helpful to your call, the people using your API to specify what the parameters look like what you expect them to look like.
05:37 And there's so many options within Python now.
05:40 And also that to, you know, return value.
05:44 And here is an example, it's an optional item.
05:47 So I actually hadn't thought about that, of like using optional as a return type.
05:51 That's pretty cool, which means you can either, and you could probably do like item or none to say it can return none or something.
06:00 That's a, it is good to, especially if it's possible to return none, good to have that in the types.
06:08 So that's the low-hanging fruit.
06:11 That's I think a lot of people have gotten there already.
06:14 The other thing that I found recently is I've got some types that are like tuples or dictionaries or specifically a specific kind of dictionary like a string to any or even, I use named tuples a lot which are a little bit better than just your normal types, but his recommendation is to go ahead and use data classes because they're more descriptive, even if it's similar information.
06:42 You can write up a little data class and then like in the example, instead of saying that you're returning a dictionary, go ahead and return like a person item, specific types.
06:55 And I'm kind of used to that from C++ of like writing little types because they're more They're more descriptive and they're easier to read sometimes.
07:02 So bringing this into Python is kind of a cool idea.
07:06 One of the things I thought was really awesome is this idea, there's an example using these packet types.
07:15 And since I work with communications a lot, this really hit home.
07:21 A packet might be either a header or payload or a trailer. This is a Rust example.
07:27 But you can do the same sort of thing within Python to say, I can have different data types using data classes to specify what kind of information you're going to get from these.
07:38 And then you can create a union type and have that be a different name, but related to everything.
07:45 And I kind of love this idea of using a union type instead of using the ORs.
07:51 I mean, using OR for types is good too, but combining that into a union type is pretty slick.
07:58 >> Yeah, that is pretty interesting. I like that.
08:01 Is that if you're going to receive, say, a packet off a network and it had first the header bit, and then the payload, and then the trailer or something like that?
08:08 >> Yeah, or a function that takes that can count the bits in there or something like that.
08:14 It can either be a header or payload or a trailer.
08:17 You could do something different with those and having a union type is pretty cool.
08:23 Now, within it, and here's an example of how do you deal with that, you'd still with inside, you'd have to either do pattern matching or if clauses.
08:34 I've been using a lot more pattern matching lately to be able to just, this is great for you.
08:40 You take the packet type, but then you can match it against either a header or payload or trailer.
08:46 This is a really clean way to have union types and then unpack them with the pattern matching.
08:52 It's a pretty cool way to deal with that.
08:54 So, yeah, that is actually pretty clean.
08:56 That's one of the better examples of pattern matching that I've seen lately.
09:01 And this is just like a third of the article, but the rest of it does talk about different ways to basically, we have a lot of these tools within our, within Python now to make it more, to utilize data types that we're used to in other languages.
09:19 and you can kind of write some really clean looking code and easier to read, so it's nice.
09:24 - Yeah, very nice, I like it.
09:26 So Kim out there has a question in the audience.
09:29 Ryan, is there possibly some overlap with writing Python after writing a bunch of C as you do, as in same way Rust leads to some good ideas in Python?
09:38 - Yeah, well, I mean, this person's writing it from the experience of Rust, but I'm looking at it going, this is a lot of the C++ stuff that I use.
09:48 So it is, yeah, I'm looking at it.
09:52 We're actually, my team is having a lot more fun with Python with the pattern matching statement because the, I know it can do a lot more stuff, but it really does, even if you're just using it to get away from a long list of if clauses and make it more like a switch statement, it is so much nicer.
10:13 It's one of the little easy bits.
10:16 - That's a good example.
10:16 Yeah, Marco out there says, "Been thRuff a lot of rust, "missing mismatch." As well.
10:22 All right, shall we move on?
10:23 - Sure.
10:25 - All right, well, go ahead with your first, I know you had an announcement as well, you wanted to give out.
10:30 - No, I was just wondering, do we wanna, today's episode is not bRufft to you by an external sponsor, but it's bRufft to you by us.
10:38 - It is bRufft to you by us.
10:40 - And I'd like to hear some of the news from Michael.
10:43 - Well, the big news for me, which I have put in as an extra now and then is the mobile apps.
10:50 People go out there, download the mobile apps, talkbython.fm/apps, and in there, if you create an account or log in with your account, at a minimum, you'll find six different courses that are free.
11:01 Just tap on them and you can take those courses right away within the mobile apps.
11:05 If you get this super, super quickly, if you're one of the very, very prompt listeners, there's a chance that our Git course actually is free as well as part of a celebration of the mobile app launch, but that lasts for about eight hours from the time of recording, which will be a few less hours from the time I actually released this to the general public, not in a live stream, so you'll have to act fast on that one.
11:29 But do check out the mobile apps if you're interested in Python courses.
11:33 They're a great way to take it.
11:34 They have some free ones, and they also are the best way to take ones that you paid for as well.
11:38 So four months of work, finally really, really nice apps that we got out there.
11:44 I'm listening to a couple, watching and listening to a couple courses right now.
11:48 Not right now, but in some of my free time.
11:52 I love the mobile app, it's working great.
11:54 - Awesome, thanks.
11:55 And you also have a thing to shout out as well, right?
11:57 - Yeah, I wanted to let people know I wrote a book.
12:01 No, you all know that.
12:03 But the exciting bit, I just got this email this morning.
12:06 So my book, Python Testing with PyTest, second edition.
12:10 I've had a lot of great feedback of saying, I didn't, people saying they read the first one and it was good, but the second one really nailed, they really got some of the concepts in.
12:21 So I'm glad that I wrote the second.
12:23 So the news, I just got this this morning, an email from Pragmatic saying that there is a sale right now.
12:30 So there's a whole bunch of other books, but Python Testing with PyTest is one of them.
12:34 And if you use the coupon code SPRING2023, and you can save 50% off of the e-book.
12:42 and that expires June 1st, so don't delay, spring 2023.
12:47 - Awesome, spring into some testing.
12:49 - Well, that's us, how about a new topic?
12:54 - Yeah, thank you everyone for supporting the show by supporting our work.
12:58 Let's talk about pip.
13:00 So this is about a month old, I've been looking to grab a slot to talk about it, but there's been other sort of higher important stuff, but I do wanna point this out.
13:09 So Zertex over on Reddit, who if you follow over to the GitHub and then from GitHub, I think to Twitter, maybe named Damien, not entirely clear, so I wanna give credit, but it's not easy to do, says that pip 23 or points out that pip 23.1 was released with massive improvements to backtracking.
13:29 And backtracking is an algorithm that is part of the requirements resolver.
13:34 So if you say, you know, pip install requests, Flask and you know, something else.
13:40 pip has to say, okay, well, we know what those are, but both requests and Flask may depend on some library.
13:48 I don't think that's true, but I don't think there's an intersection there, but you know, follow along.
13:51 If they did, then it's got to figure out, well, okay, Flask requires this range of versions and request requires that range.
13:59 So let me find a version that will satisfy both of those requirements, right?
14:03 And there might be a transitive dependency upon that, right?
14:07 Like that shared, potentially shared library itself has another thing that it depends on.
14:13 So the article or not article, Reddit post says, for example, let's say you require packages A and B, the latest versions of A and B are downloaded, pip checks their requirements, and it finds that A depends on C version two, but B depends on C version one.
14:27 And so it's got to figure out like, well, can I go back and get a older version of A that would allow, say, C equals one to work, right?
14:38 So prior to pip 20.3, the default process would allow pip to install conflicting requirements with a warning saying that this may or may not go well, we couldn't find one that was a good fit, but that's no longer an option.
14:52 I have very mixed feelings about that.
14:54 I love that it tries to be more strict and correct, but at the same time, the alternative or the trade-off is we guarantee correctness 100% of the time in terms of a version match for all the transitive dependencies across all the different things.
15:11 And instead of saying, we'll install something that doesn't work or may not work because there might be some functionality that you may or may not interact with that is incompatible version-wise, we're just gonna say, your application cannot run.
15:23 It's impossible for your app to use these dependencies and run.
15:26 Personally, I would prefer to say, huge warning, this is not a great idea, but at least you can take a shot at it rather than it's impossible for you to run this application.
15:34 But that's the trade-off pip made, and because of that, it has to be even better at tracking down these version matches as best it can, because the alternative is your application cannot be installed and run.
15:49 So there's a lot of interesting history here, but it talks about some of the algorithms that have been used, and points out that Pip now separates out the resolution logic to a library called ResolveLib, and it was discovered that there was an error, logical error, that both for performance and for correctness as well, better backtracking technique called backjumping and an actual error that were fixed and implemented in ResolveLib and now come out in 23.1.
16:19 So if you're using PIP, and if you're listening to us, there's a real good chance that you are, you wanna upgrade your pip to 23.1 or higher.
16:28 I, whenever I install requirements, I just have like a multi-step macro or alias.
16:35 The first thing it does is say, pip install dash dash upgrade pip.
16:39 Now go try to do the other stuff.
16:41 You know, it's like a concept for me, but I know not everyone does that.
16:44 So when you see that little warning that says, hey, warning, your pip is out of date.
16:49 If it's less than 23.1, you probably wanna take, take the advice and update it this time.
16:56 Yeah, just this morning I got a message.
16:58 Sorry, we cannot install your website because some, you know, Sentry requires this version of EuroLib 3 and request requires a different version of EuroLib 3.
17:09 So you can't run your app, goodbye.
17:11 It's like, come on.
17:12 I'm sure that it's not actually using the conflicting.
17:16 And one thing that this does point out here is, traditionally, people haven't had to worry about this.
17:22 So they'll, you'll see things like, one of the dependencies will say, It has to be exactly like 1.2.3 when really what it means is it's got to be lighter than 1.2, you know, and they've just pinned it overly tight.
17:38 And you end up with this crash where, you know, for, for sure that it wouldn't actually be a problem in your situation.
17:45 Like how do you know?
17:46 Well, because before pip 20.1, it was running, you know, those kinds of things.
17:50 And so there's this little bit of, you know, I know it was great that is trying to be more accurate and precise, but sometimes I'd rather have at least an option than none.
17:59 And so, I don't know, it's, there's a whole interesting discussion down here.
18:02 People can check it out in the comments.
18:04 There, it devolves into a debate about Python two to three for a little while, which is weird.
18:09 And then just skip that.
18:10 That's not productive reading, but there's some interesting conversations going on there.
18:14 And also before we move on really quick, Brian, there is, I think it's Damien as I said, points out that there is a PEP 658, which is accepted for what version of Python is this?
18:30 I don't know, the 2021.
18:31 So a couple of versions ago that allows the metadata.
18:35 It used to be that pip would actually have to download and install a package just to see what the dependencies were.
18:41 Now that's separated out the metadata so you can get a very simple small download without trying to do stuff to it to go, What does this actually need? This version needs what?
18:49 Right? So there are some improvements that are being bRufft into here, but still, there we have it.
18:53 Yeah, a couple of comments, which I kind of agree with, it'd be from Grant.
18:59 It'd be nice if there was a warn unresolvable or something to keep the old behavior.
19:05 I agree with Grant on that, yeah.
19:07 So I guess this is a reminder to library authors as well, that your dependencies you might know that you have a lower limit on some dependency that you need you need version like one point two of this library or above think about it i prefer to have libraries in their dependencies the transit transit dependencies in a lower bound and not upper bound version because I mean, you don't know what the upper bound is, unless you do, unless there really is, there was a breaking change and you really know that there's a break.
19:44 >> Right. The thing for me more is about, which I agree with you, Brian, and the comments, but it's about there might be an absolute 100 percent conflict.
19:54 If this library tries to do, so for example, let's say, request tries to use Kerberos authentication instead of basic authentication.
20:03 In that scenario, this other library does something crazy, it crashes unless it's high enough.
20:08 If I'm never using that authentication mechanism, I'm never gonna, so like, yes, it is actually a break and change, but it's not a break and change for me.
20:16 - Oh yeah.
20:17 - In my use case of the combination of those two things.
20:19 Right, like that's kind of where I've been thinking about this.
20:22 - Oh yeah, interesting.
20:23 Yeah, 'cause there's a lot of like, a lot of Swiss Army knife libraries out there.
20:28 And you're not using all of them.
20:29 - Right, and you probably, it's very unlikely you're hitting 100% surface area of a thing in its dependencies, right?
20:35 - Yeah, interesting.
20:36 - Yep, yeah.
20:37 All right, well, anyway, this is an improvement.
20:40 I feel like we're kind of like debating the 20.3 debate at the field.
20:44 This is an improvement on the stuff that has already been decided to be done.
20:48 So 23.1 is a good way to go.
20:51 - Yeah, it's good.
20:52 Last item was a kind of a cool tool called Markdown Code Runner.
21:00 So this did remind me of a tool that I've known before. So Markdown Code Runner is a package that automatically executes code blocks within a Markdown file.
21:11 It can include hidden code blocks, so you can have the code blocks can be in comments, and so you can't see the Markdown file. It just runs it.
21:21 So it runs the snippet, and then you can have the output show up somewhere.
21:25 So this, in the example, let's run to an example.
21:30 You've got a little code block that says Python, but instead of just Python, you say, you know, you got your back ticks and then you say, Python space markdown-code-runner.
21:41 And then it runs the code in the code block.
21:43 And then it pops it out. You've got another couple comments for output start and output end.
21:48 And it'll throw the output in there.
21:51 The kind of the neat thing is it's not just for Python, it's for Bash also.
21:55 So you can run some Bash scripts.
21:57 Like if you want to show a...
21:59 I was thinking if you wanted to show what the directory looked like with the tree command, you can go ahead and run tree within a markdown file and run it or other stuff.
22:11 Has several examples that they think would be neat.
22:16 Things like, I don't know, like diagrams or tables or various things that you might want to output with Python visualizations, you can use that.
22:27 >> That's really cool.
22:28 It did kind of remind me of cog, but the syntax is a little different.
22:33 So cog from Ned Batchelder is a similar sort of thing. You throw some code in place with some special tags.
22:41 He uses like three bracket tags instead of an actual code block.
22:46 So the thing I kind of like about this is a lot of times I actually do want to show the code block.
22:52 So you can go ahead and show the code block and then run it.
22:55 So that's neat.
22:57 Some some it's fun. I tried it a little bit.
23:00 There's an example of using rust so you can have actually running rust also. I couldn't get the rust example to work, but I got the the markdown in the or the the Python and the the bash examples to work. So actually pretty cool. Within the documentation it also talks about running this as a GitLab or yeah, GitHub CI snippet.
23:25 That'd be a great place to do it is to just rerun, reproduce the code output from your readme on the new code. Cool idea.
23:34 >> Yeah. My first thought was, I have a code example and it says the output is this, rather than trying to maintain those, just let it put the output there.
23:42 But it also could be useful for just, I have a little Python bit of code that generates some other output that is useful.
23:50 like here's the go thRuff and generate a little all the topics that it saw in the sub directory or something like that.
23:56 - Oh yeah.
23:57 - Yeah, like kind of just a markdown, like a macro within a markdown.
24:01 - Generated table of contents or something.
24:03 - Yeah, exactly.
24:04 Something like that.
24:05 - Cool. - Cool.
24:06 That's all of it, right?
24:07 That's all the main topics?
24:08 - That is our main topics, yes.
24:10 - All right, I have a few extras to throw out here.
24:12 Let's jump over there real quick.
24:15 So same person who pointed out the Ruff plugin, John Hagen also pointed out, I had talked previously about how I wish PIP would update itself when I create a virtual environment by default.
24:29 So if I say Python 3-M VNV, VNV, the very next thing after activating it is your pip is out of date.
24:36 I'm like, ah, geez, okay.
24:38 So hence that's partly why my first thing to do is always upgrade it is just to not see the warning more than anything, honestly.
24:45 But pointed out that since Python 3.9, there's an additional option you can pass to the virtual environment creation story.
24:55 So instead of just dash mv and v in a directory, you can also pass dash dash upgrade depends, which will automatically do that upgrade of pip and dependencies as well.
25:07 pip set up tools to the latest version as part of creating the virtual environment.
25:11 - Sweet.
25:12 - Yeah, so nothing major, but quite nice, right?
25:15 >> Yeah. I mean, I usually have that as a second step within my little macro.
25:19 >> So do I. I was looking to replace that.
25:23 I'm like, you know what? Not quite, because I also want to install things like pip-tools and a couple of other things that this doesn't include.
25:32 So I'm like, I still would have to write that line, so I'll just leave it. But anyway, still it's really nice to have --upgradeDepth.
25:38 You want it to have a shiny new virtual environment all the time.
25:42 >> Yeah. One of the things I really love that came in a few versions ago is if you do the dash dash prompt and give it a dot, it uses the directory name.
25:51 >> Yeah, that's really excellent. It names the virtual environment containing directory names.
25:56 So it has the name of the virtual environment is the name of your project often, which is great.
26:00 >> Yeah.
26:01 >> All right. More things, more extras.
26:04 One is PyCon South Africa.
26:07 PyCon ZA will be held in Durban.
26:11 And the most important part here is that the call for proposals is out.
26:19 And when is the timeframe?
26:22 Kim will have to let us know.
26:23 I know he's out in the audience, but yeah.
26:26 Oh, here we go.
26:26 Talks need to be submitted by August 18th, 2023.
26:31 And it's pretty good.
26:32 I think it's both virtual and in-person.
26:36 So some good options for people to attend and down in October.
26:40 And it's pretty convenient for Africa, Europe, much of Asia, although less so for you and me, Brian.
26:46 That's all right.
26:48 - That's all right.
26:49 - Yeah, cool.
26:50 So people, if they wanna talk at PyCon South Africa, be sure to submit that talk.
26:57 And Kim says that's a soft deadline, but sooner is better.
27:02 - Okay.
27:03 - Generally true.
27:03 - I got a friend that's in the cybersecurity area and he's up all night anyway.
27:09 So maybe-- - Yeah, there you go.
27:10 So yeah, you could definitely do it if you just live off hours.
27:14 - Yeah.
27:15 - Real quick follow up from something before, Brian, and then we'll get to a joke.
27:18 I had put out a call to everyone and say, "Help me find some off-road trails "for this adventure bike thing that I got into." I didn't really get any feedback.
27:26 So I'm gonna instead pay it forward to other people out there who might be listening on a ride.
27:30 So some really cool apps on X, off-road, you can go thRuff and find, you just click a spot on the map and it'll show you like, here's all the public legal trails for you to go tear around on and they're even rated like five out of 10 or seven out of 10 with pictures and distance and challenges.
27:46 So you can decide upfront whether or not you want to go down that path, I suppose.
27:52 There's also a GAIA, G-A-I-A, which is a similar thing.
27:57 And then back country discovery roads, which allow you to find like, how do I traverse my state, at least in the US or similar things in Europe with a TET.
28:07 How do you say traverse all of Oregon, almost 100% off-road thRuff the forest and the mountains and the deserts.
28:12 And so there's this app that has all these GPS trails.
28:15 So anyway, I found some cool trails way up in the mountains using this app and can recommend it to people.
28:21 - Neat, cool.
28:22 - Yeah, cool.
28:23 All right, a joke.
28:24 You got a joke for us.
28:25 - Yeah, I can't remember where I found this, but there's a website called userinyourface.com.
28:34 So instead of user interface, user in your YER face.com.
28:39 So you just have to fill it out.
28:42 - Like an anti-pattern, a whole combination of anti-patterns into one UI.
28:52 - Okay, so just start off right off the bat.
28:55 So for people listening, I'm sorry, you're gonna have to watch this on the video or something.
29:00 - Or visit the link.
29:01 - Or go visit the link.
29:02 It says, "Hi and welcome to User Interface, a challenge exploration of user interactions and design patterns.
29:10 To play the game, simply fill in the form as fast and accurate as possible with a button that says, 'No,' big green button." So it says, "Please click, underscore, underlined click here to go to the next page and the next page is highlighted." And the trick is, the only thing that you can click on is the here button.
29:31 It's not a button, it's just, that's it.
29:37 Is that a problem for you?
29:38 Yes, and yes, doesn't do anything.
29:41 Okay, no, not really.
29:42 That goes away.
29:43 Can we help?
29:44 There's a help field with no enter.
29:49 Just send the bottom.
29:50 - What are those dreadful chat messages that pops up?
29:53 - Yeah, it's great.
29:55 Choose your password, you click on it, And the highlighted choose your path or the preview text is already there.
30:04 So if you add your password to it, it doesn't delete the old one.
30:08 You gotta like fill that out.
30:11 Oh, you can't tab thRuff anything.
30:12 So you have to click, oh, the email's bad too.
30:15 - Yeah, instead of a placeholder, it's just gray, actual gray text.
30:18 - Yeah, but you also can't delete it.
30:21 Domain, oh, this one you have to delete also.
30:27 And oh, there's a hurry up time is ticking.
30:31 A pop-up, one minute before.
30:34 Can I hit the, oh, the X isn't an X, it's a maximize button.
30:39 Lock? - The copyrights are closed.
30:42 - Lock, unlock, this doesn't do anything.
30:44 Oh, the close is the copyright, right?
30:46 That isn't obvious.
30:49 Yeah, okay.
30:50 I do not accept these terms, okay.
30:52 Cancel, oh, I'm not, no, I meant okay.
30:56 You sure you want to cancel?
30:57 Cancel, cancel.
31:00 Oh, it says already selected.
31:03 I do not accept.
31:04 So you have to uncheck it to accept the terms and conditions.
31:07 What are the terms?
31:09 Yeah, okay.
31:10 - Good luck getting out of that dialogue.
31:12 You got to scroll down to accept them now to get out of it.
31:16 - Okay, well, we're stuck now 'cause you can't even.
31:21 This is terrible.
31:22 Anyway, I did get thRuff it.
31:24 The fastest time I have so far is like five minutes.
31:28 - People are gonna speed run the in your face interface.
31:33 - Yeah, I'd love to see a speed run to see how fast somebody can really get thRuff it in like a couple minutes.
31:38 Please do a video, I wanna see that.
31:40 - Jeff out in the audience says, I worked for the company that made that site.
31:48 - Yeah, so yeah, the company looks like Veerheart.
31:52 So nice.
31:54 - All right, well, that's enough frustration for one day.
31:58 - Indeed.
31:59 - Thanks again for joining us and doing another Python Bytes.
32:03 Thank you everybody for watching and listening and supporting us thRuff the courses and books and everything.
32:11 And Patreon supporters, we still have Patreon supporters.
32:13 Thank you, Patreon supporters.
32:15 - Absolutely.
32:16 - And thanks, Michael.
32:16 - Thanks, Brian.