WEBVTT

00:00:00.001 --> 00:00:05.460
Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to your earbuds.

00:00:05.460 --> 00:00:10.800
This is episode 159, recorded November 26, 2019.

00:00:10.800 --> 00:00:12.160
I'm Brian Okken.

00:00:12.160 --> 00:00:13.080
And I'm Michael Kennedy.

00:00:13.080 --> 00:00:15.340
And this episode is brought to you by DigitalOcean.

00:00:15.340 --> 00:00:17.500
Thank you, DigitalOcean. More about them later.

00:00:17.500 --> 00:00:19.520
Michael, what are we talking about right away?

00:00:19.520 --> 00:00:24.640
You know, I'm a big fan of type annotations, and I don't know how I missed this one.

00:00:24.640 --> 00:00:26.160
I can't remember what I was reading.

00:00:26.160 --> 00:00:31.620
It was something we covered on a show recently, and it was talking about the final type annotation.

00:00:31.620 --> 00:00:33.440
I'm like, wait a minute, what? There's a final?

00:00:33.440 --> 00:00:42.740
As in, with object-oriented programming, you know, there's like abstract methods, virtual methods that can be overridden, protected types.

00:00:42.740 --> 00:00:48.660
And some of those things appear in Python, abstract method, for example, but others don't, such as protected or internal.

00:00:48.800 --> 00:01:01.020
Another thing that, until very recently, did not appear in Python is a final type, saying this class cannot be overridden, or this method cannot be overridden in a type hierarchy.

00:01:01.020 --> 00:01:02.040
But now you can.

00:01:02.040 --> 00:01:02.580
Oh, cool.

00:01:02.580 --> 00:01:06.600
And this is actually already in Python 3.8, if I'm reading this right.

00:01:06.740 --> 00:01:09.200
So, this is PEP 591.

00:01:09.200 --> 00:01:12.780
Its status is accepted, and its Python version is 3.8.

00:01:12.780 --> 00:01:16.260
So, I have not actually had a chance to test this out.

00:01:16.260 --> 00:01:19.180
But, yeah, it looks like it is part of it.

00:01:19.180 --> 00:01:26.480
And, you know, because it has to do with typing, of course, Gita Von Rossum is the BDFL delegate, which is kind of interesting.

00:01:26.480 --> 00:01:29.020
He's his own delegate, in a sense.

00:01:29.020 --> 00:01:31.120
But now the steering council is there.

00:01:31.120 --> 00:01:31.900
It's a little bit different.

00:01:31.900 --> 00:01:35.400
But, yeah, so he was part of this, and it adds a final type.

00:01:35.400 --> 00:01:38.320
So, I can say this class cannot be derived from.

00:01:38.320 --> 00:01:41.320
This method should not be overridden.

00:01:41.320 --> 00:01:42.980
And those sound pretty straightforward.

00:01:42.980 --> 00:01:50.520
But as far as I can tell from the use cases they put in the PEP, it's something that is very, very close to a constant value as well.

00:01:50.520 --> 00:01:51.000
What do you mean?

00:01:51.000 --> 00:02:03.140
So, one of the things I can do is I can put an at final decorator on a class, and then if I try to derive from it, the type checker will give me an error saying you cannot inherit from final class, whatever, right?

00:02:03.140 --> 00:02:03.520
Yeah.

00:02:03.520 --> 00:02:11.700
If I put it on a method, and then I try to have a derived class that replaces that method effectively, like implicitly overriding it, I'll get an error.

00:02:11.700 --> 00:02:14.720
It says cannot override final method foo, whatever, right?

00:02:14.720 --> 00:02:15.500
It was first defined.

00:02:15.660 --> 00:02:21.600
But I can also say that there is a variable called rate, which is final, and it equals 3,000.

00:02:21.600 --> 00:02:29.140
And if I try to set it to another value, like rate equals 300, the type checker will give me an error, say cannot assign to a final attribute.

00:02:29.140 --> 00:02:29.620
Okay.

00:02:29.620 --> 00:02:44.020
Or I can go to a class, and I can put that on a field, and if I try to change the field, like if I have a class called base, and it has a default ID, if I say base.defaultID equals something other than what it was initially set to, error cannot override final attribute.

00:02:44.160 --> 00:02:48.780
So the error doesn't say this is a constant value, you cannot do this, but it's like a constant.

00:02:48.780 --> 00:02:49.320
Yeah.

00:02:49.320 --> 00:02:50.220
Okay.

00:02:50.220 --> 00:02:50.880
That's nice.

00:02:50.880 --> 00:02:51.680
It's interesting, right?

00:02:51.680 --> 00:02:59.380
Well, I guess it totally makes sense, because overriding, like deriving from a class or something is kind of similar.

00:02:59.580 --> 00:03:06.460
Certainly changing the name, like the redefining the method in a base class is like replacing the name of it.

00:03:06.460 --> 00:03:15.060
And so the implementation seems to just catch straight up attributes as well, just probably with not much extra work, if any.

00:03:15.060 --> 00:03:15.780
Yeah.

00:03:15.880 --> 00:03:19.880
So this is all the stuff that I'm telling you, this is all type checker magic.

00:03:19.880 --> 00:03:22.240
This is not real, right?

00:03:22.240 --> 00:03:24.640
This is not runtime behavior.

00:03:24.640 --> 00:03:25.140
Right.

00:03:25.260 --> 00:03:34.880
But, you know, I suspect that tooling like PyCharm, for example, if you tried to set that, it would like turn it like yellowish and say, warning, this is a problem here.

00:03:34.880 --> 00:03:40.580
And already, if your editor tells you not to do it, your continuous integration maybe checks these things.

00:03:40.580 --> 00:03:41.640
I think you're in a pretty good place.

00:03:41.640 --> 00:03:52.120
And I think that more and more we're going to see as the years come on that people's workflow is just going to include type checkers with their code, with large projects at least.

00:03:52.120 --> 00:03:53.420
Yeah, at least with large projects.

00:03:53.420 --> 00:03:53.820
I agree.

00:03:53.820 --> 00:03:54.540
Cool.

00:03:54.540 --> 00:03:56.180
Well, I'm pretty excited about this.

00:03:56.180 --> 00:04:01.940
I was really surprised to see that was in 3.8, but I'm happy to spread the news about PEP 5.9.1.

00:04:01.940 --> 00:04:02.920
How about you?

00:04:02.920 --> 00:04:05.280
You've got some numbers that are incrementing as well, huh?

00:04:05.280 --> 00:04:06.060
Yes.

00:04:06.060 --> 00:04:09.360
So, Flit, have we talked about packaging?

00:04:09.360 --> 00:04:11.480
I know.

00:04:11.480 --> 00:04:13.460
I don't think we have enough.

00:04:13.460 --> 00:04:13.960
Not enough.

00:04:13.960 --> 00:04:14.820
Let's keep going.

00:04:14.820 --> 00:04:17.160
I'm almost positive we've covered Flit before.

00:04:17.160 --> 00:04:20.780
Yeah, we certainly discussed it, if not made it its own pure topic.

00:04:20.780 --> 00:04:21.800
We've definitely talked about it.

00:04:21.800 --> 00:04:22.120
Right.

00:04:22.120 --> 00:04:26.120
So, one of the beefs I had with Flit, which was just a minor thing.

00:04:26.120 --> 00:04:29.600
So, Flit makes it easy so that you can, like super easy.

00:04:29.600 --> 00:04:38.340
So, if you've got some code that you want to share with somebody, you just install Flit and say Flit init, and essentially it does the right thing to create a package for you.

00:04:38.340 --> 00:04:40.780
You don't have to read up on setup tools or anything.

00:04:40.980 --> 00:04:42.300
It just kind of works.

00:04:42.300 --> 00:04:43.040
Oh, that's interesting.

00:04:43.040 --> 00:04:44.880
It's like npm init, sort of.

00:04:44.880 --> 00:04:45.400
Okay.

00:04:45.400 --> 00:04:47.420
I don't know what that is, but I'll believe you.

00:04:47.420 --> 00:04:49.600
That creates a good job of like an npm package.

00:04:49.600 --> 00:04:49.940
Yeah, yeah.

00:04:49.940 --> 00:04:51.960
The news right now is Flit 2 is here.

00:04:51.960 --> 00:04:57.140
So, when initially playing with Flit, I noticed a lot of quirks with it.

00:04:57.280 --> 00:05:01.340
So, for instance, you couldn't use a source directory to put your source code in it.

00:05:01.340 --> 00:05:05.500
Your package needed to be a top-level directory or just a module.

00:05:05.500 --> 00:05:11.760
That was actually a pull request that I did to try to get the source directory added to Flit.

00:05:12.180 --> 00:05:13.080
And now it's in.

00:05:13.080 --> 00:05:13.820
So, it's in 2.

00:05:13.820 --> 00:05:15.320
But it also wouldn't play.

00:05:15.320 --> 00:05:15.680
That's awesome.

00:05:15.680 --> 00:05:16.220
Yeah.

00:05:16.220 --> 00:05:22.880
So, when playing with it now also, it used to be that it really assumed you were going to be in a Git repository.

00:05:22.880 --> 00:05:23.800
That's fine.

00:05:23.800 --> 00:05:25.580
Except for when you're just playing with stuff.

00:05:26.140 --> 00:05:27.160
Sometimes you're not.

00:05:27.160 --> 00:05:28.060
You're just trying.

00:05:28.060 --> 00:05:28.360
Yeah.

00:05:28.360 --> 00:05:29.760
I want to just try this out.

00:05:29.760 --> 00:05:31.540
I'm not committed yet to this even working.

00:05:31.540 --> 00:05:32.700
Let's just see what happens, right?

00:05:32.700 --> 00:05:33.180
Right.

00:05:33.180 --> 00:05:35.880
Flit now does work without if you're not in a Git.

00:05:35.880 --> 00:05:43.240
It determines what files to include in a package with Git stuff or with, you know, what's in Git and what's not in Git.

00:05:43.240 --> 00:05:46.220
And I don't know how it works when you're not in a Git repo.

00:05:46.220 --> 00:05:48.860
But right now, it does work if you're just playing around.

00:05:48.860 --> 00:05:51.360
If you don't have anything checked in, it still works.

00:05:51.360 --> 00:05:52.500
And that's pretty handy.

00:05:52.500 --> 00:05:55.500
I mean, I definitely want everybody to use version control.

00:05:55.660 --> 00:05:57.720
But if you're just trying this out, you can now.

00:05:57.720 --> 00:05:58.920
And it's really cool.

00:05:58.920 --> 00:06:00.540
And there's a whole bunch of improvements.

00:06:00.540 --> 00:06:04.680
I'm linking to the release notes or the history.

00:06:04.680 --> 00:06:08.820
It's just sort of, if you've tried it before and were frustrated, try it again.

00:06:08.820 --> 00:06:16.600
The caveats I'd like to say is this kind of a lightweight packaging system, it does not work for compiled code.

00:06:16.600 --> 00:06:22.080
So, it's not built yet to deal with compiled parts of it.

00:06:22.080 --> 00:06:22.320
Right.

00:06:22.320 --> 00:06:25.380
If I had like some Cython bits or something, it doesn't deal with that.

00:06:25.460 --> 00:06:25.880
It doesn't.

00:06:25.880 --> 00:06:30.280
And then there's a couple other reasons why you might not want to use this.

00:06:30.280 --> 00:06:37.780
But for, I think, the 80% case where people are just trying to share some Python code with each other, this is the way to go.

00:06:37.780 --> 00:06:38.120
Okay.

00:06:38.120 --> 00:06:39.040
That sounds super cool.

00:06:39.220 --> 00:06:40.220
Yeah.

00:06:40.220 --> 00:06:45.340
That's what I love in the second version is your email address is optional now.

00:06:45.480 --> 00:06:47.060
It used to be required.

00:06:47.300 --> 00:06:51.900
But you're not required to put an email address in PyPI.

00:06:52.260 --> 00:06:54.700
So, why require it for these tools?

00:06:54.700 --> 00:06:55.360
Yeah.

00:06:55.360 --> 00:06:56.340
That makes a lot of sense.

00:06:56.340 --> 00:06:56.840
Yay.

00:06:56.840 --> 00:07:01.660
So, now my big beef with the split not supporting source is I'm done with that beef.

00:07:01.660 --> 00:07:02.120
You know what?

00:07:02.120 --> 00:07:04.100
This is a super cool example as well, right?

00:07:04.100 --> 00:07:07.940
Like, it's one thing to just complain and say, you know what?

00:07:08.780 --> 00:07:12.340
This thing is crappy or it doesn't work the way I want or something.

00:07:12.340 --> 00:07:16.000
It's another to say, and I'll help to make a difference, right?

00:07:16.000 --> 00:07:19.300
So, like, the reason it supports it is your PR was merged in, right?

00:07:19.300 --> 00:07:19.780
That's awesome.

00:07:19.780 --> 00:07:20.160
Yeah.

00:07:20.200 --> 00:07:24.280
And it also, it doesn't add any, I didn't add any flags, didn't add anything.

00:07:24.280 --> 00:07:26.720
It's just within the init part of it.

00:07:26.720 --> 00:07:30.900
It detects that your code is in a source directory and it just uses that.

00:07:30.900 --> 00:07:31.460
Yeah.

00:07:31.460 --> 00:07:31.820
Super.

00:07:31.820 --> 00:07:32.600
Nice work.

00:07:32.600 --> 00:07:33.720
Do you know what else is cool?

00:07:33.720 --> 00:07:34.520
DigitalOcean.

00:07:34.520 --> 00:07:36.020
DigitalOcean is very cool.

00:07:36.020 --> 00:07:43.160
DigitalOcean is making Kubernetes easier with their DigitalOcean container registry and one-click

00:07:43.160 --> 00:07:43.600
apps.

00:07:43.600 --> 00:07:49.460
After building your app into Docker containers, you'll often want to store container images in

00:07:49.460 --> 00:07:52.680
a centralized location called a container registry.

00:07:52.680 --> 00:07:59.760
From there, you can pull images into a Kubernetes cluster or a VM, whether it's a development,

00:07:59.760 --> 00:08:01.820
testing, staging, or production environment.

00:08:01.820 --> 00:08:07.660
While you can post your containers' images into the open internet freely using services like

00:08:07.660 --> 00:08:12.620
Docker Hub, clearly you don't want to do that with confidential software or, you know,

00:08:12.620 --> 00:08:14.100
your own private stuff.

00:08:14.100 --> 00:08:19.220
So, DigitalOcean introduced a new managed service called DigitalOcean Container

00:08:19.220 --> 00:08:20.000
Container Registry.

00:08:20.000 --> 00:08:24.060
And it's now available in early access mode.

00:08:24.060 --> 00:08:29.200
So, DigitalOcean Container Registry is simple, private, secure, and fast.

00:08:29.200 --> 00:08:34.180
And you can get started using it by going to pythonbytes.fm/digitalocean.

00:08:34.180 --> 00:08:34.500
Cool.

00:08:35.380 --> 00:08:39.920
I feel like this next item that I want us to talk about, I feel like we talked about it

00:08:39.920 --> 00:08:42.880
before, but I went back and I searched and I couldn't find anything about it.

00:08:42.880 --> 00:08:46.240
So, if we covered it like three years ago, we're going to cover it again.

00:08:46.240 --> 00:08:48.960
Nonetheless, it deserves to be covered because it's really cool.

00:08:48.960 --> 00:08:52.760
This comes to us from Andrew Simon and it's called Pint.

00:08:53.760 --> 00:08:55.800
So, how many cups is in a pint?

00:08:55.800 --> 00:08:57.700
Or do pints go into cups?

00:08:57.700 --> 00:08:59.880
Is there, like, how many gallons go in there?

00:08:59.880 --> 00:09:05.080
And if I had to convert that to liters or milligrams, like, what would, like, I don't know.

00:09:05.140 --> 00:09:09.600
All these questions are completely unknown to me without, like, some chart and a calculator

00:09:09.600 --> 00:09:10.320
or Google.

00:09:10.320 --> 00:09:12.580
And I would suspect they are to a lot of folks.

00:09:12.580 --> 00:09:20.180
Mixing some form of units, even if they're in the same system, like meters and millimeters,

00:09:20.180 --> 00:09:21.920
can be tricky, right?

00:09:21.920 --> 00:09:30.100
So, this pint thing, its job is to basically apply units to numbers and calculations in Python.

00:09:30.760 --> 00:09:35.880
Okay, so, I'm sure you took physics and, you know, in physics or maybe even chemistry,

00:09:35.880 --> 00:09:39.820
like, your professor would tell you, like, you cannot just tell me the number is seven.

00:09:39.820 --> 00:09:41.300
You have to say seven what?

00:09:41.300 --> 00:09:47.140
You have to put units on this number or this number doesn't really tell us what the answer is

00:09:47.140 --> 00:09:48.260
or what we're working with, right?

00:09:48.260 --> 00:09:50.700
And so, pint lets you do that.

00:09:50.700 --> 00:09:52.900
It has all these different types of measurements.

00:09:52.900 --> 00:09:59.760
It has, like, energy and, you know, like, joules and it has distance and weight and all these

00:09:59.760 --> 00:10:00.580
these different types of things.

00:10:00.580 --> 00:10:01.340
Even wavelength.

00:10:01.340 --> 00:10:05.300
It'll help you, like, convert wavelength types of measurements and stuff.

00:10:05.300 --> 00:10:10.860
So, if you've got some numbers you need to add together, like, for example, it's super easy to add

00:10:10.860 --> 00:10:14.620
two meters and five inches and get the right answer in the units that you want.

00:10:14.620 --> 00:10:15.260
Oh, that's cool.

00:10:15.260 --> 00:10:16.220
Yeah, super cool, right?

00:10:16.220 --> 00:10:22.400
So, I'm linking to basically a Python document that has a TXT ending on GitHub.

00:10:23.200 --> 00:10:25.480
So, read that however you want when you get to it.

00:10:25.480 --> 00:10:26.600
It's a little unformatted.

00:10:26.600 --> 00:10:30.560
But it shows you all the different units and types of units that you can work with, right?

00:10:30.560 --> 00:10:35.680
It knows what a decigram or a decimeter is and all those different types of things.

00:10:35.680 --> 00:10:37.840
So, I just want to share a quote.

00:10:37.840 --> 00:10:40.700
It's on the homepage there that talks on the pint.

00:10:40.700 --> 00:10:41.320
Read the docs.

00:10:42.200 --> 00:10:46.820
So, it talks about the Mars Climate Orbiter.

00:10:46.820 --> 00:10:50.460
And it said the MCO has determined...

00:10:50.460 --> 00:10:55.580
This is an orbiter that went around Mars until it didn't go around Mars anymore and it hit Mars,

00:10:55.580 --> 00:10:56.520
I believe.

00:10:56.520 --> 00:10:59.540
It met Mars in an unfortunate way.

00:10:59.540 --> 00:11:06.040
It said the MCO Mission Investigation Board, MIB I'm guessing, that's what that stands for,

00:11:06.040 --> 00:11:11.420
has determined the root cause for the loss of the MCO spacecraft was a failure to use metric units

00:11:11.420 --> 00:11:16.800
in the coding of the ground software file, small forces, used in trajectory models.

00:11:16.800 --> 00:11:22.520
Specifically, the thruster performance data in English units instead of metric units

00:11:22.520 --> 00:11:25.860
was used in the software application titled SM underscore forces.

00:11:25.860 --> 00:11:28.560
Hence, orbiter meet planet.

00:11:29.080 --> 00:11:30.020
So, yeah.

00:11:30.020 --> 00:11:33.380
You know, this is not the type of code I write a lot.

00:11:33.380 --> 00:11:36.740
So, it's not directly useful for me, but I've studied science a bunch.

00:11:36.740 --> 00:11:41.300
And it seems if it is the kind of code you write, it's very simple and very powerful.

00:11:41.300 --> 00:11:47.500
Yeah, one of the things I like about it is it's not the units separate so that you can look these up.

00:11:47.500 --> 00:11:49.040
It stores the values.

00:11:49.040 --> 00:11:52.280
It just has values with units associated with it.

00:11:52.280 --> 00:11:55.780
And so, you can pass them around and use them in other places.

00:11:55.780 --> 00:11:57.860
And all the math operators work on it.

00:11:58.020 --> 00:12:02.100
And it's, I mean, if you really want to, I mean, you kind of have to know the units anyway.

00:12:02.100 --> 00:12:09.080
But one other way to do that people have often used is like suffixing variable names with what the units are.

00:12:09.080 --> 00:12:14.280
But then that's, there's nothing telling the software that it has to comply with that.

00:12:14.360 --> 00:12:17.060
It's just, it's just convention at that point.

00:12:17.060 --> 00:12:21.780
But so, if you, especially with mission critical stuff, I think this is a really great idea.

00:12:21.780 --> 00:12:22.200
Absolutely.

00:12:22.200 --> 00:12:27.820
So, the way you would create like three meters is you would create an instance of a unit registry.

00:12:27.820 --> 00:12:30.760
And then you would just take the number three times meter.

00:12:30.760 --> 00:12:31.220
Yeah.

00:12:31.340 --> 00:12:32.620
And now it's a three meter quantity.

00:12:32.620 --> 00:12:35.960
So, they override what the multiplication thing means.

00:12:35.960 --> 00:12:37.500
And yeah, it's pretty cool.

00:12:37.500 --> 00:12:37.980
That's clear.

00:12:37.980 --> 00:12:42.880
You can add different units together like meters and centimeters together and it just works right.

00:12:42.880 --> 00:12:43.860
And that's great.

00:12:43.860 --> 00:12:44.120
Yep.

00:12:44.120 --> 00:12:45.120
Nice and simple.

00:12:45.120 --> 00:12:45.460
Yep.

00:12:45.460 --> 00:12:46.220
Speaking of simple.

00:12:46.380 --> 00:12:55.580
I gotta say that the unit thing that you looked at, you linked to, it has, I didn't know this, that yada is 1 times 10 to the 24th.

00:12:55.580 --> 00:12:59.360
So, yada, yada, yada is a really big number.

00:12:59.360 --> 00:13:00.220
I had no idea.

00:13:00.220 --> 00:13:01.260
That's a huge number.

00:13:01.260 --> 00:13:01.880
How interesting.

00:13:01.880 --> 00:13:02.900
What a cool piece of trivia.

00:13:02.900 --> 00:13:03.420
Yeah.

00:13:03.420 --> 00:13:04.060
Okay.

00:13:04.060 --> 00:13:07.000
Speaking of a bunch of numbers and great things.

00:13:07.000 --> 00:13:10.200
We're gonna take a look at some pytest plugins.

00:13:10.200 --> 00:13:15.140
So, Jeff Triplett wrote an article called Eight Great pytest Plugins.

00:13:15.680 --> 00:13:18.540
And there was even some fun stuff for me.

00:13:18.540 --> 00:13:20.440
I'll just list them quickly.

00:13:20.440 --> 00:13:22.400
There's a couple that I'll highlight.

00:13:22.400 --> 00:13:23.820
So, pytest Sugar.

00:13:23.820 --> 00:13:24.680
So sweet.

00:13:24.680 --> 00:13:28.220
It's just a fun one that like changes the output.

00:13:28.220 --> 00:13:29.980
But it isn't just fun.

00:13:29.980 --> 00:13:32.000
It like changes the output so it looks kind of nice.

00:13:32.000 --> 00:13:34.400
You get green check marks and stuff instead of the dots.

00:13:34.400 --> 00:13:34.860
Add the progress bar.

00:13:34.860 --> 00:13:35.260
Yeah.

00:13:35.260 --> 00:13:35.980
Progress bar.

00:13:35.980 --> 00:13:36.560
Progress bar.

00:13:36.560 --> 00:13:41.780
But it also shows failing tests instantly instead of waiting to the end or something.

00:13:41.780 --> 00:13:42.880
So, that's nice.

00:13:42.880 --> 00:13:43.940
It's cool.

00:13:43.940 --> 00:13:45.560
pytest-Cov.

00:13:45.560 --> 00:13:53.580
It hooks into the coverage so that you can, you know, more succinctly check your coverage on your code using pytest.

00:13:53.580 --> 00:13:54.240
I use that.

00:13:54.240 --> 00:13:54.980
It works great.

00:13:54.980 --> 00:14:00.960
The next one I want to, which I hadn't heard of before, is called pytest-Picked.

00:14:01.620 --> 00:14:04.120
And this is like a brilliant idea.

00:14:04.120 --> 00:14:08.400
So, if you've ran your pytest code, you know, you think your stuff is good.

00:14:08.400 --> 00:14:11.580
But what this one does is you're working on your code.

00:14:11.900 --> 00:14:18.720
And if you're using Git, you've got modified and unstaged and uncommitted code within your repo.

00:14:18.720 --> 00:14:21.920
So, that's the stuff that probably the new bugs are in.

00:14:21.920 --> 00:14:30.760
And so, what pytest-Picked does is it only, it tests files that, it runs tests that use the files that have been changed since your last commit.

00:14:30.860 --> 00:14:31.580
That is super cool.

00:14:31.580 --> 00:14:37.020
It probably runs your test code that have been changed since your last commit.

00:14:37.020 --> 00:14:48.260
But what I would love to see, and maybe it does this, you tell me if you know, is if it would look at the coverage data and it would rerun the tests that were covered by your tests.

00:14:48.260 --> 00:14:53.280
The files that were covered by your tests but then changed, it would rerun those tests that covered it.

00:14:53.280 --> 00:14:54.420
Oh, did I get it wrong?

00:14:54.420 --> 00:14:55.300
Does it just run?

00:14:55.300 --> 00:14:57.840
I think it just straight up runs the files.

00:14:57.840 --> 00:15:00.880
It's just like if your tests have changed.

00:15:00.880 --> 00:15:03.520
Yeah, I'm pretty sure.

00:15:03.520 --> 00:15:08.660
It says the tagline is runs the test related to the unstaged files.

00:15:08.660 --> 00:15:11.020
So, not sure.

00:15:11.020 --> 00:15:11.980
Yeah, yeah, not sure.

00:15:11.980 --> 00:15:13.200
I'll have to try that one out.

00:15:13.200 --> 00:15:13.940
Report back.

00:15:13.940 --> 00:15:15.160
Yeah, we definitely got to try it.

00:15:15.160 --> 00:15:21.980
My first impression from looking at it is it runs the tests that were changed, not the code that was changed covered by the test.

00:15:21.980 --> 00:15:24.160
But, yeah, we'll report back.

00:15:24.160 --> 00:15:25.880
Both of them are interesting.

00:15:25.880 --> 00:15:27.540
They're both very interesting, yes.

00:15:27.540 --> 00:15:30.820
They're like already, I think it is a super cool idea and I love it.

00:15:30.820 --> 00:15:33.600
If it does the second thing I said, then I'll love it even more.

00:15:33.600 --> 00:15:35.820
Yeah, okay.

00:15:35.820 --> 00:15:38.440
The next one is pytest InstaFail.

00:15:38.440 --> 00:15:43.100
Modifies the default output so that failures show up immediately.

00:15:43.580 --> 00:15:48.380
Right now, if you run pytest, if you just run it with no options, you get a bunch of dots for all your passes.

00:15:48.380 --> 00:15:52.300
You will see the F for the fails, but you don't get the output right away.

00:15:52.300 --> 00:15:54.100
Like what the traceback is.

00:15:54.100 --> 00:16:02.820
And so, if you really want to like start debugging before your test suite is done, InstaFail might be the thing for you to show your failures right away.

00:16:02.820 --> 00:16:04.080
The details of your failures.

00:16:04.580 --> 00:16:14.560
Now, for people that really think that pytest is already giving you too much information, pytest TLDR is hilarious, but it's actually quite useful.

00:16:14.560 --> 00:16:19.100
And it will kind of remove some of the stuff from the pytest output.

00:16:19.100 --> 00:16:24.500
Some of the boilerplate that comes at the top and bottom and also just kind of reduces the output.

00:16:24.500 --> 00:16:25.160
It's kind of nice.

00:16:25.300 --> 00:16:27.500
And this is by Freakboy.

00:16:27.500 --> 00:16:29.200
Kenneth, I'm going to get this wrong.

00:16:29.200 --> 00:16:30.140
Keith Russell McGee.

00:16:30.140 --> 00:16:31.060
Yeah, that's it.

00:16:31.060 --> 00:16:33.500
Now, next one is pytest XDist.

00:16:33.500 --> 00:16:38.600
A lot of people think of XDist as the way to run all your tests in parallel.

00:16:38.600 --> 00:16:40.260
You can run them on multiple processors.

00:16:40.900 --> 00:16:48.820
The surprising thing is you can also run them on not just multiple processors, but multiple instruments or multiple machines.

00:16:48.820 --> 00:16:55.060
You can have them spawn into other computers to run tests, which is really cool.

00:16:55.060 --> 00:16:59.360
But you can also do things like loop on fail and just perpetual.

00:16:59.360 --> 00:17:01.320
You can just have these things just keep running.

00:17:01.320 --> 00:17:02.300
So, that's pretty cool.

00:17:02.300 --> 00:17:02.980
That is cool.

00:17:02.980 --> 00:17:06.460
Just periodically just say, try it, try it, try it until it turns green.

00:17:06.600 --> 00:17:12.280
Yeah, especially if you're actively working on a fix, why not just have that pop up whenever it's done?

00:17:12.280 --> 00:17:12.620
Nice.

00:17:12.620 --> 00:17:20.960
The last two are pytest Django and Django Test Plus are both things that will help you if you're testing Django,

00:17:20.960 --> 00:17:26.240
which is not surprising that this came from Jeff Triplett because he's a Django guy.

00:17:26.240 --> 00:17:27.300
Yeah, very cool ones.

00:17:27.300 --> 00:17:27.980
I like these.

00:17:27.980 --> 00:17:29.680
Although, I feel like you cheated, Brian.

00:17:29.680 --> 00:17:33.140
I mean, we're supposed to cover like six things each show, and here you've covered eight.

00:17:33.140 --> 00:17:34.720
Eight great pytest plugins.

00:17:34.720 --> 00:17:35.240
Come on.

00:17:35.240 --> 00:17:36.560
Like, who would do that?

00:17:36.560 --> 00:17:40.040
You know, I told you I was a sucker for link bait articles.

00:17:40.040 --> 00:17:41.260
So, listicles.

00:17:41.260 --> 00:17:42.200
Yeah, for sure.

00:17:42.200 --> 00:17:44.600
Well, the next one I have is 11 new web frameworks.

00:17:44.600 --> 00:17:46.160
Oh, and you're giving me a bad time.

00:17:46.160 --> 00:17:47.680
Not for long, though.

00:17:47.680 --> 00:17:48.940
No, I think it's great.

00:17:48.940 --> 00:17:51.140
It's cool to touch on a bunch of those little things real quickly.

00:17:51.140 --> 00:17:56.400
Now, people know that I do a bunch of web development, and I'm a fan of web frameworks.

00:17:56.400 --> 00:18:02.060
And for a long time, we had kind of the mainstays, Blast, Django, and so on.

00:18:02.800 --> 00:18:10.960
But recently, and I feel like two things, both the type hints and the async-capable ASGI servers,

00:18:10.960 --> 00:18:14.400
those two things have created just like a blossoming of all these different types,

00:18:14.400 --> 00:18:18.420
because they're like, well, if we've got to rewrite it so that it supports async and await,

00:18:18.420 --> 00:18:23.420
or if we're going to rewrite it so I can use type hints to like grab stuff out of the query string,

00:18:23.720 --> 00:18:26.040
let's just go crazy and create all these new frameworks.

00:18:26.040 --> 00:18:28.180
And well, 11 new ones is what we get.

00:18:28.180 --> 00:18:30.560
Actually, more than that, because there's some that are not listed.

00:18:30.560 --> 00:18:34.320
Some we've spoken about, some we haven't spoken about, but I've heard of,

00:18:34.320 --> 00:18:35.480
and some I've not even heard of.

00:18:35.480 --> 00:18:36.760
So it's pretty cool.

00:18:36.760 --> 00:18:38.240
I'll just go down the list really quick.

00:18:38.240 --> 00:18:40.900
One of the things that's interesting, if you look at a lot of these frameworks,

00:18:40.900 --> 00:18:43.100
a lot of them are Flask-inspired.

00:18:43.640 --> 00:18:46.680
like, you know, you create an app, and then you do app.

00:18:46.680 --> 00:18:49.740
you know, decorate app.route to define it and stuff like that.

00:18:49.740 --> 00:18:56.480
A lot of them have adopted the Flask API without actually being Flask or coming from Flask.

00:18:56.480 --> 00:19:03.060
So anyway, so the number one is Sanic, which is a web server framework meant to go fast.

00:19:03.060 --> 00:19:06.680
And this one is mostly focused around enabling async and await.

00:19:06.680 --> 00:19:08.100
That's pretty cool.

00:19:08.100 --> 00:19:13.620
Probably the most widely used, at least in terms of other projects,

00:19:13.620 --> 00:19:17.580
for the ASGI, the async type of frameworks, is Starlet.

00:19:17.580 --> 00:19:19.180
So Starlette is cool.

00:19:19.180 --> 00:19:24.680
Comes from, I believe, Tom Christie and folks who are involved with the Django REST framework.

00:19:24.680 --> 00:19:31.160
And it's a lightweight ASGI framework, which is great for high-performance async and await services.

00:19:31.160 --> 00:19:36.240
And you can either use it as its own web framework, or it's interesting as a foundation.

00:19:36.240 --> 00:19:39.320
For example, Responder is built atop it.

00:19:39.320 --> 00:19:41.560
I believe FastAPI may be as well.

00:19:41.560 --> 00:19:42.220
Yeah, I think so.

00:19:42.220 --> 00:19:42.500
Yeah.

00:19:42.500 --> 00:19:45.160
So there's a bunch of things that are derived from it.

00:19:45.160 --> 00:19:45.920
That's pretty cool.

00:19:45.920 --> 00:19:47.620
And both those first two are Flask-like.

00:19:47.620 --> 00:19:52.700
A Masonite I had, Joseph, from the Masonite team on Talk Python not long ago.

00:19:52.700 --> 00:19:53.680
And it's interesting.

00:19:53.680 --> 00:19:57.180
This is not an async and await framework.

00:19:57.180 --> 00:20:00.580
It's like a standard framework like Flask or Django, at least at the moment.

00:20:01.000 --> 00:20:08.240
But what makes it unique is it has this command line tool that lets you do things to the project called Craft.

00:20:08.240 --> 00:20:11.700
So the Craft CLI is like what makes this kind of unique.

00:20:11.700 --> 00:20:14.560
That was a really good episode with that interview.

00:20:14.560 --> 00:20:22.880
And I like the example of somebody bringing in good ideas from other languages and helping out the Python community with that.

00:20:22.960 --> 00:20:23.360
Yeah, thanks.

00:20:23.360 --> 00:20:23.800
I agree.

00:20:23.800 --> 00:20:25.340
It was definitely fun to talk to Joseph.

00:20:25.340 --> 00:20:31.260
So, for example, like with a lot of these projects, you create the project and then you're on your own, right?

00:20:31.260 --> 00:20:35.620
It's like, okay, well, I use maybe cookie cutter or some other technique to create the project.

00:20:35.860 --> 00:20:38.300
And now I've got to write every little bit.

00:20:38.300 --> 00:20:44.560
But with Masonite, you can actually go and say, now add this model or go add, you know, these other things.

00:20:44.560 --> 00:20:49.460
And it'll continue to like let you evolve it using these sort of starter cookie cutter type things.

00:20:49.460 --> 00:20:50.320
So it's cool.

00:20:50.320 --> 00:20:51.400
FastAPI.

00:20:51.400 --> 00:20:55.300
If I was building an API these days, I would definitely, definitely look at this.

00:20:55.300 --> 00:21:00.860
Fast modern framework for building APIs with Python 3.6 based on type hints.

00:21:00.860 --> 00:21:01.540
That's cool.

00:21:01.540 --> 00:21:02.520
Responder.

00:21:02.520 --> 00:21:03.780
This is from Kenneth Wright.

00:21:03.880 --> 00:21:13.360
It's based on Starlette and its primary reason for existing is to bring the niceties both from Flask and Falcon over into a single framework.

00:21:13.360 --> 00:21:13.840
That's cool.

00:21:13.840 --> 00:21:21.340
Molten, which is a minimal, extensible, fast framework for building HTTP APIs with Python.

00:21:21.340 --> 00:21:23.800
And it's sort of magic.

00:21:23.800 --> 00:21:28.600
One of its magic things is it can automatically validate requests according to schemas.

00:21:28.600 --> 00:21:29.760
So you're building an API.

00:21:29.760 --> 00:21:30.980
It takes a JSON document.

00:21:30.980 --> 00:21:34.940
It can validate that by saying this is what this method takes.

00:21:34.940 --> 00:21:38.120
It takes an integer and it has this thing in the JSON document and so on.

00:21:38.120 --> 00:21:38.820
It's pretty cool.

00:21:38.820 --> 00:21:42.120
Jopronto, another one of the async and await frameworks.

00:21:42.120 --> 00:21:45.280
This one's based on uvloop and Pico HTTP parser.

00:21:45.280 --> 00:21:46.720
So it's super, super fast.

00:21:46.720 --> 00:21:48.800
Like basically its foundation is all C.

00:21:48.800 --> 00:21:49.780
Klein.

00:21:49.780 --> 00:21:50.880
Have you ever heard of Klein?

00:21:50.880 --> 00:21:51.500
No.

00:21:51.500 --> 00:21:52.220
Me either.

00:21:52.540 --> 00:21:55.320
But apparently it's a micro framework for Python.

00:21:55.320 --> 00:22:00.620
And it's incredibly, it's got an incredibly small API like bottle or Flask.

00:22:00.620 --> 00:22:02.640
Speaking of Flask, there's Cort.

00:22:02.640 --> 00:22:06.720
This is the one that's closest to Flask because it is literally a superset of Flask.

00:22:06.720 --> 00:22:07.960
It's so compatible.

00:22:07.960 --> 00:22:11.080
It even takes like Flask extensions and just runs those.

00:22:11.320 --> 00:22:15.200
But the difference here is, is it adds async and await to Flask.

00:22:15.200 --> 00:22:19.060
So if you have a Flask app, you do a find and replace the word Flask with Cort.

00:22:19.060 --> 00:22:21.100
And now you can use async and await and Flask.

00:22:21.100 --> 00:22:21.840
That's pretty cool.

00:22:21.840 --> 00:22:22.300
That's cool.

00:22:22.300 --> 00:22:22.960
Blacksheep.

00:22:22.960 --> 00:22:24.340
We talked a little bit about that.

00:22:24.340 --> 00:22:27.900
This one is inspired by Flask in ASP.NET Core.

00:22:27.900 --> 00:22:35.680
One of its bits of magic is it automatically supports binding request values into variables,

00:22:35.680 --> 00:22:37.580
either by convention or type annotation.

00:22:37.580 --> 00:22:43.140
So I could have a view method and it takes a username and it takes a product ID.

00:22:43.140 --> 00:22:48.440
And I could put a little decorative that says the username comes from, I don't know, a cookie or something.

00:22:48.440 --> 00:22:52.060
And the product ID comes from the query string.

00:22:52.060 --> 00:22:55.960
And it'll automatically go and pull those all together and just pass them as arguments.

00:22:55.960 --> 00:22:57.080
That's pretty cool.

00:22:57.080 --> 00:23:01.440
And finally, wrap this up, is Cyclone.

00:23:01.440 --> 00:23:05.640
Another one I have never heard of, but it's a framework that implements the Tornado API

00:23:05.640 --> 00:23:12.140
and the Twisted protocol to bridge Tornado's Elegant API and Twisted's Event Loop, enabling

00:23:12.140 --> 00:23:13.760
a vast number of protocols.

00:23:13.760 --> 00:23:14.660
So very, very cool.

00:23:14.660 --> 00:23:15.080
Yeah.

00:23:15.080 --> 00:23:18.400
So unlike my list, you should not use all of these at once.

00:23:18.400 --> 00:23:19.200
No.

00:23:19.200 --> 00:23:19.700
Yeah.

00:23:19.700 --> 00:23:20.760
Your list would be great.

00:23:20.760 --> 00:23:24.320
If you try to use all these at once, yeah, you're just going to mess things up.

00:23:24.320 --> 00:23:24.840
It's not good.

00:23:24.840 --> 00:23:26.360
Like pick one or maybe two.

00:23:26.360 --> 00:23:30.880
Maybe if you have APIs and you've got a web framework, but you probably don't even need

00:23:30.880 --> 00:23:31.320
to do that.

00:23:31.320 --> 00:23:31.960
Just pick one.

00:23:32.360 --> 00:23:35.100
Or you could end up with like crashes and exceptions.

00:23:35.100 --> 00:23:36.740
All sorts of error messages.

00:23:36.740 --> 00:23:37.060
Yeah.

00:23:37.060 --> 00:23:42.340
And one of the things that there's an application I'm thinking of doing that I assumed I would,

00:23:42.340 --> 00:23:45.920
I don't want to do, go crazy with the micro, micro architecture.

00:23:45.920 --> 00:23:47.260
What are those things called?

00:23:47.260 --> 00:23:48.220
Micro frameworks?

00:23:48.220 --> 00:23:52.520
Not the micro frameworks, but like the whole bunch of microservices.

00:23:52.780 --> 00:23:53.060
That's it.

00:23:53.060 --> 00:23:53.480
Oh, yes.

00:23:53.480 --> 00:24:00.160
However, things like FastAPI and stuff make it so easy to write the API part that I am

00:24:00.160 --> 00:24:06.560
thinking about doing like a two, two level thing of doing a FastAPI and then a, and then

00:24:06.560 --> 00:24:08.220
a web interface based on that.

00:24:08.220 --> 00:24:09.880
It's just two services.

00:24:09.880 --> 00:24:11.020
It seems totally reasonable.

00:24:11.020 --> 00:24:11.320
Yeah.

00:24:11.320 --> 00:24:12.160
It seems fine.

00:24:12.160 --> 00:24:16.820
And with engine X and stuff, you can put it under the same domain and just put like proxies

00:24:16.820 --> 00:24:21.200
to different parts of your app based on like slash API or not slash API.

00:24:21.200 --> 00:24:23.200
Oh, cool.

00:24:23.200 --> 00:24:24.580
So the deployment is really easy.

00:24:24.580 --> 00:24:26.040
It's a good thing I have friends like you.

00:24:26.040 --> 00:24:26.460
Yeah.

00:24:26.460 --> 00:24:27.300
Yeah, that's right.

00:24:27.300 --> 00:24:28.220
Happy to help.

00:24:28.220 --> 00:24:31.280
So next up, I want to talk about exceptions.

00:24:31.280 --> 00:24:33.540
Like I am exceptional and you're exceptional.

00:24:33.540 --> 00:24:34.580
We're all exceptional.

00:24:34.580 --> 00:24:35.880
Everyone's special.

00:24:35.880 --> 00:24:36.680
We're all snowflakes.

00:24:36.680 --> 00:24:37.380
Yes.

00:24:37.380 --> 00:24:43.040
This is a nice article that just came out this November called raise better exceptions

00:24:43.040 --> 00:24:43.740
in Python.

00:24:43.740 --> 00:24:49.900
So this is just sort of a, I guess, kind of like a public service announcement, actually

00:24:49.900 --> 00:24:54.960
kind of a nice article though, about when you're raising exceptions, it's, you know, you

00:24:54.960 --> 00:24:59.500
throw an assert in sometimes to be like that.

00:24:59.500 --> 00:25:04.680
I should really never get here, but exceptions are not really unexpected things.

00:25:04.820 --> 00:25:07.600
There, you should be, your software should handle it.

00:25:07.600 --> 00:25:12.140
It's really bad if you're, if your software is not handling exceptions at the top level.

00:25:12.140 --> 00:25:18.460
However, often exceptions will happen if like you're raising from a trial, you try some stuff,

00:25:18.460 --> 00:25:23.580
you grab a value error or something, and then you raise a more meaningful exception.

00:25:23.580 --> 00:25:26.300
That's a pattern that's often used.

00:25:26.300 --> 00:25:40.780
The article's really pointing at just don't put like f-strings with value stuff within your, just all within one string as a value error or any sort of, just don't just like try to bundle it all together.

00:25:40.780 --> 00:25:49.260
The point is most exceptions, unless you've mucked something up in the init, most exceptions take a unlimited number of parameters.

00:25:49.480 --> 00:26:03.480
So if you want to raise an exception with a whole bunch of values for your exception handler to, to be able to introspect and use, just put them in, put them in more parameters in the list of the constructor to the exception.

00:26:03.480 --> 00:26:04.160
That's super cool.

00:26:04.160 --> 00:26:05.780
And I honestly, I didn't know about this.

00:26:06.080 --> 00:26:13.820
This is great because to the example is if I raise a value error and the message is the value is too small, it's like, okay, great.

00:26:13.820 --> 00:26:14.840
So now what?

00:26:14.840 --> 00:26:20.980
Maybe you can't even get back to like what the value was because the way, you know, it got passed around or it wasn't in a variable.

00:26:20.980 --> 00:26:23.400
So what can you like report on that value?

00:26:23.400 --> 00:26:24.560
Could you log the value?

00:26:24.560 --> 00:26:25.820
Whatever, right?

00:26:25.820 --> 00:26:35.920
But if you can just say, here's the message, comma, thing one, thing two, thing three, thing four, and it just appears in the exception.args later and you can deal with it in your catch clause.

00:26:35.920 --> 00:26:36.420
It's great.

00:26:36.420 --> 00:26:36.680
Right.

00:26:36.680 --> 00:26:43.640
And some people will realize that, but not realizing that you can put them as parameters, but realize that you want to know the value.

00:26:43.640 --> 00:26:53.760
So they'll try to put the value in a string, but that depends that it depends on the wrapper function or the stir function being valid.

00:26:53.760 --> 00:26:57.040
And maybe that's the thing that blew up in the first place.

00:26:57.040 --> 00:26:58.020
So, yeah.

00:26:58.020 --> 00:26:58.340
Exactly.

00:26:58.340 --> 00:27:00.980
It's simple, but it's going to be really handy.

00:27:00.980 --> 00:27:01.480
Yeah.

00:27:01.480 --> 00:27:02.160
Love it.

00:27:02.160 --> 00:27:02.980
All right.

00:27:02.980 --> 00:27:04.060
Well, that's it for our main items.

00:27:04.240 --> 00:27:06.380
You got anything extra you want to chat about quick?

00:27:06.380 --> 00:27:07.400
Yeah, I did.

00:27:07.400 --> 00:27:10.500
It showed up on your list, but I'm going to bring it up anyway.

00:27:10.500 --> 00:27:14.920
So I was reading around on realpython.com and I came across this thing.

00:27:14.920 --> 00:27:17.160
I don't know, there was this guy that was being interviewed.

00:27:17.160 --> 00:27:20.320
It said, a Python community interview with Brian Okken.

00:27:20.320 --> 00:27:20.760
Yep.

00:27:20.760 --> 00:27:21.820
I did that thing.

00:27:21.820 --> 00:27:23.280
Awesome.

00:27:23.280 --> 00:27:23.680
That's cool.

00:27:23.680 --> 00:27:23.860
Yeah.

00:27:23.860 --> 00:27:27.480
So if people want to learn more about you, they can go check out this interview on real Python, right?

00:27:27.480 --> 00:27:32.580
One of my favorite questions and answers is the question of, how did you get into testing?

00:27:32.580 --> 00:27:35.800
And really, I never did.

00:27:35.800 --> 00:27:37.780
I've always been a software engineer.

00:27:37.780 --> 00:27:39.660
So that was a fun question to answer.

00:27:39.660 --> 00:27:40.480
That's cool.

00:27:40.480 --> 00:27:41.080
Anything else?

00:27:41.080 --> 00:27:41.440
Yeah.

00:27:41.440 --> 00:27:43.080
I got two more things I want to talk about.

00:27:43.080 --> 00:27:45.960
One of them comes from Brett Cannon, sort of.

00:27:45.960 --> 00:27:51.300
It also had you appearing on this little list of mine that I've got.

00:27:51.680 --> 00:28:02.460
So Brett Cannon put out a poll and the poll said, if you typically keep your virtual environment locally with your code, as I do, like so at the top level of your project folder, what do you call it?

00:28:02.460 --> 00:28:04.580
Is it venv?

00:28:04.580 --> 00:28:05.900
Is it dot env?

00:28:05.900 --> 00:28:07.800
Is it dot venv?

00:28:07.800 --> 00:28:08.920
Is it something else?

00:28:08.920 --> 00:28:09.860
And so on.

00:28:09.860 --> 00:28:11.780
And that's pretty interesting.

00:28:11.780 --> 00:28:13.420
You can see the polls straight up.

00:28:13.420 --> 00:28:15.780
No dot venv is what came up the most.

00:28:16.020 --> 00:28:23.540
That's what I've migrated towards these days, mostly because some of the tooling works better than the hidden ones or dot env.

00:28:23.540 --> 00:28:27.000
But, you know, you've got some replies in here and all sorts of stuff.

00:28:27.000 --> 00:28:34.260
But the one that caught my eye the most, and I think maybe you commented on it, was from Brian here, as in Brian Skin.

00:28:34.260 --> 00:28:40.240
And he said, I actually use the ability to change the prompt name, right?

00:28:40.240 --> 00:28:45.800
So normally when you activate that virtual environment, it would just say parentheses venv.

00:28:45.800 --> 00:28:46.820
And you're like, okay, super.

00:28:46.820 --> 00:28:53.220
So something somewhere in my entire computer is different about Python and but which, right?

00:28:53.220 --> 00:29:03.400
But if you do --prompt equals, you can give it a name so that when you activate it, it says, you know, like Python Bytes Web App or whatever it is you want.

00:29:03.400 --> 00:29:04.480
Yeah, I always use that.

00:29:04.480 --> 00:29:04.800
You do?

00:29:04.800 --> 00:29:05.360
That's cool.

00:29:05.500 --> 00:29:11.020
Yeah, because otherwise all my virtual environments are named venv, and that's boring.

00:29:11.020 --> 00:29:11.820
That's quite boring.

00:29:11.820 --> 00:29:12.900
So, yeah, it's pretty cool.

00:29:12.900 --> 00:29:16.840
And you can even pair that with, like, the read command and then take that.

00:29:16.840 --> 00:29:21.320
So when you create the virtual environment, you could set up a script that will ask, what do you want your prompt to be called?

00:29:21.320 --> 00:29:23.980
And then it'll just put it into the virtual environment.

00:29:23.980 --> 00:29:26.520
So when it activates it, it converts it over to that, which is pretty cool.

00:29:26.520 --> 00:29:35.940
So my request is, I haven't actually requested this yet, but I would like it to be the name of the directory that the virtual environment is in.

00:29:35.940 --> 00:29:38.440
Not the venv one, but the parent directory.

00:29:38.440 --> 00:29:41.160
Yes, that would actually almost always be the right answer, wouldn't it?

00:29:41.160 --> 00:29:43.480
Yeah, it's usually my project name.

00:29:43.480 --> 00:29:44.400
That's what I want to know.

00:29:44.400 --> 00:29:46.120
So that's what I'd like.

00:29:46.120 --> 00:29:49.800
And then Al Swigert said, I use venv.

00:29:49.800 --> 00:29:56.340
Al said he uses dot venv for the reason that you shouldn't muck with it.

00:29:56.340 --> 00:29:58.600
It's just there, but you shouldn't change it.

00:29:58.600 --> 00:30:00.920
And I'm frustrated that he's right.

00:30:00.920 --> 00:30:06.940
And I think I'm going to try using it with a dot from now on, or for at least a little while and see what I think.

00:30:06.940 --> 00:30:16.080
Yeah, the reason I like not having the dot is when I'm in the Finder, if I go over there, I can see, okay, this one already has a virtual environment set up.

00:30:16.080 --> 00:30:17.400
I haven't been on this project.

00:30:17.400 --> 00:30:18.060
It was in GitHub.

00:30:18.060 --> 00:30:19.140
It's been like six months.

00:30:19.140 --> 00:30:21.840
I come back to it like, do I need to create a virtual environment?

00:30:21.840 --> 00:30:23.140
Or is there already one here?

00:30:23.140 --> 00:30:24.000
I just go activate.

00:30:24.000 --> 00:30:24.980
In Finder?

00:30:24.980 --> 00:30:26.960
You can't see the dot files?

00:30:26.960 --> 00:30:28.000
No, it hides them.

00:30:28.000 --> 00:30:28.760
That's hidden.

00:30:28.760 --> 00:30:31.540
Oh, I guess I use command line more than anything else.

00:30:31.540 --> 00:30:31.960
Yeah, yeah.

00:30:31.960 --> 00:30:34.800
So if you want to see them in Finder, you have to go into the dot folder.

00:30:34.800 --> 00:30:37.480
And then you can say open dot or open that folder.

00:30:37.480 --> 00:30:40.080
And then it'll like be half grade out in Finder.

00:30:40.080 --> 00:30:47.340
But if you just browse to a project, you won't know whether or not it has a virtual environment if it's a dot something.

00:30:47.340 --> 00:30:47.740
Okay.

00:30:47.740 --> 00:30:51.680
Anyway, it's not a huge benefit, but that's why I kind of stopped using the dot, which I had been before.

00:30:51.680 --> 00:30:57.360
So for the subset of people that are on Macs but don't like a command line.

00:30:57.360 --> 00:31:02.220
I also like the command line, but I don't exclusively use it, right?

00:31:02.220 --> 00:31:03.040
Okay, okay.

00:31:03.040 --> 00:31:03.460
All right.

00:31:03.520 --> 00:31:06.940
Anyway, this is a whole long discussion about this.

00:31:06.940 --> 00:31:09.720
And I thought it was actually pretty interesting, all the threads there.

00:31:09.720 --> 00:31:10.080
Yeah.

00:31:10.080 --> 00:31:10.420
Yeah.

00:31:10.420 --> 00:31:10.800
Pretty cool.

00:31:10.800 --> 00:31:11.360
All right.

00:31:11.360 --> 00:31:11.800
Last thing.

00:31:11.800 --> 00:31:13.480
I told you about a new course last time, right?

00:31:13.480 --> 00:31:13.780
Yeah.

00:31:13.780 --> 00:31:16.680
Well, since then, I wrote another course and recorded it.

00:31:16.680 --> 00:31:18.840
And I think this one's going to be really fun for people as well.

00:31:18.840 --> 00:31:26.240
I wanted to write a course for people who are team leads, who are decision makers at their company.

00:31:26.320 --> 00:31:32.620
And they're trying to decide or they're working with their team to decide, like, should we adopt Python or is Python the right thing for this project or not?

00:31:32.800 --> 00:31:36.700
So I wrote a course called Python for decision makers and business leaders.

00:31:36.700 --> 00:31:44.220
If you need ammunition to help sell Python in your organization, or if you want to know, like, maybe when it's not the best choice.

00:31:44.220 --> 00:31:46.140
Like, this talks to all those things.

00:31:46.140 --> 00:31:52.640
And it also looks at, like, the job market and hiring developers and all kinds of random stuff that I think those groups would care about.

00:31:52.720 --> 00:31:54.680
So, anyway, another course is coming shortly.

00:31:54.680 --> 00:31:55.620
That's really cool.

00:31:55.620 --> 00:31:55.880
Yeah.

00:31:55.880 --> 00:31:56.160
Thanks.

00:31:56.160 --> 00:32:00.320
I might want to do an alternate course of Python for indecisive cogs.

00:32:00.320 --> 00:32:04.840
You might want to work on the name.

00:32:04.840 --> 00:32:06.720
It might not, like, attract, like, you know what?

00:32:06.720 --> 00:32:08.060
I am an indecisive cog.

00:32:08.060 --> 00:32:08.600
I will.

00:32:08.600 --> 00:32:10.580
Maybe.

00:32:10.580 --> 00:32:10.960
Yeah.

00:32:10.960 --> 00:32:11.140
Yeah.

00:32:11.140 --> 00:32:11.360
Maybe.

00:32:11.360 --> 00:32:11.660
Maybe.

00:32:11.660 --> 00:32:13.460
Anyway, it was a lot of fun to put together.

00:32:13.460 --> 00:32:15.460
And it'll be out pretty soon.

00:32:15.460 --> 00:32:15.840
Okay.

00:32:15.840 --> 00:32:16.920
You got a joke for us?

00:32:16.920 --> 00:32:17.900
I got something for you.

00:32:17.900 --> 00:32:19.200
You can tell me whether it's a joke.

00:32:19.200 --> 00:32:20.980
So this comes to us from Daniel Pope.

00:32:21.300 --> 00:32:22.120
He didn't send it in.

00:32:22.120 --> 00:32:23.100
I just found it on the internet.

00:32:23.100 --> 00:32:23.820
And it was his joke.

00:32:23.820 --> 00:32:25.940
So I'm going to, at least, it came through him.

00:32:25.940 --> 00:32:26.960
So I'm going to share it.

00:32:26.960 --> 00:32:29.600
This one is about farm implements.

00:32:29.600 --> 00:32:30.040
Okay.

00:32:30.040 --> 00:32:30.420
Okay.

00:32:30.420 --> 00:32:34.240
What is a tractor's least favorite programming language?

00:32:34.240 --> 00:32:35.020
I don't know.

00:32:35.020 --> 00:32:35.320
What?

00:32:35.320 --> 00:32:36.080
Rust.

00:32:36.080 --> 00:32:38.760
That's bad, right?

00:32:38.760 --> 00:32:40.080
Definitely a groaner.

00:32:40.080 --> 00:32:40.560
Yeah.

00:32:40.560 --> 00:32:41.920
But that reminds me.

00:32:41.920 --> 00:32:45.520
So how do you tell when a joke is a bad joke?

00:32:45.520 --> 00:32:47.040
When it's fully grown?

00:32:47.040 --> 00:32:49.200
Oh, that's a good one.

00:32:49.200 --> 00:32:49.760
I like it.

00:32:49.760 --> 00:32:51.040
Thanks a lot.

00:32:51.160 --> 00:32:51.340
Yeah.

00:32:51.340 --> 00:32:51.560
Yeah.

00:32:51.560 --> 00:32:52.180
Thanks for being here, Brian.

00:32:52.180 --> 00:32:52.460
It was fun.

00:32:52.460 --> 00:32:52.760
Bye.

00:32:52.760 --> 00:32:53.080
Yeah.

00:32:53.080 --> 00:32:53.260
Bye.

00:32:53.260 --> 00:32:55.340
Thank you for listening to Python Bytes.

00:32:55.340 --> 00:32:57.800
Follow the show on Twitter at Python Bytes.

00:32:57.800 --> 00:33:00.840
That's Python Bytes as in B-Y-T-E-S.

00:33:00.840 --> 00:33:03.720
And get the full show notes at pythonbytes.fm.

00:33:03.720 --> 00:33:08.800
If you have a news item you want featured, just visit pythonbytes.fm and send it our way.

00:33:08.800 --> 00:33:10.840
We're always on the lookout for sharing something cool.

00:33:10.840 --> 00:33:12.000
This is Brian Okken.

00:33:12.000 --> 00:33:16.100
And on behalf of myself and Michael Kennedy, thank you for listening and sharing this podcast

00:33:16.100 --> 00:33:17.260
with your friends and colleagues.

