WEBVTT

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

00:00:06.000 --> 00:00:12.200
This is episode 338, recorded May 30th, 2023.

00:00:12.200 --> 00:00:13.440
I'm Michael Kennedy.

00:00:13.440 --> 00:00:14.680
And I am Brian Okken.

00:00:14.680 --> 00:00:19.520
And this episode is brought to you by us, our courses and books and things like that.

00:00:19.520 --> 00:00:20.980
Talk to you more about that later.

00:00:20.980 --> 00:00:25.460
Also, connect with us on Mastodon or all over on Fosstodon,

00:00:25.460 --> 00:00:28.460
at mkennedy, @brianokken, and at Python Bytes.

00:00:28.600 --> 00:00:30.560
And we love it when people join the live show.

00:00:30.560 --> 00:00:36.540
If you want to be part of that, you can see the next scheduled upcoming one at pythonbytes.fm/live

00:00:36.540 --> 00:00:38.500
and click that notify me and YouTube.

00:00:38.500 --> 00:00:39.340
And guess what?

00:00:39.340 --> 00:00:40.500
It'll notify you when it's live.

00:00:40.500 --> 00:00:43.700
So that's the front matter, Brian.

00:00:43.700 --> 00:00:45.600
I think we should start it off with some basics.

00:00:45.600 --> 00:00:46.300
What do you think?

00:00:46.300 --> 00:00:47.840
Yeah, let's go back to the basics.

00:00:47.840 --> 00:00:49.920
Basics of Python packaging.

00:00:49.920 --> 00:00:57.040
So actually, this is something near and dear to what I've been paying a lot of attention to lately is packaging.

00:00:57.200 --> 00:00:59.200
And just how it's changed.

00:00:59.200 --> 00:01:03.740
And it's kind of in the most people have switched over to pyproject.toml now.

00:01:03.740 --> 00:01:06.500
And that's really what this is about.

00:01:06.500 --> 00:01:10.800
So when you're packaging, especially a pure Python package.

00:01:10.800 --> 00:01:13.920
Well, one of the things I like about this is it's not just for pure Python.

00:01:14.120 --> 00:01:15.440
But that's the easy part.

00:01:15.440 --> 00:01:20.720
If we're using pure Python packaging, you're probably using a pyproject.toml now.

00:01:20.720 --> 00:01:24.420
And there has been several write-ups of it.

00:01:24.420 --> 00:01:27.320
But some of them are kind of tool-centric.

00:01:27.320 --> 00:01:30.000
So I like about this write-up from JQui.

00:01:30.000 --> 00:01:31.300
Or JQui?

00:01:31.300 --> 00:01:31.880
Not sure.

00:01:32.780 --> 00:01:38.700
That talks about just sort of the easy, a fairly standard setup.

00:01:38.700 --> 00:01:43.640
So it does talk about the peps in this article.

00:01:43.640 --> 00:01:45.900
But you don't really need to know much about that.

00:01:45.900 --> 00:01:47.700
You can just kind of skip to how do I do it.

00:01:48.420 --> 00:01:58.840
So using the peps and using pyproject.toml, you do have to specify what your build backend is.

00:01:58.840 --> 00:02:04.620
So in the top example of this article, it talks about using a flit core.

00:02:04.620 --> 00:02:07.460
And that's one I've used a lot of that.

00:02:07.460 --> 00:02:10.460
But then what else do you put in there?

00:02:10.460 --> 00:02:15.800
So within the rest of the pyproject.toml is mostly metadata.

00:02:15.800 --> 00:02:18.000
You can have other stuff, too, like black and everything.

00:02:18.220 --> 00:02:23.120
But for your project building, the project metadata, there's not a lot that goes in it.

00:02:23.120 --> 00:02:25.300
I mean, it looks like a lot when you just glance.

00:02:25.300 --> 00:02:30.860
But it's really, you know, it's your name for the name of the project, the version, description of it.

00:02:30.860 --> 00:02:36.120
Your author, I will point out that this is not minimal because it includes the email.

00:02:36.120 --> 00:02:37.700
You don't have to include the email.

00:02:37.700 --> 00:02:39.380
If you don't want to, you can just put the name.

00:02:39.380 --> 00:02:42.900
And where your license and readme and classifiers are.

00:02:42.900 --> 00:02:47.340
One of the things I want to highlight is make sure you have the license.

00:02:47.460 --> 00:02:55.580
At the very least, have your license classifier listed because that's how the license shows up on the PyPI.

00:02:56.220 --> 00:02:59.520
So when PyPI is looking at projects, it looks at the classifier.

00:02:59.520 --> 00:03:05.840
And then try to throw in which Python is required and then any of your dependencies that you're using.

00:03:05.840 --> 00:03:07.080
And then some links.

00:03:07.080 --> 00:03:13.720
I mean, it's really, when you just talk about it as a stream of conscious, it seems like a lot, but it's really not that much.

00:03:13.940 --> 00:03:15.260
And you're pretty much done.

00:03:15.260 --> 00:03:17.600
You can do a build now with this.

00:03:17.600 --> 00:03:18.880
This is-

00:03:18.880 --> 00:03:22.180
I think, Brian, before you move on from that, that I just noticed that I really like.

00:03:22.180 --> 00:03:33.860
If you do a setup.py, what you've got to put is the readme and details and the descriptions and all those kinds of things, at least a long description.

00:03:33.860 --> 00:03:38.140
You've got to actually load the file and inject the content to the file.

00:03:38.140 --> 00:03:43.420
And here you just put the file names for the license and for the readme, and it'll just pull those in, right?

00:03:43.480 --> 00:03:43.800
That's cool.

00:03:43.800 --> 00:03:51.640
It is one of the things I've harassed people about before is it's weird that the readme and license are specified completely different.

00:03:51.640 --> 00:03:57.840
So the license has this, like, what, curly braces and then file equals license.

00:03:57.840 --> 00:03:58.580
Dictionary-ish.

00:03:58.580 --> 00:03:59.300
Yeah, it's a dictionary.

00:03:59.300 --> 00:04:03.080
Whereas the readme is just a text string with the name of the readme.

00:04:03.080 --> 00:04:05.040
It's odd.

00:04:05.040 --> 00:04:11.040
I think that maybe we could have it so the license could just be a string with the license file on it also.

00:04:11.300 --> 00:04:15.140
But anyway, there's probably reasons, I'm sure.

00:04:15.140 --> 00:04:20.280
The thing that I also want to point out is you can put as many URLs as you want in here.

00:04:20.280 --> 00:04:22.920
You can have, like, this example as homepage and bug tracker.

00:04:22.920 --> 00:04:27.620
A lot of people just list home that lists the GitHub link.

00:04:27.620 --> 00:04:30.800
But you can have your documentation and other stuff.

00:04:30.800 --> 00:04:34.840
And all these show up in PyPI also if you're published to PyPI.

00:04:34.840 --> 00:04:49.580
And if you don't want to publish to PyPI, one extra is to, that Kim reminds us of, is another classifier I learned about, is private do not upload, which tells PyPI to not upload it.

00:04:49.580 --> 00:04:51.900
So this is all great.

00:04:51.900 --> 00:04:58.500
And a lot of this also, if you want to watch it in video form, is covered in the sharing is carrying video.

00:04:58.500 --> 00:05:01.240
It's a talk I gave in PyCascades.

00:05:01.240 --> 00:05:02.840
The video is now online.

00:05:02.840 --> 00:05:04.180
We'll put a link in the show notes.

00:05:05.140 --> 00:05:15.140
But this document or this article goes through some of the different, make sure that you understand the build step of Python-M build is one way to do it.

00:05:15.140 --> 00:05:15.840
There's other ways.

00:05:15.840 --> 00:05:24.280
But then it talks about some of the discussion around why pyproduct.toml is there instead of setup.py.

00:05:24.280 --> 00:05:26.000
I think we're all convinced, hopefully.

00:05:26.620 --> 00:05:28.800
But then also some choices of backends.

00:05:28.800 --> 00:05:31.800
So this article used Flit Core to start with.

00:05:31.800 --> 00:05:36.520
But there's also Hatchling and setup tools and Poetry Core.

00:05:36.520 --> 00:05:39.480
So why would you choose different ones?

00:05:39.480 --> 00:05:42.960
And one of the, and it's because there's extra features.

00:05:42.960 --> 00:05:46.020
Some of them allow extra tags to go in there.

00:05:46.340 --> 00:06:00.700
And the example they're using, and that's one of the reasons why I use Hatch a lot, is you can have include and exclude things to say, you know, the normal stuff that you'd probably include in a source distribution.

00:06:00.700 --> 00:06:04.440
Also add the tests, for instance, or something else.

00:06:04.440 --> 00:06:12.900
The test is one that, like, distributors, redistributors, like Linux distros, like to have your tests in the source distribution.

00:06:12.900 --> 00:06:15.780
So throwing those in there is a good idea.

00:06:16.100 --> 00:06:18.020
I'm not sure why they're in there by default.

00:06:18.020 --> 00:06:21.680
But anyway, it's a cool discussion.

00:06:21.680 --> 00:06:27.240
One of the things I also love is it talks about what happens if you're not just Python.

00:06:27.240 --> 00:06:28.900
What if you have to include C?

00:06:28.900 --> 00:06:31.420
Well, it doesn't really discuss it too much.

00:06:31.420 --> 00:06:32.800
It just points you in the right direction.

00:06:32.800 --> 00:06:38.500
So if you have C or C++ extension, there's a Psykit build core that you can use.

00:06:38.500 --> 00:06:39.840
I haven't tried any of these.

00:06:39.840 --> 00:06:43.140
If you're into Mason, you can use Mason Python.

00:06:43.780 --> 00:06:46.180
And then also setup tool supports it.

00:06:46.180 --> 00:06:49.120
So there's a direction for that sort of stuff.

00:06:49.120 --> 00:06:49.640
Yeah.

00:06:49.640 --> 00:06:51.040
Straightforward.

00:06:51.040 --> 00:06:52.040
Back to the basics.

00:06:52.040 --> 00:06:52.560
I like it.

00:06:52.560 --> 00:06:52.940
Yeah.

00:06:52.940 --> 00:06:55.160
Definitely demystify some of that.

00:06:55.160 --> 00:07:01.640
Henry points out in the audience, the license key will likely change via PEP 649.

00:07:01.820 --> 00:07:04.260
And currently, Flit just ignores whatever you put there.

00:07:04.260 --> 00:07:08.420
The Trove classifiers are the canonical location for the license.

00:07:08.420 --> 00:07:10.520
So just FYI.

00:07:10.520 --> 00:07:11.780
Thanks for that, Henry.

00:07:11.780 --> 00:07:15.820
He always has such excellent extra information, background information.

00:07:15.820 --> 00:07:18.880
And we're so lucky to have some smart people show up on the chat.

00:07:18.880 --> 00:07:19.600
So thank you.

00:07:19.820 --> 00:07:20.400
Yes, absolutely.

00:07:20.400 --> 00:07:22.100
All right.

00:07:22.100 --> 00:07:23.580
Let's talk vectors.

00:07:23.580 --> 00:07:26.280
So I want to talk about VEX.

00:07:26.280 --> 00:07:31.540
And this project comes to us from Olly, who open sourced this, Olly Rice.

00:07:31.540 --> 00:07:36.660
Now, before I actually tell you about what VEX is and what it does, let's take a step back

00:07:36.660 --> 00:07:41.860
and talk about the PG vector extension for Postgres, the database.

00:07:41.860 --> 00:07:46.200
So this is an open source because VEX has to like build on top of this.

00:07:46.200 --> 00:07:52.700
So this is an open source vector similarity search extension for Postgres.

00:07:52.700 --> 00:07:58.180
So you can do things like given a bunch of points in different dimensions.

00:07:58.180 --> 00:08:03.820
This could be XY, could be XYZ, could be, you know, temperature and time.

00:08:03.820 --> 00:08:04.340
I don't know.

00:08:04.340 --> 00:08:04.720
Right.

00:08:04.720 --> 00:08:06.540
It could be whatever you come up with.

00:08:06.540 --> 00:08:11.600
It'll give you the exact and approximate nearest neighbors, allow you to query that, like

00:08:11.600 --> 00:08:16.440
given some measurement, what other measurement is closest or give me the five measurements

00:08:16.440 --> 00:08:18.520
or positions that are closest to this.

00:08:18.520 --> 00:08:20.560
Gives you L2 distance.

00:08:20.560 --> 00:08:22.800
It'll do the inner product and cosine distance.

00:08:22.800 --> 00:08:25.380
So different metrics, if that makes sense.

00:08:25.380 --> 00:08:29.320
And any language with a Postgres client can speak to it.

00:08:29.320 --> 00:08:30.280
It's pretty cool, right?

00:08:30.280 --> 00:08:30.840
Yeah.

00:08:30.840 --> 00:08:31.320
Yeah.

00:08:31.320 --> 00:08:32.940
So let me see if I can find some examples.

00:08:33.160 --> 00:08:37.960
So I can say, get me the nearest neighbor by L2 distance.

00:08:38.380 --> 00:08:51.600
And it says the way you would do that directly is you say, select star from items, order by embedding, whatever the value is, is closest to, in this case, the vector value 3, 1, 2.

00:08:51.760 --> 00:08:54.000
And then limit 5, just like you do in databases.

00:08:54.000 --> 00:08:55.200
You know, give me the first 5.

00:08:55.200 --> 00:08:57.360
So order by closest to farthest.

00:08:57.360 --> 00:08:58.400
And then just give me 5.

00:08:58.400 --> 00:09:00.160
That'll give you the 5 nearest, right?

00:09:00.160 --> 00:09:02.300
You could do things like sort by distance.

00:09:03.160 --> 00:09:04.660
You can find exact matches.

00:09:04.660 --> 00:09:06.700
And you can also do other database things.

00:09:06.700 --> 00:09:07.820
Let's see.

00:09:07.820 --> 00:09:12.980
Like, give me where the ID is or is not equal to some value, and so on.

00:09:12.980 --> 00:09:13.460
All right.

00:09:13.460 --> 00:09:14.820
So pretty neat.

00:09:14.820 --> 00:09:19.920
Now, that's the pg vector extension just for Postgres.

00:09:19.920 --> 00:09:23.940
So you're speaking to it in a special flavor of SQL, sort of.

00:09:24.140 --> 00:09:29.520
In Python, you can talk to this using this thing called VEX, okay?

00:09:29.520 --> 00:09:41.460
So with VEX, you just pip install it, and then you insert a bunch of vectors, and then you can write queries that are more API-based, I guess, not just direct SQL statements.

00:09:41.460 --> 00:09:47.160
So you give it the vector that you want to query against, and then, you know, like how many you want back.

00:09:47.660 --> 00:09:55.360
If there's a filter to say, I only want the ones for a certain year, right, filter it down, and then do that query based on distance or whatever.

00:09:55.360 --> 00:09:56.900
So pretty cool.

00:09:56.900 --> 00:10:01.120
If people are out there doing that kind of work, I think they might find this pretty helpful.

00:10:01.120 --> 00:10:02.260
Yeah.

00:10:02.260 --> 00:10:03.200
Very.

00:10:03.200 --> 00:10:04.020
Oops.

00:10:04.020 --> 00:10:13.900
It's not something that I have exact direct use for these days, but, you know, a lot of scientific or geospatial type of things seems relevant.

00:10:13.900 --> 00:10:14.760
Yeah.

00:10:14.860 --> 00:10:19.560
I've been spending more and more time in SQL queries lately, so anything to help with that is good.

00:10:19.560 --> 00:10:20.280
Yeah, absolutely.

00:10:20.280 --> 00:10:21.880
Now, one final thing.

00:10:21.880 --> 00:10:27.000
It says in here, it says you've got to have, I can't remember which one, talked about getting Postgres.

00:10:27.000 --> 00:10:31.940
One of them, yeah, this one says, if you don't have a Postgres database, see some hosting options.

00:10:31.940 --> 00:10:36.300
And if you're on Mac, I just want to throw out there really quick, postgresapp.com.

00:10:36.300 --> 00:10:45.820
All you do for this one is, it's super awesome, you download it, you unzip it or un-DMG, whatever its packaging format is, and it's just a postgres.app.

00:10:45.820 --> 00:10:47.440
You double-click it, Postgres is running.

00:10:47.440 --> 00:10:48.940
You close it, Postgres is not running.

00:10:48.940 --> 00:10:50.320
It auto-updates itself.

00:10:50.320 --> 00:10:50.820
Yeah.

00:10:50.820 --> 00:10:52.420
So pretty sweet.

00:10:52.420 --> 00:10:53.380
And it's open source, too.

00:10:53.380 --> 00:10:54.040
Cool.

00:10:54.040 --> 00:10:54.580
Neat.

00:10:54.820 --> 00:10:55.100
Yeah.

00:10:55.100 --> 00:10:56.240
Yeah, very neat.

00:10:56.240 --> 00:10:57.780
I'll be needing that very soon.

00:10:57.780 --> 00:10:58.720
Yeah.

00:10:58.720 --> 00:10:58.960
So.

00:10:58.960 --> 00:11:00.140
Yeah, cool.

00:11:00.140 --> 00:11:00.520
Check it out.

00:11:00.520 --> 00:11:01.760
Yeah, that one's, that's pretty nice.

00:11:01.760 --> 00:11:02.140
Okay.

00:11:02.140 --> 00:11:06.720
Now, before we move on, Brian, brought to you by us, this episode is.

00:11:06.720 --> 00:11:11.680
So I wanted to remind people to, you know, please check out the brand new Talk Python training apps.

00:11:11.680 --> 00:11:14.440
They're rebuilt for iOS and Android.

00:11:14.440 --> 00:11:17.000
I really think it's a cool experience for people to take it.

00:11:17.000 --> 00:11:22.560
It has offline playback and obviously way better on the mobile and tablet type of things.

00:11:22.700 --> 00:11:28.820
And it comes with six free courses that you can just tap on and join the free courses plus anything you might have gotten.

00:11:28.820 --> 00:11:30.020
So check that out.

00:11:30.020 --> 00:11:33.360
And I want to shout out your book or what do you want to shout out today?

00:11:33.360 --> 00:11:33.820
Yeah.

00:11:33.820 --> 00:11:40.480
Well, there's, there's, time is running out, but the, yeah, let's, the book is still on a promo.

00:11:40.480 --> 00:11:45.920
So Python testing with pytest, there is, what is the promo?

00:11:45.920 --> 00:11:48.680
It is spring 2023.

00:11:48.680 --> 00:11:50.940
All caps, all one word.

00:11:50.940 --> 00:11:52.540
And you get 50% off.

00:11:52.620 --> 00:11:54.540
And it's just for like today and tomorrow.

00:11:54.540 --> 00:11:56.580
I think it runs out at the end of May.

00:11:56.580 --> 00:12:01.640
But anytime you want it, there is a 25, that's 50% off.

00:12:01.640 --> 00:12:08.460
But if you want to sign up and get to their email list, you can get 50%, 25% off normally.

00:12:08.460 --> 00:12:11.040
So anyway, that's a good thing.

00:12:11.040 --> 00:12:11.740
Excellent.

00:12:11.740 --> 00:12:13.640
Also really quick follow up.

00:12:14.060 --> 00:12:18.820
Henry points out that it was actually PEP 639, not 649.

00:12:18.820 --> 00:12:19.700
Not a typo there.

00:12:19.700 --> 00:12:20.100
Yeah.

00:12:20.100 --> 00:12:24.900
So 639 is improved license clarity with better package metadata.

00:12:24.900 --> 00:12:29.560
It's in draft, but hopefully there'll be, it's in draft really?

00:12:29.900 --> 00:12:35.660
Anyway, some changes to how you specify the license, which would be good.

00:12:35.660 --> 00:12:37.140
All right.

00:12:37.140 --> 00:12:38.840
Let's talk about plagues next.

00:12:38.840 --> 00:12:40.300
Plagues?

00:12:40.300 --> 00:12:43.020
Like, you know, locusts and grasshoppers?

00:12:43.020 --> 00:12:44.480
Yes, exactly.

00:12:44.480 --> 00:12:45.560
Nice.

00:12:45.560 --> 00:12:47.680
No, I like these kind of plagues.

00:12:47.680 --> 00:12:48.540
These are awesome tools.

00:12:48.840 --> 00:12:51.300
So I've used locusts before.

00:12:51.300 --> 00:12:53.440
I think you've used locusts for-

00:12:53.440 --> 00:12:54.180
I love locusts.

00:12:54.180 --> 00:12:54.360
Yeah.

00:12:54.360 --> 00:12:55.160
For load testing.

00:12:55.160 --> 00:12:55.820
So good.

00:12:55.820 --> 00:13:01.140
So there's a company, AlterX, maybe?

00:13:01.140 --> 00:13:05.640
Anyway, they've introduced grasshoppers.

00:13:05.640 --> 00:13:07.540
So it's a locust grasshopper.

00:13:07.540 --> 00:13:12.860
It's an open source Python library for load testing, but it's built on locusts.

00:13:12.860 --> 00:13:14.640
So what's the difference?

00:13:15.020 --> 00:13:23.740
So we're linking to an article that discusses the introduction and discusses why they love locusts and everything, which is great.

00:13:23.740 --> 00:13:28.100
But they have a check, like grasshopper, what does it add?

00:13:28.100 --> 00:13:36.640
Well, it adds a whole bunch of really cool features that you might need if you're load testing and developing a package and keeping track of your load testing over time.

00:13:36.640 --> 00:13:39.120
So it has these extra checks in here.

00:13:39.520 --> 00:13:48.260
And checks, if I get this right, are things like special validation functions, Boolean functions that can run.

00:13:48.260 --> 00:13:54.240
And you can tell different checks whether or not they're passing or failing over time, which is based on your-

00:13:54.240 --> 00:13:54.240
I see.

00:13:54.240 --> 00:13:59.660
The document had this text in it to make sure it wasn't insane in the response or something.

00:13:59.960 --> 00:14:01.580
Yeah, actually, I'm not quite sure.

00:14:01.580 --> 00:14:03.020
So I'd have to dig into that more.

00:14:03.020 --> 00:14:13.040
But one of the things I really like is these custom trends, which custom trends and timing thresholds and integration with pytest.

00:14:13.040 --> 00:14:14.020
Of course, that's awesome.

00:14:14.020 --> 00:14:17.180
Time series database integration and reporting.

00:14:17.180 --> 00:14:18.580
This all sounds great.

00:14:18.720 --> 00:14:26.700
One of the things I really love that's talked about in the readme a little bit more is this idea of, like, tagging your test suite.

00:14:26.700 --> 00:14:28.140
So tag-based suites.

00:14:28.140 --> 00:14:34.500
So you can see your load test results based on different versions.

00:14:34.500 --> 00:14:45.080
So if you're tagging with using version tagging on your repo, you can see what the progression is and how well your application is doing based on different load requirements.

00:14:45.080 --> 00:14:46.960
And you can have thresholds.

00:14:46.960 --> 00:14:51.940
Like, with this load, you need to have, like, 90% of the speeds of things.

00:14:51.940 --> 00:14:54.320
The other thing is some speed thresholds.

00:14:54.320 --> 00:15:05.320
Like, you can have multiple timing little functions that have multiple time, multiple HTTP requests.

00:15:05.320 --> 00:15:11.320
So an action that really is like a user action often is several interactions.

00:15:11.320 --> 00:15:14.000
Like, how fast can somebody log in or something like that?

00:15:14.000 --> 00:15:15.480
Or go through the checkout.

00:15:15.480 --> 00:15:18.000
That's going to be a multiple sequence thing.

00:15:18.000 --> 00:15:21.200
You can time that under load and under stress.

00:15:21.200 --> 00:15:23.040
And that's a pretty cool addition.

00:15:23.040 --> 00:15:29.640
Or even to load this page, we're going to, it's probably some complicated JavaScript front end.

00:15:29.640 --> 00:15:34.400
So it's going to call this API and that API and that API just to load this HTML page.

00:15:34.400 --> 00:15:34.720
Yeah, sure.

00:15:34.720 --> 00:15:40.480
So you kind of want to treat that as, like, the page is loaded when these seven API calls finish, right?

00:15:40.480 --> 00:15:41.460
Something like that.

00:15:41.460 --> 00:15:41.900
Yeah.

00:15:41.900 --> 00:15:45.900
Because they're not using HTTPX like they should or HTMX like they should.

00:15:45.900 --> 00:15:50.640
Also, a nice shout out to a sponsor there, InfluxDB.

00:15:50.640 --> 00:15:52.880
So pythonbyes.fm slash InfluxDB.

00:15:52.880 --> 00:15:55.740
This is the time series database that it integrates into.

00:15:55.740 --> 00:15:59.360
When I looked at this, Brian, I'm like, yeah, but Locus is pretty awesome.

00:15:59.360 --> 00:16:04.500
Why would somebody go create another one of these for the Python world when Locus exists?

00:16:04.500 --> 00:16:05.520
And then I read it.

00:16:05.520 --> 00:16:07.220
It's like, oh, we've extended Locus.

00:16:07.220 --> 00:16:08.520
Oh, and here's why.

00:16:08.520 --> 00:16:09.660
And they give some pretty good reasons.

00:16:09.660 --> 00:16:11.880
Another trend that would be cool.

00:16:11.960 --> 00:16:17.100
I don't know if you can actually measure it here, but it talks about custom trends is one of the things you can track.

00:16:17.100 --> 00:16:23.100
Things like CPU load and memory load on the server would be really interesting.

00:16:23.100 --> 00:16:29.680
Or, you know, maybe CPU load on the database server while we're hammering the web server.

00:16:29.680 --> 00:16:33.160
If you could pull those kinds of things in, that would be really cool.

00:16:33.160 --> 00:16:34.240
Yeah, maybe you can.

00:16:34.240 --> 00:16:34.920
Yeah, maybe.

00:16:34.920 --> 00:16:38.520
I kind of get the sense that it might be possible, but let's see.

00:16:38.520 --> 00:16:39.700
Not sure.

00:16:39.700 --> 00:16:42.340
But very cool.

00:16:42.340 --> 00:16:43.800
Yeah, this looks nice.

00:16:43.800 --> 00:16:44.700
It's definitely worth checking out.

00:16:44.700 --> 00:16:49.440
Some of the check functions, you might be able to, like, abuse that for that purposes, too.

00:16:49.440 --> 00:16:56.160
While your load tester is running, check CPU levels and stuff like that.

00:16:56.160 --> 00:16:56.600
I don't know.

00:16:56.600 --> 00:16:57.260
Yeah, exactly.

00:16:57.260 --> 00:17:00.040
So anyway, neat project.

00:17:00.040 --> 00:17:01.880
Yeah, that's a good project.

00:17:01.880 --> 00:17:03.720
So Grasshopper, right?

00:17:03.720 --> 00:17:04.180
Yeah.

00:17:04.180 --> 00:17:08.260
Oh, one of the things that they talk about in the...

00:17:08.260 --> 00:17:13.680
I wasn't clear on it because I went and looked at PyPI and looked for Grasshopper, and I found the wrong one.

00:17:14.040 --> 00:17:16.740
So it's locust-grasshopper.

00:17:16.740 --> 00:17:22.760
So that's the GitHub repos under that, and that's what you pip install also is locust-grasshopper.

00:17:22.760 --> 00:17:23.800
So just to be clear.

00:17:23.800 --> 00:17:24.180
Got it.

00:17:24.180 --> 00:17:28.680
I wonder if it's like a superset, probably.

00:17:28.680 --> 00:17:29.060
Yeah.

00:17:29.060 --> 00:17:34.900
So if I have already written a bunch of locust tests, could I run them, or how easy is it to...

00:17:34.900 --> 00:17:38.540
I don't know, but I imagine it's not that bad to convert.

00:17:38.540 --> 00:17:38.860
Yeah.

00:17:38.860 --> 00:17:41.240
It looks like the code is super similar.

00:17:41.240 --> 00:17:50.300
So worst case, you maybe change the base class, but possibly the base class is derived from the locust base class that you use for your test cases or test suites.

00:17:50.300 --> 00:17:50.540
Yeah.

00:17:51.020 --> 00:17:53.140
Anyway, I haven't played with it yet, but it looks cool.

00:17:53.140 --> 00:17:55.080
The readme's got tons of information too.

00:17:55.080 --> 00:17:58.980
Good job on loading up the readme with lots of examples.

00:17:58.980 --> 00:17:59.680
Indeed.

00:18:01.000 --> 00:18:09.000
And before we move on, Kim says, it could possibly hook into telemetry tooling like Prometheus, which would enable metrics from other servers and stuff like that.

00:18:09.000 --> 00:18:14.460
Yeah, that's kind of what I was talking about, but not with actually concrete ways of doing it like Prometheus.

00:18:14.460 --> 00:18:15.000
So cool.

00:18:15.000 --> 00:18:15.500
Neat.

00:18:15.500 --> 00:18:16.460
Yeah.

00:18:16.460 --> 00:18:22.980
And I want to talk to you about something that is near and dear to this podcast.

00:18:23.480 --> 00:18:26.360
We talk about a lot of topics, right, Brian?

00:18:26.360 --> 00:18:27.400
Yeah.

00:18:27.400 --> 00:18:37.320
And if you go over to Python Bytes and you pick a particular episode and you scroll through here, you can see it is chock full of links.

00:18:37.960 --> 00:18:42.480
So one of the things you might want to do, you might want to say, oh, I'm listening to this.

00:18:42.480 --> 00:18:47.080
I want to remember not all of them, but just three things that I can come back to.

00:18:47.080 --> 00:18:59.020
And if you're on your iThing, your iPhone, iPad, et cetera, or even on your Mac, technically, if you've got an Apple Silicon Mac, you can use this thing called MemoCast.

00:18:59.020 --> 00:19:04.600
So MemoCast was created by Daniel Engvall.

00:19:05.600 --> 00:19:13.440
It's interesting on its own, but it's also interesting in a way to kind of script iOS with Python, which I hadn't really thought about doing.

00:19:13.440 --> 00:19:17.560
So first of all, let me tell you about MemoCast and then you can think how this might apply to you.

00:19:17.560 --> 00:19:23.940
So this is a small iOS app that allows you to add links heard about in a podcast as a reminder.

00:19:23.940 --> 00:19:28.840
So you can check them off your reminder list, you know, the at reminder app when you're done with them.

00:19:28.840 --> 00:19:30.040
So check this out.

00:19:30.040 --> 00:19:32.480
Imagine this is reading the website.

00:19:32.680 --> 00:19:40.160
Imagine you just as often as I do listen to a podcast such as Python Bytes, a fantastic one.

00:19:40.160 --> 00:19:40.840
Thank you.

00:19:40.840 --> 00:19:41.280
Thank you.

00:19:41.280 --> 00:19:48.040
Using Google Podcasts, walk around, you know, you're doing it while you're out and maybe busy, like mowing the lawn or something.

00:19:48.040 --> 00:19:48.420
Right.

00:19:48.420 --> 00:19:52.820
And then there's some thing talked about you wish you had more time to check out.

00:19:52.820 --> 00:19:58.280
Thankfully, the reference in the show notes, but you'd have to look it up and go through it and copy paste and all that.

00:19:58.280 --> 00:20:01.060
So there's a little video here.

00:20:01.060 --> 00:20:02.340
Notice this.

00:20:02.340 --> 00:20:03.000
Nice.

00:20:03.000 --> 00:20:03.900
On this page.

00:20:03.900 --> 00:20:06.600
And it shows all you got to do is say share.

00:20:06.600 --> 00:20:07.840
Go to the podcast player.

00:20:07.840 --> 00:20:08.480
Say share.

00:20:08.480 --> 00:20:09.740
Click MemoCast.

00:20:09.740 --> 00:20:11.420
And it gives it a second.

00:20:11.420 --> 00:20:14.860
Then it has a list of all the links that it's discovered in there.

00:20:14.860 --> 00:20:15.700
Isn't that cool, Brian?

00:20:15.700 --> 00:20:16.480
That is neat.

00:20:16.480 --> 00:20:16.820
Yeah.

00:20:16.820 --> 00:20:18.300
I can't really zoom that without the.

00:20:18.540 --> 00:20:22.440
I can't really zoom it without the responsive design only making it smaller.

00:20:22.440 --> 00:20:25.300
But so how is this possible?

00:20:25.300 --> 00:20:28.460
The thing you share it to is you don't share it directly to MemoCast.

00:20:28.460 --> 00:20:30.240
You say run in Pythonista.

00:20:30.240 --> 00:20:40.120
And so this is a Python script that that Daniel wrote that basically you run it through Pythonista Python 10 on iOS.

00:20:40.480 --> 00:20:49.100
It does a guessing request or something called over to our website and parses out all the links and then turns that into a UI that you can interact with.

00:20:49.100 --> 00:20:49.660
Cool, right?

00:20:49.660 --> 00:20:51.320
That's all done on the phone then?

00:20:51.320 --> 00:20:51.740
Yeah.

00:20:51.740 --> 00:20:52.120
That's pretty cool.

00:20:52.120 --> 00:20:52.640
Yeah.

00:20:52.640 --> 00:20:53.440
It's pretty cool.

00:20:54.100 --> 00:21:01.580
And so basically this is an example supports Python by Stock, Python, I mean, real Python as the three supportive podcasts.

00:21:01.580 --> 00:21:03.180
But you can integrate new ones if you wish.

00:21:03.180 --> 00:21:09.080
And you install it once you have Pythonista, which I think costs $10 US one time.

00:21:09.080 --> 00:21:14.960
But then you can install it scanning the QR code here with Pythonista and that will download it.

00:21:14.960 --> 00:21:16.740
Then you can just turn it into a thing that you can run.

00:21:16.740 --> 00:21:20.400
It also talks about how you add new podcasts if you want to add a different one.

00:21:20.400 --> 00:21:22.880
But that's somewhat interesting.

00:21:23.380 --> 00:21:33.340
I think what's more interesting is he took this Python code and the code is right here to build kind of a scriptable GUI for iOS, which I think is pretty cool.

00:21:33.340 --> 00:21:34.720
Yeah, that is nice.

00:21:34.720 --> 00:21:35.160
Cool.

00:21:35.160 --> 00:21:38.940
So talked about like I did try to do this with Kivy and other stuff.

00:21:38.940 --> 00:21:43.540
But let me tell you, the build chain and code signing and all of that is like a nightmare.

00:21:43.540 --> 00:21:48.200
And so here you just write a Python script and just run it inside of this app that already exists.

00:21:48.820 --> 00:21:52.320
And final bonus before I call all the time on this one.

00:21:52.320 --> 00:22:02.680
Daniel also discovered that if you're on a Mac with a Apple Silicon, then you can run Pythonista as an iOS app within macOS.

00:22:02.680 --> 00:22:06.280
So you go to the App Store, search for it on Mac and it doesn't come up.

00:22:06.320 --> 00:22:10.720
So then you click, say, show me tablet, you know, iPad apps, and then it'll come up.

00:22:10.720 --> 00:22:15.380
And then it integrates with your favorite IDE, such as PyCharm, and you can run it.

00:22:15.380 --> 00:22:20.780
So you can develop these little things on your Mac with a proper keyboard and everything.

00:22:20.960 --> 00:22:24.500
And then just deploy it to Pythonista on iOS.

00:22:24.500 --> 00:22:25.660
Yeah, that's pretty cool.

00:22:25.660 --> 00:22:28.780
So yeah, people can check that out, MemoCast.

00:22:28.780 --> 00:22:40.440
It's kind of cool that it's about our podcast in this way, but it's also more cool that it just kind of shows you how to take Python and leverage Pythonista a little bit more than maybe I realized you could, like an OS integration level.

00:22:40.440 --> 00:22:41.920
Yeah, I didn't know you could do that.

00:22:41.920 --> 00:22:42.560
That's cool.

00:22:42.560 --> 00:22:43.560
I did not either.

00:22:43.560 --> 00:22:44.780
Nice.

00:22:45.340 --> 00:22:57.040
And I guess before we jump out of here as well, Kim points out on Android, which I have some but not tons of experience with, you can run Python code with QPython should someone want to emulate this for Android.

00:22:57.040 --> 00:22:57.700
Thanks, Kim.

00:22:57.700 --> 00:22:58.220
Cool.

00:22:58.220 --> 00:22:59.080
All right.

00:22:59.080 --> 00:23:00.340
Is that all of our topics, Brian?

00:23:00.340 --> 00:23:02.060
That is all of our main topics.

00:23:02.060 --> 00:23:02.480
Yes.

00:23:02.480 --> 00:23:03.100
Yes.

00:23:03.100 --> 00:23:04.360
Of course, we always have extras.

00:23:04.360 --> 00:23:05.580
Yeah.

00:23:05.580 --> 00:23:05.940
I'm a joke.

00:23:05.940 --> 00:23:07.340
Any extras for you, though?

00:23:07.340 --> 00:23:08.080
Yeah.

00:23:08.080 --> 00:23:09.620
I can kick this off.

00:23:09.620 --> 00:23:11.860
So just a few.

00:23:13.220 --> 00:23:15.920
A shout out from, oh, who wrote this?

00:23:15.920 --> 00:23:16.680
I'm not sure.

00:23:16.680 --> 00:23:17.440
Hugo.

00:23:17.440 --> 00:23:19.200
Hugo Van Kimenad.

00:23:19.200 --> 00:23:23.800
Wrote, help test Python 3.12 beta.

00:23:23.800 --> 00:23:25.340
So 3.12 is in beta.

00:23:25.340 --> 00:23:32.840
If you are a package maintainer or just your own application, you may as well start testing to make sure that you don't have any surprises.

00:23:32.840 --> 00:23:42.020
So this article does talk through basically how to hook up your GitHub actions so that you're testing 3.12 also.

00:23:42.520 --> 00:23:49.780
And then whether it's the official Ubuntu latest or the Dead Snakes version, a couple ways to do it.

00:23:49.780 --> 00:23:52.840
And then even if you're using Travis CI still, bye.

00:23:52.840 --> 00:23:56.240
Anyway, you can do that with that as well.

00:23:56.240 --> 00:23:58.000
So that's the first.

00:23:58.000 --> 00:24:06.660
Secondly, I wanted to say that at the Python Software Foundation blog, there is a whole bunch of new articles.

00:24:06.980 --> 00:24:12.300
I basically wrote up, there's articles writing up all the different things that happened at the Python Language Summit.

00:24:12.300 --> 00:24:14.240
I haven't gone through these.

00:24:14.240 --> 00:24:15.040
They're just available.

00:24:15.040 --> 00:24:16.220
Wanted to shout that out.

00:24:16.220 --> 00:24:18.260
It's some interesting stuff, though.

00:24:18.500 --> 00:24:18.820
There is.

00:24:18.820 --> 00:24:22.360
I just interviewed Brett Cannon over on Talk Python about this.

00:24:22.360 --> 00:24:28.340
He gave us the walkthrough of all the presentations and thoughts at the Language Summit.

00:24:28.340 --> 00:24:28.820
Okay.

00:24:29.080 --> 00:24:36.560
And then from the news from the weird, I don't have much information about this other than on the Python Package Index blog.

00:24:36.560 --> 00:24:39.360
They say, hey, PyPI was subpoenaed.

00:24:39.360 --> 00:24:41.120
And, you know, this thing happened.

00:24:41.120 --> 00:24:43.240
And we complied and talked to lawyers.

00:24:43.240 --> 00:24:44.140
And it's weird.

00:24:44.140 --> 00:24:46.160
But, you know, it's just odd.

00:24:46.160 --> 00:24:47.240
Yeah.

00:24:47.480 --> 00:24:48.780
So how about you?

00:24:48.780 --> 00:24:49.340
Any extras?

00:24:49.340 --> 00:24:50.040
Yeah.

00:24:50.040 --> 00:24:52.840
I wonder if this has to do with some of the malware, crypto jacking.

00:24:52.840 --> 00:24:53.480
Maybe.

00:24:53.480 --> 00:24:55.200
Stuff that was uploaded to it.

00:24:55.200 --> 00:24:57.400
And they're like, all right, we're going to try to track down some of these people.

00:24:57.400 --> 00:25:03.620
There are certain places that are not allowed to say whether they received a request.

00:25:03.620 --> 00:25:04.980
And I think this is not a subpoena.

00:25:04.980 --> 00:25:07.160
This is more of a, what is it, FASA?

00:25:07.320 --> 00:25:11.720
Like the more international crime investigation laws.

00:25:11.720 --> 00:25:14.600
So we'll have a subpoena canaries.

00:25:14.600 --> 00:25:18.280
It'll be like the canary will be here unless we are subpoenaed.

00:25:18.280 --> 00:25:19.360
Then the canary is gone.

00:25:19.360 --> 00:25:20.220
We won't say anything.

00:25:20.220 --> 00:25:23.380
But we'll just, this bird won't be on the page or something anymore.

00:25:23.380 --> 00:25:24.280
So you can kind of know.

00:25:24.280 --> 00:25:26.260
But, yeah, it's kind of cool.

00:25:26.260 --> 00:25:28.340
They're being transparent about that.

00:25:28.340 --> 00:25:28.580
Yeah.

00:25:28.580 --> 00:25:36.160
One of the things that was interesting is that they got asked for addresses, including mailing and residential addresses.

00:25:36.160 --> 00:25:37.920
But they don't collect that.

00:25:37.920 --> 00:25:41.760
They just, I mean, that information isn't saved.

00:25:41.760 --> 00:25:42.680
So it's not there.

00:25:42.680 --> 00:25:42.860
Yeah.

00:25:42.860 --> 00:25:43.840
I'm sure it's a form.

00:25:43.840 --> 00:25:45.200
And like, we would like this information.

00:25:45.200 --> 00:25:46.420
Well, we don't have that.

00:25:46.420 --> 00:25:47.660
So we'll give you what we got.

00:25:47.660 --> 00:25:48.160
Yeah.

00:25:48.160 --> 00:25:49.020
Okay.

00:25:49.020 --> 00:25:49.880
Nice.

00:25:49.880 --> 00:25:50.120
All right.

00:25:50.120 --> 00:25:51.940
I got a couple of real quick ones here.

00:25:51.940 --> 00:25:53.100
Not Python.

00:25:53.100 --> 00:25:56.580
One, I wrote something called, you can ignore this post.

00:25:56.580 --> 00:25:58.300
Trying to get a lot of attention, of course.

00:25:58.300 --> 00:26:05.980
What it actually was is I just wrote about the github.com/github slash git ignore repo.

00:26:05.980 --> 00:26:12.020
Which has all, like when you go to github and you say create a new project and it says, do you want an ignore file?

00:26:12.020 --> 00:26:13.040
And it gives you a list.

00:26:13.400 --> 00:26:20.900
These are all the ignore files for every language supported there, including Python, which is in here somewhere right there.

00:26:20.900 --> 00:26:23.600
And so you can actually see what they all are.

00:26:23.600 --> 00:26:25.120
You could even do a PR.

00:26:25.120 --> 00:26:26.780
Like we really need to start ignoring.

00:26:27.200 --> 00:26:32.520
You know, if there's a new file format, that's like a build output of some new pyproject.tominal tooling.

00:26:32.520 --> 00:26:34.860
And it starts to, you know, needs to be ignored.

00:26:34.860 --> 00:26:36.780
You could say do a PR against this.

00:26:36.780 --> 00:26:39.420
So every repo on GitHub starts to adopt it.

00:26:39.460 --> 00:26:45.160
But also if you're doing, say, Python and front end stuff, you could go look for Node.

00:26:45.160 --> 00:26:51.440
And you could select one and then copy some stuff out of another to kind of create a combined one.

00:26:51.440 --> 00:26:51.780
Right.

00:26:51.780 --> 00:26:53.720
So you're not like, well, is it Node or is it Python?

00:26:53.720 --> 00:26:54.980
I really want to ignore for.

00:26:54.980 --> 00:26:59.300
So anyway, that article is just sort of about that.

00:26:59.300 --> 00:26:59.680
Really short.

00:26:59.680 --> 00:27:00.680
People can check that out.

00:27:00.840 --> 00:27:07.180
I use that all the time because I'm also on GitLab and GitLab doesn't fill those out for you.

00:27:07.180 --> 00:27:08.220
Oh, yeah.

00:27:08.220 --> 00:27:11.400
I hadn't really thought about it, but you could nab it for other purposes as well, right?

00:27:11.400 --> 00:27:11.600
Yeah.

00:27:11.600 --> 00:27:12.080
Yep.

00:27:12.080 --> 00:27:16.580
And then someone on Masset, I'll point out, you can do nox Python ignore.

00:27:16.580 --> 00:27:20.420
And I think it'll generate that file for you and uses that as the backend.

00:27:20.420 --> 00:27:21.420
I think.

00:27:21.420 --> 00:27:22.140
I think so.

00:27:22.140 --> 00:27:26.260
Some of the nox and some incantation will generate an ignore file for you.

00:27:26.260 --> 00:27:28.820
And if we have that wrong, somebody will correct us.

00:27:28.820 --> 00:27:29.800
They sure will.

00:27:29.800 --> 00:27:30.840
And we appreciate it.

00:27:30.840 --> 00:27:33.220
And speaking of incantations, are you ready for the joke?

00:27:33.220 --> 00:27:33.900
Yes.

00:27:33.900 --> 00:27:34.640
Okay.

00:27:34.640 --> 00:27:37.040
So here's the joke for developers.

00:27:37.040 --> 00:27:39.620
It says, careful where you might end up summoning a demon.

00:27:39.620 --> 00:27:45.680
And it has two categories, what you do in programming and what you do in demon summoning.

00:27:45.680 --> 00:27:49.780
So first one is you must know a language unspoken by mankind.

00:27:49.780 --> 00:27:50.920
Programming.

00:27:50.920 --> 00:27:51.220
Check.

00:27:51.220 --> 00:27:52.760
Demon summoning.

00:27:52.760 --> 00:27:53.060
Check.

00:27:53.060 --> 00:27:57.760
Requires that you be exact or suffer dire consequences.

00:27:57.760 --> 00:27:58.520
Programming.

00:27:58.520 --> 00:27:58.860
Check.

00:27:58.860 --> 00:27:59.780
Demon summoning.

00:27:59.780 --> 00:28:00.220
Check.

00:28:00.220 --> 00:28:05.700
Involves much cursing, swearing of oaths, and pleading with a higher power.

00:28:05.700 --> 00:28:06.360
Programming.

00:28:06.360 --> 00:28:06.720
Check.

00:28:06.720 --> 00:28:08.440
Demon summoning.

00:28:08.440 --> 00:28:08.700
Check.

00:28:08.700 --> 00:28:13.980
Another one is not understanding the true power you wield or the consequences of your actions.

00:28:13.980 --> 00:28:14.580
Programming.

00:28:14.580 --> 00:28:14.860
Check.

00:28:14.860 --> 00:28:15.980
Demon summoning.

00:28:15.980 --> 00:28:16.240
Check.

00:28:16.240 --> 00:28:20.900
The only differentiation, which I think is debatable, is candles.

00:28:20.900 --> 00:28:23.060
Do you use candles to accomplish this job?

00:28:23.060 --> 00:28:23.720
Programming?

00:28:23.720 --> 00:28:24.320
No.

00:28:24.320 --> 00:28:25.260
Demon summoning?

00:28:25.460 --> 00:28:25.820
Yes.

00:28:25.820 --> 00:28:25.820
Yes.

00:28:25.820 --> 00:28:27.360
And if you look over on Reddit.

00:28:27.360 --> 00:28:29.560
The comments are pretty glorious.

00:28:29.560 --> 00:28:31.400
That's funny.

00:28:31.400 --> 00:28:34.500
Let me see if I'm finding these good ones just here.

00:28:34.500 --> 00:28:42.980
Someone has said something like, I've been trying for hours to get this demon to run, and I just can't get it to work.

00:28:42.980 --> 00:28:43.920
That's what I'm writing on.

00:28:44.460 --> 00:28:46.100
Well, we're trying.

00:28:46.100 --> 00:28:47.660
Damon, not demon, right?

00:28:47.660 --> 00:28:48.160
Of course.

00:28:48.160 --> 00:28:48.660
Damon.

00:28:48.660 --> 00:28:56.720
And then someone else points out, you know, there actually is a candle app platform, which sounds truly demonic to me.

00:28:56.720 --> 00:28:57.500
So let me describe.

00:28:57.500 --> 00:28:58.560
This is like a real thing.

00:28:58.560 --> 00:28:59.160
This is not a joke.

00:28:59.160 --> 00:29:00.240
Candlescript.org.

00:29:00.240 --> 00:29:01.000
Somebody created this.

00:29:01.280 --> 00:29:05.220
Let me lay out the beautiful technologies that Candlescript combines.

00:29:05.220 --> 00:29:19.520
Are you ready to use the new open source platform that unifies core features of XSLT, XQuery, XML schema, RelaxNG, BNF, and XQuery update, and more into a single language called Candle?

00:29:19.520 --> 00:29:20.940
No, please, no.

00:29:20.940 --> 00:29:22.040
XSLT, no.

00:29:22.040 --> 00:29:24.720
Yeah, that sounds pretty demonic already.

00:29:24.720 --> 00:29:26.860
So I'm a little suspicious of that one.

00:29:27.300 --> 00:29:37.020
Yeah, and I think that actual demon summoning, they're probably worried about climate change and probably switching to low carbon lighting.

00:29:37.020 --> 00:29:37.340
Yes, yes.

00:29:37.340 --> 00:29:40.520
So probably LEDs now instead of actual candles.

00:29:40.520 --> 00:29:41.900
Yep, LEDs.

00:29:41.900 --> 00:29:43.860
Got to be careful about home automation.

00:29:43.860 --> 00:29:47.260
You might complete all the checkboxes.

00:29:47.260 --> 00:29:50.520
Yeah, I think sometimes you have to execute a child.

00:29:50.520 --> 00:29:51.420
That's funny.

00:29:51.420 --> 00:29:52.700
Child processes.

00:29:52.700 --> 00:29:54.240
Yeah, they both execute children, right?

00:29:54.240 --> 00:29:56.020
I mean, that's a pretty rough one.

00:29:56.900 --> 00:30:02.060
Kim, I believe, maybe has done enough XSLT as I have to know that it should never, ever be done.

00:30:02.060 --> 00:30:04.580
And says, Candlescript has just triggered my PTSD.

00:30:04.580 --> 00:30:07.760
Yeah, funny.

00:30:07.760 --> 00:30:09.160
Oh, the battle XML days.

00:30:09.160 --> 00:30:11.620
Well, that's it, Brian.

00:30:11.620 --> 00:30:13.100
Great show as always.

00:30:13.100 --> 00:30:13.840
Thank you for being here.

00:30:13.840 --> 00:30:14.720
Well, thank you.

00:30:14.720 --> 00:30:18.780
Thanks to you, everyone, for listening and those of you who joined live.

