WEBVTT

00:00:00.001 --> 00:00:03.980
Hello and welcome to Python Bytes, where we deliver Python news and headlines directly to

00:00:03.980 --> 00:00:10.720
your earbuds. This is episode 203, recorded October 7th, 2020. I'm Michael Kennedy.

00:00:10.720 --> 00:00:11.780
And I am Brian Okken.

00:00:11.780 --> 00:00:16.480
And this episode is brought to you by Datadog. Thank you, Datadog, for supporting us.

00:00:16.480 --> 00:00:20.400
PythonBites.fm slash Datadog. And a lot of cool stuff out there. We'll tell you more about it

00:00:20.400 --> 00:00:25.460
later. Brian, can you believe we're like well into the 200s? Well, by three.

00:00:25.460 --> 00:00:27.740
Yeah, we're getting a good start already. Yeah.

00:00:27.740 --> 00:00:31.260
A month almost. Yeah, I guess a month because that's zero based, which is pretty awesome.

00:00:31.260 --> 00:00:37.200
Now, speaking of things that are awesome, DigitalOcean was a sponsor of the show for a while.

00:00:37.200 --> 00:00:43.840
But before they were sponsors, we actually just use them as, you know, hosting our infrastructure.

00:00:43.840 --> 00:00:49.720
And we still do. So when you download the MP3, your podcast player talks to something,

00:00:49.720 --> 00:00:55.820
it's talking to our services on DigitalOcean and so on. And over there, we just have a set of virtual

00:00:55.820 --> 00:01:00.940
machines, some database servers, some other things. And they manage themselves as kind of a cluster.

00:01:00.940 --> 00:01:03.280
And by manage themselves, I mean, I manage them.

00:01:03.280 --> 00:01:09.380
I mean, they mostly take care of themselves, but I do have to log in and take care of them.

00:01:09.380 --> 00:01:16.340
But there are different ways of hosting your apps that don't require you to actually log in and

00:01:16.340 --> 00:01:20.620
configure servers and make sure they're all good and so on. Often that's called platform as a service.

00:01:20.620 --> 00:01:25.840
We also have Kubernetes clusters and things like that where you just say, here's a definition of my code.

00:01:25.840 --> 00:01:30.940
Please make it go on the internet. Right. So what I want to talk about is DigitalOcean just launched a new

00:01:30.940 --> 00:01:36.620
app platform that is a platform as a service. And like I said, I'm a fan of DigitalOcean because they're simple

00:01:36.620 --> 00:01:40.320
and straightforward and affordable and easy to use, but really high quality.

00:01:40.580 --> 00:01:44.780
So I think that it's worth pointing out this new platform that they just launched.

00:01:44.780 --> 00:01:48.800
You're comfortable with doing your own, what, droplet or whatever it is?

00:01:48.800 --> 00:01:49.240
Yeah, exactly.

00:01:49.240 --> 00:01:53.540
I'm not. So I'm kind of looking forward to trying something like this.

00:01:53.540 --> 00:01:59.020
And I've got a ton of different apps and they have inner connections within each other that they have to care about.

00:01:59.020 --> 00:02:06.220
And like, there's a lot of stuff where, you know, at some point it makes sense to go down that path with various things that all work together.

00:02:06.220 --> 00:02:17.460
But if I just got an app and I wanted to get on the internet, you know, often you don't want to deal with or worry about those things or, you know, forget to apply an OS patch or, you know, how many, how many times?

00:02:17.460 --> 00:02:27.900
I mean, I'm large scale VC funded professional web apps say we're going to be experiencing downtime for the next 30 minutes or for four hours.

00:02:27.900 --> 00:02:31.680
I'm just like, what could you possibly be doing that takes four hours?

00:02:31.680 --> 00:02:36.680
I just, it's like boggles my mind that you're not able to do it better than four hours of downtime.

00:02:36.680 --> 00:02:41.460
And so platforms like this mean zero downtime deployment and things like that.

00:02:41.460 --> 00:02:42.500
So really, really neat.

00:02:42.500 --> 00:02:43.840
So they've announced this new app platform.

00:02:43.840 --> 00:02:45.100
I want to point out, this is not an ad.

00:02:45.100 --> 00:02:46.480
This is just something I think is cool.

00:02:46.480 --> 00:02:47.400
So I'm sharing with you.

00:02:48.060 --> 00:02:48.220
Yeah.

00:02:48.220 --> 00:02:48.960
So, yeah.

00:02:48.960 --> 00:02:54.100
So they, they came up with this new app platform that, you know, you say it's pretty modern.

00:02:54.100 --> 00:02:56.840
It's like, how do you get your code into it?

00:02:56.840 --> 00:02:58.680
You point it at your GitHub repository.

00:02:58.680 --> 00:03:01.340
You don't like log into it and do a Git thing.

00:03:01.340 --> 00:03:06.100
You just say, I'm going to give you access to my source code and it will automatically deploy from that.

00:03:06.100 --> 00:03:09.560
That would be one nice way to get it over there and get it set up.

00:03:09.560 --> 00:03:11.840
But you also might want continuous deployment.

00:03:11.840 --> 00:03:17.140
So if I push, like, how do you get a new version with zero downtime deployments and all that?

00:03:17.140 --> 00:03:23.460
Well, you just push to a particular branch that you decide upon and it automatically notices that and does it redeploy.

00:03:23.460 --> 00:03:24.520
That's pretty sweet.

00:03:24.520 --> 00:03:27.500
Like, so I have that for like Talk Python training.

00:03:27.500 --> 00:03:33.800
If I push to a production branch, it'll automatically do the checkout, ensure the requirements are built, recreate it.

00:03:34.180 --> 00:03:34.940
I had to write that.

00:03:34.940 --> 00:03:35.800
This just happened.

00:03:35.800 --> 00:03:37.060
This is just part of it, right?

00:03:37.060 --> 00:03:38.080
That's pretty neat.

00:03:38.080 --> 00:03:38.500
Yeah.

00:03:38.500 --> 00:03:38.920
Yeah.

00:03:38.920 --> 00:03:39.880
I don't want to do that myself.

00:03:39.880 --> 00:03:42.520
I didn't either, but it was better than logging in all the time.

00:03:42.920 --> 00:03:51.480
So this is built on top of DigitalOcean Kubernetes, which is interesting because a lot of platform as a service type of things are just opaque.

00:03:51.480 --> 00:03:54.740
They're like, well, you can give us access to your code and we'll make it run.

00:03:54.740 --> 00:03:55.100
Magic.

00:03:55.400 --> 00:04:09.380
But really all this is, is they'll orchestrate running your code on top of their Kubernetes clusters, which means you can like define Docker files in your repository that are going to be part of the app that runs in Kubernetes.

00:04:09.660 --> 00:04:14.140
You can use some of the tools actually to talk to the underlying infrastructure.

00:04:14.140 --> 00:04:16.180
So it's not a closed environment.

00:04:16.180 --> 00:04:19.460
You can actually kind of get down to the infrastructure layer a little bit more.

00:04:19.460 --> 00:04:21.620
So all these things are pretty neat.

00:04:21.620 --> 00:04:26.420
It has automatic handling of traffic spikes for simple, simple, simple apps.

00:04:26.420 --> 00:04:29.400
For static apps, it's free for a three limit.

00:04:29.400 --> 00:04:30.600
For three of them, right?

00:04:30.600 --> 00:04:34.580
For real apps, I guess, apps that run code like Python.

00:04:34.580 --> 00:04:38.620
You can pay five bucks for like a simple version, like on a shared server.

00:04:38.940 --> 00:04:47.440
Or you can pay 12 bucks for a more pro version that has more features, CDN, SSL, all those kinds of things.

00:04:47.440 --> 00:04:50.580
And then if you want to scale it up, you can pay tons, right?

00:04:50.580 --> 00:04:55.040
You can pay like $150 to run it on a huge server or a bunch of different small servers.

00:04:55.040 --> 00:04:58.420
And there's a whole scaling thing that you can do, but there's a pretty decent offering.

00:04:58.420 --> 00:05:00.300
It's still not as cheap as running on your own.

00:05:00.300 --> 00:05:05.160
But just like you said, a lot of people don't want to run it on their own and that's not their expertise.

00:05:05.160 --> 00:05:06.940
And why should they be doing that, right?

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

00:05:08.220 --> 00:05:15.280
Like if you were to offer to do all of my server stuff for me, I would totally buy you dinner once a month.

00:05:15.280 --> 00:05:16.440
Yeah.

00:05:16.440 --> 00:05:17.660
And that's kind of the price, right?

00:05:17.900 --> 00:05:24.780
But this would be like a cheap dinner, like a muchos gracias type of, you know, enchiladas and a Coke, not a filet mignon.

00:05:24.780 --> 00:05:25.380
Yeah.

00:05:25.380 --> 00:05:28.120
Maybe just like a $5 gift card to Starbucks.

00:05:28.120 --> 00:05:28.520
Yeah.

00:05:28.520 --> 00:05:28.880
There you go.

00:05:28.880 --> 00:05:29.900
I could totally get two scones.

00:05:29.900 --> 00:05:34.960
Anyway, if you were thinking about running your, you know, I talked to so many people, students of the courses and stuff.

00:05:34.960 --> 00:05:38.020
And they're like, I got my app, but now I got to put it online.

00:05:38.020 --> 00:05:38.840
Like what a pain.

00:05:38.840 --> 00:05:40.920
Like I can't get engine X configured, right?

00:05:40.920 --> 00:05:42.400
Or this other thing or so on.

00:05:42.900 --> 00:05:50.420
This is another solid option now that has a nice, you know, push to a branch, deploy, run your stuff, zero downtime.

00:05:51.120 --> 00:05:55.960
You know, it's probably most comparable to Heroku, I would say, in the Python ecosystem.

00:05:55.960 --> 00:05:56.360
Yeah.

00:05:56.360 --> 00:05:56.640
Yeah.

00:05:56.640 --> 00:05:57.220
All right.

00:05:57.220 --> 00:05:58.180
Well, people can check this out.

00:05:58.180 --> 00:05:59.420
I think it's, I think it's a cool offering.

00:05:59.420 --> 00:06:06.060
I will not be personally using it because there's a bunch of little gotchas like, you know, it would be better if, right?

00:06:06.060 --> 00:06:10.200
For example, I don't want to use their hosted Postgres database.

00:06:10.200 --> 00:06:12.680
I want to run a MongoDB server, which is fine.

00:06:12.680 --> 00:06:13.140
It's no problem.

00:06:13.140 --> 00:06:13.860
You can do that there.

00:06:13.860 --> 00:06:20.400
But you can't, like what I do on the MongoDB server is in order to talk to it, you have to be within a white list of

00:06:20.400 --> 00:06:25.440
known IP addresses that the servers, the web servers and API servers have.

00:06:25.440 --> 00:06:25.920
All right.

00:06:25.920 --> 00:06:29.440
So there's like 10 APIs in the world that can talk to that server and no others.

00:06:29.440 --> 00:06:36.700
The thing is with these Kubernetes clusters, when you push redeploy, it will regenerate it and rehost it potentially somewhere else.

00:06:36.700 --> 00:06:38.680
And the IP address keeps changing.

00:06:38.680 --> 00:06:45.600
So you can't do things like have a custom database server that has, you know, firewall limited, restricted, like VPN type of stuff.

00:06:45.600 --> 00:06:47.020
Those types of things don't exist.

00:06:47.020 --> 00:06:48.440
Most people probably don't care.

00:06:48.440 --> 00:06:49.900
I care, so I'm not doing it.

00:06:50.180 --> 00:06:52.740
You can't do Mongo with this thing?

00:06:52.740 --> 00:07:03.700
You can do Mongo, but you would have to have the MongoDB database port listen on the open internet rather than be restricted to just a few IP addresses.

00:07:03.700 --> 00:07:07.340
Maybe they've figured this out and it's buried in the fine brain.

00:07:07.340 --> 00:07:11.860
It's something that like there's a whole conversation about like, here's the things we're going to add.

00:07:11.860 --> 00:07:13.760
Here's the things that it doesn't currently do.

00:07:13.760 --> 00:07:15.520
Here's some workarounds, et cetera, et cetera.

00:07:15.520 --> 00:07:17.360
So anyway, there's a whole conversation.

00:07:17.360 --> 00:07:18.120
You can check it out.

00:07:18.360 --> 00:07:25.320
But if you do things like use their hosted database, which would make sense in a pass type of story, you don't have these problems, right?

00:07:25.320 --> 00:07:26.820
They automatically wire that stuff up.

00:07:26.820 --> 00:07:29.340
Because when you want to break the rules, you get in trouble.

00:07:29.340 --> 00:07:32.360
So you're a fan of Shakespeare.

00:07:32.360 --> 00:07:32.920
Is that right?

00:07:32.920 --> 00:07:34.180
Head down to Medford.

00:07:34.180 --> 00:07:35.880
I've never been.

00:07:35.880 --> 00:07:36.500
Ashland, sorry.

00:07:36.500 --> 00:07:37.520
It's Ashland down there.

00:07:37.520 --> 00:07:38.000
Ashland.

00:07:38.000 --> 00:07:40.120
There's a whole like Shakespeare week.

00:07:40.120 --> 00:07:40.900
Yeah.

00:07:40.900 --> 00:07:43.360
Is Ashland still there with the fires and all?

00:07:43.360 --> 00:07:44.300
God, I hope so.

00:07:44.300 --> 00:07:45.380
Yeah.

00:07:45.480 --> 00:07:49.540
No, I've always wanted to, but people that don't live in Oregon have no idea what we're talking about.

00:07:49.540 --> 00:07:55.200
But there's a small town in Southern Oregon that does a lot of Shakespeare plays.

00:07:55.200 --> 00:07:59.520
And that sort of transition was because I want to talk about Playwright.

00:07:59.520 --> 00:08:03.760
So Microsoft put out an announcement announcing Playwright for Python.

00:08:03.760 --> 00:08:05.940
I was trying to look into this.

00:08:05.940 --> 00:08:12.920
I guess I haven't quite got whether or not Playwright was a thing before Playwright for Python or not.

00:08:13.120 --> 00:08:22.720
But in any case, it's a Microsoft thing and it's a way to drive and test your web application through easily.

00:08:22.720 --> 00:08:25.060
So it's an end-to-end testing solution.

00:08:25.060 --> 00:08:27.500
It's open source and whatnot.

00:08:27.500 --> 00:08:30.180
But in their announcement, it's a pretty cool announcement.

00:08:30.180 --> 00:08:31.460
It gives examples and everything.

00:08:31.460 --> 00:08:33.160
So I'm going to read their pitch.

00:08:33.160 --> 00:08:40.760
The pitch for it is, with the Playwright API, you can author end-to-end tests that run on all modern web browsers.

00:08:41.260 --> 00:08:47.580
Playwright delivers automation that is faster, more reliable, and more capable than existing testing solutions.

00:08:47.580 --> 00:08:54.760
And I'm guessing by existing testing solutions, there's a nice way of them to say we are better than Selenium.

00:08:54.760 --> 00:08:56.280
Yeah, that's what I was thinking as well.

00:08:56.280 --> 00:08:57.740
So there's already a pytest plugin.

00:08:57.740 --> 00:08:59.680
There's runs on Python.

00:08:59.680 --> 00:09:05.580
We've said that we like animated GIFs of how it works.

00:09:05.580 --> 00:09:08.020
And on their announcement page, there's a little animation.

00:09:08.020 --> 00:09:11.300
And I was actually pretty impressed with that little bit.

00:09:11.300 --> 00:09:16.940
So you can drive it even from a command line or an interactive shell.

00:09:16.940 --> 00:09:20.680
You can drive some playing with it, which is nice.

00:09:21.260 --> 00:09:22.600
So a few of the benefits.

00:09:22.600 --> 00:09:24.620
Apparently, it's timeout-free automation.

00:09:24.620 --> 00:09:31.740
So the Playwright automatically waits for the user interface to be ready before you act on it again.

00:09:31.740 --> 00:09:36.760
I know there's some workarounds and there's some wrappers on top of Selenium that do that also.

00:09:36.760 --> 00:09:38.860
But this is built into the system.

00:09:39.080 --> 00:09:45.440
It's intended to stay modern with emulation of mobile viewports, geolocation, web permissions.

00:09:45.440 --> 00:09:48.980
You can automate scenarios across multiple pages.

00:09:48.980 --> 00:09:53.940
I don't really test websites that much, but I didn't know that that was difficult before.

00:09:53.940 --> 00:09:55.640
So apparently that's easier now.

00:09:55.640 --> 00:10:02.260
Cross-platform, of course, or cross-browser, of course, because you got to test against different things.

00:10:02.260 --> 00:10:10.020
They use a Chromium driver for Chrome and Edge emulation, WebKit driver for Safari, and a Firefox driver.

00:10:10.020 --> 00:10:15.940
And supposedly the Safari rendering driver even works on Windows and Linux.

00:10:15.940 --> 00:10:19.980
So you don't actually have to have an Apple computer to do that.

00:10:19.980 --> 00:10:22.700
So pytest compatible and Django compatible.

00:10:22.700 --> 00:10:24.580
I'm sure it's compatible with lots of other stuff too.

00:10:24.580 --> 00:10:29.780
But the examples on the announcement show pytest examples and Django examples, which is cool.

00:10:30.060 --> 00:10:38.660
They even mentioned that, of course, you can run this from your continuous integration server, including GitHub Actions and others.

00:10:38.660 --> 00:10:45.380
You must be happy to see that it's pytest, like natively pytest friendly, like with fixtures and whatnot.

00:10:45.380 --> 00:10:54.420
I love that obviously we're to the point now where if you have a new testing tool, you may as well, in the announcement, tell people whether or not you can run it with pytest.

00:10:54.420 --> 00:10:55.560
Because people are going to ask.

00:10:55.560 --> 00:10:58.720
That's a good state to be in in the Python world, I think.

00:10:58.720 --> 00:11:05.880
So for example, like the simple hello world sort of test is just go to make sure that you get like a header text on a page.

00:11:05.880 --> 00:11:12.240
So it says define a function which takes a page with type annotations, by the way, double props for that.

00:11:12.240 --> 00:11:16.900
So page and then that's already a fixture from the framework in pytest.

00:11:16.900 --> 00:11:18.800
So it automatically passes that over setup.

00:11:18.960 --> 00:11:27.760
All you do is say it takes a page and page go to URL, assert page.intertext of h1 equal equal, you know, the text you're looking for.

00:11:27.760 --> 00:11:29.880
There's also more like that you could do.

00:11:29.880 --> 00:11:31.580
It's like beautiful soup like stuff.

00:11:31.580 --> 00:11:33.980
But there's more of the kind of drive it.

00:11:33.980 --> 00:11:34.500
Yeah, go ahead.

00:11:34.500 --> 00:11:38.160
That's two lines of code for a test to make sure that something's on a web page.

00:11:38.160 --> 00:11:38.780
That's pretty cool.

00:11:38.900 --> 00:11:39.820
Yeah, that is pretty slick.

00:11:39.820 --> 00:11:41.280
And the fixture bit is neat.

00:11:41.280 --> 00:11:44.000
You can also go and like do a test to log in.

00:11:44.000 --> 00:11:46.040
So get a new page.

00:11:46.040 --> 00:11:47.500
Go to the URL.

00:11:47.500 --> 00:11:49.340
Do page.fill.

00:11:49.340 --> 00:11:53.060
Give it a CSS selector for the username field.

00:11:53.060 --> 00:11:54.300
Heck, the input field.

00:11:54.300 --> 00:11:57.040
Give it a CSS selector for the passwords they fill with that.

00:11:57.040 --> 00:12:00.560
And then click where the text of a button equals login.

00:12:00.560 --> 00:12:02.580
You don't have to do the CSS stuff or anything.

00:12:02.580 --> 00:12:06.960
Just find me a button or a thing or a URL that has the text login and click that.

00:12:07.120 --> 00:12:07.900
And it's off.

00:12:07.900 --> 00:12:10.800
And so like one of the examples here is it does that first.

00:12:10.800 --> 00:12:11.960
And then it logs in.

00:12:11.960 --> 00:12:15.360
Then it creates a session that remembers that it's logged in for the rest of the testing.

00:12:15.360 --> 00:12:17.420
So that's like one of the setup phases, which is pretty cool.

00:12:17.420 --> 00:12:17.720
Yeah.

00:12:17.720 --> 00:12:18.060
Yeah.

00:12:18.060 --> 00:12:19.400
Let me throw out one other thing.

00:12:19.400 --> 00:12:22.000
You talked about Chromium as one of the drivers, right?

00:12:22.000 --> 00:12:25.080
So a lot of times when you're doing Selenium, I don't know about this, but it looks the same.

00:12:25.080 --> 00:12:27.260
You have to install Chromium.

00:12:27.260 --> 00:12:29.260
And then there's like a little hidden one.

00:12:29.260 --> 00:12:33.320
You can also do the Firefox browser for Selenium.

00:12:33.580 --> 00:12:39.200
But I was talking to the guys at Attila from Scraping Hub on Talk Python.

00:12:39.200 --> 00:12:48.180
And he pointed out that Scraping Hub makes a headless browser specifically designed to be a headless browser called Splash.

00:12:48.740 --> 00:12:56.980
So their headline is the headless browser designed specifically for web scraping turn JavaScript heavy web pages into data.

00:12:56.980 --> 00:13:02.380
So I don't know how much better that is, but it's interesting to think that you can swap out these browsers.

00:13:02.380 --> 00:13:03.820
And here's a cool example as well.

00:13:03.820 --> 00:13:05.620
Something that maybe people don't know about.

00:13:05.800 --> 00:13:08.020
Yeah, I listened to that episode and thanks for reminding me.

00:13:08.020 --> 00:13:09.740
I was like, I got to check that out.

00:13:09.740 --> 00:13:11.760
Yeah, I do too, but I haven't checked it out.

00:13:11.760 --> 00:13:12.560
But it definitely looks neat.

00:13:12.560 --> 00:13:15.280
So this though, I like it.

00:13:15.280 --> 00:13:18.480
I mean, it looks at least as neat as Selenium.

00:13:18.480 --> 00:13:18.980
I don't know.

00:13:18.980 --> 00:13:19.960
Maybe it's even better.

00:13:19.960 --> 00:13:20.980
So pretty cool.

00:13:20.980 --> 00:13:21.260
Yeah.

00:13:21.260 --> 00:13:22.900
Also cool, Datadog.

00:13:22.900 --> 00:13:25.360
They're actually sponsoring the show.

00:13:25.360 --> 00:13:29.320
Unlike DigitalOcean where I just found something that I like from someone who happened to be a sponsor.

00:13:29.460 --> 00:13:32.940
But Datadog are sponsoring the show, not making them any less cool.

00:13:32.940 --> 00:13:34.820
So let me ask you a question.

00:13:34.820 --> 00:13:37.220
Do you have an app in production that's slower than you like?

00:13:37.220 --> 00:13:37.940
It's performant.

00:13:37.940 --> 00:13:39.340
Maybe it's all over the place.

00:13:39.340 --> 00:13:40.600
Sometimes fast, sometimes slow.

00:13:40.600 --> 00:13:42.180
Here's the important question.

00:13:42.180 --> 00:13:43.320
Do you know why?

00:13:43.320 --> 00:13:44.460
With Datadog, you will.

00:13:44.460 --> 00:13:48.000
You can troubleshoot your app's performance with Datadog's end-to-end tracing.

00:13:48.000 --> 00:13:50.160
Get detailed flame graphs.

00:13:50.160 --> 00:13:53.200
Identify bottlenecks and latency in that finicky app of yours.

00:13:53.200 --> 00:13:57.160
Be the hero that got your app back on track at your company.

00:13:57.280 --> 00:13:58.700
Get started with a free trial.

00:13:58.700 --> 00:14:04.760
And I believe they send you a t-shirt, a little cool t-shirt still, over at pythonbytes.fm/Datadog.

00:14:04.760 --> 00:14:09.860
So, Brian, something we haven't spoken about nearly enough is async.io and async and await.

00:14:09.860 --> 00:14:10.980
Should we touch on that a little?

00:14:10.980 --> 00:14:11.940
Sure.

00:14:11.940 --> 00:14:14.880
Okay.

00:14:14.880 --> 00:14:16.640
Yeah, we've talked about it some.

00:14:16.640 --> 00:14:17.720
Some.

00:14:17.720 --> 00:14:18.560
I believe some, maybe.

00:14:18.560 --> 00:14:27.260
So, one of the things that async.io is for, I mean, if you look at the name, it's around...

00:14:27.260 --> 00:14:28.320
Waiting on IO.

00:14:28.320 --> 00:14:32.940
Waiting on external things like network calls, API calls, and so on, right?

00:14:32.940 --> 00:14:34.940
Oh, I thought it was just trying to be cool.

00:14:34.940 --> 00:14:36.100
Like all the .io.

00:14:36.100 --> 00:14:37.540
It could be that.

00:14:37.540 --> 00:14:39.760
Or it could just be like the Italian pronunciation.

00:14:39.760 --> 00:14:40.940
Async, yo.

00:14:40.940 --> 00:14:42.280
Async, yo.

00:14:42.280 --> 00:14:43.700
No, it's beautiful.

00:14:43.700 --> 00:14:46.760
So, when I think of files, I think of IO.

00:14:46.760 --> 00:14:48.360
Like, if somebody said, what is IO?

00:14:48.400 --> 00:14:49.460
I would think file IO.

00:14:49.460 --> 00:14:50.520
That's the first thing I would say.

00:14:50.520 --> 00:14:56.840
And yet, Python doesn't have built-in support for asynchronously working with file IO.

00:14:56.840 --> 00:14:58.120
That's bizarre, right?

00:14:58.120 --> 00:14:58.600
Yeah.

00:14:58.600 --> 00:14:59.520
It is.

00:14:59.520 --> 00:15:01.040
I believe there's an external package.

00:15:01.040 --> 00:15:06.300
I think I saw it somewhere on like awesome async.io or some list like that, that somebody

00:15:06.300 --> 00:15:08.120
had built something along those lines.

00:15:08.620 --> 00:15:15.160
But, there's a cool article called Asynchronously Opening and Closing Files in Async.io by Chris

00:15:15.160 --> 00:15:15.540
Wellens.

00:15:15.540 --> 00:15:16.160
Nice.

00:15:16.160 --> 00:15:21.300
So, he wrote this and said, look, Async.io has great support for networking, subprocess, interprocess

00:15:21.300 --> 00:15:25.680
communication stuff, but no file operations like opening, reading, writing, and closing files.

00:15:25.960 --> 00:15:29.180
And if you're talking to something that might take a long time, I mean, I don't know about

00:15:29.180 --> 00:15:32.140
you, but I've got a pretty raging SSD on both my computers.

00:15:32.140 --> 00:15:33.780
So, maybe I don't need this.

00:15:33.780 --> 00:15:40.000
Unless you're at that corporate, maybe you're logged in through a corporate VPN and you've

00:15:40.000 --> 00:15:44.260
mapped a network share over to your drive and then you try to read from that, all of a sudden

00:15:44.260 --> 00:15:46.500
your file IO might get super slow, right?

00:15:46.500 --> 00:15:50.240
Well, even on SSDs, file IO is slower than memory reads.

00:15:50.240 --> 00:15:51.120
Yeah, it's much slower.

00:15:51.660 --> 00:15:56.320
So, there's certainly situations where this could be extreme like the network one, but

00:15:56.320 --> 00:16:00.340
you're right, even normal file IO can be slow if you're really looking to squeeze out the

00:16:00.340 --> 00:16:01.220
most concurrency.

00:16:01.220 --> 00:16:07.200
So, basically, he wrote a little article working through it and it's ridiculously short, actually,

00:16:07.200 --> 00:16:09.800
on how you can do this, right?

00:16:09.800 --> 00:16:16.940
So, basically, he says, look, if I use open, open file in Python, I would, as a decent Pythonic

00:16:16.940 --> 00:16:21.560
bit of code, typically I would write with open thing as file IO object.

00:16:21.720 --> 00:16:21.840
Right?

00:16:21.840 --> 00:16:22.440
File Street.

00:16:22.440 --> 00:16:22.660
Yes.

00:16:22.660 --> 00:16:26.300
Let's build that for something we're going to call a open, which is an asynchronous one.

00:16:26.300 --> 00:16:30.540
And it's kind of bizarre and weird that Python has this, but it does and I think it's neat.

00:16:30.540 --> 00:16:36.960
It has an async with blocks when you do async things that have to be asynchronously managed

00:16:36.960 --> 00:16:38.160
within context managers.

00:16:38.700 --> 00:16:45.260
So, he said, let's write this so it implements the async with style, which is really simple.

00:16:45.260 --> 00:16:46.920
You basically implement a couple of methods.

00:16:46.920 --> 00:16:51.600
Instead of dunder enter, dunder exit, you do dunder a enter, dunder a exit, and so on.

00:16:51.600 --> 00:16:51.920
Okay.

00:16:52.040 --> 00:16:55.320
And then he says, okay, well, what we're going to do is we're going to define a function

00:16:55.320 --> 00:16:56.640
that just opens a file.

00:16:56.640 --> 00:16:57.620
Super easy.

00:16:57.620 --> 00:17:04.740
But then we're going to run it in an asyncio event loop by saying run in executor.

00:17:04.740 --> 00:17:11.840
And what that means is asyncio will create a thread pool where it's going to run over

00:17:11.840 --> 00:17:15.540
on a background thread and then it just runs that and lets you await it.

00:17:15.540 --> 00:17:17.100
And that's basically it.

00:17:17.100 --> 00:17:17.520
Wow.

00:17:17.520 --> 00:17:18.020
Isn't that neat?

00:17:18.020 --> 00:17:18.840
That's not much code.

00:17:18.840 --> 00:17:19.180
No.

00:17:19.180 --> 00:17:21.500
It's like the opening bit is one, two, three.

00:17:21.500 --> 00:17:25.320
It's six lines of code, including the function name, which has to be there.

00:17:25.320 --> 00:17:27.360
The five lines of writing code.

00:17:27.360 --> 00:17:27.800
Yeah.

00:17:27.860 --> 00:17:32.780
And one of the things I like about this is not because I really want to do async file

00:17:32.780 --> 00:17:33.180
stuff.

00:17:33.180 --> 00:17:38.540
It's because it's a neat, neat little example that I can get my head around so that if I

00:17:38.540 --> 00:17:44.500
have some other process or other slow thing that I want to make asyncified, this might be

00:17:44.500 --> 00:17:46.180
an example to how to do that.

00:17:46.180 --> 00:17:46.840
Yeah, absolutely.

00:17:46.840 --> 00:17:50.260
So I think this is super instructive and interesting.

00:17:50.260 --> 00:17:54.660
I'll also throw out that there is an AIO files package.

00:17:54.660 --> 00:17:56.740
I think it's files plural.

00:17:57.100 --> 00:17:57.900
Maybe it's file?

00:17:57.900 --> 00:17:59.300
No, file singular.

00:17:59.300 --> 00:18:05.440
AIO file, which you can pip install and then just do this instead of like see the tutorial.

00:18:05.440 --> 00:18:11.480
But I think the value here is like, well, what else doesn't have async support and what could

00:18:11.480 --> 00:18:15.600
I just kick over to a thread but then integrate into asyncio event loops?

00:18:15.600 --> 00:18:16.740
Yeah, it's nice.

00:18:16.740 --> 00:18:17.160
Indeed.

00:18:17.160 --> 00:18:18.500
You know what else is nice?

00:18:18.500 --> 00:18:19.640
Excel.

00:18:19.640 --> 00:18:24.020
Like so many people who can't do any programming or any scripting or anything, they can just

00:18:24.020 --> 00:18:29.220
go to Excel and like drag a droppy, a little, you know, a formula and paste it over and then

00:18:29.220 --> 00:18:29.780
they're good to go.

00:18:29.780 --> 00:18:30.440
Yeah.

00:18:30.440 --> 00:18:31.800
Except?

00:18:31.800 --> 00:18:32.920
Except what?

00:18:32.920 --> 00:18:35.020
Except it's 2020.

00:18:35.020 --> 00:18:35.880
That's the problem.

00:18:35.880 --> 00:18:36.420
Yeah.

00:18:36.540 --> 00:18:39.680
So this is only tangentially related to Python.

00:18:39.680 --> 00:18:45.380
Mostly it's that people start using databases in Python, stop using Excel so much.

00:18:45.380 --> 00:18:51.060
This article, we had a lot of people actually say, did you guys see this?

00:18:51.060 --> 00:18:51.420
Yeah.

00:18:51.540 --> 00:18:54.460
So yeah, lots of people brought this up to us.

00:18:54.460 --> 00:18:56.680
I've got an article that I picked.

00:18:56.680 --> 00:19:01.860
There's a bunch of articles also, but I picked a BBC.com article because it didn't have very

00:19:01.860 --> 00:19:02.420
many ads.

00:19:02.420 --> 00:19:09.480
So the BBC article says, Excel, why using Microsoft's tool caused COVID-19 results to be lost?

00:19:09.480 --> 00:19:10.340
Wow.

00:19:10.340 --> 00:19:17.160
So there's apparently, if you haven't heard about this, apparently there were 16,000 coronavirus

00:19:17.160 --> 00:19:19.340
cases that went unreported in England.

00:19:19.340 --> 00:19:21.760
The good news is, is they, well, sort of good.

00:19:21.760 --> 00:19:27.040
They, they did, it only took like a few days for somebody to notice this, but there is a

00:19:27.040 --> 00:19:30.360
few days where, where there was some stuff not getting tracked right.

00:19:30.360 --> 00:19:33.420
And policy was like, Hey, things are getting better.

00:19:33.500 --> 00:19:34.400
We're trending down.

00:19:34.400 --> 00:19:35.060
This is amazing.

00:19:35.060 --> 00:19:35.420
Yeah.

00:19:35.420 --> 00:19:35.760
Except.

00:19:35.760 --> 00:19:36.180
No.

00:19:36.180 --> 00:19:37.200
Yeah.

00:19:37.200 --> 00:19:39.020
So I just didn't read it.

00:19:39.020 --> 00:19:45.940
So apparently what you had, you had, several commercial for testing firms filling out CSV files

00:19:45.940 --> 00:19:52.780
and sending them to, I forget the name of the place, something, some health organization

00:19:52.780 --> 00:19:56.080
in England that was pulling all this stuff together.

00:19:56.080 --> 00:20:03.320
And they were pulling it together by putting it all in an Excel, XLS template that could be

00:20:03.320 --> 00:20:09.160
then uploaded to a central system and made available to NHS test and trace team, as well as other

00:20:09.160 --> 00:20:10.640
government computer dashboards.

00:20:10.640 --> 00:20:18.480
But the use of the XLS template made it so that there was a limit of 65,000 rows.

00:20:18.480 --> 00:20:25.100
Actually, that just gives me nightmares to think of a 65,000 row Excel spreadsheet, but apparently

00:20:25.100 --> 00:20:25.880
that's the limit.

00:20:25.880 --> 00:20:27.940
Nobody quite noticed that they'd hit it.

00:20:27.940 --> 00:20:30.080
It didn't say anything about failing.

00:20:30.820 --> 00:20:36.960
And, people noticed, some people said, well, you should have used XLS X because that

00:20:36.960 --> 00:20:41.440
increases the limit by 16 times, but still Excel for this.

00:20:41.440 --> 00:20:43.520
Of course, I was thinking, why are you doing this in Excel?

00:20:43.520 --> 00:20:50.440
And in this article, they had a quote from professor John Croft, Crow, sorry, Crowcroft from the

00:20:50.440 --> 00:20:51.380
university of Cambridge.

00:20:51.380 --> 00:20:57.200
He says, Excel is always meant for people mucking around with a bunch of data on their small

00:20:57.200 --> 00:20:58.800
company to see what it looked like.

00:20:58.800 --> 00:21:02.700
And then when you need something more serious, you build something bespoke that works.

00:21:02.700 --> 00:21:07.100
There's dozens of other things that could do, but you wouldn't use an XLS.

00:21:07.100 --> 00:21:08.700
Nobody would start with that.

00:21:08.700 --> 00:21:10.460
Exactly.

00:21:10.460 --> 00:21:11.720
Exactly.

00:21:11.720 --> 00:21:13.880
Apparently people did though.

00:21:14.000 --> 00:21:16.240
And so people should be using Python.

00:21:16.240 --> 00:21:16.600
Yeah.

00:21:16.600 --> 00:21:17.360
That's not good.

00:21:17.360 --> 00:21:18.520
That is not good.

00:21:18.520 --> 00:21:25.240
So I think there's a really interesting trend of moving towards things like pandas to answer

00:21:25.240 --> 00:21:25.900
these questions.

00:21:25.900 --> 00:21:26.400
Right.

00:21:26.400 --> 00:21:26.900
Yeah.

00:21:26.900 --> 00:21:29.080
I don't think that's the answer for everybody.

00:21:29.080 --> 00:21:29.540
Right.

00:21:29.540 --> 00:21:32.020
Like, oh, well, Excel is kind of clumsy for you.

00:21:32.020 --> 00:21:36.360
So here's what you should do is you should learn a whole bunch of programming.

00:21:36.360 --> 00:21:36.860
Right.

00:21:36.920 --> 00:21:41.840
I mean, here's a random story that I would, one of the more frustrating things from my

00:21:41.840 --> 00:21:46.460
corporate days is when I was doing training, we would have to write proposals to send off

00:21:46.460 --> 00:21:48.180
to clients and like, here's what we're going to cover.

00:21:48.180 --> 00:21:48.940
Here's what I'm going to teach.

00:21:48.940 --> 00:21:49.780
Here's your goals.

00:21:49.780 --> 00:21:51.940
And here's the timeline and so on.

00:21:51.940 --> 00:21:55.900
And I would send that off as a word document and work with one of the salespeople I worked

00:21:55.900 --> 00:21:56.140
with.

00:21:56.140 --> 00:22:00.980
And they said they'd send it off to a client and some, some had changed the word doc, like

00:22:00.980 --> 00:22:04.800
a doc X said, oh, Michael, I need you to replace this word with that word.

00:22:05.220 --> 00:22:09.980
And so she sent me the document back and asked me to replace that word with that word.

00:22:09.980 --> 00:22:13.220
I'm like, do you not know about command R or control R?

00:22:13.220 --> 00:22:15.720
Like, or whatever the replace hotkey is.

00:22:15.720 --> 00:22:20.680
And why would you ever send me a file and just, I need this word to do a find and replace

00:22:20.680 --> 00:22:22.900
with that one, but I need to do it for it.

00:22:22.900 --> 00:22:26.140
I was just like, so anyway, I'm thinking of that person using Excel.

00:22:26.140 --> 00:22:29.140
Like you would, I would never suggest that that person learn it.

00:22:29.140 --> 00:22:34.920
That said, a lot of Excel power users, I think would do really well to adopt Jupyter

00:22:34.920 --> 00:22:36.580
Overlab and pandas and stuff.

00:22:36.580 --> 00:22:41.620
And actually Chris Moffitt, who's does practical business Python, just did a webcast with us

00:22:41.620 --> 00:22:44.540
over, we talked about it before, but the recording's up now.

00:22:44.540 --> 00:22:48.960
You can check that out and that'll give you some concrete tips to avoid the Excel if possible.

00:22:48.960 --> 00:22:49.680
Oh, nice.

00:22:49.680 --> 00:22:50.520
Good resource.

00:22:50.520 --> 00:22:52.420
And that links in our show notes.

00:22:52.420 --> 00:22:52.720
Yeah.

00:22:52.720 --> 00:22:57.340
Would you be a fan of getting documents sent to you and asked to do a finder in place on

00:22:57.340 --> 00:22:57.600
a word?

00:22:57.600 --> 00:22:58.960
I've totally had that happen.

00:22:59.420 --> 00:22:59.820
Yeah.

00:22:59.820 --> 00:23:00.200
I'm saying.

00:23:00.200 --> 00:23:01.780
Like I sent you the doc.

00:23:01.780 --> 00:23:07.420
You could just, I mean, maybe send it back to me and say, hey, I made some updates and

00:23:07.420 --> 00:23:10.120
here's my updates if you need to store the version.

00:23:10.120 --> 00:23:10.420
Yeah, exactly.

00:23:10.420 --> 00:23:10.820
Yeah.

00:23:10.820 --> 00:23:11.780
Just make sure I did it right.

00:23:11.780 --> 00:23:12.200
Maybe.

00:23:12.200 --> 00:23:14.040
But I mean, it was pretty straightforward.

00:23:14.040 --> 00:23:17.240
Anyway, let's move on.

00:23:17.900 --> 00:23:22.080
I'm sure everyone out there has a story like that of you wouldn't believe what I had to

00:23:22.080 --> 00:23:24.360
do in my corporate job.

00:23:24.360 --> 00:23:30.560
So this next one comes to us from a listener, Preston Daniel, who's given us lots of cool

00:23:30.560 --> 00:23:32.260
feedback and ideas.

00:23:32.260 --> 00:23:35.380
And this one is called locust.io.

00:23:35.380 --> 00:23:38.260
This is actually a pretty good pairing with Playwright.

00:23:38.260 --> 00:23:38.620
Okay.

00:23:38.620 --> 00:23:44.180
So Playwright is about validating that what is on the web page makes sense.

00:23:44.180 --> 00:23:48.200
I can go log in and press the button and then I go to this page and this text is here.

00:23:48.200 --> 00:23:49.060
Something like that, right?

00:23:49.060 --> 00:23:50.700
As a continuous integration.

00:23:50.700 --> 00:23:53.920
So locust is about, okay, you know that works.

00:23:53.920 --> 00:23:56.180
What if 10 people do it at the same time?

00:23:56.180 --> 00:23:59.440
What if 100 people do it at the same time on our current infrastructure?

00:23:59.440 --> 00:23:59.880
Yeah.

00:23:59.880 --> 00:24:05.860
You hear about things like the whole healthcare debacle where they spent hundreds of millions

00:24:05.860 --> 00:24:11.760
of dollars of code on code on these projects and like a few people logged in and it just

00:24:11.760 --> 00:24:12.100
failed.

00:24:12.100 --> 00:24:15.620
And you just wonder, like, could you just tried it?

00:24:15.620 --> 00:24:22.120
Just maybe just seeing like if we call that API 10 times a second, will it actually take

00:24:22.120 --> 00:24:22.260
it?

00:24:22.260 --> 00:24:22.500
Right.

00:24:22.500 --> 00:24:25.240
And so tools like this are exactly what you want.

00:24:25.240 --> 00:24:29.820
It's really cool for just simulating, accessing a bunch of different sites.

00:24:29.820 --> 00:24:33.300
I was just thinking one good use for this may have been, sorry to interrupt.

00:24:33.780 --> 00:24:39.160
Maybe the schools could have done this before they had everybody log in so that everybody,

00:24:39.160 --> 00:24:44.420
all the kids on their laptops or their tablets wouldn't have said on day one, I don't know

00:24:44.420 --> 00:24:45.000
what's going on.

00:24:45.000 --> 00:24:45.780
It won't let me in.

00:24:45.780 --> 00:24:46.400
Yeah.

00:24:46.400 --> 00:24:47.540
The page won't load.

00:24:47.540 --> 00:24:49.140
It just, it keeps giving me the numbers.

00:24:49.140 --> 00:24:49.520
500.

00:24:49.520 --> 00:24:50.500
Is this a math class?

00:24:50.500 --> 00:24:52.420
Anyway.

00:24:52.600 --> 00:24:53.260
Yeah, exactly.

00:24:53.260 --> 00:24:54.600
So you should test your code.

00:24:54.600 --> 00:24:56.560
And so I've used these before, these types of tools.

00:24:56.560 --> 00:25:00.200
And often it's like, okay, what you're going to do is open a web browser and you're going

00:25:00.200 --> 00:25:06.260
to go to the site and it'll record like the URLs and you can like use some weird like selection

00:25:06.260 --> 00:25:07.180
syntax.

00:25:07.180 --> 00:25:08.980
I guess weird clumsy GUI.

00:25:08.980 --> 00:25:12.100
Maybe it stores it as XML, but you have like a UI on top of it.

00:25:12.100 --> 00:25:12.780
It's all crummy.

00:25:13.260 --> 00:25:16.200
And they probably charge you a ridiculous amount of money for this.

00:25:16.200 --> 00:25:17.840
So here's the thing with Locus.

00:25:17.840 --> 00:25:21.760
It basically looks like you're writing like unit test code.

00:25:21.760 --> 00:25:25.340
So if you look at the, there's an example in the show notes, just check that out.

00:25:25.340 --> 00:25:31.080
So what you do is you define a user and then you give the user some tasks or some behaviors.

00:25:31.080 --> 00:25:32.320
Oh, this is the one that I was thinking.

00:25:32.320 --> 00:25:32.600
I'm sorry.

00:25:32.600 --> 00:25:34.400
I was confused this with your playwright.

00:25:34.400 --> 00:25:40.040
So for example, with the user, like you would say something like self.client.post to log

00:25:40.040 --> 00:25:41.740
in and you just give it a dictionary.

00:25:41.740 --> 00:25:43.120
Username is this.

00:25:43.320 --> 00:25:44.200
Password is that.

00:25:44.200 --> 00:25:44.840
Boom.

00:25:44.840 --> 00:25:45.360
That's it.

00:25:45.360 --> 00:25:51.720
And that will actually go over there and submit the login form with that data, which is pretty

00:25:51.720 --> 00:25:52.000
awesome.

00:25:52.000 --> 00:25:53.420
And then you give it tasks.

00:25:53.420 --> 00:25:57.480
And these are kind of like tests, like go to the index page, do a get on slash and do

00:25:57.480 --> 00:25:58.300
a get on the JavaScript.

00:25:58.300 --> 00:26:03.180
Go to the about page and do a get on slash about or, you know, go click this button or

00:26:03.180 --> 00:26:04.260
go make this thing happen.

00:26:04.260 --> 00:26:10.160
And then once you have this, then you can turn that into like a bunch of distributed parallel

00:26:10.160 --> 00:26:16.480
requests to see if you get any 500 errors, timeout errors, like what the average latency is for

00:26:16.480 --> 00:26:19.040
10 users, 100 users, a thousand users at a time.

00:26:19.040 --> 00:26:21.880
You can run it on distributed machines.

00:26:22.440 --> 00:26:28.200
So you can have it simulate millions of users if you want to run it on like 20 cloud VMs

00:26:28.200 --> 00:26:30.780
or something like that and turn it on onto your website.

00:26:30.780 --> 00:26:31.600
What do you think?

00:26:31.600 --> 00:26:32.940
I think this is cool.

00:26:32.940 --> 00:26:36.860
And you're saying that there's a game website that's using this?

00:26:36.860 --> 00:26:37.540
There is.

00:26:37.540 --> 00:26:40.920
In the notes that they say when they talk about the features, they say, look, you can define

00:26:40.920 --> 00:26:41.980
user behavior in code.

00:26:41.980 --> 00:26:44.520
Just plain Python code, which is neat.

00:26:44.520 --> 00:26:46.720
It's scalable so you can run it, like I said.

00:26:46.720 --> 00:26:48.620
And then it's battle tested.

00:26:48.620 --> 00:26:56.520
Because Locus has been used to simulate millions of simultaneous users on Battlelog, the web app for

00:26:56.520 --> 00:26:57.680
Battlefield games.

00:26:57.680 --> 00:27:02.380
And so they could say, you really could say, Locus is battlefield, battle tested.

00:27:02.380 --> 00:27:03.400
Nice.

00:27:03.400 --> 00:27:06.160
I don't know if anybody's seen the trailer for the Battlefield games.

00:27:06.160 --> 00:27:09.880
I've not been paying attention to it for ever, but for many, many years at least.

00:27:09.880 --> 00:27:11.900
Wow, these games have come a long ways.

00:27:11.900 --> 00:27:15.000
Like if you watch the trailer for the latest one, that's crazy, crazy stuff.

00:27:15.000 --> 00:27:17.040
But it's kind of also beside the point.

00:27:17.040 --> 00:27:20.760
I think this way of saying like, this is what a website user does.

00:27:20.760 --> 00:27:23.780
They log in and then they go to this page and I might also visit this page.

00:27:23.780 --> 00:27:26.320
And you set up things like, not just, I want to have.

00:27:26.320 --> 00:27:29.340
So when you answer questions like, how many users can we support?

00:27:29.340 --> 00:27:32.320
Typical users are not like pathological.

00:27:32.320 --> 00:27:36.860
They don't go to like your account page and hold down Command R or Control R and just refresh

00:27:36.860 --> 00:27:38.140
it as hard as they can, right?

00:27:38.140 --> 00:27:41.100
They'll go there and they'll spend like three or four seconds, five seconds.

00:27:41.100 --> 00:27:42.360
And then they'll go to another thing.

00:27:42.360 --> 00:27:43.800
They'll spend 10 seconds there.

00:27:43.800 --> 00:27:45.700
Then they'll go off and they'll click this button, right?

00:27:45.700 --> 00:27:47.240
They'll have normal human behavior.

00:27:47.240 --> 00:27:51.980
So one of the things you set up in this class you define that represents a user on your

00:27:51.980 --> 00:27:52.940
site is a wait time.

00:27:52.940 --> 00:27:56.060
So say the wait time is between five and 15 seconds.

00:27:56.060 --> 00:27:58.500
And then you ask, can it take a million users?

00:27:58.500 --> 00:28:00.220
It doesn't just do a million concurrent requests.

00:28:00.220 --> 00:28:04.940
It has like a million of these things randomly waiting between five to 15 seconds as they're

00:28:04.940 --> 00:28:07.600
kind of like interacting randomly with your site.

00:28:07.600 --> 00:28:08.640
Oh, cool.

00:28:08.640 --> 00:28:11.060
So you could sort of scale this then.

00:28:11.060 --> 00:28:16.580
You could start with something like some long wait times and then make sure that it can

00:28:16.580 --> 00:28:22.060
handle like a thousand users or something and then gradually make it shorter so that it's

00:28:22.060 --> 00:28:23.440
hitting on your server harder.

00:28:23.440 --> 00:28:24.440
Yeah, exactly.

00:28:24.440 --> 00:28:25.700
I think this is really neat.

00:28:25.700 --> 00:28:29.700
So I don't know that I would necessarily be using it right now, but if I create something

00:28:29.700 --> 00:28:34.700
new, especially something I'm sure is going to get a lot of traffic, then I would definitely

00:28:34.700 --> 00:28:35.160
use this.

00:28:35.160 --> 00:28:36.060
It looks really neat.

00:28:36.060 --> 00:28:37.280
It's free and open source.

00:28:37.280 --> 00:28:38.820
Like it's right in Python.

00:28:38.980 --> 00:28:40.100
Like why the heck not?

00:28:40.100 --> 00:28:44.060
The only reason I wouldn't use it now is I've already had like some really big spike

00:28:44.060 --> 00:28:44.340
events.

00:28:44.340 --> 00:28:48.280
I'm like, okay, well, it's, you know, everything's running at like 2%, 5% CPU.

00:28:48.280 --> 00:28:49.240
It's like, it's fine.

00:28:49.240 --> 00:28:50.200
I don't know.

00:28:50.200 --> 00:28:51.260
You can totally see.

00:28:51.260 --> 00:28:55.240
I mean, there's a huge use case for this is that like people that have the, they're rolling

00:28:55.240 --> 00:29:00.880
out a new app or even if they're an existing company rolling out something new and everything

00:29:00.880 --> 00:29:05.000
looks fine on their server, even when they're testing with like two or three consecutive

00:29:05.000 --> 00:29:05.940
tests or something.

00:29:05.940 --> 00:29:07.920
But are we ready to roll it out?

00:29:08.040 --> 00:29:09.560
We don't know how many people are going to hit it.

00:29:09.560 --> 00:29:12.160
So they can sort of gauge that.

00:29:12.160 --> 00:29:16.140
The one that I always have in mind when I think about this is you've got some app that's been

00:29:16.140 --> 00:29:20.080
out there and it's kind of getting some traction and your company's getting some traction in

00:29:20.080 --> 00:29:20.240
it.

00:29:20.240 --> 00:29:25.720
And the company decides we're going to run a Superbowl ad or we're going to spend, we're

00:29:25.720 --> 00:29:28.740
going to launch some huge marketing campaign on Black Friday.

00:29:28.740 --> 00:29:33.040
that's like on like way, way out of bounds of what we normally do.

00:29:33.040 --> 00:29:38.080
The last thing, I mean, you only get one shot for your app to work when that Superbowl ad

00:29:38.080 --> 00:29:39.880
runs or on that Black Friday event.

00:29:39.880 --> 00:29:43.960
If it just goes down for that little bit of time, it's not like, well, we got it up.

00:29:43.960 --> 00:29:44.320
It's fine.

00:29:44.320 --> 00:29:48.420
Now it's, you've lost that moment and that million dollar spend or whatever the heck it turns

00:29:48.420 --> 00:29:48.820
out to be.

00:29:48.860 --> 00:29:54.000
So it's like those moments where the spike is unknown, but also the time which you get

00:29:54.000 --> 00:29:54.940
to deal with it is short.

00:29:54.940 --> 00:29:55.500
Yeah.

00:29:55.500 --> 00:30:01.360
Or things like, yeah, I'm pretty sure that the healthcare marketplace website's ready.

00:30:01.360 --> 00:30:02.380
It's fine.

00:30:02.380 --> 00:30:02.600
Yeah.

00:30:02.600 --> 00:30:02.940
Sure.

00:30:02.940 --> 00:30:04.680
Mr. President, this is going to be fine.

00:30:04.680 --> 00:30:07.240
It won't be like blemish your record for all of history.

00:30:07.240 --> 00:30:08.080
All right.

00:30:08.080 --> 00:30:10.340
Speaking of things that I'm sure are going to be fine.

00:30:10.340 --> 00:30:14.040
Hacktoberfest was such a, it's a good idea in theory, potentially.

00:30:14.040 --> 00:30:18.100
We're like in, in middle October or deep into October already.

00:30:18.180 --> 00:30:21.140
I don't know how your repos did, but I got a lot of attention.

00:30:21.140 --> 00:30:21.780
Did you?

00:30:21.780 --> 00:30:22.620
Yeah.

00:30:22.620 --> 00:30:23.280
No, mine.

00:30:23.280 --> 00:30:23.700
Yes.

00:30:23.700 --> 00:30:24.720
Mine didn't so much.

00:30:24.720 --> 00:30:27.160
I'll tell you about that, but go ahead and tell, tell people where we're going with this.

00:30:27.160 --> 00:30:27.500
Okay.

00:30:27.500 --> 00:30:32.240
So Hacktoberfest, hopefully you know about it, but if you don't, it's an interesting idea

00:30:32.240 --> 00:30:34.340
sponsored by DigitalOcean and other sponsors.

00:30:34.340 --> 00:30:37.020
Again, DigitalOcean not sponsoring this episode.

00:30:37.020 --> 00:30:38.980
Overall, it's a good idea.

00:30:38.980 --> 00:30:43.680
So the idea is to encourage people to contribute to open source by bribing them with a t-shirt

00:30:43.680 --> 00:30:44.440
and other swag.

00:30:44.440 --> 00:30:45.420
That works for geeks.

00:30:45.420 --> 00:30:46.300
We love our t-shirts.

00:30:46.660 --> 00:30:49.200
Like, how else are you going to be like wearing your clothes?

00:30:49.200 --> 00:30:50.080
What do you put in your closet?

00:30:50.080 --> 00:30:50.520
Yeah.

00:30:50.520 --> 00:30:54.640
Maybe, maybe you can buy a t-shirt with a half an hour of work, but we're going to like have

00:30:54.640 --> 00:30:58.080
you work for like hours and just get one t-shirt.

00:30:58.080 --> 00:31:03.180
Anyway, there's always been some spam with this, people abusing it, but I think it was

00:31:03.180 --> 00:31:05.100
not as prevalent as this year.

00:31:05.260 --> 00:31:12.260
But what happened this year, and I'm going to link to a video by Anthony Satili titled

00:31:12.260 --> 00:31:13.820
What's Wrong with Hacktoberfest?

00:31:13.820 --> 00:31:19.980
He introduces what Hacktoberfest is, some of the problems, and he recommended some solutions.

00:31:19.980 --> 00:31:21.380
We're not going to cover those today.

00:31:21.640 --> 00:31:23.980
But apparently there was a YouTuber this year.

00:31:23.980 --> 00:31:31.340
I think it was in India that did a video on how to get a free t-shirt by doing like, it's

00:31:31.340 --> 00:31:34.260
basically how to get free swag with not much work.

00:31:34.260 --> 00:31:41.000
And he did this video to show you how to submit a pull request to a project and only do things,

00:31:41.000 --> 00:31:47.520
something like update the readme to say an awesome project or change its with it is or

00:31:47.520 --> 00:31:48.400
something like that.

00:31:48.400 --> 00:31:54.740
And then do a pull request saying document or improve docs and do that for four different

00:31:54.740 --> 00:31:55.160
repos.

00:31:55.160 --> 00:31:56.020
And there you got a t-shirt.

00:31:56.020 --> 00:31:56.280
Yeah.

00:31:56.280 --> 00:31:57.700
I met many of these people.

00:31:59.280 --> 00:32:00.800
It turned into a big problem.

00:32:00.800 --> 00:32:08.080
So I was actually really thrilled with how fast DigitalOcean and whoever's working on

00:32:08.080 --> 00:32:13.080
Hacktoberfest fixed it, or at least hopefully, I'm sure people are still trying to do this.

00:32:13.080 --> 00:32:16.240
So I'm sure there's a lot of spam going on, but they changed the rules.

00:32:16.240 --> 00:32:21.520
So as of the third, they updated the rules to try to reduce the spam.

00:32:21.520 --> 00:32:28.540
One of the big things is maintainers can opt in by adding a Hacktoberfest topic to their

00:32:28.540 --> 00:32:28.820
repo.

00:32:28.820 --> 00:32:32.740
So a whole bunch of stale old repos won't get hit, hopefully.

00:32:32.740 --> 00:32:38.940
And then also you can mark any PR that's dumb as invalid and it invalidates stuff.

00:32:38.940 --> 00:32:43.780
And actually the full rules is, let's see, we're going to have it in the show notes.

00:32:43.780 --> 00:32:45.860
It's a little pseudo code.

00:32:45.860 --> 00:32:53.600
So if you submit a PR in the month of October and the PR is labeled as Hacktoberfest accepted

00:32:53.600 --> 00:33:01.300
by the maintainer or you submitted it to a repo with Hacktoberfest topic and the pull request

00:33:01.300 --> 00:33:03.140
was merged or it was approved.

00:33:03.140 --> 00:33:06.220
So you can't just submit it and get your t-shirt.

00:33:06.220 --> 00:33:11.280
It has to be like some maintainer has to say, yeah, this is good or I approve it or whatever.

00:33:11.280 --> 00:33:13.360
It's not automatic anymore.

00:33:13.800 --> 00:33:18.180
And also if you are a maintainer and you're, and you've dealt with all the spam, sorry about

00:33:18.180 --> 00:33:18.540
that.

00:33:18.540 --> 00:33:23.500
But also I'd like to, I'd like to encourage more people to do Hacktoberfest because it's

00:33:23.500 --> 00:33:24.160
a cool thing.

00:33:24.160 --> 00:33:28.340
I didn't want to bring it up before because I didn't want to encourage spam, but I think

00:33:28.340 --> 00:33:29.700
these changes will help.

00:33:30.000 --> 00:33:35.300
And if you're a maintainer, please be sure to do those notifications by November 1st because

00:33:35.300 --> 00:33:36.640
that's the deadline.

00:33:36.640 --> 00:33:37.320
Yeah.

00:33:37.320 --> 00:33:37.740
Interesting.

00:33:37.740 --> 00:33:44.840
I had no idea what was going on until I saw Anthony Cotili's post or Twitter message.

00:33:44.840 --> 00:33:50.660
You know, somebody came over to some of the, I have 222 repositories, most of which are public

00:33:50.660 --> 00:33:53.320
between the courses and various other things.

00:33:53.320 --> 00:33:56.840
So there's a bunch of opportunity to go in and make changes, right?

00:33:57.180 --> 00:34:02.300
So somebody came along to the beginner, the Python for Absolute Beginners course and said,

00:34:02.300 --> 00:34:06.040
I would like to add a few little tips for some beginners to make this slightly better.

00:34:06.040 --> 00:34:09.220
You know, we can't change anything because it needs to match what's in the video.

00:34:09.220 --> 00:34:13.580
But if you had a little section that had like some tips and they were meaningful, sure, I

00:34:13.580 --> 00:34:14.160
guess that's okay.

00:34:14.160 --> 00:34:18.520
And then the next day I woke up and it was like 10 PRs, not necessarily all from this person,

00:34:18.520 --> 00:34:23.120
but from a bunch of different people with weird things like change the read me from this,

00:34:23.120 --> 00:34:26.980
you know, check out our latest course to check out the latest course.

00:34:27.160 --> 00:34:31.780
And just changing like the word hour to the, and I'm like, what is going on?

00:34:31.780 --> 00:34:35.740
Then I saw Anthony's thing and I'm like, okay, close, close, close, close, close, close, close.

00:34:35.740 --> 00:34:36.940
Just straight out.

00:34:36.940 --> 00:34:38.400
Like, I don't even want to talk to these people.

00:34:38.400 --> 00:34:39.960
This is super annoying.

00:34:39.960 --> 00:34:41.740
And they weren't just making changes to the read me.

00:34:41.740 --> 00:34:45.940
They would go in and they would make changes to like XML configuration documents.

00:34:45.940 --> 00:34:47.940
I'm like, you can't change that.

00:34:47.940 --> 00:34:49.120
That's, that's machine.

00:34:49.120 --> 00:34:50.320
That's read by the machine, right?

00:34:50.320 --> 00:34:52.120
That's going to break something if I accept this.

00:34:52.120 --> 00:34:55.120
Not only is it like annoying that I got to deal with it, but if I were to accept that,

00:34:55.160 --> 00:34:59.120
I'm pretty sure it would break, I think maybe it was like formatting, like putting a node,

00:34:59.120 --> 00:35:03.700
closing node bit, like on, on a line above or like putting a space.

00:35:03.700 --> 00:35:06.360
I mean, I don't think it actually broke it, but it was really weird stuff.

00:35:06.360 --> 00:35:08.540
And I didn't understand it was coming from Hacktoberfest.

00:35:08.540 --> 00:35:11.060
I was being hacked by the Hacktoberfesters.

00:35:13.000 --> 00:35:13.320
Yeah.

00:35:13.320 --> 00:35:16.060
But it has stopped since they made these changes, which is great.

00:35:16.060 --> 00:35:16.820
Oh, it hasn't stopped?

00:35:16.820 --> 00:35:18.740
So most of that stuff was in the first few days.

00:35:18.740 --> 00:35:19.080
Yeah.

00:35:19.080 --> 00:35:20.240
I haven't seen the last couple of days.

00:35:20.240 --> 00:35:22.200
I didn't realize that's probably because the rules changed.

00:35:22.200 --> 00:35:25.480
I just went through and like, just denied everything that I saw coming in.

00:35:25.480 --> 00:35:25.920
Yeah.

00:35:25.920 --> 00:35:30.120
I wonder if they forced the takedown of that video or maybe it's gone.

00:35:30.120 --> 00:35:30.440
Yeah.

00:35:30.440 --> 00:35:30.980
Yeah.

00:35:30.980 --> 00:35:31.280
Who knows?

00:35:31.280 --> 00:35:32.300
Who knows?

00:35:32.300 --> 00:35:34.800
Well, I know that that's it for all of our main topics.

00:35:34.800 --> 00:35:38.060
Got anything else you want to throw out real quick before we wrap it up with a joke?

00:35:38.420 --> 00:35:38.880
They don't.

00:35:38.880 --> 00:35:40.020
I could totally use a joke.

00:35:40.020 --> 00:35:41.280
But do you have any extra things?

00:35:41.280 --> 00:35:42.060
I do.

00:35:42.060 --> 00:35:43.780
There's a really cool conference.

00:35:43.780 --> 00:35:50.100
It's, I believe, theoretically was supposed to be this year in Vancouver, BC, which is an

00:35:50.100 --> 00:35:53.240
absolutely wonderful town to visit, called Pie Cascades.

00:35:53.240 --> 00:35:56.140
Cycles between Vancouver, Seattle, and Portland.

00:35:56.140 --> 00:36:02.260
Well, this year it's taken a diversion to cycle to the internet because 2020, although it's

00:36:02.260 --> 00:36:04.500
in 2021, like still planning now.

00:36:04.900 --> 00:36:10.900
So Pie Cascades 2021 will take place Saturday, February 20th from the world.

00:36:10.900 --> 00:36:16.440
I don't know if they're having any local stuff going on, but anyway, it's basically a virtual

00:36:16.440 --> 00:36:18.940
conference and the call for proposals is open.

00:36:18.940 --> 00:36:23.380
So if you'd like to give a presentation there, you can do that by November 10th.

00:36:23.380 --> 00:36:25.080
Submit proposals.

00:36:25.080 --> 00:36:26.040
So that would be cool.

00:36:26.740 --> 00:36:33.300
You know, I think talking at get-togethers like this, meetups, the smaller, not full-blown

00:36:33.300 --> 00:36:37.060
PieCon, but Pie Cascades and other types of events are a really good way to sort of raise

00:36:37.060 --> 00:36:40.100
your profile and stretch your comfort zone as a developer.

00:36:40.100 --> 00:36:41.700
So I encourage people to do it.

00:36:41.700 --> 00:36:42.700
Also, Patricia.

00:36:42.700 --> 00:36:45.400
I spoke at the 2020 version.

00:36:45.400 --> 00:36:48.060
That was just before the world fell apart.

00:36:48.060 --> 00:36:48.960
That's right.

00:36:48.960 --> 00:36:49.580
I was there.

00:36:49.580 --> 00:36:51.240
My daughter and I watched from the back.

00:36:51.240 --> 00:36:51.600
It was great.

00:36:52.160 --> 00:36:58.300
Next thing, other thing, Patricio Reins, who is a researcher at the Barcelona Supercomputing

00:36:58.300 --> 00:37:01.240
Center, which by the way, they have this virtual tour he sent me.

00:37:01.240 --> 00:37:02.940
Oh my God, it is so awesome.

00:37:02.940 --> 00:37:04.880
They have like a pop song for it.

00:37:04.880 --> 00:37:11.460
It is held inside, literally the supercomputer is inside an old cathedral.

00:37:11.460 --> 00:37:17.320
So like where all the arches are and where the sermons would have been given, that's where

00:37:17.320 --> 00:37:18.180
the supercomputer is.

00:37:18.180 --> 00:37:18.900
That's pretty awesome.

00:37:18.900 --> 00:37:20.840
Can we put that link in the show notes too?

00:37:20.840 --> 00:37:21.120
Yeah.

00:37:21.120 --> 00:37:21.380
Yeah.

00:37:21.380 --> 00:37:21.480
Yeah.

00:37:21.480 --> 00:37:21.920
I'll put it in there.

00:37:21.920 --> 00:37:23.640
But that's not why he sent it to me.

00:37:23.640 --> 00:37:26.760
He just said, hey, I happen to work here and I use Jupyter a lot.

00:37:26.760 --> 00:37:34.140
You spoke about Black Cell Magic and then another black formatter plugin for Jupyter

00:37:34.140 --> 00:37:34.560
Notebooks.

00:37:34.560 --> 00:37:40.200
So he said, you should also check out NB Black, NB underscore black, which works in Jupyter

00:37:40.200 --> 00:37:41.140
and JupyterLab.

00:37:41.140 --> 00:37:45.900
And there's another one that only works in JupyterLab called the JupyterLab code formatter.

00:37:45.900 --> 00:37:51.720
So just like always, we mentioned one thing that we kind of discover and then listeners are

00:37:51.720 --> 00:37:52.320
like, that's great.

00:37:52.320 --> 00:37:54.260
And, and, and, and here's a bunch of other stuff.

00:37:54.260 --> 00:37:55.660
So thank you for that, Patricio.

00:37:55.660 --> 00:37:55.960
Yeah.

00:37:55.960 --> 00:37:56.620
Nice.

00:37:56.620 --> 00:37:57.440
But I love that.

00:37:57.440 --> 00:37:58.960
I like the multiple tool thing.

00:37:58.960 --> 00:37:59.460
That's fine.

00:37:59.460 --> 00:37:59.960
Yeah, indeed.

00:37:59.960 --> 00:38:00.620
All right.

00:38:00.620 --> 00:38:01.100
Let's do a joke.

00:38:01.100 --> 00:38:04.360
I've chosen some very clear ones that actually have a visual component.

00:38:04.360 --> 00:38:06.580
As you know, I don't know why I do that, but that's what I've done.

00:38:07.220 --> 00:38:10.220
So why don't you, I'll let you do the first one.

00:38:10.220 --> 00:38:11.500
I'll do the second one.

00:38:11.500 --> 00:38:16.380
So the way people who don't know, this is a classical programmer painting.

00:38:16.540 --> 00:38:21.960
And the idea is this is a legitimate real painting from some museum.

00:38:21.960 --> 00:38:29.200
Typically they're hundreds of years old, but there's, instead of having, you know, like flowers

00:38:29.200 --> 00:38:36.080
in the tide pools or whatever, some random thing that the artist named it, it's renamed

00:38:36.080 --> 00:38:38.280
with a programming title.

00:38:38.820 --> 00:38:39.380
Okay.

00:38:39.380 --> 00:38:40.060
Yeah.

00:38:40.060 --> 00:38:44.600
So why don't you quickly describe your picture and then tell us the title.

00:38:44.600 --> 00:38:45.240
Okay.

00:38:45.240 --> 00:38:50.380
So, the picture is, it's a white, kind of a white gray background.

00:38:50.380 --> 00:38:52.800
I think it's snow or something.

00:38:52.800 --> 00:38:54.080
There's some horses running.

00:38:54.080 --> 00:38:54.860
There's a white out blizzard almost.

00:38:54.860 --> 00:38:55.100
Yeah.

00:38:55.100 --> 00:38:55.500
It's horrible.

00:38:55.500 --> 00:38:55.860
Yeah.

00:38:55.860 --> 00:39:01.940
And there's some horses running, two horses running, pulling a, what, like a sled or something?

00:39:01.940 --> 00:39:02.680
I don't know.

00:39:02.680 --> 00:39:03.960
And there's somebody laying on the sled.

00:39:03.960 --> 00:39:04.240
All right.

00:39:04.240 --> 00:39:04.720
What's the title?

00:39:04.720 --> 00:39:07.400
Delivering a feature in the time of a code freeze.

00:39:07.400 --> 00:39:13.100
This is by Anthony Petrowski, oil on wood, 1883.

00:39:13.100 --> 00:39:13.640
Yeah.

00:39:13.640 --> 00:39:14.040
It's beautiful.

00:39:14.040 --> 00:39:15.140
All right.

00:39:15.140 --> 00:39:23.680
So the one that I got here, it's these three guys, they look highly skeptical, almost like

00:39:23.680 --> 00:39:28.820
they're on some kind of mission, sneaking out of like really tall grass on a boat in some

00:39:28.820 --> 00:39:29.640
kind of swamp.

00:39:29.640 --> 00:39:32.380
You can see them like really slowly sort of approaching.

00:39:32.740 --> 00:39:38.440
And the title is Red Hat Enterprise Linux, sys admins entering the Docker convention floor.

00:39:38.440 --> 00:39:40.040
Oil on canvas, 1882.

00:39:40.040 --> 00:39:42.500
Isn't that a great one?

00:39:42.500 --> 00:39:43.420
Like, look at their face.

00:39:43.420 --> 00:39:44.120
Yeah.

00:39:44.120 --> 00:39:45.820
People got to check this out.

00:39:45.820 --> 00:39:47.920
Click on the link in your podcast player and see it.

00:39:47.920 --> 00:39:50.040
They're like angry pirates in a canoe.

00:39:50.040 --> 00:39:50.480
Yeah.

00:39:50.480 --> 00:39:52.200
It's sort of a piratey feel to it.

00:39:52.200 --> 00:39:53.660
Like they're like, oh, what are we doing here?

00:39:53.660 --> 00:39:54.420
We're breaking in.

00:39:54.420 --> 00:39:55.580
It's such a weird world.

00:39:55.580 --> 00:39:56.960
This Docker Kubernetes.

00:39:56.960 --> 00:40:02.120
I love this thing of like programmer quotes on old on paintings.

00:40:02.120 --> 00:40:03.460
It's a, it's funny.

00:40:03.460 --> 00:40:03.840
Yeah.

00:40:03.840 --> 00:40:09.300
If there's ever some sort of like artwork exhibition at a PyCon, this is happening.

00:40:09.300 --> 00:40:12.800
Oh, we could probably do it virtually somehow.

00:40:12.800 --> 00:40:14.260
Try to do it at a virtual conference.

00:40:14.260 --> 00:40:14.780
Yes.

00:40:14.780 --> 00:40:15.880
I think we could.

00:40:15.880 --> 00:40:16.220
Yeah.

00:40:16.220 --> 00:40:16.560
Yep.

00:40:16.560 --> 00:40:16.900
All right.

00:40:16.900 --> 00:40:18.060
Well, thanks for being here as always.

00:40:18.060 --> 00:40:19.420
And thank you everyone out there.

00:40:19.420 --> 00:40:19.520
Thank you.

00:40:19.520 --> 00:40:19.800
Let's listen.

00:40:19.800 --> 00:40:20.340
Yep.

00:40:20.340 --> 00:40:20.680
Bye-bye.

00:40:20.680 --> 00:40:21.020
Bye.

00:40:21.020 --> 00:40:22.940
Thank you for listening to Python Bytes.

00:40:22.940 --> 00:40:25.460
Follow the show on Twitter via at Python Bytes.

00:40:25.560 --> 00:40:28.320
That's Python Bytes as in B-Y-T-E-S.

00:40:28.320 --> 00:40:31.560
And get the full show notes at Python Bytes.fm.

00:40:31.560 --> 00:40:35.760
If you have a news item you want featured, just visit Python Bytes.fm and send it our way.

00:40:35.760 --> 00:40:38.460
We're always on the lookout for sharing something cool.

00:40:38.460 --> 00:40:41.580
On behalf of myself and Brian Okken, this is Michael Kennedy.

00:40:41.580 --> 00:40:45.000
Thank you for listening and sharing this podcast with your friends and colleagues.

