WEBVTT

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

00:00:05.420 --> 00:00:10.980
This is episode 172, recorded March 4th, 2020.

00:00:10.980 --> 00:00:12.500
And I am Brian Okken.

00:00:12.500 --> 00:00:13.360
And I'm Michael Kennedy.

00:00:13.360 --> 00:00:16.240
And this episode is brought to you by DigitalOcean.

00:00:16.240 --> 00:00:20.080
And they've got all sorts of cool stuff we'll hear about later.

00:00:20.080 --> 00:00:21.900
Who's going first? I always forget.

00:00:21.900 --> 00:00:25.860
You know, I guess I'm going to jump in on this one because I've got some cool stuff from Hank.

00:00:25.860 --> 00:00:29.240
Hank! He even messed his name up worse than I do.

00:00:29.240 --> 00:00:29.960
Hennyk?

00:00:30.260 --> 00:00:31.160
Okay, cool.

00:00:31.160 --> 00:00:32.440
All right. Sorry, Hennyk.

00:00:32.440 --> 00:00:34.900
I have to give you a bad time because he gives me a bad time all the time.

00:00:34.900 --> 00:00:40.580
Yeah, well, it's a cool but unusual name, which is probably going to result in some mispronunciation.

00:00:40.580 --> 00:00:47.120
He's got a cool article he tweeted about a little while ago, a week or two ago.

00:00:47.120 --> 00:00:48.620
And I just thought it was really interesting.

00:00:48.620 --> 00:00:53.880
And basically, it's his thoughts on running Python in production.

00:00:54.560 --> 00:00:59.360
So it's kind of a look back on some places.

00:00:59.360 --> 00:01:12.500
He heard interesting discussions on people running Python in production, as well as maybe some got some nice little call outs on things that seem solved, but aren't solved that are interesting to talk about and whatnot.

00:01:12.500 --> 00:01:14.540
So I just thought I'd maybe talk about that a little bit.

00:01:14.540 --> 00:01:14.840
Yeah.

00:01:15.040 --> 00:01:15.180
Yeah.

00:01:15.180 --> 00:01:19.180
I mean, I definitely relate to this being someone who runs Python in production.

00:01:19.180 --> 00:01:28.420
So in order to keep the two podcasts, the courses and various other things, other services running, there's like eight servers and whatnot.

00:01:28.420 --> 00:01:33.920
So there's a non-trivial amount of DevOps production architecture stuff.

00:01:34.020 --> 00:01:40.800
It's not anywhere near Facebook, Google or whatever, but it's way more than, you know, a $5 host running some like WordPress thing.

00:01:40.800 --> 00:01:40.960
Right.

00:01:40.960 --> 00:01:42.860
So it's meaningful, I guess.

00:01:42.860 --> 00:01:54.920
So anyway, his article, basically the premise is that he's missing a key part of the public Python discourse in that it seems like people really aren't talking about running Python in production.

00:01:55.200 --> 00:01:58.860
Although maybe the exception of Instagram or Spotify, right?

00:01:58.860 --> 00:01:59.120
Yeah.

00:01:59.120 --> 00:01:59.980
That's pretty interesting.

00:01:59.980 --> 00:02:01.760
And he listened to this podcast episode.

00:02:01.760 --> 00:02:06.840
He recommended, or I guess listen to this podcast episode, sort of kicked him off down this path of thinking about it.

00:02:06.840 --> 00:02:10.400
Like there was this podcast and I'm trying to remember what was it called?

00:02:10.400 --> 00:02:11.100
Here, I'll pull it up.

00:02:11.100 --> 00:02:13.560
It's called, well, running in production.

00:02:13.560 --> 00:02:18.840
Actually, it's a pretty interesting one by Nick Gentakis.

00:02:18.840 --> 00:02:21.200
Probably mispronounced that name as well.

00:02:21.200 --> 00:02:29.940
But Nick's got an interesting thing where he talks to people from all sorts of different technology backgrounds, JavaScript or Ruby or Python or whatever.

00:02:29.940 --> 00:02:48.180
And he interviewed this guy named Gareth Thomas from the UK where they have some Plone, I believe it's Plone app, that is actually running like 10% of, getting like traffic from 10% of the UK schools or something really interesting in this.

00:02:48.800 --> 00:02:58.920
But it was more interesting to just think about listening to that episode, looking at Hank's article and saying, when do I agree with them?

00:02:58.920 --> 00:02:59.980
When do I disagree?

00:02:59.980 --> 00:03:03.480
And he said, look, I disagree with a lot of their choices, actually.

00:03:03.480 --> 00:03:06.000
I think they're using microservices a bunch.

00:03:06.000 --> 00:03:10.460
And he was like, thank goodness, I'm not doing microservices, basically.

00:03:11.160 --> 00:03:15.560
And it's really interesting, even if you disagree, to think about the trade-offs that people made.

00:03:15.560 --> 00:03:27.160
Because while you might make different trade-offs, that might be because you have different goals or different things you're optimizing or different experiences or things that you need over what they need.

00:03:27.160 --> 00:03:27.680
Right?

00:03:27.680 --> 00:03:32.980
So I just think this idea of exploring how people are running Python in production, how they're solving problems, it's pretty interesting.

00:03:32.980 --> 00:03:45.100
Yeah, I also kind of have to agree that I like the idea of hearing more about the pathway of why people are where they're at, what decisions they made and what things they faced and why they made those choices.

00:03:45.100 --> 00:03:53.220
Because that's almost more interesting than what end product they came up with is what the path they took to it.

00:03:53.220 --> 00:03:57.220
I mean, like Lord of the Rings would be nothing without the path to the end, right?

00:03:57.620 --> 00:03:58.100
Exactly.

00:03:58.100 --> 00:03:59.800
Oh, yeah, and they get the ring back.

00:03:59.800 --> 00:04:01.020
Yeah.

00:04:01.020 --> 00:04:06.320
Yeah, so his article, like all good complaints, comes with a suggestion.

00:04:06.320 --> 00:04:11.020
And he says, at the end, here's a bunch of things that could get discussed more.

00:04:11.020 --> 00:04:12.460
And so here's an offer.

00:04:12.460 --> 00:04:24.460
I would love to encourage people doing interesting stuff with Python, running websites or APIs and whatnot, to tell them basically to do talks at PyCon, at meetups, and in blogs.

00:04:24.820 --> 00:04:30.820
And I think he even offered to help mentor people to get those kind of talks accepted more frequently at conferences.

00:04:30.820 --> 00:04:31.920
I think that's a great idea.

00:04:31.920 --> 00:04:32.740
I think it's a great idea.

00:04:32.740 --> 00:04:37.460
And, you know, maybe we should do that at the PDX Python West meetup.

00:04:37.460 --> 00:04:38.680
That'd be fun.

00:04:38.680 --> 00:04:38.980
Yeah.

00:04:38.980 --> 00:04:39.320
Yeah.

00:04:39.320 --> 00:04:40.480
We think about that.

00:04:40.480 --> 00:04:46.580
But yeah, I definitely like this idea because on one hand, if it's kind of always the same story, it's not that interesting.

00:04:46.580 --> 00:04:49.260
But I do think there's a lot of trade-offs that people are making.

00:04:49.260 --> 00:04:52.520
And I think it's pretty fun to see what's working.

00:04:52.520 --> 00:04:54.240
And it's clearly going on.

00:04:54.240 --> 00:05:04.620
We're just not talking about it because we're, I mean, you and I have noticed that there's a lot of people in the Python community that are in the website or the website of the Python community.

00:05:05.120 --> 00:05:09.880
And it's way more than just the Instagrams and Dropboxes of the world.

00:05:09.880 --> 00:05:11.040
Yeah, absolutely.

00:05:11.040 --> 00:05:11.700
Absolutely.

00:05:11.700 --> 00:05:13.180
Yeah, it's really cool.

00:05:13.180 --> 00:05:15.520
And there's a bunch of more stuff that I'm not covering in this article.

00:05:15.720 --> 00:05:21.900
But I mostly covered it because I love his offer of like, hey, let's get more of this conversation out there.

00:05:21.900 --> 00:05:23.360
You know, we could do open spaces.

00:05:23.360 --> 00:05:29.580
We could do Python, PyCon talks, suggestions, you know, proposals, things like that.

00:05:29.580 --> 00:05:44.620
I guess one final thing to throw out there is Dan Bader and I did have this conversation for Talk Python and the training and Python Bytes and whatnot, as well as for RealPython over on Talk Python episode 215 at the last PyCon.

00:05:44.860 --> 00:05:46.160
We recorded that one.

00:05:46.160 --> 00:05:49.060
So we'll see what happens with this PyCon.

00:05:49.060 --> 00:05:51.880
But that's a small contribution towards that.

00:05:51.880 --> 00:05:53.840
And that was a really popular episode.

00:05:53.840 --> 00:06:02.840
But I definitely want to encourage people to take Hennick up on this, up on his offer here and get the word out a little bit more.

00:06:02.840 --> 00:06:03.420
All right.

00:06:03.420 --> 00:06:04.260
Yeah.

00:06:04.260 --> 00:06:04.440
Yeah.

00:06:04.440 --> 00:06:11.100
So, Brian, when I think about testing and whatnot, I feel like you should really be honest and like testing to tell a true story.

00:06:11.100 --> 00:06:13.940
And you should never like cheat with testing, should you?

00:06:14.020 --> 00:06:16.120
Yeah, only, yes, you should definitely cheat.

00:06:16.120 --> 00:06:17.400
Cheat as much as you can.

00:06:17.400 --> 00:06:19.100
Tell us about this next one.

00:06:19.100 --> 00:06:22.020
So this comes from, I think it's Simon Willison.

00:06:22.020 --> 00:06:26.700
The article is called How to Cheat at Unit Tests with pytest and Black.

00:06:26.700 --> 00:06:35.080
It's got all my favorite things, testing, pytest, Black, and well, I'm not a fan of the unit part, but we'll get there.

00:06:35.080 --> 00:06:43.180
So the premise is, I'm going to quote this, in pure test-driven development, you write a test first and you don't start on the implementation

00:06:43.180 --> 00:06:45.780
until you've watched a test fail.

00:06:45.780 --> 00:06:46.720
Okay.

00:06:46.720 --> 00:06:50.340
So the idea is you, it's the red-green refactor thing.

00:06:50.340 --> 00:06:55.380
So you write a failing test, you write code to make it pass, and then you refactor it so you're happy with it.

00:06:55.380 --> 00:06:56.600
And if I don't do that, I'm cheating?

00:06:56.600 --> 00:06:57.300
Yeah, apparently.

00:06:57.480 --> 00:06:59.800
I think I might have cheated accidentally, recently.

00:06:59.800 --> 00:07:00.280
Okay.

00:07:00.280 --> 00:07:01.520
Well, yeah.

00:07:01.520 --> 00:07:07.280
My thoughts partly on that is there is no such thing as pure test-driven development.

00:07:07.280 --> 00:07:10.560
Even Kent Beck himself says he didn't make this stuff up.

00:07:10.560 --> 00:07:14.040
He rediscovered it from previous best practices.

00:07:14.580 --> 00:07:17.060
So there's no pure in test-driven development.

00:07:17.060 --> 00:07:21.220
We can't even agree on, like, whether a mox are good or evil or what a unit is.

00:07:21.220 --> 00:07:23.060
So whatever works for you, man.

00:07:23.060 --> 00:07:26.680
So Simon's process really was to cheat on this.

00:07:26.680 --> 00:07:30.320
And the way, and I think this is just clever pragmatism.

00:07:30.820 --> 00:07:39.620
His cheat method was to write a pytest test that calls a function that he's, so he's been working on a function, and he thinks he's happy with it.

00:07:39.620 --> 00:07:46.740
And he writes a test that calls it, but then compares the output to, you know, something he knows won't pass.

00:07:46.740 --> 00:07:49.800
Like, just the output equals false or something.

00:07:49.800 --> 00:07:51.640
And you know that a cert's going to fail.

00:07:51.640 --> 00:07:55.600
So you run the test, and when it fails, you take a look at the output.

00:07:55.720 --> 00:08:02.920
And if you're happy with the output, you just copy that, just highlight it, copy and paste it into your test, and now your test should pass.

00:08:02.920 --> 00:08:11.340
So this feels like cheating, but it's really just taking a manual test and turning it into an automated regression test.

00:08:11.340 --> 00:08:16.980
Especially when you're exploring stuff, I think this is a great way to build up some of your test coverage.

00:08:17.180 --> 00:08:27.400
The bit about black is that the output might be this big, long blob something, like a dictionary or a big list or something, and it might not be formatted well.

00:08:27.400 --> 00:08:33.380
And that's where he just turns black on his test code and reformat it nicely and makes sure it still passes.

00:08:33.380 --> 00:08:35.600
So I think this is a good time saver.

00:08:35.600 --> 00:08:36.260
This is interesting.

00:08:36.260 --> 00:08:45.860
I was working on some tests recently where I had a big chunk of test data that I wanted to compare against something, kind of like he's describing here.

00:08:46.740 --> 00:08:47.920
And I was really torn.

00:08:47.920 --> 00:08:49.500
I'd love to hear your thoughts on this.

00:08:49.500 --> 00:08:54.500
You know, I put this at the top of my test file so I could reference it, right?

00:08:54.500 --> 00:08:55.620
I didn't put it in the test.

00:08:55.620 --> 00:08:59.440
I put it kind of separate because I'm like, well, this thing is, you know, it basically fills the screen.

00:08:59.440 --> 00:09:01.900
So I didn't want it to generate a huge test.

00:09:01.900 --> 00:09:03.860
I want to say compare against that thing, right?

00:09:04.520 --> 00:09:13.920
And one of the thoughts I had was creating like a, I don't know, a test data module where I could pull those things out, like put it completely into a different file and pull it back.

00:09:13.920 --> 00:09:18.060
And it sounds like that might also be a nice way to organize things here.

00:09:18.060 --> 00:09:26.760
But at the same time, it takes what you would see as I'm comparing against this and it hides it away behind, you know, a label of whatever that test module is.

00:09:26.760 --> 00:09:27.960
What are your thoughts on that?

00:09:27.960 --> 00:09:29.300
Good, bad, indifferent?

00:09:29.480 --> 00:09:39.260
I think there's lots of times where that is a good thing, especially like you said, it's a data, a big structure or something that you're comparing against.

00:09:39.260 --> 00:09:51.020
One common method to do something like that is if there's like, for instance, it isn't really what you're asking, but if there's, instead of comparing a whole bunch of different fields or something, to actually compare structures.

00:09:51.020 --> 00:09:56.880
So to create the expected data structure, especially with data classes, it makes it pretty easy.

00:09:56.880 --> 00:09:59.640
You can just say, this is my expected object.

00:09:59.640 --> 00:10:03.260
And what I got back was this thing and compare those two.

00:10:03.260 --> 00:10:12.560
Now, if that thing, if all the data is huge and it makes it more clean to work with your test, to stick it in a different file, then go for it.

00:10:12.560 --> 00:10:13.380
I think that's fine.

00:10:13.840 --> 00:10:23.420
I mean, there's a method of regression testing, which is kind of the model of, I know it works now and I'm going to modify the code for some reason.

00:10:23.420 --> 00:10:31.500
So I, instead of trying to come up with thorough tests for everything, just running it with a bunch of logging and stuff and capturing all that.

00:10:31.500 --> 00:10:32.320
Yeah, absolutely.

00:10:32.320 --> 00:10:38.280
And then running it again and make sure all of your output and logging is the same and just comparing against that.

00:10:38.560 --> 00:10:44.160
It's yucky to work with in the long run, but in the short term, it's a pretty handy, quick thing to do.

00:10:44.160 --> 00:10:44.420
Yeah.

00:10:44.420 --> 00:10:49.100
Instead of changing your entire architecture so you can mock out everything and then who knows if you get that right.

00:10:49.100 --> 00:10:51.760
You're just like, all right, I don't want it to change.

00:10:51.760 --> 00:10:54.100
Let's just start from like, keep it where it is.

00:10:54.100 --> 00:10:58.440
And if it breaks, then we'll figure out if that's a change we wanted.

00:10:58.440 --> 00:10:58.740
Right.

00:10:58.740 --> 00:11:00.820
But just to know that it didn't change is really helpful.

00:11:00.820 --> 00:11:01.800
And that's a quickies way.

00:11:01.800 --> 00:11:02.200
I like it.

00:11:02.200 --> 00:11:02.420
Right.

00:11:02.420 --> 00:11:06.800
And I mean, change detector tests are a smell that you need to be aware of because they're not.

00:11:07.240 --> 00:11:09.420
You want to be able to change your architecture.

00:11:09.420 --> 00:11:14.260
As long as you can make sure that you're checking for, you don't want the behavior to change.

00:11:14.260 --> 00:11:16.360
Sometimes those are good things.

00:11:16.360 --> 00:11:16.760
Yep.

00:11:16.760 --> 00:11:17.160
I agree.

00:11:17.160 --> 00:11:18.000
Be a pragmatist.

00:11:18.000 --> 00:11:18.300
For sure.

00:11:18.300 --> 00:11:18.780
Good advice.

00:11:18.780 --> 00:11:20.220
You know what else is good advice?

00:11:20.220 --> 00:11:21.300
Work with DigitalOcean.

00:11:21.300 --> 00:11:22.300
Yeah, definitely.

00:11:22.300 --> 00:11:27.420
We've been working with DigitalOcean and we've got a lot of our infrastructure there and we've been really happy with it.

00:11:27.980 --> 00:11:32.780
And so one of the things they've got, they've got Kubernetes clusters and all sorts of stuff.

00:11:32.780 --> 00:11:40.560
So, however, getting started with hosting and running Linux servers or Kubernetes clusters and all that stuff can be a little tricky.

00:11:40.560 --> 00:11:47.540
And getting into that, going from just building on your own computer to dealing with all of this, some people might not know how to do that.

00:11:47.720 --> 00:11:51.720
And so that's one of the reasons why DigitalOcean launched their new support center.

00:11:52.260 --> 00:11:58.380
So the support center makes it easier to find the answers to your questions and to get help that you need right when you need it.

00:11:58.380 --> 00:12:05.140
You can search across product docs or community tutorials and forums and it's all in one place and you can get all your answers.

00:12:05.140 --> 00:12:08.340
So I'm sure that's going to help a lot of people really a lot.

00:12:08.340 --> 00:12:09.900
So check this out.

00:12:09.900 --> 00:12:15.240
You can visit pythonbytes.fm/do support to see their tutorials.

00:12:15.240 --> 00:12:22.700
And of course, you can use pythonbytes.fm/digitalocean to get $100 credit for new users.

00:12:22.700 --> 00:12:24.780
Their tutorials are pretty awesome.

00:12:24.780 --> 00:12:29.400
And I just want to tell people like how helpful they have been.

00:12:29.400 --> 00:12:36.060
So typically, you know, especially when I was getting started, I'm like, man, how come this micro whiskey thing won't start?

00:12:36.060 --> 00:12:38.340
It seems like it should work when I run it, but it won't.

00:12:38.340 --> 00:12:43.320
It's probably something like the logging file didn't have permission to write through or something weird like that.

00:12:44.160 --> 00:12:47.900
You go search for that and it's very likely that one of these tutorials is going to come up.

00:12:47.900 --> 00:12:51.480
But, you know, I just went and put micro whiskey into their tutorial thing here.

00:12:51.480 --> 00:12:56.700
And it comes up how to serve a flask app with micro whiskey and Nginx on Ubuntu 18.04.

00:12:56.700 --> 00:12:57.940
But then it has a dropdown.

00:12:57.940 --> 00:13:04.100
Oh, would you like to do that on 16.04 or 14.04 or maybe on CentOS 7 or whatever?

00:13:04.100 --> 00:13:09.060
And you can actually change the operating system it's running on and the tutorial will adapt.

00:13:09.060 --> 00:13:11.980
I mean, it's ridiculous like how involved it is.

00:13:11.980 --> 00:13:14.100
Yeah, they've really done a lot to help.

00:13:14.100 --> 00:13:18.040
Novice users come up to speed to get things running well.

00:13:18.040 --> 00:13:20.000
Yeah, I just remember how helpful that stuff was for me.

00:13:20.000 --> 00:13:22.860
So, yeah, check them out at pythonbytes.fm/digitalization.

00:13:22.860 --> 00:13:26.000
Get that credit, but then use their support center to actually get going.

00:13:26.000 --> 00:13:27.820
You know what I'm glad I don't have to support?

00:13:27.820 --> 00:13:29.960
Hundreds of microservices.

00:13:29.960 --> 00:13:31.640
Yeah, me too.

00:13:32.780 --> 00:13:42.480
So, I think I found this from Mahenyuk's article when he was talking about how people were running in production and whether or not they should have microservices or not.

00:13:42.480 --> 00:13:45.920
And that podcast I told you about, I believe those people were using microservices.

00:13:46.300 --> 00:13:47.800
He's like, yeah, no way.

00:13:47.800 --> 00:13:48.520
No, thank you.

00:13:48.520 --> 00:13:55.500
And referred to this article by Alexandra Noonan, who works for a company called Segment.

00:13:56.320 --> 00:13:59.500
And this is like a retrospective on their experience.

00:13:59.500 --> 00:14:01.680
So, they had started out with a monolith app.

00:14:01.680 --> 00:14:03.640
I believe they're doing JavaScript, but it doesn't really matter.

00:14:03.640 --> 00:14:08.960
Basically, it's like package managers and maintaining versions that talk to APIs.

00:14:08.960 --> 00:14:10.420
The same story for Python.

00:14:10.420 --> 00:14:14.520
You know, you just switch the code samples or whatever, and they're not really relevant.

00:14:14.760 --> 00:14:21.240
So, there's this article called Goodbye Microservices from 100 Problem Children to One Superstar.

00:14:21.240 --> 00:14:30.340
And it talks about how Segment was founded during the height of microservices as the architecture du jour, right?

00:14:30.340 --> 00:14:31.340
Architecture of the day.

00:14:31.340 --> 00:14:36.060
And how to sort of decided that was going to solve all their problems.

00:14:36.060 --> 00:14:37.700
And at first, it did.

00:14:37.700 --> 00:14:42.260
But as they grew and grew and grew, it turned out to be such a huge headache.

00:14:42.840 --> 00:14:44.940
So, they had three software developers.

00:14:44.940 --> 00:14:58.660
And eventually, they said, basically, their three software developers were spending almost all their time tracking down broken tests across these hundreds of different variations of microservices and all sorts of stuff.

00:14:58.660 --> 00:15:00.340
And they were just going nowhere.

00:15:00.340 --> 00:15:12.820
So, it talks about how all the benefits that microservices should have, like prove modularity, reduce testing burden, better functional composition, isolation, team autonomy, and all that.

00:15:12.820 --> 00:15:20.700
And how many of those things turned around to actually become like molasses in their world and slowed them down instead of letting them work faster.

00:15:20.700 --> 00:15:28.360
So, basically, it's a really concrete story about how they took a step back from microservices, how they actually made that step backwards.

00:15:28.360 --> 00:15:32.840
Because with 100 microservices into one app, that's kind of a beast to pull off.

00:15:33.520 --> 00:15:37.000
And how it helped them basically get everything under control again.

00:15:37.000 --> 00:15:41.560
So, what's really interesting is basically the places where things broke down.

00:15:41.560 --> 00:15:49.360
So, for example, each microservice was talking to a similar but slightly different API, like customer integrations and stuff.

00:15:50.100 --> 00:15:53.120
And they had slight different needs.

00:15:53.120 --> 00:16:01.380
So, over time, some of the core bits of those libraries were slightly different across the different APIs.

00:16:01.380 --> 00:16:09.980
And it became, instead of having things you manage separately for each endpoint, you actually ended up with 100 different services, all of which you had to manage.

00:16:10.180 --> 00:16:13.320
And, like, if you're going to make a big change, you've got to test it against all these variations.

00:16:13.320 --> 00:16:15.880
Their tests were super slow to run.

00:16:15.880 --> 00:16:17.920
And there's just a lot of things.

00:16:17.920 --> 00:16:22.660
Like, also dependencies, you know, as in requirements.txt type dependencies.

00:16:22.660 --> 00:16:23.160
Yeah.

00:16:23.160 --> 00:16:29.160
They wouldn't upgrade all of them at the same time because they wanted to make sure that they had to test it and whatnot.

00:16:29.160 --> 00:16:40.080
And so, if you're going to, you know, be running on, say, requests 2.1 over here and 2.2 over there, are you sure, you know, like, if there's a problem with that?

00:16:40.080 --> 00:16:41.680
Like, how do you deal with that?

00:16:41.680 --> 00:16:49.220
Now, I'm a big fan of the big monolith type apps and keeping a little more control over it that way.

00:16:49.220 --> 00:16:51.100
So, I'm all behind this sentiment.

00:16:51.100 --> 00:16:57.240
But I do feel like they could have actually done a lot of work on the DevOps side to make this dramatically better.

00:16:57.240 --> 00:16:59.880
And maybe, who knows, maybe they would have never switched.

00:16:59.880 --> 00:17:00.380
Yeah.

00:17:00.380 --> 00:17:03.820
Did somewhere I catch that there was a limited number of developers?

00:17:03.820 --> 00:17:05.340
I think there was, like, three or something.

00:17:05.340 --> 00:17:08.620
At one point, there was three working on all these things.

00:17:08.620 --> 00:17:15.360
And, you know, microservices are often touted as being really great ways for dev teams to have autonomy.

00:17:15.360 --> 00:17:18.440
But when your dev team consists of three, you know.

00:17:18.440 --> 00:17:19.640
You don't really need autonomy.

00:17:19.640 --> 00:17:20.520
You're already autonomous.

00:17:20.520 --> 00:17:20.540
Exactly.

00:17:20.900 --> 00:17:21.540
Yeah, exactly.

00:17:21.540 --> 00:17:22.620
Like, that's one team.

00:17:22.620 --> 00:17:24.920
It doesn't need more than one thing to be autonomous, right?

00:17:24.920 --> 00:17:27.000
Generally, basically speaking.

00:17:27.000 --> 00:17:39.260
But, you know, so let me just, like, take a step back and say, for example, like, one of the big problems I said is we've got 100 different services that behave similar but not the same with slightly different integrations against different API endpoints.

00:17:39.260 --> 00:17:45.940
And we're feathering out or fanning out requests to those services based on which thing they're kind of integrated with.

00:17:45.940 --> 00:17:48.000
And the big problem was the dependencies.

00:17:48.000 --> 00:17:51.620
Well, if they had used something like Docker and Kubernetes.

00:17:51.620 --> 00:17:59.180
And they forced them all to say, we're going to install the same runtime environment with the dependencies pre-configured.

00:17:59.180 --> 00:18:09.360
And the only way you get to release a new version is you get your little thing to work with the latest image that has a uniform set of dependencies across the board.

00:18:10.060 --> 00:18:14.400
Well, that sounds like that would have completely taken out one of these problems to me, right?

00:18:14.400 --> 00:18:20.400
I mean, sure, you might have to do a little work to replace a new version of some thing, but you're keeping it in sync, right?

00:18:20.400 --> 00:18:23.200
So it seems like there's a couple of things like that that they could have done.

00:18:23.200 --> 00:18:27.740
There's other issues on the testing side that were caused by these variations.

00:18:27.740 --> 00:18:31.820
And I feel like there could have been some uniformity stuff done, especially around Docker.

00:18:31.820 --> 00:18:34.400
That could have made this a lot better.

00:18:34.400 --> 00:18:37.020
But still, I think there's a lot of interesting lessons there.

00:18:37.020 --> 00:18:40.560
Yeah, I think I'm looking forward to reading this because that sounds like an interesting story.

00:18:40.560 --> 00:18:41.420
Yeah, yeah, it's pretty good.

00:18:41.420 --> 00:18:42.220
Well done.

00:18:42.220 --> 00:18:42.880
Has nice pictures.

00:18:42.880 --> 00:18:43.840
Yeah, neat.

00:18:43.840 --> 00:18:45.040
Oh, I like pictures.

00:18:45.200 --> 00:18:46.940
Speaking of tests and running them on the web.

00:18:46.940 --> 00:18:52.080
Yeah, so one of the workhorses of front-end web testing is often Selenium.

00:18:52.080 --> 00:18:56.220
And Selenium's awesome, but it can be abused.

00:18:56.220 --> 00:18:59.360
And also, it takes a little bit of knowledge.

00:18:59.360 --> 00:19:01.340
So I think we've covered others.

00:19:01.340 --> 00:19:06.820
There are some higher-level APIs that use Selenium under the hood but have a different interface.

00:19:06.820 --> 00:19:14.240
And I'm a fan of a lot of this sort of stuff because if it simplifies your life, go for it.

00:19:14.460 --> 00:19:17.040
One of the things we're going to cover today is Helium.

00:19:17.040 --> 00:19:18.340
It's a newer...

00:19:18.340 --> 00:19:19.520
Oh, it's very much newer.

00:19:19.520 --> 00:19:20.700
It's only a few months old.

00:19:20.700 --> 00:19:23.400
Python library for automating web browsers.

00:19:23.400 --> 00:19:27.240
It's a project that's built on top of Selenium.

00:19:27.240 --> 00:19:33.000
And even though it's fairly new, it's already got like over a thousand stars on GitHub.

00:19:33.000 --> 00:19:33.860
That's cool.

00:19:33.860 --> 00:19:38.120
The claim is Selenium Python 50% easier.

00:19:38.120 --> 00:19:41.940
Helium is the best Python library for web automation.

00:19:41.940 --> 00:19:43.600
Well, of course, it's saying that to itself.

00:19:43.980 --> 00:19:45.300
But it does look pretty clean.

00:19:45.300 --> 00:19:52.780
There's some pretty clean drivers to be able to control Chrome, control your browser, and navigate some stuff.

00:19:52.780 --> 00:19:54.560
So it looks good.

00:19:54.560 --> 00:19:55.540
Yeah, I really like this.

00:19:55.540 --> 00:19:58.860
I think Michael Herrmann did an interesting job on this.

00:19:58.940 --> 00:20:07.440
And the reason that I think this is neat is it takes you away from working at the structure level.

00:20:07.740 --> 00:20:12.920
So for example, just like Selenium, you say, I'm going to open up this website, right?

00:20:12.920 --> 00:20:15.700
So you say start Chrome, GitHub.com slash login.

00:20:15.960 --> 00:20:22.760
But instead of doing some kind of CSS selector to find the text box, you just say write.

00:20:22.760 --> 00:20:27.320
If you want to set something to a text box, you say write this text into.

00:20:27.680 --> 00:20:33.880
And you just, you know, give it like a short bit of text, like the label that is right before, immediately before the text box.

00:20:33.880 --> 00:20:34.680
All right.

00:20:34.680 --> 00:20:37.400
So write something into username.

00:20:37.400 --> 00:20:39.020
And that'll just fill out the username thing.

00:20:39.020 --> 00:20:40.580
Then write something into password.

00:20:41.080 --> 00:20:43.620
And that'll type in the password and then click the button.

00:20:43.620 --> 00:20:45.280
They say click sign in.

00:20:45.280 --> 00:20:47.820
And it just finds the button with the text sign in.

00:20:47.820 --> 00:20:53.760
What is nice is like what a human sees about the page is how the code interacts with it.

00:20:53.760 --> 00:20:55.940
And you might say, well, that's unstable, right?

00:20:55.940 --> 00:20:57.380
What if somebody changes the text?

00:20:57.380 --> 00:21:04.940
Well, if you've ever had to work with CSS selectors and then somebody redesigned the site and your automation stopped working, it's not a whole lot better.

00:21:04.940 --> 00:21:08.820
So you might as well make it easy for humans as far as I see it.

00:21:08.820 --> 00:21:09.140
Yeah.

00:21:09.140 --> 00:21:12.800
And the, I mean, the API is like so clean and short.

00:21:12.800 --> 00:21:22.380
So you've got like, think like function calls, like click man with, you just give it like the tag of thing, the button tag that you're going to click on.

00:21:22.380 --> 00:21:24.540
So like, yeah, it's pretty sweet.

00:21:24.540 --> 00:21:30.240
And to fill in a username, for instance, in a username field, it just is right.

00:21:30.240 --> 00:21:36.600
And then you give it two parameters that the name of the field that you're going to write into and then what you're going to write in there.

00:21:36.600 --> 00:21:38.340
So this is pretty slick.

00:21:38.420 --> 00:21:38.880
I like it.

00:21:38.880 --> 00:21:39.540
Yeah, for sure.

00:21:39.540 --> 00:21:43.880
Too many things get the for humans tag in Python, but this one kind of could get that.

00:21:43.880 --> 00:21:44.160
Yeah.

00:21:44.160 --> 00:21:46.460
And so since this is new, I'll be curious.

00:21:46.460 --> 00:21:48.920
And there's a lot of web testing going on.

00:21:48.920 --> 00:21:52.880
I'll be curious to see if, where this goes, keep an eye on it.

00:21:52.880 --> 00:21:53.500
Yeah, absolutely.

00:21:53.500 --> 00:22:02.040
And the easiest way, if you want to get a sense of like, whether or not this is interesting for you is just go watch the, there's a little GIF animated GIF.

00:22:02.100 --> 00:22:05.820
Just watch that for 10 seconds and you'll have a quick idea what you can work with there.

00:22:05.820 --> 00:22:06.940
We've said this before.

00:22:07.560 --> 00:22:12.360
The animated GIFs of how things work are a good thing to get people excited about a project.

00:22:12.360 --> 00:22:17.140
This project also includes a cheat sheet of some of the common things you might want to do.

00:22:17.140 --> 00:22:20.340
Single page with a whole bunch of stuff.

00:22:20.460 --> 00:22:25.460
It's kind of like an FAQ, but, but just sort of, no questions, just answers.

00:22:25.460 --> 00:22:26.340
Yeah.

00:22:26.340 --> 00:22:30.180
So I'm pretty certain that's a good idea, but sometimes you're not certain.

00:22:30.180 --> 00:22:31.460
Yeah.

00:22:31.460 --> 00:22:32.180
Lots of times.

00:22:32.180 --> 00:22:35.640
So I remember, I don't know where I learned more about this.

00:22:35.640 --> 00:22:40.860
Either this was in physics or this was in statistics or something.

00:22:40.860 --> 00:22:44.000
I think it was one of my science classes in college.

00:22:44.000 --> 00:22:45.200
I promptly forgotten it.

00:22:45.220 --> 00:22:49.880
So there's no way I could, could work with uncertainties and measurements really well.

00:22:49.880 --> 00:22:51.020
Maybe it was even engineering.

00:22:51.020 --> 00:22:54.620
I'll tell you a quick example and then I'll ask you a question.

00:22:54.620 --> 00:22:58.180
You can't look ahead and don't cheat because I have the answer in the notes further down.

00:22:58.180 --> 00:23:02.360
So imagine we're back in school or you're solving a real problem.

00:23:02.360 --> 00:23:04.880
Jane, she needs to calculate the volume of her pool.

00:23:04.880 --> 00:23:06.540
So she knows how much water it'll take, right?

00:23:06.540 --> 00:23:09.900
So she measures the length, the width and the height.

00:23:09.900 --> 00:23:12.640
Now, of course you can't measure it ultra precisely.

00:23:12.640 --> 00:23:14.640
And also there's probably some variation in there.

00:23:14.640 --> 00:23:20.840
So she determines the length is 5.56 meters plus or minus 2.5%.

00:23:20.840 --> 00:23:22.960
Like that's her guess on the inaccuracy.

00:23:22.960 --> 00:23:25.980
And the width, 3 meters plus or minus 2.6%.

00:23:25.980 --> 00:23:29.660
And the depth, 3 meters plus or minus 3.7%.

00:23:29.660 --> 00:23:33.640
So what is the uncertainty, right?

00:23:33.640 --> 00:23:35.260
That plus or minus a little bit, that uncertainty.

00:23:35.260 --> 00:23:37.300
What is the uncertainty in the volume?

00:23:37.700 --> 00:23:40.660
Which is the length times the width times the depth.

00:23:40.660 --> 00:23:42.140
Oh, I can't even remember.

00:23:42.140 --> 00:23:42.940
Is it right?

00:23:42.940 --> 00:23:43.920
Do you multiply them together?

00:23:43.920 --> 00:23:44.680
Yeah.

00:23:44.680 --> 00:23:45.900
Do you multiply them?

00:23:45.900 --> 00:23:47.360
Do you add them?

00:23:47.360 --> 00:23:48.400
Do you average them?

00:23:48.400 --> 00:23:49.420
Like what the heck?

00:23:49.420 --> 00:23:50.680
Do you take the max?

00:23:50.680 --> 00:23:51.340
I don't know.

00:23:51.340 --> 00:23:55.280
Well, there's actually very strict rules about how you do it.

00:23:55.280 --> 00:23:59.040
So when you multiply things, apparently, I didn't remember this, but I've looked it up.

00:23:59.580 --> 00:24:04.220
Apparently, you add the uncertainties when you multiply things.

00:24:04.220 --> 00:24:09.500
So in this case, it's 2.5 plus 2.6 plus 3.7 is 8.8% uncertainty.

00:24:09.500 --> 00:24:11.800
That is super tricky.

00:24:11.800 --> 00:24:20.040
And these kinds of calculations are the kind that ends up with spacecraft burrowing into like a desert or into a moon.

00:24:20.580 --> 00:24:23.040
Because they're like, oh, did we get that wrong?

00:24:23.040 --> 00:24:23.540
Whoops.

00:24:23.540 --> 00:24:24.040
Right?

00:24:24.040 --> 00:24:27.360
Did we use the wrong units or did we get the wrong uncertainty or whatever?

00:24:27.360 --> 00:24:27.680
Right?

00:24:27.680 --> 00:24:28.540
Yeah.

00:24:28.540 --> 00:24:31.280
So there's this really cool library called uncertainty.

00:24:31.920 --> 00:24:34.760
And it comes with all these different math operations.

00:24:34.760 --> 00:24:37.100
Like it has values, like a float.

00:24:37.100 --> 00:24:40.300
And it has a sine, right?

00:24:40.300 --> 00:24:42.780
Which is like, you know, sine, cosine, tangent sort of thing.

00:24:42.780 --> 00:24:45.820
So you can do mathematical computation.

00:24:45.820 --> 00:24:50.060
But instead of having a regular float, it has an uncertain float, a u float.

00:24:50.060 --> 00:24:53.800
So you create like x would say like a u float of 1 is the value.

00:24:53.800 --> 00:24:56.060
And then comma 0.1 is the uncertainty.

00:24:56.880 --> 00:25:05.680
And then if you were to do math with it and print it out, it'll say like 2 times x would be 2 plus or minus 0.2.

00:25:05.680 --> 00:25:07.900
And so it always carries its uncertainty.

00:25:07.900 --> 00:25:18.600
And then as you take like the sine of it or you multiply or you square it, it will actually integrate and consider all those different uncertainties to give you a final uncertainty in your output.

00:25:18.600 --> 00:25:19.240
Isn't that awesome?

00:25:19.240 --> 00:25:20.240
That's very cool.

00:25:20.240 --> 00:25:21.100
Yeah.

00:25:21.100 --> 00:25:23.000
This is useful in lots of fields.

00:25:23.000 --> 00:25:23.300
Yeah.

00:25:23.300 --> 00:25:28.360
If you ever have to compute with uncertainty, this seems so glorious.

00:25:28.360 --> 00:25:30.200
This and pint, right?

00:25:30.200 --> 00:25:32.780
If you could put this and pint together, then it's on.

00:25:32.780 --> 00:25:38.020
Because pint lets you work with different units of measurement and then add and multiply and divide them.

00:25:38.020 --> 00:25:40.300
And then you throw the uncertainty on top of that.

00:25:40.300 --> 00:25:41.020
Boom, you're golden.

00:25:41.020 --> 00:25:41.580
Yeah.

00:25:41.580 --> 00:25:42.700
Yeah, that'd be cool.

00:25:43.460 --> 00:25:48.360
We had worked with once with a measurement value that it was a power level for a cell phone.

00:25:48.360 --> 00:25:56.100
And the uncertainty ended up being plus or minus like the amount of power that the sun produces.

00:25:56.100 --> 00:26:01.060
So it's like we essentially don't know the answer if that's the uncertainty.

00:26:01.060 --> 00:26:02.060
Right, right, right.

00:26:02.060 --> 00:26:05.140
It could take a AA battery or it could melt the earth.

00:26:05.140 --> 00:26:06.020
We're not really sure which.

00:26:06.020 --> 00:26:07.600
We're not sure which.

00:26:07.600 --> 00:26:07.900
Yeah.

00:26:08.700 --> 00:26:10.260
Not ready for shipment yet.

00:26:10.260 --> 00:26:11.040
Exactly.

00:26:11.040 --> 00:26:13.860
Maybe we've got to get more accuracy there.

00:26:13.860 --> 00:26:20.200
Anyway, this comes from Tim Head who mentioned it on Talk Python where we recently did an episode on Binder,

00:26:20.200 --> 00:26:22.140
which is super interesting but not yet released.

00:26:22.140 --> 00:26:24.400
So eventually we'll talk more about that there as well.

00:26:24.400 --> 00:26:29.460
Anyway, uncertainty, cool little library if you've got to do any sort of computation with this kind of stuff.

00:26:29.460 --> 00:26:31.560
Yeah, I think it's cool but I'm not sure about it yet.

00:26:31.560 --> 00:26:33.220
Yeah, well, can you ever be?

00:26:33.220 --> 00:26:33.640
No.

00:26:33.640 --> 00:26:37.960
But you can be sure about the level at which you can't be sure using it.

00:26:37.960 --> 00:26:38.320
Yes.

00:26:39.280 --> 00:26:39.720
Awesome.

00:26:39.720 --> 00:26:43.060
I'm pretty sure that I wish my Python prompt was cooler.

00:26:43.060 --> 00:26:46.800
Well, I'm okay with my Python prompt.

00:26:46.800 --> 00:26:47.720
Are you?

00:26:47.720 --> 00:26:48.480
I don't know.

00:26:48.480 --> 00:26:49.200
I mean, come on.

00:26:49.200 --> 00:26:50.540
Think of all the options.

00:26:50.540 --> 00:26:55.020
You could do anything you wanted and I never thought to do that.

00:26:55.020 --> 00:26:58.240
I mean, I do it with my like a bash prompt and stuff.

00:26:58.240 --> 00:27:01.740
You know, we put our virtual environment name in there.

00:27:01.740 --> 00:27:03.080
It's stuff like that.

00:27:03.080 --> 00:27:05.040
Get status, get branch, all that kind of stuff.

00:27:05.040 --> 00:27:06.540
Yeah, definitely.

00:27:06.540 --> 00:27:07.860
So you can change those things.

00:27:07.860 --> 00:27:08.940
So why not?

00:27:08.940 --> 00:27:15.520
This article comes from, I think, Arpete Bayani and it's called Personalize Your Python Prompt.

00:27:15.520 --> 00:27:17.760
Those three right angle, right, what is it?

00:27:17.760 --> 00:27:22.680
The right, left, greater than signs that are together when you're doing interactive Python.

00:27:23.120 --> 00:27:24.660
Apparently you can muck with those.

00:27:24.660 --> 00:27:29.960
There's a sys.ps1 variable that if you sign to that, you can change it to whatever you want.

00:27:30.660 --> 00:27:38.320
And of course, the author didn't stop there.

00:27:38.320 --> 00:27:38.940
You have a non-string object.

00:27:38.940 --> 00:27:42.140
You have a non-string object to make it dynamic.

00:27:42.140 --> 00:27:49.300
So he gives a little example to where you can, and the way you do that is you have an object that has a dunder stir method.

00:27:49.660 --> 00:27:52.940
If that has dynamic action, that gets called every time.

00:27:53.000 --> 00:27:54.220
So for every prompt.

00:27:54.220 --> 00:27:55.420
So this is pretty neat.

00:27:55.420 --> 00:28:01.100
He has an example of doing some stuff, but I wanted, I didn't have time to do it this morning, but I was working on it.

00:28:01.220 --> 00:28:11.480
I was trying to get a prompt that would mimic the Windows command prompt because apparently I want that on my Mac because that would be fun.

00:28:11.480 --> 00:28:14.500
You just want to confuse people like, what are you doing?

00:28:14.500 --> 00:28:15.240
This isn't.

00:28:15.240 --> 00:28:28.200
I mean, I mean, the C colon backslash greater than was easy, but I wanted to also put the Windows, the path in there and flip the direction of the slashes and stuff like that.

00:28:28.200 --> 00:28:28.560
Yeah.

00:28:28.560 --> 00:28:28.880
Yeah.

00:28:28.880 --> 00:28:30.120
That's really cool.

00:28:30.120 --> 00:28:37.180
And I didn't, one didn't know that you could just set that, the Sys, you know, import Sys, Sys.ps1 equals something.

00:28:37.180 --> 00:28:38.200
And that now is your prompt.

00:28:38.200 --> 00:28:44.600
But I didn't really think that it could be a dynamic object like that has a stir, dunder stir.

00:28:44.600 --> 00:28:45.740
That's pretty cool.

00:28:45.740 --> 00:28:46.500
Yeah, that is neat.

00:28:46.500 --> 00:28:48.860
You could easily set up something like the Jupyter.

00:28:48.860 --> 00:28:50.740
You have Jupyter notebooks.

00:28:50.740 --> 00:28:55.200
You have bracket one, bracket two, bracket three for your various calculations, like five lines.

00:28:55.200 --> 00:28:57.300
You got that in your Python prompt if you want it.

00:28:57.620 --> 00:29:01.860
It doesn't have quite as much value because you can't change the order, but still, it's pretty interesting, I think.

00:29:01.860 --> 00:29:02.360
Yeah.

00:29:02.360 --> 00:29:03.220
Yeah, that's cool.

00:29:03.220 --> 00:29:04.180
Yeah, quite cool.

00:29:04.180 --> 00:29:04.500
All right.

00:29:04.500 --> 00:29:05.840
Well, that's a good little find.

00:29:05.840 --> 00:29:07.200
A quick and easy to play with.

00:29:07.200 --> 00:29:09.140
Well, do you have any extra stuff for us?

00:29:09.140 --> 00:29:10.020
Oh, not really.

00:29:10.020 --> 00:29:11.560
I'll go and throw one thing out for you.

00:29:11.580 --> 00:29:13.980
So, I finished my Python for Absolute Beginners course.

00:29:13.980 --> 00:29:21.980
And so, now I'm starting a new course, which is like adding a CMS to a proper data-driven web app.

00:29:21.980 --> 00:29:35.840
So, if you've got a Flask app or Pyramid or Django or something like that, and you want to let other people write part of the site, and the rest is more like Amazon would be with, you know, here's the categories, here's the products, here's the product page, and here's the review page.

00:29:35.900 --> 00:29:39.040
Like, you know, very structured, but you want to just let them like write freeform stuff.

00:29:39.040 --> 00:29:44.060
So, I'm working on a course that lets you kind of add that to existing sites.

00:29:44.060 --> 00:29:44.740
So, that'll be fun.

00:29:44.740 --> 00:29:45.960
I'm having a lot of fun working on that.

00:29:45.960 --> 00:29:46.300
Okay.

00:29:46.300 --> 00:29:47.200
Interesting.

00:29:47.200 --> 00:29:47.840
Yeah.

00:29:47.840 --> 00:29:51.760
Is this kind of where the markdown work that you were working on comes in play?

00:29:51.760 --> 00:29:52.860
Yes, exactly.

00:29:53.060 --> 00:30:08.700
So, I decided the work that I did for TalkBuyLon training to build out the landing pages and like the interesting stuff to basically make a whole section of that site just driven by markdown and just editors and whatnot.

00:30:08.700 --> 00:30:17.120
I'm going to like take that, extract it, and sort of take it to the next level like with rich markdown editors and, you know, database backends and stuff like that.

00:30:17.120 --> 00:30:17.560
It'll be fun.

00:30:17.560 --> 00:30:17.880
Nice.

00:30:17.880 --> 00:30:18.420
Okay.

00:30:18.420 --> 00:30:18.740
Cool.

00:30:18.740 --> 00:30:20.400
Shall we close it out with a limerick?

00:30:20.400 --> 00:30:21.280
Sure.

00:30:22.700 --> 00:30:25.640
I'm not very good at limericks, so I'll give this a shot.

00:30:25.640 --> 00:30:27.760
But this comes to us from Alexander A.

00:30:27.760 --> 00:30:29.360
He sent this over.

00:30:29.360 --> 00:30:30.600
He had written it.

00:30:30.600 --> 00:30:31.140
This is his.

00:30:31.140 --> 00:30:32.260
He wrote it recently.

00:30:32.260 --> 00:30:33.580
And this is submitted.

00:30:33.580 --> 00:30:36.500
Apparently, there's some kind of limerick contest at Manning.

00:30:36.500 --> 00:30:44.500
You win free content like books and whatnot if you submit a winning programming limerick.

00:30:44.500 --> 00:30:45.180
All right.

00:30:45.180 --> 00:30:45.880
So, here goes.

00:30:45.880 --> 00:30:47.420
Coding environments in three parts.

00:30:47.420 --> 00:30:49.780
To this day, some prefer BBEdit.

00:30:49.780 --> 00:30:51.800
VS Code is now getting some credit.

00:30:51.800 --> 00:30:52.660
Vim and Emacs.

00:30:52.660 --> 00:30:53.260
Vim and Emacs are fine.

00:30:53.260 --> 00:30:54.980
So are Atom and Sublime.

00:30:54.980 --> 00:30:57.320
But it doesn't matter much if you don't let it.

00:30:57.320 --> 00:30:58.100
But wait.

00:30:58.100 --> 00:30:59.720
Let's not forget IDEs.

00:30:59.720 --> 00:31:01.720
Using PyCharm sure is a breeze.

00:31:01.720 --> 00:31:04.360
Komodo, Eclipse, and Idea.

00:31:04.360 --> 00:31:06.360
Sea Lion is my panacea.

00:31:06.360 --> 00:31:08.320
And Xcode leaves me at ease.

00:31:08.320 --> 00:31:11.300
But Jupyter Notebook is also legit.

00:31:11.300 --> 00:31:13.360
Data scientists must prefer it.

00:31:13.800 --> 00:31:14.980
In the browser you code.

00:31:14.980 --> 00:31:16.400
Results are then showed.

00:31:16.400 --> 00:31:19.020
But good luck when you try to use Git.

00:31:21.720 --> 00:31:22.400
I love it.

00:31:22.400 --> 00:31:22.900
It's good, right?

00:31:22.900 --> 00:31:23.840
This is great.

00:31:23.840 --> 00:31:24.220
Yeah.

00:31:24.220 --> 00:31:24.880
Oh my gosh.

00:31:24.880 --> 00:31:25.600
It's so good.

00:31:25.600 --> 00:31:28.000
Especially that last line.

00:31:28.000 --> 00:31:28.800
I love it.

00:31:28.800 --> 00:31:30.700
Definitely makes the whole thing worth it.

00:31:30.700 --> 00:31:31.600
Yeah.

00:31:31.600 --> 00:31:33.040
Yes, indeed.

00:31:33.040 --> 00:31:35.080
So, well done, Alexander.

00:31:35.080 --> 00:31:37.240
Thanks for sharing that and letting us use it on the show.

00:31:37.240 --> 00:31:37.720
That's great.

00:31:37.720 --> 00:31:38.680
All right.

00:31:38.680 --> 00:31:39.180
Anything else?

00:31:39.180 --> 00:31:40.600
Do you got anything you want to share with folks?

00:31:40.740 --> 00:31:43.760
I guess I jumped ahead of you and did my limerick.

00:31:43.760 --> 00:31:44.480
No, no.

00:31:44.480 --> 00:31:45.400
No, it's good.

00:31:45.400 --> 00:31:49.940
We've got a whole bunch of great feedback from the recent testing code episodes.

00:31:49.940 --> 00:31:52.180
So, it's been good.

00:31:52.180 --> 00:31:52.740
Yeah.

00:31:52.740 --> 00:31:53.820
What are some of the ones?

00:31:53.820 --> 00:31:56.100
No, you just did one with Anthony Shaw.

00:31:56.100 --> 00:31:57.040
Yeah.

00:31:57.040 --> 00:31:57.620
And his plugin.

00:31:57.620 --> 00:31:58.120
Yeah.

00:31:58.120 --> 00:31:59.480
So, we talked about security.

00:31:59.480 --> 00:32:02.100
We've talked about Django recently.

00:32:02.100 --> 00:32:09.340
And just the most recent one is talking about the most downloaded pytest plugins.

00:32:10.340 --> 00:32:14.840
So, Anthony Sotili and I talked about 28 of the top plugins.

00:32:14.840 --> 00:32:16.880
That sounds like the perfect show.

00:32:16.880 --> 00:32:17.500
That's really great.

00:32:17.500 --> 00:32:17.860
Yeah.

00:32:17.860 --> 00:32:19.340
Really geeked out on a lot of stuff.

00:32:19.340 --> 00:32:22.500
I found some super interesting ones that I'm going to talk about in the next show.

00:32:22.500 --> 00:32:23.960
But we'll leave it at that.

00:32:23.960 --> 00:32:24.360
Awesome.

00:32:24.360 --> 00:32:24.940
Thanks.

00:32:24.940 --> 00:32:25.220
Cool.

00:32:25.220 --> 00:32:25.720
All right.

00:32:25.720 --> 00:32:25.980
Yeah.

00:32:25.980 --> 00:32:27.640
Well, thank you as well.

00:32:27.640 --> 00:32:29.120
Happy to be here with you like every week.

00:32:29.120 --> 00:32:29.360
Bye.

00:32:29.360 --> 00:32:29.680
Bye.

00:32:29.680 --> 00:32:31.660
Thank you for listening to Python Bytes.

00:32:31.660 --> 00:32:34.120
Follow the show on Twitter at Python Bytes.

00:32:34.120 --> 00:32:37.140
That's Python Bytes as in B-Y-T-E-S.

00:32:37.140 --> 00:32:40.040
And get the full show notes at Pythonbytes.fm.

00:32:40.040 --> 00:32:45.120
If you have a news item you want featured, just visit Pythonbytes.fm and send it our way.

00:32:45.120 --> 00:32:47.160
We're always on the lookout for sharing something cool.

00:32:47.160 --> 00:32:48.340
This is Brian Okken.

00:32:48.340 --> 00:32:52.420
And on behalf of myself and Michael Kennedy, thank you for listening and sharing this podcast

00:32:52.420 --> 00:32:53.600
with your friends and colleagues.

