Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds.
This is episode 269, recorded February 2nd, 2022.
And I'm Brian Okken.
And I'm Luciana.
And?
I'm Brett Cannon.
And we have Brett.
So we invited Luciana on and we decided to have Brett on also.
So we got to have some fun.
Michael's actually gone this week, but I hope he enjoys listening.
So hi, Michael.
And we'll talk to him next week.
So before we get into the topics, though, I think people hopefully know who Brett is.
Brett Cannon, you've been on the show before.
A couple times.
Yeah.
Thank you very much for having me back spontaneously.
Spontaneously.
Like minutes ago, we said, hey, we should get Brett on.
So Luciana, welcome to the show.
Can you tell people a little bit about who you are?
Thank you.
Yes.
I am, well, Luciana.
I work with Brett on the Python extension for Visual Studio Code.
But I'm a program manager.
And, yeah, I'm very excited to be here on the show.
I was telling Brian that I used to listen to Python Bytes going to work back when we worked on offices.
Went to work.
So it's really, really cool to be here.
Yeah.
Nice.
Well, thanks.
I'm glad to have you here.
So let's jump into the topics.
We have an abbreviated list of topics, but we'll make it fun anyway.
I'm going to start with Rich CLI.
So, Will McGoogan.
It seems like we talk about him every show.
But this is cool.
So I was like, oh, I'll try it out first.
And I'm already hooked.
So Rich CLI is, it seems lame if I describe it.
So you install it.
I installed it with PipX because I just want to use it everywhere.
And then what it does is it does, like, pretty printing of stuff.
Like, you can give it a file.
And basically, that's what I use it for.
Maybe it does other stuff.
But you can give it a file, like, example.py or example.markdown or something.
And it will do the rich printing, pretty printing, right on your screen in the terminal.
That seems like not that big of a deal, right?
But it is so cool because it's all, like, nice colors.
And you can have themes.
And I used, what, you can do pretty printing of JSON.
So it will format your JSON for you without having to reformat it.
You can do a dash M flag for markdown.
I've been doing that to see my markdown.
And it does some cool stuff with markdown.
Although, supposedly, like, with Python files and C++ files and stuff,
it's going to do syntax highlighting based on extension.
I'm wondering why I got to pass in a dash M for markdown.
It seems like a dash MD should work fine.
But anyway.
That's actually going to be my immediate question was,
why do you have to specify the dash M just for markdown?
And then, like, and then there's some flags that's cool, like, whether or not you want to use it with pipes.
So you can, if it's pipe it to something, it'll strip out the formatting stuff, like the color codes and whatever.
But you can force that to be on.
Well, I wanted to, I tried to use it with a big file, and it just flew past me.
And then, so I tried to pipe it to more or less, and it stripped out the formatting.
And so, well, I tried to fix that, and then more and less don't handle that.
And so, and this was just yesterday.
I'm like, kind of really be cool if Rich CLI has supported paging within it.
And so today, Will said, hey, I added paging to Rich CLI.
So Rich CLI now has paging.
Of course he did.
Like, within a day.
So anyway, pretty cool projects.
Have either of you checked this out yet?
I did the exact same thing you did.
I used PipX and installed Rich CLI yesterday.
One thing is, I will say, I use a, I've actually been using a replacement.
So this is kind of like a replacement for the cat tool on Unix, right?
And I've been using an alternative called bat, B-A-T, that's implemented in Rust, and has
a lot of this as well in terms of color syntax and stuff.
But I'm willing to bet Rich is, Rich, I'm willing to bet Will's going to move a bit faster.
So I'm just going to probably switch over to using Rich CLI over bat and just see where
this goes.
But I mean, come on, Will even made the output.
It looked great.
Yeah.
Sorry for the output for the help.
It looks phenomenal.
One of the things that I noticed was that the default theme, the coloring, didn't look quite
right on the black background that I was using.
So I just, I exactly, I was using it for cat.
So I just aliased my cat to use Rich with the Monokai format turned on.
So Luciana, would you use this for anything?
Yeah.
I was going to say I'm behind.
I haven't tried it yet.
But once I saw the amazing things they have there, it's quite a few.
So I was excited to try it out.
So we'll do it today, hopefully.
Yeah.
Cool.
Well, let's switch over to debugging.
Yeah.
So I guess most folks, I don't know, at least I, when I started learning Python, I used to debug
using print statements, which is like no shame in that.
It works very well.
I still do that when it's like for real quick things.
But I wanted to bring up this awesome tool that we have, the bug pie.
It's a debugger for Python.
And you can use it like as a CLI tool.
You can also just import it and set breakpoints normally.
I'm a big fan of UI debugging.
So I actually prefer to use it built into the Python extension for VS Code, which is the
thing that we work on every single day.
So yeah, I wanted to bring up a few features that are really, really cool and I find very
helpful and that save up, helps me save up a lot of time when I'm debugging code.
So the first one of them is kind of like conditional breakpoints.
Yeah.
Sorry.
Go ahead.
No, no, go ahead.
Neat.
Yeah, it's super neat.
And this conditional breakpoints is something that I bring up because I guess when you're
trying out debugging for the first time using the UI, you set up a breakpoint and then you
hit it there and then you always reload the window or reload the bugger, sorry, to hit that
breakpoint again.
And then you keep stepping over into a hit to condition that you want.
And in this GIF there, they have an example on TypeScript, but it works on Python files as
well once you install the Python extension.
But basically you added the breakpoint to insert a certain condition so that the bugger will
only stop when that expression is met or the condition is met.
So one example there is hit count.
So you can imagine if you have like a for loop and you really want to stop when, for example,
after 10 iterations of that loop.
So you don't want to stop on that breakpoint and hit the step over 10 times.
You just want to stop when it hits 10 times.
So you can do that with the hit point.
You can also add expressions.
So if you know like, oh, I want this debugger to stop only when this variable gets the value
of, I don't know, five, then you can also do that.
And it's pretty cool.
It saves up a lot of time.
And you can also do log points instead.
If you're not interested in breaking the execution, just want to make sure that line was executed.
So it prints out on the output that, hey, this is, we hit that point.
This is like a log point.
So it doesn't really break anything.
But it's very informative.
Cool.
So this is, this is an extension for, for VS Code.
Yes.
I believe most IDEs support that same feature.
But it's a feature that I always recommend folks to look for in their IDEs or editors because
it does save up a lot of time.
So, so to be clear about the tech stack on this.
So there's a couple of layers to this.
So at the bottom layer is PyDevD by Fabio Zdrasny.
Key, we have him on contract as a consultant to do anything we need to have get fixed and stuff
and just support the project.
Because on top of this, we have another project that we have called DebugPy, which implements
what's called the DebugAdapter Protocol or DAP.
It's a, meant to be a language agnostic protocol for debuggers to talk to editors.
It comes out of VS Code.
It's used by Visual Studio as well.
And actually, it's now used by Jupyter.
This is how Jupyter was able to launch recently with debugger support.
Because they actually run DebugPy.
And then on top of that, we have support.
Because we're a VS Code extension, we support the debug adapter.
So we ship DebugPy in box right now for supporting this.
Although we are talking about breaking the extension, breaking debugging out to its own extension so that we can actually update it at a better cadence with DebugPy.
Because we can do platform-specific V6s now, extensions for VS Code.
So we'll be able to shrink that down a bit for our users.
So is there like a tutorial somewhere that has like all of the cool Python extensions that I need for VS Code to get VS Code with Python to work really great?
Yeah.
We have our Get Started tutorial.
It has like, it doesn't have a lot of extensions.
So there's definitely more extensions that I find to be personally cool.
Maybe we could have a blog post about this and like cool extensions for Python, specifically in VS Code.
Because there are some of them.
I think Don Giamani, he's the one who created the Python extension before it was a Microsoft thing.
And Microsoft Hirem and everything.
So he has one that I always talk about, which is the Python Environments Manager extension.
It just displays the environments that it can find on your machine and what packages are installed there.
It's kind of like an environment viewer.
And it's pretty cool.
It's one that I always tell people about.
You know, a deep dive into all the useful extensions to add would be a great testing code episode.
Just saying.
I love that idea.
I like it.
Okay.
Well, speaking of plugging stuff, I want to take a moment to thank our sponsor.
So this episode is sponsored by Datadog.
Datadog is a real-time monitoring platform that unifies
metrics, traces, and logs into one tightly integrated platform.
Datadog APM empowers developer teams to identify anomalies, resolve issues, and improve application performance.
Begin collecting stack traces, visualizing them as flame graphs and organizing them into profile types such as CPU, IO, and more.
Plus Datadog APM.
Plus Datadog APM's live search.
So you can perform searches across full streams of ingested traces generated by your application over the last 15 minutes.
Try Datadog APM free for a 14-day free trial.
And Datadog will send you a free T-shirt.
And actually, I have one of these purple T-shirts, and I love it.
So visit pythonbytes.fm/datadog, or just click on the link in your podcast player show notes to get started.
Awesome.
I got to pay the bills.
So where are we at now?
We're back on me again.
Unless, Brett, you got something right out of the blue you want to talk about?
I'll put you on the spot.
That's okay.
I believe you've talked about exception groups on the podcast already.
I don't.
Oh, yeah.
I think so.
Yeah.
So just because Datadog sponsor actually cares about trace packs and stuff.
One interesting thing that's coming up in terms of a PEP, it has not been given to the steering council yet.
But there's actually a PEP coming up that's going to add a Dunder notes field potentially to exceptions.
This actually came out of the exception group work because Zach from Hypothesis was working with it over on that side and realized that it would be convenient to be able to kind of just basically, literally, the name says, add a note to extensions to kind of help explain why this came about.
And so there's a PEP coming that's going to basically just allow libraries and stuff that work with exceptions to just attach a little note saying, this is why this happened.
More than just a little thing, especially for exception groups, you can kind of get kind of big and murky by having a single note added to it to help explain why this came about.
It's hopefully going to help make it easier for users to understand a bit more why something happened.
So that's pretty neat.
I like it.
Nice.
I got some feedback recently that I'm not covering enough test stuff on Python bytes.
So I'm going to try to I'm going to try to try to solve that.
I'm not going to cover test of every week, but I've got a test thing this week that I'm pretty excited about.
So Simon Willison, great guy.
He wrote an article called documenting unit tests.
And this.
Wow, it's old.
It came out in 2018.
I just noticed it.
So, yeah, there's the Internet for you.
But it's like it's a super cool idea.
So the idea is we've got tests like pytest and other test runners.
You can do anything.
He's using pytest to test your source code.
But why not?
And Python has all these introspection things you can do.
So he's using introspection to look at the code and then introspection to look at the documents with with his test code and then make some make sure that there's some items that are definitely in the docs.
As an example, so in this, this is example in the in the doc, in the blog post is mentoring data, his project data set.
And so the test for this is right there.
So you can go take a look at what he's doing.
But he takes a look at the repo.
And for instance, for all, if he adds a config option, he's got a test to make sure that the config option gets documented.
That's cool.
So it's just tests or fail if he forgets to document a new option.
Also, plug in hooks and different views within data set.
They all have to make sure that he has special the views like he wants special pages for each view.
So it makes sure that there's a page there.
So I just there's a couple neat things here.
Just the concept of using tests to make sure that there's things documented.
It doesn't tell he makes a comment that it's not telling like a lot of tests.
It's not telling you that the documents are good or documented well, but that they're documented at all, which is which is good.
And same with our code tests don't necessarily tell you that your code is perfect.
It's just that they're tested.
The other thing that I wanted to point out about this is there's some nice use of features of of py tests.
So there's a nice use of fixtures and parameterization.
So he's got like the views, for instance.
He goes out and looks at generate like goes and gets a list of views from the code and then use that list to have a generated test to make sure that each of those views is tested or is documented.
It's a nice idea.
I've been trying to do that sort of generated generated parameter lists.
I'm trying to do that more in my code because it it's just kind of a cool idea to generate your own test cases.
So anyway, good job, Simon.
Yeah, as someone who spends more time reading code and writing code, I definitely appreciate this initiative.
It's very much better to have documented code out there.
Well, a combination of like making sure that the test, the documents are tested or things are covered.
And then also, I think a few episodes ago, we talked about a project projects using generating documents themselves.
So like, for instance, instead, if you're going to plop your help text in your document, don't copy and paste it.
Use code to generate that.
And then it's always going to be correct if you got it in your build system.
So nice ideas.
And it was about using cog, right?
Yeah, that was it.
Cog, I forgot.
Yeah.
And what I really love about that is when I came across cog a long time ago, I thought, I got to have a use for this, but I can't think of it.
But this is the perfect use because we often do that within our little readme or something is just to plop a little example of code using your tool, whatever library you have.
So having cog generate that for you is great.
So I think I need to go back and do it.
So I've got a little toy project called cards that I use for teaching testing.
And I changed the interface for it for layout reasons.
The tables that I was using didn't show up in e-books very well.
So I switched the table format, but then I forgot to change the readme.
But if I had cog in place, I would already be doing it.
So it's neat.
My first thought was to write tests to make sure that the output in my readme was the same as the code.
But I think a better idea is to just have the readme generated.
So, I mean, either one works, but both are good ideas.
Yeah.
And to tie this back to this point, Simon's the one that actually started the trend on Twitter of everyone using cog to use this on their readme.
At least that's how I first came across it.
And then I subsequently saw multiple people do it.
And then I finally had the same reaction you had.
Brian's like, oh, yeah, I've been looking for a reason to use cog for ages.
I never quite had one.
I was like, this is a great one.
So I went and updated the readme for the Python launcher to use this to generate all the URLs for downloading the built binaries for it.
So it's great.
Gulf binaries?
Built.
Built binaries.
Okay.
Yes.
Because I tried to build the launcher for like a bazillion different platforms.
And I'm grateful for that because I'm using the launcher like almost every day now.
Oh, fantastic.
We are.
Thank you, Brett.
Well, so let's pop over to talking about ourselves.
Oh, that was such a good.
Wow.
I'm impressed.
Yes.
So this is a 7373 self type.
I heard from, well, Brett Cannon there that it has been recently accepted.
And it's interesting for me because I'm now learning more about types in Python.
I'm very new to it, admittedly.
And I thought it was interesting because, well, adds this way to another thing methods that return an instance of their class.
And they give a very cool example there of a class or shape and then we have circle.
Then here it's for shape.
And then shape has this method called set scale.
And then the type that returns is shape.
And because it returns self.
And for circle, it returns self as well.
So it's a type circle.
And then it shows like there are some, for example, editors that may throw in error when you call circle set scale, which is a method from shape and then set radius, which is something from circle.
But once you call them, it will say error because shape doesn't have this method that is specific to circle.
So to kind of like have this better way to frame that would be to return self.
And it was accepted.
And it's very interesting.
I feel like it seems very clean to me and a very good solution.
So I'm personally excited that it was accepted.
It was very well explained as well.
And that was real.
For people on the podcast who can't see what Brian's scrolling through, basically, think of capital S self as the return type for all those class methods you write that construct an instance of your object.
This is what this is built for, right?
It's fantastic.
If you have the from whatever method, class method on your class to construct that class from something else, you'd now have a return self with a capital S versus specifying the exact class that would have returned.
So you don't have to worry about what that's going to look like and having to worry about the spelling or any of that forward declaration problems you can have if you don't do from Dunder future import annotations, right?
Where it's like, oh, I'm referring to a name that doesn't exist yet.
And Python throws a fit because that object doesn't exist yet by that name.
So it solves a couple problems like that.
But it's it's really basically if you write class methods that construct instances of that class.
It's great.
Well, I don't, but I probably will now when this comes out.
So is this is this part of 3.11?
Do we know?
3.11, right?
Yes.
Nice.
Yeah.
So you can probably get that probably today, if not in the near future from the typing extensions package, which kind of tries to do a back port and forward port of anything in the typing world.
That's experimental or has been landed, but not in a release yet.
And I believe the type checkers.
I don't know if they all support it yet, but I'm sure very shortly they will support this.
So you can you can get to it today.
And then we get we keep people that are writing tools like flake and black on their toes, catching up with all these changes.
Well, luckily, it won't hit them because it's all typing.
So just strings to black.
And I don't think flakey don't care.
But but like my pi, pi right slash pilance, pi type, pyre, all those type checkers are the ones that have to get updated for this.
But they were all in on the discussion of even proposing this.
Nice.
But is that we repeat that?
So the all these these people writing these tools were involved with this, these sorts of type processes.
Yeah.
So the way typically decisions around typing happen, especially from a static typing perspective, not I don't want to make statements on pydantics part in the dynamic typing world, because there's kind of two parts to typing.
Right.
There's the general typing as in.
Oh, there's the concept of typing now in Python.
But there's the people who do static typing.
Right.
And that's the kind of thing where you add your type annotations, your type hints, and you run a tool later that somehow reads them offline, as it were.
Right.
Like my pi or pi right or whatever.
And then there's the dynamic typing folks.
That's like pydantic where during runtime, they actually look at the annotations.
From the static typing perspective, there is something called the typing sig.
It's a mailing list.
And all the major static type checkers all work there together to try to figure out where they want to take things and kind of what gaps there are in terms of typing.
Basically, how can they move typing forward in Python?
It's also a place people can go to ask for help if they have a generic typing question that isn't too tool specific.
But to answer your direct question, Brian, the tools that are involved there, which are basically all the type checkers, static type checkers that I know of.
So there's py write, which underlines py lance, which is what we use for our completions in VS Code.
There's my pi.
There is pi type that comes from Google.
And then there's py that comes from meta.
Okay.
Wow.
Dizzying.
Yeah.
Although, I mean, one of the nice things about all the peps, right, is this is all backed by specs.
So there's not a lot of crazy deviation, as it were, from the semantics.
It's more of a bug if someone disagrees.
So they're all pretty consistent.
But some of them do a bit more like inferencing.
Like py type does more like runtime inferencing and other inferencing to try to kind of fill in the gaps.
That's actually why Google wrote it, I think, to help them move over to Python 3, start introducing types to their code base.
Yeah.
So they all have slightly different strengths and weaknesses.
But they should at least typewise, more or less, once they've all implemented the same specs, lead to the same type outcomes, as it were.
Yeah.
Okay.
Cool.
See, I learned so much about typing just by listening right now.
Yeah.
Well, we're to the end of our normal topics.
But Luciana, do you have any extras for us?
Yeah.
So it was announced in my team that Black is no longer in beta version.
So version 2020.1.0 has come out.
So it's their first table for these, I believe.
So that's very exciting.
I really like the highlights that they have there that Python 2 is no longer supported.
Nice.
So that's a cool announcement for the week.
And the other one that I have is to remind folks about PyCascades 2022.
It's happening this weekend.
It's remote.
Tickets are on sale.
So if you're interested in joining the event, it's really awesome.
It was my first Python conference.
And the community there is just really amazing.
So again, remote, join us this weekend.
PyCascades was your first conference?
It was.
Wow.
Which one?
It was back in 2019.
Pretty recent.
Was that the Portland one?
It was in Seattle.
Seattle.
Okay.
Yeah, I guess it was the 2021 that was in Portland.
Right before everything shut down.
Yes, 2020.
It was right before it.
Yeah.
Because that was the one I had to miss because I was out of the country on vacation when it happened.
Yeah.
Not in China, I hope.
No, I was in Thailand for a friend's wedding.
Interesting.
Nice.
That was back in the day when we kept track of what countries do have COVID cases, not how many cases in every country.
So it was a different time.
Yeah.
So long ago.
So I only have like, I guess, one.
I don't have anything to show for this, but I did a couple extra things.
I wasn't going to talk about it too much, but I did notice that pip is now at 22, version 22 dot something.
It's what we're at 22.02 now.
But one of the neat things about it is there's some cool stuff around having pip vendor.
There's a couple neat things.
There's one of their vendor and some of rich.
So some of the, especially the error output.
If everything goes great, you probably won't notice much of a difference, except for maybe the progress bar if things are slow.
But the error report, if something goes wrong, like if it's building something, that's where things apparently show up really neat.
Some better error outputs.
And better error outputs are always great.
Also, interesting that they replaced Tox in their development workflow with Nox.
And I don't know if that's worth noting or not, but it's interesting nonetheless.
Yeah, I know Predun, one of the core developers of Pip, is a big Nox fan.
I'm also a Nox fan.
So I think part of that's just kind of the difference.
For those of you who don't know the difference between Tox and Nox other than the letter, Nox is a bit more of a, I would say, general task runner.
So because you can write just, it's writing just straight Python code.
So I think for projects that like to use it for like release process stuff, like on the packaging project,
Predun wrote a Nox file that has like literally a release command that will do everything you need from within Nox.
So you don't have to have a separate shell script or something else.
So it can all be in the same file that you also specify how to run your linter and how to run your tests and stuff.
That's pretty neat.
One of the things that I've, and I don't remember if there's a way to get around it or not, Tox operates in a virtual environment.
So it creates, so one of the things, the default behavior at least, creates a virtual environment and then runs whatever you're going to have it do within that virtual environment.
So like the idea being, you're going to have multiple Python versions.
So it creates a virtual environment for each Python version that you're running.
There's some stuff like this extra stuff.
Like I just want to publish now.
I'm already like, I'm already in a virtual environment because I'm always in a virtual environment.
I don't really need Tox to generate another one just to run a command.
Do you know if that sort of thing is easier in Nox or does Nox also create a virtual environment before it does stuff?
So Nox can create a virtual environment.
I can't remember if it does automatically for every command.
Putting you on the spot.
Yeah.
But it's something I'll look up then.
Ask Thea.
She can tell you.
Yeah.
Yeah, definitely.
So go ahead.
Sorry.
I was going to say that.
Speaking of pip being updated, I was trying to use it with pip-tools today.
And it seems that pip-tools is not working with the latest version of pip.
Just FYI, there's an open issue.
I'm sure the team's investigating.
But for all pip-tools users there, you're not alone.
Yeah, so the problem.
Yeah, so what so I can.
Yeah.
So what happened was is pip-tools is using the private API of pip.
And it changed.
And so pip-tools broke.
So pip-tools, if you use it, you will need to pin to a version pip 2021 or older to work with pip-tools until they figure out what they need to do to use the API.
The changes that pip made to their internal API.
And to be fair to the pip-tools team, pip 22 just came out like a handful of days ago.
So it's really new.
Yeah.
I'm a huge fan of pip-tools.
Definitely love it.
Well, one other thing actually.
Yeah, just one other thing on the new pip release for people to be aware of.
So one thing that happened here is to try to cut down on the vendoring.
Pip stopped vendoring HTML5 lib.
And now use the HTML parser in the standard library.
And that actually broke a bunch of simple repo API indexes.
For those of you who don't know the simple repo API, if you go to any URL in PyPI for a project and replace the project part of the URL with simple, you'll see what I'm talking about.
But basically, there's a spec that just says there's a PEP that says, hey, write this HTML.
And then packaging installers can read it and figure out where to find all the files and the projects for something.
It turns out a lot of people weren't following the spec.
And so a lot of these indexes broke because pip wasn't able to read them anymore because it couldn't be parsed as pure HTML.
They were doing funky things that broke.
So they, I believe, either have or are planning to roll it back with a flag to let you alternatively use HTML5 lib for now with the goal of getting all these projects that have broken output.
They don't follow the spec to fix themselves so that they can go back to not having HTML5 lib in the box.
So just a heads up, if you use an alternative package index and it suddenly broke, that's why they're working on a fix.
But I would talk to the project that creates that index for you and have them work on making sure that that project creates valid HTML5 that can be parsed by the HTML parser in the standard library.
So that going, because that'll probably go away in pip 23.
But it's not broken now, right?
It's just, it's flagged.
It was broken.
They didn't realize how much of the world was doing invalid HTML for these indexes.
So I don't know if it's in 22.0.2 or if it's going to be in the next release.
But there is an open issue where they're, where I at least was looking at where they were fixing it.
Because I got looped in because I have one of my side projects, Mouse Bender, that actually wrote some code around this originally.
There's talk about moving up to packaging.
A lot of behind the scenes stuff that people don't need to care about.
I hope that, yeah.
No, go ahead.
Well, I was just going to say, so the plan is, I think, is to add a flag to say, use old HTML parser or something along those lines for now.
So you can say, hey, use the HTML5 lib version of parsing HTML.
But it's just, just to be clear here, there will be a fix, but it's a temporary fix.
Because people should be getting after their projects that create these indexes to do the right thing and actually follow the standard.
Okay.
So as someone that got bit by this, because we have an internal PyPI caching server that also we store our own stuff on.
And we don't own it.
We like, it's a third party thing that we're licensed.
So I don't know how long it's going to be.
So hopefully that, hopefully they move quickly.
But at the same time, hopefully this extra use the old one flag or whatever will work for a while.
I was a little surprised when I saw the warning pop up of like, oh, you're not using a good, you know, it's invalid HTML.
And I'm like, what am I supposed to do about it?
Well, and I don't think the bit developers were expecting it to be so widely broken either.
Right.
It's like, what are these projects doing that are creating invalid HTML?
But apparently.
I did it all the time though.
Like, okay.
But it's fair.
It works.
If it works, it works.
It's HTML.
Yeah.
Well, and that was the problem, right?
Is the spec very, the PEP that defines it very specifically says it must be valid HTML5.
And I think it was specifically so that it could be parsed by the standard library.
So it also means none of these pages could even have been parsed by the standard library.
So I think that's what happened, right?
Is people, because people, because pip had been using HTML5 lib, which is obviously way
more lax in terms of what it can parse.
Everyone just like, oh, okay, it's good enough.
And didn't realize that the spec specifically mandated valid HTML5.
And so hopefully all these projects that got caught up can get a fix out over the next year.
Because as I said, I suspect this will be in until pip 20, pip 23, which will come out
in 2023.
So it's not like it's going to disappear in a month, this flag.
So I'll let the fix out, but hopefully everyone can kind of get caught up so that they can
get back to not vendoring HTML5.
Okay.
Before we go jump to a joke, I want one last extra is for the first time in like 18, 20 months,
I'm not writing a book.
I'm no longer writing this book.
The writing is done.
The editing is done.
So it's off to all the rest of the cogs that have to go through the process to get it.
But the ebook right now is really solid.
So anybody that grabs the ebook now, if you've grabbed it before, it's all the updates are there.
But this has got all the copy edit changes and the final edits, the rest of its layout and
stuff to try to get the physical book form.
So that's coming out sometime this month, maybe, hopefully.
So that's my hope is by the end of February, I'll have a physical copy in my hands.
Well, congratulations.
Everyone who listens to this podcast and testing code and anywhere else for you have known you
put a lot of blood, sweat, tears and love into that book.
So congratulations for reaching this book.
I just was realizing that my youngest daughter is 12.
I spent a year and a half on this book, a year and a half on the first edition.
So I've been writing about pytest in book form for a quarter of her life.
It's pretty weird.
Are you ready for a joke?
Thank you for your work, Brian.
I'm going to be ready to physical copy, hopefully.
So one of the goals of the second edition was to try to put it in a format that would be easy
to teach, easier to teach and learn.
So I'm the next step is I'm going to work on trying to teach people in person, teach people
in person and through video courses and stuff like that.
Turn this into because I know a lot of people don't read.
But you're coders.
Why don't you read?
You have to read your code.
But still, some people don't read books.
How about something funny?
Yes.
Today's joke brought to you by Luciana.
Thank you for finding something funny.
And we'll add this to the thing.
So I love this.
So for people listening, there's a picture of an ocean and you've got a really big ship.
It's called.
I don't know what's on the ship.
It's a big ship.
I don't know.
But it says, but it looks all official like and everything.
It says proper software design.
And then there's a guy on a surfboard standing up.
So it's like a wakeboard thing.
And he's holding an umbrella, getting pulled by an umbrella on a surfboard and says, whatever
I'm doing.
So it's funny.
That's how I feel whenever I'm coding.
And sometimes it feels like this going from the old days of like these huge design documents
to now.
Oh, we're doing agile.
So let's just write some ideas on some post-it notes and stick them on board and run from
it with there.
So anyway.
If it works, it works, right?
Yeah.
It's got tests, right?
Well, I think so.
It's unit tested.
It's 100% coverage.
It's good.
Let's ship it.
Perfect.
Nice.
Well, first of all, thank you, Luciana, for joining the show.
I think it's your first time, right?
Yes, it was.
My first podcast.
Awesome.
Participation.
Thank you for having me.
And thanks, Brett, for joining last minute.
Yeah, thanks, Brett.
It's always good to see you.
I'm happy to play the fake Michael for this episode.
Thanks, everybody, on the stream for showing up.
And we'll see you all next week.
Thanks for listening to Python Bytes.
Follow the show on Twitter via at Python Bytes.
That's Python Bytes as in B-Y-T-E-S.
Get the full show notes over at pythonbytes.fm.
If you have a news item we should cover, just visit pythonbytes.fm and click Submit in the
nav bar.
We're always on the lookout for sharing something cool.
If you want to join us for the live recording, just visit the website and click Livestream
to get notified of when our next episode goes live.
That's usually happening at noon Pacific on Wednesdays on YouTube.
This is Brian Okken.
On behalf of myself and Michael Kennedy, thank you for listening and sharing this podcast
with your friends and colleagues.