WEBVTT

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

00:00:05.340 --> 00:00:09.880
This is episode 348, recorded August 15th, 2023.

00:00:09.880 --> 00:00:11.240
I'm Michael Kennedy.

00:00:11.240 --> 00:00:12.360
And I'm Brian Okken.

00:00:12.360 --> 00:00:15.660
And Brian, this episode is brought to everybody by us.

00:00:15.660 --> 00:00:21.360
I think you might be making a more concrete case for that than other times today.

00:00:21.360 --> 00:00:25.360
So, but yeah, check out all of our courses, books, things like that.

00:00:25.360 --> 00:00:28.840
It genuinely makes it possible for us to do this kind of stuff.

00:00:28.840 --> 00:00:32.000
Yeah, we love doing it, but yeah, also.

00:00:32.000 --> 00:00:33.240
Yeah, yeah, also.

00:00:33.240 --> 00:00:39.520
And if you want to be part of the live show and you're not watching live now, Tuesdays at 11,

00:00:39.520 --> 00:00:42.160
I go by set.fm slash live, all the details there.

00:00:42.160 --> 00:00:43.640
Brian, let's kick it off.

00:00:43.640 --> 00:00:44.720
What's your first item?

00:00:44.720 --> 00:00:49.500
Actually, I'm kind of on a packaging, a little bit of a packaging thing today.

00:00:49.500 --> 00:00:50.320
Okay, okay.

00:00:50.320 --> 00:00:56.140
Brett Cannon wrote an article called Differentiating Between Writing Down Dependencies to Use Packages

00:00:56.140 --> 00:00:58.740
and for Packages Themselves.

00:00:58.740 --> 00:01:00.060
It's kind of a big title.

00:01:00.060 --> 00:01:01.660
But here's the idea.

00:01:01.660 --> 00:01:03.280
And I've been thinking about this also.

00:01:03.280 --> 00:01:06.780
So I really, there's requirements.txt files.

00:01:06.780 --> 00:01:09.040
And those are often used for applications.

00:01:09.040 --> 00:01:13.140
And then there's, but that was really when we had like,

00:01:13.140 --> 00:01:16.300
that was either that or setup.py for packages.

00:01:16.600 --> 00:01:18.480
And now we have pyproject.toml.

00:01:18.480 --> 00:01:20.120
So can't we just use that?

00:01:20.120 --> 00:01:24.720
I mean, I kind of want to, but it doesn't quite work that way.

00:01:24.720 --> 00:01:30.880
You install dependencies with a pyproject.toml by doing a pip installing your package.

00:01:30.880 --> 00:01:33.840
And you can install it like pip install.e.

00:01:34.200 --> 00:01:36.920
I think, yeah, pip install.e.

00:01:36.920 --> 00:01:38.540
dash e, right.

00:01:38.540 --> 00:01:42.600
And on the current directory, or you can give it a local project directory.

00:01:42.600 --> 00:01:47.720
And you can even do optional things like optional test dependencies and stuff.

00:01:47.720 --> 00:01:54.000
And I think when you do the dash e, it installs your optional test dependencies also.

00:01:54.000 --> 00:01:54.780
I'm not sure.

00:01:54.780 --> 00:01:57.940
But, and I'm used to that because I do packages also.

00:01:57.940 --> 00:02:00.660
But we still have the requirements.txt file.

00:02:00.660 --> 00:02:02.480
There really are for different things.

00:02:02.480 --> 00:02:06.840
So Brett has talks about this a lot in here.

00:02:06.840 --> 00:02:11.940
And looking at why there's a thing called like project dependencies.

00:02:11.940 --> 00:02:15.440
And the project is really meant for packaging.

00:02:15.440 --> 00:02:18.860
It's really meant just for the whole packaging system.

00:02:18.860 --> 00:02:23.540
So that when you install something, install a wheel,

00:02:23.540 --> 00:02:26.300
it knows how to get packages for it.

00:02:26.300 --> 00:02:26.900
That's it.

00:02:26.900 --> 00:02:28.820
It's not supposed to be for applications.

00:02:28.820 --> 00:02:33.440
So really, that's kind of the discussion around here, around this article.

00:02:33.440 --> 00:02:35.520
However, there's a couple ideas.

00:02:35.520 --> 00:02:42.020
He references, also references back a Donald Stuffed article from 2013

00:02:42.020 --> 00:02:45.600
about setup.py versus requirements.txt.

00:02:45.600 --> 00:02:47.680
But like I said, that was setup.py.

00:02:47.680 --> 00:02:50.540
Maybe we could do something better.

00:02:50.540 --> 00:02:55.220
Brett's consideration is maybe we could have some standard,

00:02:55.860 --> 00:02:59.640
something, some other file that we could have.

00:02:59.640 --> 00:03:05.740
I personally, I think that maybe we could expand PyProject.toml.

00:03:05.740 --> 00:03:07.160
I really like the Toml thing.

00:03:07.160 --> 00:03:10.240
So maybe we could either have a requirements.toml,

00:03:10.560 --> 00:03:15.580
or maybe we could have like instead of a project section of the Toml file,

00:03:15.580 --> 00:03:18.820
maybe we could have maybe an application section.

00:03:18.820 --> 00:03:19.760
Maybe that would work.

00:03:20.020 --> 00:03:20.180
Yeah.

00:03:20.180 --> 00:03:25.780
So yeah, I think like a dev requirements even just in the PyProject.toml

00:03:25.780 --> 00:03:27.040
seems pretty straightforward to me.

00:03:27.040 --> 00:03:27.560
Yeah.

00:03:27.560 --> 00:03:35.320
I mean, I run into it in other places too, like just in a Git repo that has like a couple Python

00:03:35.320 --> 00:03:38.560
tools in it that people can install on their own.

00:03:38.560 --> 00:03:40.500
But they might have some requirements.

00:03:40.500 --> 00:03:41.540
How do you list those?

00:03:41.540 --> 00:03:42.780
Do you stick them as applications?

00:03:42.780 --> 00:03:50.460
I mean, requirements.txt is normally the thing that's used for like Django web applications and

00:03:50.460 --> 00:03:51.580
things like that.

00:03:51.580 --> 00:03:55.540
So maybe requirements.txt is fine, but I think.

00:03:55.540 --> 00:03:55.980
Perhaps.

00:03:55.980 --> 00:04:01.780
What I have is I have for my world, I have requirements.txt, which is like from the web apps and stuff.

00:04:01.780 --> 00:04:05.200
That is what is required for the app to run without that.

00:04:05.200 --> 00:04:05.760
Yeah.

00:04:05.760 --> 00:04:06.800
You can't make it go.

00:04:06.800 --> 00:04:09.040
Then I have requirements-dev.txt.

00:04:09.040 --> 00:04:10.140
I've seen that pattern a lot.

00:04:10.140 --> 00:04:14.660
And then to actually generate those, I use pip-tools and pip compile.

00:04:14.660 --> 00:04:17.520
So I have requirements.in and requirements-dev.in.

00:04:17.620 --> 00:04:21.680
And then I can auto-update all the dependencies and keep them in sync.

00:04:21.680 --> 00:04:22.320
Yeah.

00:04:22.320 --> 00:04:23.560
That's how I do it these days.

00:04:23.560 --> 00:04:33.640
But now even people with Django or other things are using a PyProjectTunnel also to store their

00:04:33.640 --> 00:04:35.600
black settings and things like that.

00:04:35.600 --> 00:04:41.540
So we're kind of using the PyProjectTunnel for more things.

00:04:41.540 --> 00:04:43.440
And I think maybe we could extend it for this.

00:04:43.440 --> 00:04:44.700
Anyway, that's my hope.

00:04:44.700 --> 00:04:45.120
It seems reasonable.

00:04:45.120 --> 00:04:45.460
Yeah.

00:04:45.800 --> 00:04:48.160
So anyway, what do you got for us?

00:04:48.160 --> 00:04:51.280
Well, let's monkey around a little bit with the Python monkey.

00:04:51.280 --> 00:04:52.960
With the Python monkey.

00:04:52.960 --> 00:04:53.640
That's cute.

00:04:53.640 --> 00:04:54.060
That's cute.

00:04:54.060 --> 00:04:54.800
It is.

00:04:54.800 --> 00:05:00.220
So this comes to us from created by Will Pringle, I believe, amongst others.

00:05:00.220 --> 00:05:01.200
Let's see.

00:05:01.200 --> 00:05:03.660
On the contributors here.

00:05:03.660 --> 00:05:05.560
There.

00:05:05.560 --> 00:05:06.000
Yeah.

00:05:06.000 --> 00:05:06.920
There we go.

00:05:06.920 --> 00:05:07.360
Yeah.

00:05:07.460 --> 00:05:09.240
So a bunch of folks that work on this project.

00:05:09.240 --> 00:05:15.740
It's not super popular with only 276 stars, but I think it might be a pretty darn interesting

00:05:15.740 --> 00:05:18.260
compatibility layer for Python.

00:05:18.260 --> 00:05:19.580
So what do I mean by that?

00:05:19.580 --> 00:05:23.780
So imagine I'm, you can look at this from two perspectives.

00:05:24.160 --> 00:05:26.660
So don't scoff at one if you prefer the other.

00:05:26.660 --> 00:05:41.580
So imagine I'm a JavaScript developer and I've got a ton of cool JavaScript code that not just for the web front end, but, you know, kind of in the node JS sense, like a bunch of utilities or a bunch of libraries that work and do certain things.

00:05:41.580 --> 00:05:41.860
Right.

00:05:41.860 --> 00:05:42.260
Yeah.

00:05:42.260 --> 00:05:45.780
But I also have a Python app and I'd like to somehow use those together.

00:05:45.780 --> 00:05:49.020
So Python monkey is a straight way to put it.

00:05:49.020 --> 00:06:00.920
It, it basically hosts job, a JavaScript, a full on high performance JavaScript, JIT compiled to almost native performance JavaScript engine inside of Python through pip install.

00:06:00.920 --> 00:06:15.860
So if I wanted to use some of the JavaScript code, I just write my Python application and for that function or that functionality, I just import the job, you know, first spider monkey or Python monkey.

00:06:15.860 --> 00:06:20.260
And then I import the JavaScript files that you would use.

00:06:20.260 --> 00:06:22.300
And then you just call them like Python functions.

00:06:22.300 --> 00:06:23.240
Okay.

00:06:23.560 --> 00:06:37.180
Or reverse, I'm writing a Python application and you know, one option to make like slow loops go faster would be to write that in Cython and Cython is getting better with the Cython three release that we discussed already previous episode.

00:06:37.180 --> 00:06:48.160
But JavaScript, because this thing, the spider monkey JavaScript engine is the one that I believe Firefox uses does JIT compilation to native code.

00:06:48.160 --> 00:06:50.780
It basically is near native performance as well.

00:06:50.780 --> 00:06:56.360
So if you'd like, you could rewrite that part in TypeScript or JavaScript and run just that section.

00:06:56.360 --> 00:07:00.700
And it uses things like shared memory between JavaScript and Python.

00:07:00.700 --> 00:07:06.680
So if you've got like a string or a list, those are, those are the same objects, which is pretty crazy.

00:07:06.680 --> 00:07:07.300
Wow.

00:07:07.300 --> 00:07:08.280
At least for the strings.

00:07:08.280 --> 00:07:08.720
Okay.

00:07:08.720 --> 00:07:11.200
So, let's look at some examples.

00:07:11.200 --> 00:07:14.720
There's an article by will and no, I will not log into medium.

00:07:14.720 --> 00:07:15.740
You're partially evil.

00:07:15.740 --> 00:07:16.140
Okay.

00:07:16.140 --> 00:07:17.960
So here's an article by,

00:07:19.640 --> 00:07:22.880
my will here says, look at, let's look at some code examples.

00:07:22.880 --> 00:07:23.300
All right.

00:07:23.300 --> 00:07:25.520
So import Python monkey as PM.

00:07:25.520 --> 00:07:30.140
And then you say PM eval and give it JavaScript code and then boom, it runs that.

00:07:30.140 --> 00:07:31.200
That's one way.

00:07:31.200 --> 00:07:33.980
what you can do maybe is more interesting is look at this.

00:07:33.980 --> 00:07:38.400
I can say, em dot eval and give it an anonymous JavaScript function.

00:07:38.640 --> 00:07:44.100
And then what comes back, not evaluating it, but just the thing to define the function in JavaScript.

00:07:44.100 --> 00:07:44.400
Okay.

00:07:44.400 --> 00:07:48.240
And then what comes back is an object that itself is a function.

00:07:48.240 --> 00:07:49.300
Okay.

00:07:49.440 --> 00:07:50.620
So that's pretty cool.

00:07:50.620 --> 00:07:51.120
Yeah.

00:07:51.120 --> 00:07:52.980
like, and hold on.

00:07:52.980 --> 00:07:53.920
There's two parts of this.

00:07:53.920 --> 00:07:56.640
So I've got a, I've created a JavaScript function.

00:07:56.640 --> 00:07:59.940
That's jet compiled in spider monkey through this eval.

00:08:00.100 --> 00:08:04.100
And what the, I didn't say this part, what the function takes is given a function.

00:08:04.100 --> 00:08:07.760
It will call that function passing hello world to it.

00:08:07.760 --> 00:08:08.300
Okay.

00:08:08.300 --> 00:08:09.200
The string hello world.

00:08:09.200 --> 00:08:09.560
Okay.

00:08:09.700 --> 00:08:14.840
So what you do is you get the function back as a Python function and then they pass print.

00:08:14.840 --> 00:08:19.820
It somehow proxies the print function into the JavaScript space.

00:08:19.820 --> 00:08:24.840
And then JavaScript calls the Python print, which it then comes back to the console, to the terminal.

00:08:24.840 --> 00:08:25.360
Wow.

00:08:25.360 --> 00:08:26.040
Oh, okay.

00:08:26.040 --> 00:08:27.560
That's some deep integration, right?

00:08:27.560 --> 00:08:29.780
That's some pretty, pretty wild stuff.

00:08:29.780 --> 00:08:31.000
let's see.

00:08:31.000 --> 00:08:32.220
What else can we do here?

00:08:32.220 --> 00:08:33.400
This is pretty interesting.

00:08:33.400 --> 00:08:39.500
I can say, given a JavaScript module, like I described, I can, you know, here's a example.

00:08:39.600 --> 00:08:41.780
It has a say hello export.

00:08:41.780 --> 00:08:45.180
Then you can just say PM dot require that JavaScript module.

00:08:45.180 --> 00:08:50.700
And now you've got all the function, all the export behavior from that JavaScript module.

00:08:50.700 --> 00:08:51.460
Right.

00:08:51.460 --> 00:08:52.120
Which is cool.

00:08:52.120 --> 00:08:55.600
yeah, there's, there's some more examples in here.

00:08:55.600 --> 00:08:57.360
The other angle that's pretty interesting.

00:08:57.360 --> 00:09:01.340
There's two more angles that are interesting because it uses spider monkey and spider monkey

00:09:01.340 --> 00:09:03.300
is awesome with WebAssembly.

00:09:03.300 --> 00:09:09.380
It allows you to run, untrusted WASM code from languages like C, C++ and rust.

00:09:09.500 --> 00:09:15.740
You can now basically do, any, you can call any WebAssembly code as well that you'd

00:09:15.740 --> 00:09:17.220
like inside of your function.

00:09:17.220 --> 00:09:18.160
Now we're getting interesting.

00:09:18.160 --> 00:09:18.900
Yeah.

00:09:18.900 --> 00:09:23.740
It supports things like async and await using the async and await keywords to handle the

00:09:23.740 --> 00:09:25.340
callback nature of JavaScript.

00:09:25.420 --> 00:09:30.320
like the dot then type of deferreds and different things.

00:09:30.320 --> 00:09:33.000
So you can just async and await those behaviors, right?

00:09:33.000 --> 00:09:36.700
Just await a WebAssembly call, which is pretty excellent.

00:09:36.700 --> 00:09:37.260
Yeah.

00:09:37.260 --> 00:09:40.920
So there's a bunch of, examples, some pretty cool graphics here.

00:09:42.660 --> 00:09:48.600
with Spock and, captain Kerr going my mind to your mind, my object, the your dicks, your

00:09:48.600 --> 00:09:50.080
dicks to my objects.

00:09:50.080 --> 00:09:51.160
It's pretty awesome.

00:09:51.160 --> 00:09:51.480
There.

00:09:51.480 --> 00:09:57.620
another angle that is worth considering is this allows the entire Python data science

00:09:57.620 --> 00:09:59.900
stack to become accessible to JavaScript developers.

00:09:59.900 --> 00:10:01.600
developers, right?

00:10:01.600 --> 00:10:01.940
Yeah.

00:10:01.940 --> 00:10:05.900
So if you, if you want to use, you know, the machine learning stuff, if you want to use

00:10:05.900 --> 00:10:07.820
pandas or Polars, right.

00:10:07.820 --> 00:10:11.600
You just write your code and then, you know, do the integration here.

00:10:11.600 --> 00:10:13.460
And yeah, that's, that's pretty much it.

00:10:13.460 --> 00:10:19.000
it, it finishes with, some funny little pictures here of, no on the arc.

00:10:19.720 --> 00:10:23.020
Got a Python and a JavaScript, which looks like a penguin.

00:10:23.020 --> 00:10:24.520
And then it has the Python monkey.

00:10:24.520 --> 00:10:25.500
The what, what is that?

00:10:25.500 --> 00:10:26.360
What the heck is this?

00:10:26.360 --> 00:10:26.740
All right.

00:10:26.740 --> 00:10:33.460
Anyway, that's, that's Python monkey, which is, I think, potentially interesting.

00:10:33.460 --> 00:10:38.380
So with the, with the WebAssembly and stuff, you could potentially have like every other

00:10:38.380 --> 00:10:42.140
function in your system be implemented by a different language.

00:10:42.140 --> 00:10:49.280
I'm bored of, C, C++ rust go.

00:10:49.500 --> 00:10:51.180
what else do we want to write it in?

00:10:51.180 --> 00:10:51.540
Yeah.

00:10:51.540 --> 00:10:52.540
Why not everything?

00:10:52.540 --> 00:10:56.800
just make sure that your, your application is only maintainable by you.

00:10:56.800 --> 00:10:57.280
That'd be.

00:10:57.280 --> 00:10:57.960
Exactly.

00:10:57.960 --> 00:10:59.880
Like, do you know how many compilers you need to do this?

00:10:59.880 --> 00:11:00.720
No, this is a mall.

00:11:00.720 --> 00:11:03.980
That's kind of fun to, to joke about, but this does look pretty cool.

00:11:03.980 --> 00:11:04.700
So yeah.

00:11:04.700 --> 00:11:06.060
Yeah, it does look pretty cool.

00:11:06.060 --> 00:11:08.640
So, you know, congrats to the folks there.

00:11:08.640 --> 00:11:10.160
This maybe it'll go somewhere.

00:11:10.160 --> 00:11:10.520
We'll see.

00:11:10.520 --> 00:11:11.620
It's, it's pretty interesting.

00:11:11.620 --> 00:11:18.540
I think, also it's, it's worth noting, that there is, somewhere in here that there's

00:11:18.540 --> 00:11:19.540
a comparison to other things.

00:11:19.540 --> 00:11:25.440
So this apparently is not the only time such a type of creation, has been attempted.

00:11:25.440 --> 00:11:29.460
So it says there are other projects that already do JavaScript and Python, such as JS to PI,

00:11:29.460 --> 00:11:31.040
PI V8 and medical.

00:11:31.200 --> 00:11:33.960
But there's a bunch of different drawbacks or stuff.

00:11:33.960 --> 00:11:36.620
And so this is why we created it basically in addition.

00:11:36.620 --> 00:11:42.360
So JS to PI is implemented entirely in Python, which sounds awesome, except, you know, V8 and

00:11:42.360 --> 00:11:45.360
spider monkey compiled a native code and run ultra fast.

00:11:45.360 --> 00:11:48.720
Whereas, you know, if you just run in Python, it probably doesn't have any of those things.

00:11:48.720 --> 00:11:49.020
Right.

00:11:49.020 --> 00:11:56.480
PI V8, has a wrapper around Google's V8 JavaScript engine, which is great, but it's just super low level.

00:11:56.480 --> 00:12:02.040
You just like talk directly to the JavaScript bits, which for things, for example, doesn't have async and await.

00:12:02.040 --> 00:12:10.280
And finally medical is extensible, embeddable and interoperable, but you've got to install a bunch of different run times outside of just pip install.

00:12:10.340 --> 00:12:16.140
So anyway, if people are going, but it exists, it does, but this apparently is why it exists like this.

00:12:16.140 --> 00:12:17.200
Yep.

00:12:17.200 --> 00:12:17.660
Cool.

00:12:17.660 --> 00:12:18.100
Yeah.

00:12:18.100 --> 00:12:22.880
And John out in the audience says, I do this, but going the other way using transcript.

00:12:22.880 --> 00:12:23.940
Okay.

00:12:23.940 --> 00:12:24.700
Interesting.

00:12:24.700 --> 00:12:26.860
Something else to, something new to check out.

00:12:26.860 --> 00:12:27.300
Thanks, John.

00:12:27.300 --> 00:12:28.440
We'll take that out.

00:12:28.440 --> 00:12:28.840
So.

00:12:28.840 --> 00:12:29.340
All right.

00:12:29.340 --> 00:12:30.160
Over to you, Brian.

00:12:30.420 --> 00:12:38.180
well, I just, one more thing, Olivero, says, Python monkey perfect for works on my machine certification.

00:12:38.180 --> 00:12:40.920
There, there is an official works on my machine certification.

00:12:40.920 --> 00:12:42.820
If you have, I know we talked about it before.

00:12:42.820 --> 00:12:43.800
It's glorious.

00:12:43.800 --> 00:12:44.740
It comes with a sticker.

00:12:44.740 --> 00:12:52.800
Power your application code, getting the latest version of any recent changes from other developers, purely optional and not a requirement for certification.

00:12:53.200 --> 00:12:58.180
Launch the application cause one code path in the code you're checking to be executed.

00:12:58.180 --> 00:13:00.880
The preferred way to do this is with ad hoc manual testing.

00:13:00.880 --> 00:13:02.080
You can omit this step.

00:13:02.080 --> 00:13:08.760
If the code change is less than five lines, or if in the developer's professional opinion, the code could not possibly result in an error.

00:13:08.760 --> 00:13:10.460
Check your code into version control.

00:13:10.460 --> 00:13:11.280
You're certified.

00:13:11.280 --> 00:13:13.100
Yeah.

00:13:13.100 --> 00:13:13.460
There we go.

00:13:13.460 --> 00:13:14.640
Two jokes in one episode.

00:13:14.640 --> 00:13:15.600
How that, how about that?

00:13:15.600 --> 00:13:16.060
Awesome.

00:13:16.060 --> 00:13:20.900
Well, we had a little bit more, some, a little more humor, to add to it.

00:13:21.080 --> 00:13:26.700
So because, I thought it was a serious article and it is, it's just funny and weird.

00:13:26.700 --> 00:13:33.980
So Seth Larson wrote, quirks of Python packaging, versioning package, Python package versioning.

00:13:33.980 --> 00:13:34.400
That's it.

00:13:34.400 --> 00:13:48.960
so we're used to, well, we're kind of getting used to, the world where we all have some ver like 1.2.3 and for semantic versioning, but we also have calendar versioning like 2023.6.1.

00:13:48.960 --> 00:13:55.480
And then there's stuff like you can add a pre-release suffix and things like that, but it gets way weirder and fun.

00:13:55.480 --> 00:14:01.920
so, and I have noticed this, especially with get up, like get get up versioning.

00:14:01.920 --> 00:14:04.700
Sometimes people will do, V versioning.

00:14:04.700 --> 00:14:06.800
So there's V prefixes you can do.

00:14:06.800 --> 00:14:12.240
And some, I guess you can pull that into your, your Python application version as well.

00:14:12.240 --> 00:14:12.740
Why not?

00:14:13.360 --> 00:14:17.160
so V versions are allowed, epic versions.

00:14:17.160 --> 00:14:18.840
Did you know about epic versions?

00:14:18.840 --> 00:14:19.980
I just learned about this.

00:14:19.980 --> 00:14:21.020
I don't think so.

00:14:21.020 --> 00:14:30.240
So it's, you can, you can have a, a exclamation point separating your epic from the rest of your version.

00:14:30.240 --> 00:14:38.140
So this is, so like one bang 2.0.0 would be epic one version 2.0.0.

00:14:38.140 --> 00:14:38.680
Um,

00:14:38.680 --> 00:14:43.660
I got to tell you, I already had a hard time deciding when the two or when the middle zero or the last zero changes.

00:14:43.760 --> 00:14:47.360
If I put a number in front of an exclamation point, I'm going to just lost.

00:14:47.360 --> 00:14:47.960
Yeah.

00:14:47.960 --> 00:14:48.760
Apparently.

00:14:48.760 --> 00:14:49.500
Too much decision.

00:14:49.500 --> 00:14:50.200
Too many decisions.

00:14:50.200 --> 00:14:55.620
Apparently some systems use colons for epics, but Python chose, this is all based on Python

00:14:55.620 --> 00:14:56.800
PEP 440.

00:14:56.800 --> 00:15:03.220
and, the, yeah, apparently we chose the bang symbol or is that spang, right?

00:15:03.220 --> 00:15:05.320
the exclamation point.

00:15:05.320 --> 00:15:08.240
so, and that just kind of looks like a one.

00:15:08.240 --> 00:15:10.600
If you did one bang one, that would be hard to tell.

00:15:10.600 --> 00:15:12.240
local versions.

00:15:12.500 --> 00:15:17.000
and is you can, you can extend after you have versions, you're going to have alpha

00:15:17.000 --> 00:15:20.160
numerics and, other stuff.

00:15:20.160 --> 00:15:24.380
like, you know, here, plus, I don't know if the plus is part of it anyway.

00:15:24.380 --> 00:15:30.920
so after your normal version, like 1.0.0, he has an example of plus Ubuntu dash one.

00:15:30.920 --> 00:15:37.920
this gets normalized, but, but, and luckily, but this is kind of nice for local

00:15:37.920 --> 00:15:40.220
it's local versions because pipe AI doesn't like it.

00:15:40.360 --> 00:15:45.020
So pipe AI will not let you push up local versions to guy, which is probably right.

00:15:45.020 --> 00:15:49.120
local builds, long versions.

00:15:49.120 --> 00:15:54.960
Apparently you can use the, use the first 217 digits of PI and that works fine.

00:15:54.960 --> 00:16:00.580
as, as one of the digits, there's no limits, case insensitivity.

00:16:00.960 --> 00:16:02.420
so yeah.

00:16:02.420 --> 00:16:02.760
Okay.

00:16:02.760 --> 00:16:03.420
That's fine.

00:16:03.420 --> 00:16:10.560
it gets normalized lower or something so that you, you know, capital RC one is the

00:16:10.560 --> 00:16:12.260
same as lowercase RC one.

00:16:12.260 --> 00:16:13.400
That's, that's appropriate.

00:16:13.820 --> 00:16:17.940
so pre-release I've seen, I've actually used pre post.

00:16:17.940 --> 00:16:22.660
I don't know if I use pre I've seen pre and I've used post release occasionally, although

00:16:22.660 --> 00:16:25.620
it's so weird that people don't understand what's going on.

00:16:25.620 --> 00:16:26.940
So I don't do that anymore.

00:16:27.260 --> 00:16:31.460
but apparently pre post and dev are not mutually exclusive.

00:16:31.460 --> 00:16:35.300
You can have, but all three, allowed in one version.

00:16:35.300 --> 00:16:37.380
Why would you do that?

00:16:37.380 --> 00:16:41.960
so, and, yeah, no delimiters needed.

00:16:41.960 --> 00:16:44.460
there's just a lot of fun here.

00:16:44.460 --> 00:16:45.740
thanks.

00:16:45.740 --> 00:16:47.740
So implicit hyphens are allowed.

00:16:47.740 --> 00:16:50.140
So this is both the serious and non-serious.

00:16:50.140 --> 00:16:52.280
Oh, implicit zeros are weird.

00:16:52.280 --> 00:17:01.860
So, you can, you can, if you have a version 2.0.4, you can just keep adding a bunch of 0.0.0.0

00:17:01.860 --> 00:17:03.180
and it works fine.

00:17:03.180 --> 00:17:05.040
It resolves to 2.0.4.

00:17:05.040 --> 00:17:05.820
That's awesome.

00:17:05.820 --> 00:17:13.180
I, I definitely need to advertise some version say, just, just pick up 2.0.3.

00:17:13.460 --> 00:17:15.560
0.0.0.0.

00:17:15.560 --> 00:17:17.600
Yeah.

00:17:17.600 --> 00:17:18.940
It looks, makes it sound tough.

00:17:18.940 --> 00:17:19.240
Like, yeah.

00:17:19.240 --> 00:17:20.440
I mean, in releases we've had.

00:17:20.440 --> 00:17:24.180
Anyway, totally, totally fun articles.

00:17:24.180 --> 00:17:24.880
So thanks, Seth.

00:17:24.880 --> 00:17:25.860
Brian, do you hear that?

00:17:25.860 --> 00:17:26.460
No.

00:17:26.460 --> 00:17:29.800
That's the sound of a million regexes dying.

00:17:29.800 --> 00:17:35.520
That are supposed to be scanning for the version string in your code.

00:17:35.520 --> 00:17:36.060
Yeah.

00:17:36.060 --> 00:17:40.780
But maybe that's why Python just has it as a string.

00:17:40.780 --> 00:17:44.500
It's, if you do dunder version equals, it's, just a string.

00:17:44.500 --> 00:17:44.780
So.

00:17:44.780 --> 00:17:45.280
Yeah.

00:17:46.300 --> 00:17:51.980
Axel asks, if you use C++ compiled code, so I guess native code, that's like not part

00:17:51.980 --> 00:17:53.460
of just source only Python.

00:17:53.460 --> 00:17:56.560
Is there a way to define which compiler you use in the versioning?

00:17:56.560 --> 00:18:01.060
Maybe that Ubuntu type variant, that local version, but you can't publish that, right?

00:18:01.060 --> 00:18:04.120
you can't push it to PyPI like that.

00:18:04.240 --> 00:18:10.320
But like, for instance, it's a, I'm not sure how this, this relates to, like

00:18:10.320 --> 00:18:13.540
the wheel naming, the wheel download naming thing.

00:18:13.540 --> 00:18:13.780
Yeah.

00:18:13.780 --> 00:18:15.020
so.

00:18:15.020 --> 00:18:18.300
I'm sure there's some metadata you could put in there, right?

00:18:18.300 --> 00:18:20.400
Like you can do dunder version, right?

00:18:20.400 --> 00:18:23.760
You could just do dunder compiler and say, you know, print that out and it'll tell you,

00:18:23.840 --> 00:18:26.660
but it's not, there's no standard that I can think of.

00:18:26.660 --> 00:18:29.740
Well, there's the, there is the wheel standard.

00:18:29.740 --> 00:18:31.900
I just don't remember where the link is.

00:18:31.900 --> 00:18:33.080
But that's more platform based, right?

00:18:33.080 --> 00:18:34.340
Than a compiler.

00:18:34.340 --> 00:18:35.260
Oh, right.

00:18:35.260 --> 00:18:36.320
It's not compiler based.

00:18:36.320 --> 00:18:37.360
It's platform based.

00:18:37.360 --> 00:18:41.500
I mean, the compilers got to compile to the platform, but it, it doesn't say like use GCC

00:18:41.500 --> 00:18:45.700
versus LLVM, Clang, Visual Studio, whatever, right?

00:18:45.700 --> 00:18:46.040
Right.

00:18:46.040 --> 00:18:46.500
Yeah.

00:18:46.500 --> 00:18:48.400
And usually I'm just doing pure Python.

00:18:48.400 --> 00:18:51.620
So I have all listed, but the wheel, anyway.

00:18:51.620 --> 00:18:52.360
Exactly.

00:18:52.360 --> 00:18:52.960
So.

00:18:52.960 --> 00:18:53.440
Exactly.

00:18:53.440 --> 00:18:54.720
All right.

00:18:54.720 --> 00:18:59.480
Well, with all that, Python monkeying around, I could just barely stand it.

00:18:59.480 --> 00:19:00.540
Oh dear.

00:19:00.540 --> 00:19:01.960
About bear type.

00:19:01.960 --> 00:19:02.600
Nice.

00:19:02.600 --> 00:19:04.320
The bare-metal type checker.

00:19:04.320 --> 00:19:04.900
Okay.

00:19:04.900 --> 00:19:08.660
So people know I'm a huge fan of types, Python type hints and all those things.

00:19:08.660 --> 00:19:13.380
They're, they're super, super empowering and make the editors so much more helpful.

00:19:13.380 --> 00:19:18.480
It means you don't have to go into, the documentation and go, what does this take again?

00:19:18.480 --> 00:19:21.640
I know it takes an, an ARGs here, but is ARGs a dictionary?

00:19:21.640 --> 00:19:22.560
Is it a class?

00:19:22.640 --> 00:19:23.460
Is it a string?

00:19:23.460 --> 00:19:24.900
Is it an, I, what is it?

00:19:24.900 --> 00:19:25.160
Right?

00:19:25.160 --> 00:19:26.320
Like crazy stuff like that.

00:19:26.320 --> 00:19:26.480
Right?

00:19:26.480 --> 00:19:26.680
Yeah.

00:19:26.680 --> 00:19:31.920
So types are awesome for conveying that information without asking go to the docs or some other

00:19:31.920 --> 00:19:33.140
place to figure it out.

00:19:33.140 --> 00:19:42.360
However, what Python type hints, annotations generally don't do as the word hint would indicate.

00:19:42.360 --> 00:19:48.040
You can use tools like my PI and my PI will say the typing looks consistent or inconsistent,

00:19:48.040 --> 00:19:52.520
but regardless of what it says, when you run the code, whether or not the typing is consistent,

00:19:52.520 --> 00:19:56.680
long as it actually still semantically valid, it's going to run.

00:19:56.680 --> 00:20:01.540
Even if you tell the types, it takes a string, but you really pass an int and it did plus to

00:20:01.540 --> 00:20:02.300
it, but you know what?

00:20:02.300 --> 00:20:04.620
You pass two integers and two strings and it still worked.

00:20:04.620 --> 00:20:05.080
Right?

00:20:05.080 --> 00:20:09.920
So the runtime version of typing and Python is mostly absent, right?

00:20:09.920 --> 00:20:12.100
Excluding things like Pydantic and a few others.

00:20:12.200 --> 00:20:19.920
So this bear type thing is a near zero cost, near real time, pure Python runtime type checker

00:20:19.920 --> 00:20:25.280
that makes runtime mismatches for typing runtime errors.

00:20:25.280 --> 00:20:26.000
Interesting.

00:20:26.000 --> 00:20:26.500
Okay.

00:20:26.500 --> 00:20:30.560
So you can say, this sounds like a horrible idea and I will never touch it.

00:20:30.560 --> 00:20:32.860
Please don't, you know, install the bear.

00:20:32.860 --> 00:20:38.340
Or you could say, I come from a static language and this dynamic typing business is freaking me

00:20:38.340 --> 00:20:38.540
out.

00:20:38.540 --> 00:20:39.680
Can we get a little closer?

00:20:39.680 --> 00:20:40.720
Then you can have it.

00:20:40.780 --> 00:20:43.980
I feel like this is the kind of thing that for little projects is completely useless,

00:20:43.980 --> 00:20:47.280
but for huge projects, it may be, it starts to become more valuable.

00:20:47.280 --> 00:20:47.560
Right?

00:20:47.560 --> 00:20:48.000
Yeah.

00:20:48.000 --> 00:20:53.920
So if you just jump right into it, you pip install bear type, and then you can do things

00:20:53.920 --> 00:20:59.260
like, import the decorator and just put a decorator onto a function that has a type

00:20:59.260 --> 00:21:01.600
annotation or hint right there like that.

00:21:01.600 --> 00:21:07.920
So here's one that says quote Wiggum and then it passes lines in the type declaration says

00:21:07.920 --> 00:21:10.640
lines is a list of stir and it returns none.

00:21:10.640 --> 00:21:11.140
Okay.

00:21:11.140 --> 00:21:11.140
Okay.

00:21:11.140 --> 00:21:16.100
So then if you just use this function, pass it a list of strings, it just runs.

00:21:16.100 --> 00:21:16.440
Right?

00:21:16.440 --> 00:21:16.900
Yeah.

00:21:16.900 --> 00:21:22.100
If however, though you pass it a list of bytes, which kind of look like strings, but are not

00:21:22.100 --> 00:21:27.240
strings, you get an exception that says parameter such and such and such.

00:21:27.240 --> 00:21:28.140
Um,

00:21:28.140 --> 00:21:28.140
Um,

00:21:28.140 --> 00:21:32.760
it gives you the actual index in the list.

00:21:32.760 --> 00:21:36.140
It says list item zero with this value is not a string.

00:21:36.140 --> 00:21:38.980
Cause it's a B string, which is really bytes, right?

00:21:38.980 --> 00:21:39.480
Yeah.

00:21:39.480 --> 00:21:40.440
It's pretty cool, right?

00:21:40.440 --> 00:21:42.020
Yeah, it is really cool.

00:21:42.020 --> 00:21:50.080
and I, I'm kind of, agreeing with, Alvaro, said, maybe, maybe running

00:21:50.080 --> 00:21:51.200
with the test suite.

00:21:51.200 --> 00:21:57.160
And I was thinking maybe dynamically add these somehow, use the bare types during

00:21:57.160 --> 00:22:02.960
development and maybe, maybe take them off later if it, but if it's really fast,

00:22:02.960 --> 00:22:03.440
yeah.

00:22:03.700 --> 00:22:05.940
Yeah, I'll, I'll comment on that in a second.

00:22:05.940 --> 00:22:08.060
there are also validators.

00:22:08.060 --> 00:22:10.720
There's an is and an annotated validator.

00:22:10.720 --> 00:22:16.260
If you want to be more restrictive, maybe even then you might expect it's part of Python, but

00:22:16.260 --> 00:22:19.180
it's not a commonly known part of the type and then thing.

00:22:19.180 --> 00:22:25.200
So for example, I could define a new type using annotated called list of strings.

00:22:25.200 --> 00:22:25.820
Okay.

00:22:26.040 --> 00:22:31.920
And it says, it has to be a list of strings as one part of the annotation.

00:22:31.920 --> 00:22:37.640
And then another one is, well, if it's, it has to be a non-empty set of strings is what

00:22:37.640 --> 00:22:38.920
they're trying to create here.

00:22:38.920 --> 00:22:39.440
Okay.

00:22:39.440 --> 00:22:43.940
So it says if it's a list with a bunch of stuff, the bunch of stuff has to be strings,

00:22:43.940 --> 00:22:49.840
but it also contests that it's not falsy, which would be the case when it's a just, you

00:22:49.840 --> 00:22:51.440
know, zero length list.

00:22:51.440 --> 00:22:53.920
So then you can annotate with that type.

00:22:54.020 --> 00:22:58.900
And if you call with regular somewhere, you call it with a regular code is fine.

00:22:58.900 --> 00:23:02.520
But if you call it with the empty list, where it says a list of strings, it says, no, no,

00:23:02.520 --> 00:23:03.620
no, it can't be an empty list.

00:23:03.620 --> 00:23:05.860
It has to be a non-empty list of strings.

00:23:05.860 --> 00:23:09.960
So there's like some pretty crazy things that you can, can do here.

00:23:09.960 --> 00:23:11.200
yeah.

00:23:11.200 --> 00:23:16.040
Some other stuff you can check if you'd like, but yeah, it's, I wanted to read this, this

00:23:16.040 --> 00:23:19.460
introduction article here, which actually comes after all the examples.

00:23:19.920 --> 00:23:27.580
by the way, it also, in order to run this whole bunch of times, it took 33 microseconds,

00:23:27.580 --> 00:23:29.420
which is pretty incredible.

00:23:29.420 --> 00:23:36.020
The test, test this for like an array of tuples of arrays of what is that?

00:23:36.020 --> 00:23:38.180
A million, you know, 33 microseconds.

00:23:38.180 --> 00:23:39.260
So that's pretty fast actually.

00:23:39.260 --> 00:23:39.820
Yeah.

00:23:39.820 --> 00:23:44.760
You still want to like compare it like your entire, like some workflow compared to with

00:23:44.760 --> 00:23:45.220
or without.

00:23:45.220 --> 00:23:45.740
So.

00:23:45.740 --> 00:23:46.640
Yep.

00:23:46.640 --> 00:23:47.640
So let me read this.

00:23:47.640 --> 00:23:49.520
So if people are wondering, what the heck is this?

00:23:49.520 --> 00:23:55.560
Bear type brings Rust and C++ inspired zero cost abstractions into the lawless world of dynamic

00:23:55.560 --> 00:24:01.220
typing, dynamically typed Python by enforcing type safety at the granular level of functions

00:24:01.220 --> 00:24:04.800
and methods against type hints standardized by the Python community.

00:24:04.800 --> 00:24:09.340
And oh, one non amortized worst case time with negligible constant factors.

00:24:09.340 --> 00:24:10.160
How about that?

00:24:10.160 --> 00:24:12.720
So if anyone asks what bear type is, there's a good description.

00:24:12.720 --> 00:24:14.560
Yeah.

00:24:14.560 --> 00:24:16.560
Well, yeah, it's, it's pretty cool.

00:24:16.560 --> 00:24:19.200
And then there's a whole bunch of stuff about it, but anyway, that that's bear type.

00:24:19.200 --> 00:24:20.620
It looks pretty promising to me.

00:24:20.620 --> 00:24:25.860
Like the drawback of a lot of these think really is like, well, now you're doing a bunch of checking

00:24:25.860 --> 00:24:29.740
for every little function call and it's super slow, but if it's fast enough, that's, that's

00:24:29.740 --> 00:24:30.060
pretty cool.

00:24:30.060 --> 00:24:30.500
Yeah.

00:24:30.500 --> 00:24:32.740
So a couple of comments in the chat.

00:24:32.740 --> 00:24:39.600
Mike Felder doesn't Pydantic include call validators too.

00:24:39.600 --> 00:24:40.940
So I'm not sure how that relates.

00:24:40.940 --> 00:24:42.240
I don't know if that's out of beta.

00:24:42.240 --> 00:24:46.400
Last time I looked at it, it was still in like a testing phase.

00:24:46.400 --> 00:24:47.700
It may be out there.

00:24:47.700 --> 00:24:50.160
I mean, there's a ton of work that's happened on Pydantic.

00:24:50.160 --> 00:24:51.320
It's all been redone.

00:24:51.320 --> 00:24:53.100
So I don't know the status of that.

00:24:53.100 --> 00:24:53.820
Maybe Mike does.

00:24:53.820 --> 00:24:54.360
Okay.

00:24:54.500 --> 00:24:57.460
And then also, is there a mypy plugin that does that?

00:24:57.460 --> 00:25:01.500
I don't, I don't, I wasn't aware that mypy could be used at runtime, but.

00:25:01.500 --> 00:25:05.240
I wasn't aware mypy could be used at runtime either, but perhaps.

00:25:05.240 --> 00:25:06.080
Yeah.

00:25:06.080 --> 00:25:06.580
Anyway.

00:25:06.580 --> 00:25:10.300
But anyway, this, this looks pretty, you know, quite straightforward, pretty useful.

00:25:10.300 --> 00:25:14.300
You just do type ins, you put app bear type on it and it, it makes sure that it behaves.

00:25:14.300 --> 00:25:14.920
Yeah.

00:25:14.920 --> 00:25:19.420
So to do what you were looking at, sorry, to do where you might want to turn it off in production,

00:25:19.420 --> 00:25:21.400
but run it in testing, which is reasonable.

00:25:21.400 --> 00:25:23.860
I don't see any mechanism for that.

00:25:23.860 --> 00:25:24.520
There may be.

00:25:24.520 --> 00:25:25.000
Yeah.

00:25:25.000 --> 00:25:27.220
But it's a, it's a decorator mechanism.

00:25:27.220 --> 00:25:29.800
So you could, you could work around it if you needed to.

00:25:29.800 --> 00:25:35.260
Well, you could just write a decorator that looks whether that setting is on or off and

00:25:35.260 --> 00:25:39.200
either returns the bear type wrap thing or the direct function directly.

00:25:39.200 --> 00:25:43.940
And it would be like zero runtime cost once it's turned off because the function is replaced

00:25:43.940 --> 00:25:44.480
with itself.

00:25:44.480 --> 00:25:44.920
Yeah.

00:25:44.920 --> 00:25:47.140
Otherwise it's replaced by the bear type decorated one.

00:25:47.140 --> 00:25:47.380
Right.

00:25:47.420 --> 00:25:50.680
So you could, you might have to write like 10 lines of Python.

00:25:50.680 --> 00:25:51.320
Yeah.

00:25:51.320 --> 00:25:52.680
Then you've got that feature, right?

00:25:52.680 --> 00:25:57.180
The other thing is how much of your code are you really going to want to throw bear type

00:25:57.180 --> 00:25:58.920
decorators around all over the place?

00:25:58.920 --> 00:25:59.180
Yeah.

00:25:59.180 --> 00:26:00.200
That's a good point.

00:26:00.200 --> 00:26:01.520
Maybe just the boundary, right?

00:26:01.520 --> 00:26:01.940
Yeah.

00:26:01.940 --> 00:26:03.680
At the API level or something.

00:26:03.680 --> 00:26:03.820
Yeah.

00:26:03.820 --> 00:26:04.200
Exactly.

00:26:04.200 --> 00:26:04.900
Exactly.

00:26:04.900 --> 00:26:05.540
Yeah.

00:26:05.540 --> 00:26:06.280
Cool.

00:26:06.280 --> 00:26:06.620
Yep.

00:26:06.620 --> 00:26:07.560
Anyway, there it is.

00:26:07.560 --> 00:26:10.060
And I suppose that's it for all of our items.

00:26:10.060 --> 00:26:12.160
That's what we got lined up for you.

00:26:12.160 --> 00:26:12.760
Anything else?

00:26:12.760 --> 00:26:13.680
Some extras.

00:26:13.680 --> 00:26:14.260
I have.

00:26:14.260 --> 00:26:15.180
You want me to go first?

00:26:15.180 --> 00:26:15.840
You want to save yours?

00:26:15.840 --> 00:26:16.280
Yeah.

00:26:16.280 --> 00:26:17.200
You go first.

00:26:17.200 --> 00:26:17.700
All right.

00:26:17.700 --> 00:26:18.660
I already got my screen up anyway.

00:26:18.660 --> 00:26:19.180
Okay.

00:26:19.180 --> 00:26:26.780
So first of all, congratulations, Mike Falder, who is right here in the audience.

00:26:26.780 --> 00:26:27.260
Yeah.

00:26:27.260 --> 00:26:28.740
And I mispronounced his last name.

00:26:28.740 --> 00:26:29.020
Sorry.

00:26:29.020 --> 00:26:31.260
Hopefully I got it right.

00:26:31.260 --> 00:26:31.840
You did.

00:26:31.840 --> 00:26:32.620
I got it right.

00:26:32.620 --> 00:26:39.880
At Mike the man on Twitter is the new safety and security engineer for PyPI.

00:26:39.880 --> 00:26:41.220
That's awesome, Mike.

00:26:41.220 --> 00:26:42.060
Thank you so much.

00:26:42.060 --> 00:26:42.560
Cool.

00:26:42.680 --> 00:26:45.020
Clearly an area that needs lots of attention.

00:26:45.020 --> 00:26:47.440
So I just wanted to say welcome.

00:26:47.440 --> 00:26:49.260
Thanks for keeping us all safe out there.

00:26:49.260 --> 00:26:51.140
And excellent.

00:26:51.140 --> 00:26:51.660
Yeah.

00:26:51.660 --> 00:26:53.640
I got to hang out with Mike a lot at PyCon.

00:26:53.640 --> 00:26:55.160
So that's really pretty cool.

00:26:55.160 --> 00:26:55.980
Yeah.

00:26:55.980 --> 00:26:56.300
Thanks.

00:26:56.300 --> 00:26:56.640
Super cool.

00:26:56.640 --> 00:26:57.140
Super cool.

00:26:57.380 --> 00:27:00.700
And then a couple of quick announcements, two conferences for people.

00:27:00.700 --> 00:27:03.820
Packaging Con, follow up on all of your items, Brian.

00:27:03.820 --> 00:27:04.820
Packaging Con.

00:27:04.820 --> 00:27:05.400
Cool.

00:27:05.400 --> 00:27:07.820
Is happening fully online.

00:27:07.820 --> 00:27:08.760
No, hold on.

00:27:08.760 --> 00:27:08.960
No.

00:27:09.000 --> 00:27:10.740
It's happening in Berlin as hybrid.

00:27:10.740 --> 00:27:18.260
So it's in Berlin, October 26 to 28 for all things packaging, Python people, Rust people,

00:27:18.260 --> 00:27:18.760
et cetera.

00:27:18.760 --> 00:27:20.580
So check that out.

00:27:20.580 --> 00:27:24.660
And the Cloud Builders Python Conf is September 6, 2023.

00:27:24.660 --> 00:27:27.100
That's put together by a Ukrainian group.

00:27:27.100 --> 00:27:28.460
And it's just online.

00:27:28.460 --> 00:27:30.740
So people can check that out as well.

00:27:30.740 --> 00:27:34.220
And speakers, are they still have a call for proposals?

00:27:34.220 --> 00:27:35.820
Doesn't look like it.

00:27:35.820 --> 00:27:36.480
I think it's open.

00:27:36.480 --> 00:27:39.380
It's already all set for the agenda.

00:27:39.380 --> 00:27:40.680
So people can check that out.

00:27:40.680 --> 00:27:41.480
It should be fun.

00:27:41.480 --> 00:27:43.060
And on to your big news.

00:27:43.060 --> 00:27:43.660
Okay.

00:27:43.660 --> 00:27:48.580
Well, a couple, just a couple notes that I wanted to mention.

00:27:48.580 --> 00:27:54.080
The August release of Visual Studio Code has something I've been long awaiting.

00:27:54.080 --> 00:27:56.580
It's an error tolerant pytest discovery.

00:27:56.580 --> 00:27:58.220
So what does this mean?

00:27:58.220 --> 00:28:01.860
It means you've got, and there's like some comments down here.

00:28:01.860 --> 00:28:03.040
Oh, I went too far.

00:28:03.040 --> 00:28:05.360
You have to turn it on right now.

00:28:05.520 --> 00:28:06.980
But it's just in a setting.

00:28:06.980 --> 00:28:09.260
Apparently, some people have it on by default.

00:28:09.260 --> 00:28:11.020
Anyway, they should just turn it on.

00:28:11.020 --> 00:28:11.480
It's better.

00:28:11.480 --> 00:28:18.720
But the gist is, if you've got like errors in some of your code, it used to not.

00:28:18.720 --> 00:28:19.940
It used to just blow up.

00:28:19.940 --> 00:28:21.540
Like, let's say you've got a test suite.

00:28:21.540 --> 00:28:26.720
But you also have like some old junk tests off in a side directory that you don't use anymore.

00:28:26.960 --> 00:28:32.880
If they had import errors or syntax errors or whatever, it would just blow up the whole thing and you couldn't get any tests to import.

00:28:32.880 --> 00:28:39.240
Now, it's tolerant and it just turns off the, it doesn't, it doesn't import those tests that have import errors.

00:28:39.240 --> 00:28:40.000
That's great.

00:28:40.000 --> 00:28:41.500
So you can still run the rest of the suite.

00:28:41.760 --> 00:28:42.560
So that's good.

00:28:42.560 --> 00:28:45.080
Be kind of still kind of cool.

00:28:45.080 --> 00:28:45.920
There's a couple of things.

00:28:45.920 --> 00:28:51.000
Be kind of cool if it could tell you which ones have had errors instead of just making them disappear.

00:28:51.000 --> 00:28:51.740
So that'd be neat.

00:28:52.340 --> 00:28:55.700
The other thing is, guys, pytest isn't capitalized.

00:28:55.700 --> 00:28:59.480
So you've got to work on your capitalization, non-capitalization.

00:28:59.480 --> 00:29:01.920
But discovery probably should be.

00:29:01.920 --> 00:29:02.820
Oh, yeah.

00:29:02.820 --> 00:29:03.300
Oh, yeah.

00:29:03.300 --> 00:29:04.320
Discovery should be.

00:29:04.320 --> 00:29:04.880
Oh.

00:29:04.880 --> 00:29:05.760
That's all right.

00:29:05.760 --> 00:29:06.720
That's tough.

00:29:06.720 --> 00:29:07.240
Anyway.

00:29:07.240 --> 00:29:10.220
I always, I'm always unsure about my capitalization.

00:29:10.220 --> 00:29:13.020
It's so formal to capitalize everything.

00:29:13.020 --> 00:29:19.860
It's this time of year again, we got Python 3.12, release candidate 1.

00:29:20.200 --> 00:29:24.060
So we're in the release candidates for Python 3.12.

00:29:24.060 --> 00:29:24.800
It's pretty exciting.

00:29:24.800 --> 00:29:27.140
Release candidate is a big deal, though, right?

00:29:27.140 --> 00:29:31.520
It's, we think this is the final version unless there's something gone wrong.

00:29:31.520 --> 00:29:31.980
Yeah.

00:29:31.980 --> 00:29:34.060
It's right out of beta.

00:29:34.060 --> 00:29:44.940
So anyway, speaking of beta, the big news for today is that I've got a Python testing with pytest bundle course up.

00:29:44.940 --> 00:29:47.320
And I'm super excited about it.

00:29:47.320 --> 00:29:48.640
I'm working really hard.

00:29:48.980 --> 00:29:54.840
However, it is in pre-release, pre-release beta.

00:29:54.840 --> 00:29:55.360
I don't know.

00:29:55.360 --> 00:29:56.900
I made up something that.

00:29:56.900 --> 00:29:57.520
Early bird.

00:29:57.520 --> 00:29:58.720
Early bird sort of.

00:29:58.720 --> 00:30:00.240
Early beta bird.

00:30:00.240 --> 00:30:00.560
Yeah.

00:30:00.560 --> 00:30:02.280
So what is going on?

00:30:02.280 --> 00:30:07.040
So there's, in the end, it's going to be, actually, I wrote it.

00:30:07.160 --> 00:30:13.460
I included on here is a video that is got like, welcome to the pre-release beta.

00:30:13.460 --> 00:30:14.200
And what does that mean?

00:30:14.200 --> 00:30:14.640
Video.

00:30:14.640 --> 00:30:15.400
So you can watch that.

00:30:15.900 --> 00:30:21.260
The gist of it is, is the three sections of the book are going to go into three different courses.

00:30:21.260 --> 00:30:27.740
But the pre-release right now that's for sale is a bundle of all that will be all three.

00:30:28.540 --> 00:30:33.560
There's two chapters ready for, for the primary power for the first part.

00:30:33.560 --> 00:30:37.700
And, but I'm just going to chug along and people can jump in if they want.

00:30:37.700 --> 00:30:45.000
I'm, I'm doing it as a beta because the book itself really is better because of the beta program that I did when I was writing the book.

00:30:45.000 --> 00:30:54.180
And I'd love to have people come in and let me know where things need a little polish and we can, you know, we can fix it along the way.

00:30:54.180 --> 00:31:02.420
I also am setting up a job or not a job board, a discussion board for people to ask questions if they get stuck.

00:31:02.420 --> 00:31:08.920
I really want to make sure everybody's successful in getting, getting this up and running, getting up and running and py test quickly.

00:31:08.920 --> 00:31:11.560
So totally excited about getting this done.

00:31:11.560 --> 00:31:23.580
Oh, one more thing I set up, I just, just launched it last night, but, for Python bytes listeners, you can use the coupon code Python bytes with a Y.

00:31:23.580 --> 00:31:34.580
So, and, he, we'll just throw that in the show notes, use Python bytes, with a Y and you can get 20% discount now through the end of the 17th.

00:31:34.580 --> 00:31:36.440
So just a few days.

00:31:36.440 --> 00:31:39.240
but, that's enough time to grab it.

00:31:39.240 --> 00:31:39.880
So cool.

00:31:39.880 --> 00:31:40.260
Yeah.

00:31:40.260 --> 00:31:40.540
Awesome.

00:31:40.540 --> 00:31:41.520
Congrats on this, Brian.

00:31:41.520 --> 00:31:42.720
And this will be exciting.

00:31:42.720 --> 00:31:44.260
And I know it's a lot of work, so.

00:31:44.260 --> 00:31:45.960
Yeah.

00:31:45.960 --> 00:31:46.440
Good luck.

00:31:46.440 --> 00:31:46.980
Thanks.

00:31:46.980 --> 00:31:48.840
Yeah, absolutely.

00:31:48.840 --> 00:31:53.660
Oh, you know what else is a lot of work and ties back to my first item, learning JavaScript.

00:31:53.660 --> 00:31:54.800
Let's make that our joke.

00:31:54.800 --> 00:31:55.260
Okay.

00:31:55.260 --> 00:31:56.140
All right.

00:31:56.140 --> 00:31:57.800
So here's the text.

00:31:57.800 --> 00:32:03.780
It looks like a WhatsApp conversation that somebody got, unfortunately from their apartment manager.

00:32:03.780 --> 00:32:06.360
And of course it's addressed to Michael, which is extra funny.

00:32:06.360 --> 00:32:07.120
Hello, Michael.

00:32:07.320 --> 00:32:10.380
Your apartment has received the second complaint.

00:32:10.380 --> 00:32:12.940
noise from the apartment is the problem.

00:32:12.940 --> 00:32:13.860
The dog whines.

00:32:13.860 --> 00:32:16.700
Apparently you leave one home and the dog gets bored.

00:32:16.700 --> 00:32:18.420
Please address this.

00:32:18.420 --> 00:32:20.320
The response from Michael is hello.

00:32:20.320 --> 00:32:21.080
I don't have a dog.

00:32:21.080 --> 00:32:22.320
This is me learning JavaScript.

00:32:22.320 --> 00:32:25.320
Like screaming and yelling and kicking.

00:32:25.320 --> 00:32:27.760
Oh, a dog whines.

00:32:27.760 --> 00:32:28.200
Okay.

00:32:28.200 --> 00:32:29.440
Oh.

00:32:29.440 --> 00:32:31.780
Yeah.

00:32:31.780 --> 00:32:33.080
That's pretty good.

00:32:33.080 --> 00:32:34.020
That is pretty funny.

00:32:34.020 --> 00:32:35.440
It could be like learning all sorts of programs.

00:32:35.440 --> 00:32:37.000
It could be learning Python, but yeah.

00:32:37.000 --> 00:32:38.280
It feels a little extra special.

00:32:38.280 --> 00:32:39.420
A little extra special there.

00:32:39.780 --> 00:32:41.080
Have you got your web pack working?

00:32:41.080 --> 00:32:43.020
Have you got your requires working?

00:32:43.020 --> 00:32:46.580
have you got your transpiler working yet?

00:32:46.580 --> 00:32:49.940
Man, that was me with like trying to relearn CSS.

00:32:49.940 --> 00:32:56.040
so first time I learned CSS, we didn't have all these like pre compilers and stuff.

00:32:56.040 --> 00:32:59.160
so CSS is a completely different ball game now.

00:32:59.160 --> 00:32:59.480
So.

00:32:59.480 --> 00:33:00.160
Yeah.

00:33:00.160 --> 00:33:00.500
Yeah.

00:33:00.500 --> 00:33:02.080
Well, yeah, it's crazy stuff.

00:33:02.080 --> 00:33:02.900
Cool.

00:33:02.900 --> 00:33:04.880
Well, anyway, this is my joke for everyone.

00:33:04.880 --> 00:33:06.400
We've received a noise complaint.

00:33:06.400 --> 00:33:06.860
I'm sorry.

00:33:06.860 --> 00:33:07.860
I don't have a dog.

00:33:08.580 --> 00:33:09.020
Awesome.

00:33:09.020 --> 00:33:10.980
Well, it was a fun episode.

00:33:10.980 --> 00:33:11.620
Thanks again.

00:33:11.620 --> 00:33:12.880
Yeah, sure was.

00:33:12.880 --> 00:33:13.580
See you later.

