WEBVTT

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

00:00:04.860 --> 00:00:10.340
This is episode 142, recorded July 31st. I'm Michael Kennedy.

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

00:00:11.240 --> 00:00:12.100
And I'm Brett Thomas.

00:00:12.100 --> 00:00:17.200
And yes, we have a special guest this time, third co-host, Brett Thomas. Brett, welcome to the show.

00:00:17.200 --> 00:00:17.980
Thank you very much.

00:00:17.980 --> 00:00:22.420
Yeah, it's great to have you here. I also want to say thank you to Datadog for sponsoring the show.

00:00:22.420 --> 00:00:26.060
Check them out at pythonbytes.fm/datadog. More on that later.

00:00:26.060 --> 00:00:29.640
Brett, you want to just quickly tell everyone a little bit about yourself before we get into the topics?

00:00:29.640 --> 00:00:33.640
Yeah, sure. I'm the chief technology officer of a company called FasterThanLight.dev.

00:00:33.640 --> 00:00:39.280
And we do static code analysis tooling for, you know, the SAS model to help you analyze your code.

00:00:39.280 --> 00:00:40.620
And I'll talk a little bit about that later.

00:00:40.620 --> 00:00:42.760
All right. Awesome. Sounds good. Well, happy to have you here.

00:00:42.760 --> 00:00:44.460
Brian, you want to kick us off?

00:00:44.460 --> 00:00:44.880
Sure.

00:00:44.880 --> 00:00:48.840
It's great to have sustainability. And like, it's almost like Earth Day for code.

00:00:48.840 --> 00:00:51.480
And like, you always want to just have that in mind, right?

00:00:51.480 --> 00:00:52.720
Earth Day for code?

00:00:52.720 --> 00:00:55.800
Sustainability. Come on. You got to roll in the air.

00:00:55.800 --> 00:00:59.280
Yeah, I'm really worried about what climate change is going to do to my code, but...

00:00:59.280 --> 00:01:04.900
I ran across this article called Writing Sustainable Python Scripts by Vincent Burnett.

00:01:05.340 --> 00:01:10.960
And most of my time, I'm not writing... I mean, I don't really think about it too much for little scripts, but...

00:01:10.960 --> 00:01:13.840
Or little helper utilities. We've got lots of them around work.

00:01:13.840 --> 00:01:21.900
But there is an issue that I think this is a reasonable thing to talk about is if it's only going to be a short-lived script, yeah, we don't really care about it too much.

00:01:21.960 --> 00:01:27.580
But if it's going to be a long-lived script, yeah, we don't really care about it.

00:01:27.580 --> 00:01:31.200
And there are things you can do to make it a little bit more maintainable.

00:01:31.200 --> 00:01:33.200
And I like the things he put down.

00:01:33.200 --> 00:01:45.180
And then the most obvious ones, which is some people forget, is throwing a doc string at the top of the file to let people in the future know what problem you're trying to solve and kind of describe what it is.

00:01:45.180 --> 00:01:50.820
Instead of doing like hard-coded stuff, you can have easily add some command line arguments with...

00:01:51.820 --> 00:01:57.500
Defaults can be sort of hard-coded defaults, but having some way to make the script useful.

00:01:57.500 --> 00:02:00.580
And then he goes into adding logging.

00:02:00.580 --> 00:02:02.740
And I think it's kind of neat.

00:02:02.740 --> 00:02:09.700
He includes how to do debug logging and hook that into the command line argument system, which is kind of a cool trick.

00:02:09.700 --> 00:02:14.860
And then also for unattended scripts, being able to log to system logging.

00:02:15.380 --> 00:02:22.360
And then finally, finishing it off with adding some simple tests to make sure that your code does what you think it does.

00:02:22.360 --> 00:02:23.680
It's just a nice little article.

00:02:23.680 --> 00:02:31.460
Yeah, it's easy to forget about maintaining these little scripts because like they're kind of throwaway, but actually then they're throwaway until they're not.

00:02:31.460 --> 00:02:32.280
Go ahead.

00:02:32.280 --> 00:02:36.940
And the more throwaway you think it's going to be, the more it's going to be the longest-lived part of your system, of course.

00:02:36.940 --> 00:02:38.300
Of course.

00:02:38.300 --> 00:02:38.760
Yeah.

00:02:38.760 --> 00:02:43.260
Yeah, I have a bunch of these, and I find that I even forget that they exist.

00:02:43.640 --> 00:02:45.760
Like, I'll be doing something super painful.

00:02:45.760 --> 00:02:47.620
And I'm like, wow, this is really not fun.

00:02:47.620 --> 00:02:51.860
Like, I've got to like rename all these files based on like certain stuff out of the database or something.

00:02:51.860 --> 00:02:53.660
Like, man, I should automate this.

00:02:53.660 --> 00:02:54.140
Like, wait a minute.

00:02:54.140 --> 00:02:55.500
I think I did automate this.

00:02:55.500 --> 00:02:56.300
And I'll go back and look.

00:02:56.300 --> 00:02:59.260
I'm like, yeah, like I can just run this thing in the command line.

00:02:59.260 --> 00:03:01.280
And like 100 files are properly renamed.

00:03:01.280 --> 00:03:03.640
Why did I spend the last five minutes?

00:03:03.640 --> 00:03:04.620
Why do my hands hurt now?

00:03:04.620 --> 00:03:14.520
You know, like, and so the way I got around solving that problem, often that involves like setting up a virtual environment, activating it, then running that script because it has dependencies.

00:03:14.520 --> 00:03:17.840
Like I mentioned the database or whatever, the models and so on.

00:03:17.840 --> 00:03:20.580
So what I'll do is I'll create an alias in my shell.

00:03:21.040 --> 00:03:22.540
And then I just run the alias.

00:03:22.540 --> 00:03:25.720
And so if I go and just like, if I forget, I'll go look at my aliases.

00:03:25.720 --> 00:03:26.820
I only got like 50 or something.

00:03:26.820 --> 00:03:29.260
Like, it's got to be one of these, which there it is.

00:03:29.260 --> 00:03:30.160
And then I run it again.

00:03:30.160 --> 00:03:34.300
And that's like, that's my system until my computer gets formatted.

00:03:34.300 --> 00:03:35.440
Then I have to start from scratch.

00:03:35.560 --> 00:03:36.160
That's the great thing.

00:03:36.160 --> 00:03:38.740
I was actually went through and audited my like dot profile.

00:03:38.740 --> 00:03:39.780
I know six months ago.

00:03:39.780 --> 00:03:43.560
And I swear I've been, I've called around the same dot profile for, I think, two decades.

00:03:43.560 --> 00:03:43.960
Right.

00:03:43.960 --> 00:03:49.320
You know, it's like there's aliases to do things on the systems that I haven't had access to for 20 years.

00:03:49.320 --> 00:03:49.780
I'm like, what?

00:03:49.780 --> 00:03:51.320
Okay, maybe, maybe it's time to clean it up.

00:03:51.320 --> 00:03:51.940
A little pruning.

00:03:51.940 --> 00:03:52.740
Yeah.

00:03:52.740 --> 00:03:58.040
But no, this is a great, a great article, Brian, to like remind people just to do these little simple things.

00:03:58.040 --> 00:03:58.440
I don't know.

00:03:58.440 --> 00:03:59.620
Maybe there's some threshold, right?

00:03:59.620 --> 00:04:01.620
You just like play around, you do it once.

00:04:01.700 --> 00:04:05.680
But like if you use it a third time, then you should go back and like refactor and clean up a little.

00:04:05.680 --> 00:04:06.140
I don't know.

00:04:06.140 --> 00:04:07.920
Sometimes logging doesn't really make sense.

00:04:07.920 --> 00:04:11.020
And you can just, and sometimes testing.

00:04:11.020 --> 00:04:17.180
I mean, I'm shocked that I'm the person to say this, but sometimes manually testing stuff is fine.

00:04:17.180 --> 00:04:19.600
If you're going to notice when it breaks, it works.

00:04:19.600 --> 00:04:20.620
Yeah, it definitely depends.

00:04:20.620 --> 00:04:21.420
Well, what do we got next?

00:04:21.420 --> 00:04:26.680
Well, so the first thing I would like to talk about is a static code analysis using Bandit.

00:04:27.140 --> 00:04:36.040
And for anyone who's not aware of what static code analysis is, static code analysis is basically running a computer program on your computer program, right?

00:04:36.040 --> 00:04:38.680
I've actually recently heard somebody analogize it.

00:04:38.680 --> 00:04:40.560
It's like spell check for a computer program.

00:04:40.560 --> 00:04:46.540
The reason it's called static code analysis, it's that separate from what we usually do in testing, which is dynamic, right?

00:04:46.540 --> 00:04:47.600
We run the program.

00:04:47.600 --> 00:04:48.700
We give it various inputs.

00:04:48.700 --> 00:04:50.500
We see if it does what we think it should.

00:04:50.700 --> 00:05:00.600
But static code analysis is about the idea of examining either the source code or the object code and saying, okay, we're going to look for patterns that look troublesome, right?

00:05:00.600 --> 00:05:07.220
And so, for example, one thing static code analysis might help you look for might be SQL injection attacks, right?

00:05:07.220 --> 00:05:14.240
Where you've got unbound SQL variables, which is, you know, just an absolutely perennial security problem that's, you know, always in the OWASP top three.

00:05:14.240 --> 00:05:17.260
Select star from quote plus input name.

00:05:17.680 --> 00:05:18.520
Exactly, right?

00:05:18.520 --> 00:05:22.960
I mean, and there's actually all kinds of great database performance reasons you want to bind your variables anyhow.

00:05:22.960 --> 00:05:38.620
But if you don't know, definitely when you're doing SQL statements, you should be using placeholder variables and binding them instead of actually interpolating strings, especially if those strings come from some random person on the internet, as in the, you know, the famous XKCP Little Bobby Tables cartoon.

00:05:38.620 --> 00:05:42.840
And so anyway, so Bandit is an open source tool that you can just grab.

00:05:43.180 --> 00:05:49.220
And in fact, I believe you can just pip install it and it will, you run it on your code and it tells you things that are problematic.

00:05:49.220 --> 00:05:51.340
Now, of course, it doesn't know what your code's doing.

00:05:51.340 --> 00:05:59.400
Sometimes, you know, one of the rubs on static code analysis tools is that they tend to false positive a lot because they don't understand the context, right?

00:05:59.400 --> 00:06:06.000
They say, okay, well, this kind of pattern tends to be kind of dangerous, but they don't know that the way that you're using it is absolutely fine.

00:06:06.340 --> 00:06:11.200
You know, another just kind of hard example that I got out of out of it one time is Flask.

00:06:11.200 --> 00:06:20.780
You know, if you're making a Flask app and you turn debugging on when you create the Flask object, which seems like a reasonable thing to do, it actually enables a debug console.

00:06:20.780 --> 00:06:27.080
If you know the right place to go to on your web app that allows you to execute arbitrary Python code on authenticated.

00:06:27.080 --> 00:06:29.680
You probably don't want to do that on the internet.

00:06:29.900 --> 00:06:30.840
That is super bad.

00:06:30.840 --> 00:06:32.200
And Django has the same problem.

00:06:32.200 --> 00:06:34.420
And like there's tools that search for that.

00:06:34.420 --> 00:06:35.200
It's a big deal.

00:06:35.200 --> 00:06:35.760
You don't want to publish.

00:06:35.760 --> 00:06:36.480
Yeah, exactly.

00:06:36.480 --> 00:06:43.340
I mean, and that's just one of literally dozens or scores of things that Bandit can help you find, you know, those kinds of errors in your code.

00:06:43.340 --> 00:06:45.360
Does Bandit do like Pythonic code?

00:06:45.360 --> 00:06:52.640
Let's say this numeric four should be just like an enumerate loop or something like that.

00:06:52.780 --> 00:07:02.780
Yeah, there's a number of different things that you can do that, you know, that kind of like range from, oh, hey, this is not a best practice or, you know, there's not this, you know, doesn't go with, you know, the correct coding style, for example.

00:07:02.780 --> 00:07:08.040
And certainly if you are super into that, I think that can be a great resource for you.

00:07:08.040 --> 00:07:12.020
You know, my personal focus on it, I think, tends to be more from the security side of things.

00:07:12.180 --> 00:07:18.620
Somebody who has been running sensitive web apps on the Internet now for 20 years, that really is just in my DNA.

00:07:18.620 --> 00:07:27.640
My prior position, actually, I was responsible for keeping several hundred million credit cards safe at a PCI DSS level one service provider called Vendicia.

00:07:27.640 --> 00:07:30.320
That will make you a little bit paranoid.

00:07:30.320 --> 00:07:37.840
Yeah, I mean, I don't know if you see the gray hairs there, but yeah, I sleep a lot better now that I don't have that weight on my shoulders, I have to admit.

00:07:39.340 --> 00:07:48.840
I can imagine that one of the most stressful bit of codes I wrote was the credit card processing system for this company where the individual purchases would be like three or four thousand dollars.

00:07:48.840 --> 00:07:50.640
And I'm like, yeah, better not mess it up.

00:07:50.640 --> 00:07:52.460
That's what you're talking about is a whole nother level.

00:07:52.460 --> 00:07:57.660
So static code analysis and Bandit can help like find those types of problems as well there.

00:07:57.660 --> 00:07:58.180
Absolutely.

00:07:58.180 --> 00:07:59.400
I'm a fan of these things.

00:07:59.400 --> 00:08:01.940
You know, it's the problem is you kind of got it.

00:08:01.940 --> 00:08:05.440
And sometimes at least on large projects, you got to start using them early enough.

00:08:05.440 --> 00:08:06.040
Yeah.

00:08:06.040 --> 00:08:07.180
Because otherwise.

00:08:07.180 --> 00:08:08.080
Absolutely.

00:08:08.080 --> 00:08:10.560
You've just got you've got a huge thing to go through.

00:08:10.560 --> 00:08:14.980
And actually, I got to admit, my company, what we're doing is my new company, Faster Than Light.

00:08:14.980 --> 00:08:21.340
We're working on packaging this stuff up as a software as a service and definitely helping you manage that.

00:08:21.340 --> 00:08:28.720
Like, oh, hey, you know, I've already looked at this and it's not a problem kind of thing for large projects is one of the things that we're really trying to work on fixing for people.

00:08:28.720 --> 00:08:29.000
Right.

00:08:29.000 --> 00:08:34.400
If you can put the little code comment or whatever that says, please suppress this warning here because we reviewed it.

00:08:34.580 --> 00:08:38.280
Actually, a customer I was talking to, you know, it's like they've got an Android app they're shipping.

00:08:38.420 --> 00:08:45.280
You know, well, the Android scanner and this is obviously not Python, but the Android scanner is like, whoa, you've got an API key, you know, in your code.

00:08:45.280 --> 00:08:46.100
Ah, right.

00:08:46.100 --> 00:08:52.960
You know, and it's like, well, yeah, but it's an API key that has been carefully restricted so that it can only make one read only call.

00:08:52.960 --> 00:08:55.180
And so, like, it's okay, right?

00:08:55.180 --> 00:09:02.380
You know, and it's, you know, it's kind of like having, you know, kind of like that extra nervous person who occasionally freaks out and you're like, no, no, no, no, really.

00:09:02.380 --> 00:09:03.000
It's okay.

00:09:03.000 --> 00:09:04.700
It's not, it's, this isn't a problem.

00:09:04.700 --> 00:09:05.000
So.

00:09:05.000 --> 00:09:05.260
Cool.

00:09:05.260 --> 00:09:05.500
Yeah.

00:09:05.500 --> 00:09:05.940
All right.

00:09:05.940 --> 00:09:06.840
So Bandit, pretty awesome.

00:09:06.840 --> 00:09:08.540
I know it does a lot of good stuff for Python.

00:09:08.540 --> 00:09:11.040
And they actually list out all the stuff they check on their site, right?

00:09:11.040 --> 00:09:11.340
Yeah.

00:09:11.340 --> 00:09:14.020
There's definitely a, you know, big document you can get with all their tests.

00:09:14.020 --> 00:09:14.360
So.

00:09:14.360 --> 00:09:14.660
Super.

00:09:14.660 --> 00:09:15.320
All right.

00:09:15.360 --> 00:09:18.320
So the next one I want to talk about is black.

00:09:18.320 --> 00:09:19.940
And Brian, you're a fan of black, right?

00:09:19.940 --> 00:09:20.240
Yep.

00:09:20.240 --> 00:09:20.920
Brett, do you use black?

00:09:20.920 --> 00:09:21.960
Do you know this code formatter?

00:09:21.960 --> 00:09:23.200
No, I'm not familiar with it myself.

00:09:23.200 --> 00:09:23.920
I'd love to hear.

00:09:23.920 --> 00:09:30.600
It basically takes what, like, Flake 8 does and some of these other linting tools, a little bit like you were talking about.

00:09:30.600 --> 00:09:34.000
Instead of saying, this file is too long, you should change it.

00:09:34.000 --> 00:09:39.020
This variable name is unused or this indentation is not right or whatever.

00:09:39.020 --> 00:09:44.340
Instead of just giving you a bunch of warnings, it just rewrites your code to conform to its standard.

00:09:44.560 --> 00:09:51.680
And long as you are willing to live with a standard, a lot of people put it as, like, a GitHub pre-commit hook or something like that.

00:09:51.680 --> 00:09:55.260
And then just the whole team is just straight up on this type.

00:09:55.260 --> 00:09:58.480
So it's really, really popular these days over the last year or so.

00:09:58.480 --> 00:10:06.240
However, one of the things that's super annoying is there's a lot of places where you write code where you cannot apply these kind of tooling.

00:10:06.240 --> 00:10:11.260
And a lot of it is in places like Jupyter Notebooks or online editors.

00:10:11.260 --> 00:10:13.020
And you're like, well, you can type your code in here.

00:10:13.120 --> 00:10:15.900
But it's like, well, but I can't format my code in here.

00:10:15.900 --> 00:10:18.540
And I'm doing space a lot to line up stuff.

00:10:18.540 --> 00:10:19.400
And it's making me crazy.

00:10:19.400 --> 00:10:20.400
Like that kind of stuff, right?

00:10:20.400 --> 00:10:25.420
So if you use Jupyter, there's a thing that came out called Jupyter-Black.

00:10:25.420 --> 00:10:26.220
Jupyter-Black.

00:10:26.220 --> 00:10:34.940
And it's a super simple Jupyter Notebook plugin that gives you a hotkey to apply black formatting to your Jupyter Notebooks online.

00:10:34.940 --> 00:10:37.140
Does that work with the Flask debug console?

00:10:37.360 --> 00:10:38.420
No, I don't think so.

00:10:38.420 --> 00:10:39.480
I don't think so.

00:10:39.480 --> 00:10:39.820
But yeah.

00:10:39.820 --> 00:10:45.320
So I think this is super helpful for the data scientists who are out there writing code.

00:10:45.320 --> 00:10:49.600
Or maybe even if you're a teacher and you're getting other people's code, you're like, I can't look at this.

00:10:49.600 --> 00:10:50.140
What is this?

00:10:50.140 --> 00:10:51.040
Like these freshmen.

00:10:51.040 --> 00:10:53.780
Control B.

00:10:53.780 --> 00:10:54.180
Okay.

00:10:54.180 --> 00:10:55.760
Freshman-itis is gone.

00:10:55.820 --> 00:10:56.420
I can read this.

00:10:56.420 --> 00:10:58.160
It's properly formatted like a professional.

00:10:58.160 --> 00:10:59.520
Now let's review it.

00:10:59.520 --> 00:11:00.000
Things like that.

00:11:00.000 --> 00:11:03.660
I just think it really brings a cool tool to a new place.

00:11:03.660 --> 00:11:04.880
And I'm sure it would be really welcome.

00:11:04.880 --> 00:11:10.280
You answered my question that I had right away is, does it format just the current cell or the whole thing?

00:11:10.280 --> 00:11:13.540
And yeah, there's two different keyboard options.

00:11:13.540 --> 00:11:17.220
Control B and Control-Shift-B that do both of those.

00:11:17.220 --> 00:11:17.440
Yeah.

00:11:17.440 --> 00:11:19.200
Control-Shift-B is probably the one you want.

00:11:19.200 --> 00:11:22.500
But there's also a little toolbar button if you are not a hotkey person.

00:11:23.040 --> 00:11:24.220
So yeah, it's super simple.

00:11:24.220 --> 00:11:29.500
It just plugs in like a standard Jupyter notebook extension, which I don't really do a ton with.

00:11:29.500 --> 00:11:31.580
But it sounds really easy to install it.

00:11:31.580 --> 00:11:36.720
And then the only other requirement is that you have Black installed on the system or the virtual environment.

00:11:36.720 --> 00:11:40.340
Because it has to like basically shell out to Black and figure out what's happening.

00:11:40.340 --> 00:11:40.660
All right.

00:11:40.660 --> 00:11:45.760
Before we get on to the next topic, though, let me just quickly tell you about Datadog.

00:11:45.760 --> 00:11:49.340
So this episode, like many of ours, is sponsored by Datadog.

00:11:50.180 --> 00:11:55.740
They're a cloud monitoring platform built by engineers for engineers, like all of us, right?

00:11:55.740 --> 00:12:04.620
And so what it does is it auto instruments Django, Flask, Postgres, like MongoDB, AsyncIO, all these different things.

00:12:04.620 --> 00:12:14.520
And will allow you to trace your requests across servers, across processes, and bring you basically a holistic view of like what is the request doing.

00:12:14.520 --> 00:12:18.240
Because it's great to like profile your Python code, but there's a whole lot of other stuff happening.

00:12:18.240 --> 00:12:21.000
That's maybe where most of the stuff is happening, right?

00:12:21.000 --> 00:12:23.200
In the database or in the framework or whatever.

00:12:23.200 --> 00:12:24.320
And so this brings it all together.

00:12:24.320 --> 00:12:27.120
And it integrates with over 350 technologies.

00:12:27.120 --> 00:12:29.120
Hadoop, Redis, all the good stuff.

00:12:29.120 --> 00:12:30.880
So check them out.

00:12:30.880 --> 00:12:34.220
They've got a free trial, pythonbytes.fm/Datadog.

00:12:34.220 --> 00:12:36.140
And you also get a sweet Datadog t-shirt.

00:12:36.140 --> 00:12:38.280
So like that alone makes it worth it, I think.

00:12:38.280 --> 00:12:40.340
All right, Brian, what's this next one you got here?

00:12:40.340 --> 00:12:44.720
Well, I'm glad that we checked ahead of time and make sure that we've had two Jupyter articles.

00:12:44.720 --> 00:12:45.700
Yeah, right next to each other.

00:12:45.700 --> 00:12:46.080
That's perfect.

00:12:46.080 --> 00:12:46.900
Yeah.

00:12:47.460 --> 00:12:49.260
This is involving Paper Mill.

00:12:49.260 --> 00:12:52.880
And I think I'm pretty sure we've talked about Paper Mill before, at least briefly.

00:12:52.880 --> 00:12:55.020
We covered Paper Mill live at PyCon.

00:12:55.020 --> 00:12:56.000
Oh, yeah, right.

00:12:56.000 --> 00:12:56.220
Yeah.

00:12:56.220 --> 00:13:01.180
So I included this because it's a two-part article series that talks about the entire workflow,

00:13:01.180 --> 00:13:04.880
which that's where it seemed it looked pretty interesting to me.

00:13:04.880 --> 00:13:10.320
So this Chris Moffitt wrote part one and part two of automated report generation with Paper Mill.

00:13:10.320 --> 00:13:15.620
So it's taken Jupyter notebooks that use Pandas and Matplotlib to create a report.

00:13:16.020 --> 00:13:21.740
And then using nbconvert to take that and create an HTML report.

00:13:21.740 --> 00:13:30.900
And then go through and use Paper Mill to parameterize the input of this entire process and to set up execute blocks.

00:13:30.900 --> 00:13:34.400
And then he completed the process, talked about the rest of the workflow,

00:13:34.400 --> 00:13:38.520
about using a new tool that I've never heard of before, which is called Rclone,

00:13:38.520 --> 00:13:45.240
to clone different cloud directory services and keep the same directory on lots of different cloud services.

00:13:45.580 --> 00:13:53.800
And then how to, if you're in a Linux box using Cron to set up a regular process for this whole thing.

00:13:53.800 --> 00:13:59.560
I mean, the example is a simple thing like a monthly sales report that you want to have just go out.

00:13:59.560 --> 00:14:03.660
Somebody can pop in the data in a spreadsheet or something like that,

00:14:03.660 --> 00:14:07.540
but then all the reporting and the data analysis and everything can happen afterwards.

00:14:08.100 --> 00:14:13.580
And just going through the, from the top to the bottom, the whole workflow, I thought was a real nice touch.

00:14:13.580 --> 00:14:17.780
I love this because it takes the boring stuff that you don't want to do.

00:14:18.160 --> 00:14:23.560
And it just hands it over to the computers in like a beautiful way, taking some of the really new and nice tools,

00:14:23.560 --> 00:14:25.820
Paper Mill, Jupyter, and so on.

00:14:25.820 --> 00:14:27.820
And it just automates it all.

00:14:27.820 --> 00:14:34.220
So instead of like every Friday, you're like, oh, there's that two hours of like copying data from system to system for the report.

00:14:34.380 --> 00:14:36.960
It's like, it just shows up in the email, right?

00:14:36.960 --> 00:14:39.280
It's just on the internet or whatever, right?

00:14:39.280 --> 00:14:40.520
This is really cool.

00:14:40.520 --> 00:14:47.940
And just to summarize Paper Mill, basically it turns Jupyter Notebooks into like functions or command line style applications.

00:14:47.940 --> 00:14:48.520
It can be called.

00:14:48.520 --> 00:14:52.120
You provide data to it, inputs, it runs, and then output comes out.

00:14:52.200 --> 00:14:54.540
So you have the general analysis report.

00:14:54.540 --> 00:14:58.800
You feed like, hey, it's from July 1st to July 31st.

00:14:58.800 --> 00:15:00.040
Drop the files here.

00:15:00.040 --> 00:15:00.440
Go.

00:15:00.440 --> 00:15:00.840
Yep.

00:15:00.840 --> 00:15:01.420
It's nice.

00:15:01.420 --> 00:15:02.000
Yeah, very cool.

00:15:02.000 --> 00:15:04.760
Brett, you got any things like this that you guys got to do at Faster Than Light?

00:15:04.760 --> 00:15:06.440
We are still new enough.

00:15:06.440 --> 00:15:14.780
I've got to admit, I was literally was just thinking to myself this morning about how I really need to start writing some nightly reports that tell me what all everybody was doing in the system yesterday.

00:15:14.780 --> 00:15:18.220
So we actually still haven't completely fully launched.

00:15:18.460 --> 00:15:24.940
So thankfully, there isn't too much yet that I need to know about that's, you know, it's like, oh, yeah, how many tests did I run yesterday?

00:15:24.940 --> 00:15:27.900
You know, is kind of what I would be getting here.

00:15:27.900 --> 00:15:33.840
But yeah, that's definitely something that I'll be looking at as we start to do our release.

00:15:33.840 --> 00:15:40.060
Yeah, you're in that beautiful place where the molasses of real life day-to-day business operations hasn't hit you yet.

00:15:40.060 --> 00:15:41.680
You can go quick and build things.

00:15:41.680 --> 00:15:42.100
Absolutely.

00:15:42.240 --> 00:15:52.420
And I got to say, it is so strange having run four nines plus environment for, you know, a decade and a half to all of a sudden be like, oh, yeah, you know, production's down.

00:15:52.420 --> 00:15:53.680
Nobody noticed, right?

00:15:53.680 --> 00:15:55.320
You know, because you haven't actually done anything yet.

00:15:55.320 --> 00:15:56.560
So it's a different world.

00:15:56.560 --> 00:15:57.580
It's a different world.

00:15:57.580 --> 00:15:57.900
Cool.

00:15:57.900 --> 00:15:58.140
All right.

00:15:58.140 --> 00:15:59.020
Well, you got the next item.

00:15:59.020 --> 00:15:59.640
Tell us about it.

00:15:59.640 --> 00:16:13.680
Actually, it's a little bit of a rant for me because it was something that was just kind of surprising to me given the how much is in the Python standard library and how much, you know, just, you know, there's one of the things that's really great about Python is this, hey, how do I do this thing?

00:16:13.680 --> 00:16:18.040
And it's like, oh, wow, it's in the standard library and you just call a function and it works.

00:16:18.180 --> 00:16:29.460
And that is that quite a while ago, I ported a database from an application from a Postgres database to an Oracle database, which I know is a ridiculously stupid thing to do, but a customer was paying us a lot of money to do it.

00:16:29.460 --> 00:16:39.920
And I discovered that Postgres is interval types, which, you know, is just, you know, when you're doing a timestamp and you go, okay, I want to add a week to this or a day or whatever.

00:16:39.920 --> 00:16:45.700
There's an SQL type that's called an interval where you can just have arbitrary amounts of time that you can add to a timestamp.

00:16:45.700 --> 00:16:48.080
Well, so Postgres lets you do anything completely arbitrary.

00:16:48.080 --> 00:16:49.840
What turned out, Oracle didn't.

00:16:49.840 --> 00:16:52.040
And it took me a little while to kind of understand why.

00:16:52.040 --> 00:16:54.380
And I actually ended up having to write my own interval parser.

00:16:54.380 --> 00:16:56.900
So I really had to, like, understand how all this stuff works.

00:16:56.900 --> 00:17:04.320
And it turns out that all date intervals really, at the end of the day, boil down to a number of seconds or a number of months.

00:17:04.320 --> 00:17:05.820
It's one of those two things.

00:17:05.820 --> 00:17:14.200
Because if you think about it, a week is a number of days and a day is a number of hours and an hour is a number of minutes and a minute is a number of seconds.

00:17:14.200 --> 00:17:24.240
You know, if you've been a developer for any length of time, you probably know off the top of your head that there are 86,400 seconds in a day because it just comes up all the time and you remember it.

00:17:24.240 --> 00:17:27.400
But the other two is months and years.

00:17:27.400 --> 00:17:29.840
And a month is not a constant number of seconds.

00:17:29.840 --> 00:17:32.000
It's anywhere from 28 to 31 days.

00:17:32.000 --> 00:17:36.480
And depending upon how many that is, that actually varies by what year it is.

00:17:36.480 --> 00:17:39.340
And it's actually really kind of difficult to tease all that apart.

00:17:39.340 --> 00:17:52.360
And so it actually turns out if you use the date time library that comes with Python and you use the time delta object that comes with it and you try to set an offset of months or years, it just says, sorry, can't do that.

00:17:52.360 --> 00:17:52.720
Right.

00:17:52.800 --> 00:17:55.600
You can't do, I can't tell you what a month from now is.

00:17:55.600 --> 00:18:04.060
So that was just really surprising to me and really kind of frustrating because actually the reason why I needed this is actually I was setting up our subscriptions service.

00:18:04.060 --> 00:18:09.380
Although I will say, of course, I'm not actually hanging on to the credit cards now, but I wanted to be able to test it.

00:18:09.380 --> 00:18:09.560
Right.

00:18:09.560 --> 00:18:17.120
And so I want to say, okay, if we, you know, if you're, if we'll start your subscription, let's go a month and a day out and see if your subscription is still active because it shouldn't be.

00:18:17.120 --> 00:18:18.280
And said, oh, wow.

00:18:18.280 --> 00:18:18.560
Okay.

00:18:18.560 --> 00:18:19.400
You can't do that.

00:18:19.400 --> 00:18:22.720
So there is another package out there that you can just get off of pip.

00:18:22.720 --> 00:18:24.420
It's the date util package.

00:18:24.420 --> 00:18:32.440
And it has a time delta replacement called relative delta that just supports months and years and works very similar to the time delta thing.

00:18:32.440 --> 00:18:40.940
So if you've got the problem of, oh, hey, I want to know what it is a month from now or 10 years from now, that'll let you calculate those timestamps.

00:18:40.940 --> 00:18:47.640
Because, of course, the problem is that parsing that stuff, like when you write the library, when you're advancing months, I mean, it's got to be text based.

00:18:47.640 --> 00:18:47.880
Right.

00:18:47.880 --> 00:18:59.680
You got to go, okay, I'm going to turn this thing into a date string and then I'm going to increase the number of months and see if I've overflowed the number of years, increase the number of years, and then turn it back into a timestamp.

00:18:59.680 --> 00:19:03.600
So it's a much slower process from a calculation perspective.

00:19:03.600 --> 00:19:08.040
And I suspect that's probably why the original Python library doesn't just support it out of the box.

00:19:08.040 --> 00:19:08.280
Yeah.

00:19:08.280 --> 00:19:09.520
But that is frustrating, right?

00:19:09.520 --> 00:19:10.860
Because a totally reasonable thing.

00:19:10.860 --> 00:19:15.180
And actually, the hardest of all things to compute is how many months from now is it?

00:19:15.180 --> 00:19:15.860
Close to that.

00:19:15.860 --> 00:19:16.660
It's how many years, right?

00:19:16.660 --> 00:19:17.000
Yeah.

00:19:17.000 --> 00:19:17.740
It can be just.

00:19:17.860 --> 00:19:22.920
And of course, actually, we're running up, we're going to run up against the Unix 2037 thing right now.

00:19:22.920 --> 00:19:25.480
Which, by the way, I saw someone point out, I hadn't actually thought about this.

00:19:25.480 --> 00:19:30.180
There are places, businesses that are trying to do things like generate a certificate that expires in 20 years.

00:19:30.180 --> 00:19:37.240
Like, you can actually run into that problem in your code now if you're still running on, if you're not running on 64-bit native code.

00:19:37.380 --> 00:19:40.620
Which is actually, as I understand, a bit of a problem still in Linux.

00:19:40.620 --> 00:19:43.780
The Linux kernel is not doing a good job of handling all of that.

00:19:43.780 --> 00:19:47.440
That's going to be an increasing problem as we get closer to that barrier.

00:19:47.440 --> 00:19:49.360
Sounds like a great opportunity for consultants.

00:19:49.360 --> 00:19:50.200
Oh, yeah.

00:19:50.200 --> 00:19:50.860
I'm sure.

00:19:50.980 --> 00:20:00.240
I mean, it would not surprise me if I, in my career, as a year 2037 consultant, right, as one of the last people who still knows how to program those old systems.

00:20:00.240 --> 00:20:01.460
Yeah, this is a good recommendation.

00:20:01.460 --> 00:20:03.320
I like the DateUtil library.

00:20:03.320 --> 00:20:06.860
I love the parsing for it.

00:20:06.860 --> 00:20:08.600
I like parsing date times.

00:20:08.600 --> 00:20:10.100
It's annoying in Python.

00:20:10.100 --> 00:20:13.300
Parse, ST, I can't remember even.

00:20:13.300 --> 00:20:14.480
Because I stopped using it.

00:20:14.480 --> 00:20:17.660
Because I just import parse from DateUtil, and I'm good, right?

00:20:17.660 --> 00:20:18.180
Yes.

00:20:18.180 --> 00:20:22.660
It seems to be able to guess the format that you're going for really, really well.

00:20:22.660 --> 00:20:33.520
I was doing a bunch of coding recently with DynamoDB, and it was just like the timestamps you get back out of the Boto3 library is just like one character off of what you can natively parse.

00:20:33.520 --> 00:20:36.980
It was just like, why does this have to be so painful?

00:20:36.980 --> 00:20:38.000
Did DateUtil take it?

00:20:38.000 --> 00:20:39.560
Yeah, no, a date I was getting out of Boto3.

00:20:39.560 --> 00:20:43.380
I don't remember the exact details, but the date I was getting out of Boto3 had like one.

00:20:43.380 --> 00:20:51.140
It was like, so I literally am doing like a text substitution on a particular character to turn it into something else so that it'll then parse it.

00:20:51.140 --> 00:20:51.300
Cool.

00:20:51.300 --> 00:20:53.580
I do that on XML to get rid of the namespaces all the time.

00:20:53.580 --> 00:20:55.820
All right.

00:20:55.900 --> 00:21:06.400
So, Brian, before we've spoken about understanding the language and some of the core language features, and I just want to come back to this topic a little bit and focus on Python generators.

00:21:06.400 --> 00:21:10.700
So, there was a cool article recommended to us by one of the listeners.

00:21:10.700 --> 00:21:14.560
It's not super new, but we haven't covered it, so I think it's totally relevant.

00:21:14.560 --> 00:21:16.580
It's an article by Radu Raycia.

00:21:16.580 --> 00:21:18.400
Hopefully, I'm getting that roughly right.

00:21:18.500 --> 00:21:21.820
And it's called How and Why You Should Use Python Generators.

00:21:21.820 --> 00:21:27.360
So, basically, it talks about what are generators, how you should use them.

00:21:27.360 --> 00:21:40.560
And I wanted to cover this because I feel like there's a lot of people that come from other languages, and it's both a blessing and a curse of Python that people can come from C or Java or JavaScript or other languages and just go,

00:21:40.740 --> 00:21:41.380
Oh, this is simple.

00:21:41.380 --> 00:21:42.360
I learned it in a weekend.

00:21:42.360 --> 00:21:43.740
Let me write my code now.

00:21:43.740 --> 00:21:44.180
Right?

00:21:44.180 --> 00:21:49.640
And they're doing numerical for loops, and they're doing, you know, like tons of stuff that is not really Pythonic, right?

00:21:49.640 --> 00:21:49.880
Right.

00:21:49.880 --> 00:21:54.880
And they've got 27 Stack Overflow tabs open for, like, oh, how do I open a file again?

00:21:54.880 --> 00:21:55.180
Right.

00:21:55.180 --> 00:21:55.800
Yes, exactly.

00:21:55.800 --> 00:22:02.280
And so, a lot of languages don't have this idea of generators or coroutines, which are just amazing, right?

00:22:02.280 --> 00:22:03.260
Like, you've got a function.

00:22:03.260 --> 00:22:05.500
It's going to process some huge amount of data.

00:22:05.500 --> 00:22:08.960
Maybe it needs to read a 10-gigabyte file and parse it line by line.

00:22:09.560 --> 00:22:15.100
Well, if you write that as a generator, if you only pull 10 lines from it, it only reads 10 lines.

00:22:15.100 --> 00:22:19.220
Or even if you've got to go through all of it, it only loads one line into memory at a time.

00:22:19.220 --> 00:22:28.780
And often, the implementation of the generator using the yield keyword is actually simpler, shorter, cleaner than if you were to try to build it up into a list and then return that list and all those kinds of things.

00:22:28.780 --> 00:22:31.040
And code that doesn't exist doesn't have bugs in it.

00:22:31.040 --> 00:22:32.620
That's a good point, yes.

00:22:32.620 --> 00:22:35.280
Code that doesn't exist does definitely not have bugs in it.

00:22:35.340 --> 00:22:39.160
So, this article is good if these generator ideas are new to you.

00:22:39.160 --> 00:22:45.300
It talks about the lazy evaluation, which is really important to understand, and gives you a couple of simple examples.

00:22:45.300 --> 00:22:46.200
It's not super deep.

00:22:46.200 --> 00:22:47.900
So, if you're new, read through it.

00:22:47.900 --> 00:22:51.200
If you really know it pretty well, you probably won't gain a whole lot about it.

00:22:51.200 --> 00:22:52.780
But it's something you could shoot over to your coworkers.

00:22:52.780 --> 00:22:54.380
You're like, why did you write this code?

00:22:54.380 --> 00:22:55.340
Please don't do that again.

00:22:55.340 --> 00:22:55.980
Use this.

00:22:55.980 --> 00:22:57.340
Yeah, this is good.

00:22:57.480 --> 00:23:04.280
Even myself, an experienced Python person, there's certain times where I'm like, why didn't I think of using a generator earlier?

00:23:04.280 --> 00:23:04.980
Yeah, absolutely.

00:23:04.980 --> 00:23:09.860
I mean, you don't always know that that's really the best path.

00:23:09.860 --> 00:23:10.920
You just start writing the code.

00:23:10.920 --> 00:23:11.860
You're like, I'm going to have a list.

00:23:11.860 --> 00:23:12.720
I'm going to put stuff in the list.

00:23:12.720 --> 00:23:13.280
I'm going to do this.

00:23:13.280 --> 00:23:14.100
I'll get a dictionary, whatever.

00:23:14.100 --> 00:23:14.740
Like, wait a minute.

00:23:14.740 --> 00:23:16.180
Actually, I didn't need any of that.

00:23:16.180 --> 00:23:17.480
I could do it way better, right?

00:23:17.480 --> 00:23:18.620
So, you kind of got to have it in mind.

00:23:18.700 --> 00:23:24.640
I would love it if tools like PyCharm and VS Code had a button to, like, refactor to generator, right?

00:23:24.640 --> 00:23:27.900
Convert this list and return the list into, like, a generator.

00:23:27.900 --> 00:23:33.880
It probably doesn't exist because, you know, like, the way you process the results has, you know, some kind of effect, right?

00:23:33.880 --> 00:23:38.620
You can't, like, go through a generator twice, but you can go through a list twice or things like that.

00:23:38.620 --> 00:23:41.900
But it still would be really cool if you could kind of, like, automate that a little bit.

00:23:41.900 --> 00:23:47.860
Yeah, I was thinking more along the lines of when I have my custom data structure that is essentially a container structure

00:23:47.860 --> 00:23:53.580
and I forget to add iterin next to it so that it can be used, generators can be used with it.

00:23:53.580 --> 00:23:54.080
Yeah, exactly.

00:23:54.080 --> 00:23:55.740
You can fit it into that whole pipeline.

00:23:55.740 --> 00:23:56.240
Cool.

00:23:56.240 --> 00:23:58.860
Well, that's it for our main items this week.

00:23:58.860 --> 00:24:01.500
You got anything else you want to quickly give a shout out to, Brian?

00:24:01.500 --> 00:24:07.120
Well, I just saw that we've got a link to PyPI now supporting API tokens.

00:24:07.120 --> 00:24:13.400
There's been a lot of recent changes to the PyPI interface to make it more secure.

00:24:13.400 --> 00:24:16.220
And this is just one of the latest.

00:24:16.220 --> 00:24:18.220
And I think it's a good way.

00:24:18.220 --> 00:24:26.260
They're doing well about making sure that these changes are supported on the test server as well so that you can test out the changes first.

00:24:26.260 --> 00:24:28.020
Yeah, that's pretty good.

00:24:28.020 --> 00:24:33.580
So you don't have to just do it on the immutable write only or write once real version.

00:24:33.580 --> 00:24:34.900
Yeah, yeah.

00:24:34.900 --> 00:24:35.280
Super cool.

00:24:35.360 --> 00:24:43.440
So I think this is like evidence, you know, there was a big push and that funding, that grant from Mozilla to basically modernize PyPI, right?

00:24:43.440 --> 00:24:46.760
And the work that the PyPI did to move that along.

00:24:46.760 --> 00:24:52.040
It's like now you can start seeing these new features coming in because previously it was like no one wants to touch that.

00:24:52.040 --> 00:24:53.820
There's no way we're adding new features.

00:24:53.820 --> 00:24:55.480
Like we're just trying to keep it from breaking.

00:24:55.480 --> 00:24:56.580
Now it can grow.

00:24:56.580 --> 00:24:56.840
It's cool.

00:24:56.840 --> 00:24:57.480
Yeah, it's nice.

00:24:57.480 --> 00:24:59.280
I've got a couple I want to give a quick shout out to.

00:24:59.280 --> 00:25:14.560
Last week we covered possibility of this exploration of moving to peg parsers as opposed to the original sort of one-off version of the parser that Gita Van Rossum had written for Python 30 years ago.

00:25:14.820 --> 00:25:20.700
And so now he's written another article talking about building a peg parser and moving towards it and so on.

00:25:20.700 --> 00:25:24.100
So if that was interesting to you, you can check out that follow-up that he wrote.

00:25:24.100 --> 00:25:31.160
And then finally, we've talked a lot about Homebrew and obviously people know about apt and other package managers on Linux.

00:25:31.160 --> 00:25:35.320
But I don't think we've really talked that much about Windows, right?

00:25:35.320 --> 00:25:38.020
You don't have Homebrew on Windows or many other things like that.

00:25:38.360 --> 00:25:47.700
So Preston Daniel sent us over a quick message that, hey, if you guys get a chance, you should give a shout out to the chocolatey package manager on Windows.

00:25:47.700 --> 00:25:48.760
Are you familiar with this, Brian?

00:25:48.760 --> 00:25:49.880
No, I've never used it.

00:25:49.880 --> 00:25:50.640
No, I've never used it.

00:25:50.640 --> 00:25:59.600
Actually, I do all of my Python or a lot of my Python development actually under Windows, but I'm using WSL, so I don't actually do anything natively in Windows.

00:25:59.600 --> 00:26:00.220
Yeah, yeah.

00:26:00.220 --> 00:26:04.700
So in a sense, you have the Windows UI, but it's kind of Linux-y in some of the tooling.

00:26:04.700 --> 00:26:06.320
WSL was just kind of magic.

00:26:06.320 --> 00:26:12.700
I mean, it definitely is in that the thing that's amazing here is not how well the bear dances, but that it dances at all.

00:26:12.700 --> 00:26:16.260
But yeah, I have a Windows gaming laptop I bought years ago.

00:26:16.260 --> 00:26:21.540
And now that I'm in a startup, of course, I'm using whatever hardware I had lying around in order to not spend any money, right?

00:26:21.540 --> 00:26:25.220
And so yeah, that's my development laptop is my old gaming laptop.

00:26:25.220 --> 00:26:27.180
And so yeah, it's all WSL.

00:26:27.180 --> 00:26:32.160
And I'm simulating AWS services on it so that I can develop offline and stuff.

00:26:32.160 --> 00:26:36.380
It boggles me that you can actually do all of this stuff at all.

00:26:36.380 --> 00:26:37.500
Yeah, that's super cool.

00:26:37.500 --> 00:26:38.100
That's super cool.

00:26:38.100 --> 00:26:41.860
Yeah, so Chocolaty is like homebrew, basically, but for Windows.

00:26:41.860 --> 00:26:44.920
So you can say Choco install such and such.

00:26:44.920 --> 00:26:46.540
And I link to Python, right?

00:26:46.540 --> 00:26:52.680
So actually, on Chocolaty, you can now install Python 374, which is kind of impressive, right?

00:26:52.720 --> 00:26:54.260
That came out like a couple weeks ago.

00:26:54.260 --> 00:27:00.820
But if you actually look at the versions, you can install Python 3.8 beta 3, which came out yesterday, right?

00:27:00.820 --> 00:27:02.380
Like it's right on top.

00:27:02.380 --> 00:27:06.160
And they even do like limited virus scanning and like validation a little bit.

00:27:06.160 --> 00:27:08.520
So yeah, it's a pretty cool little system.

00:27:08.520 --> 00:27:12.260
And people should definitely check it out if they're doing work natively on Windows.

00:27:12.260 --> 00:27:13.080
Yeah, nice.

00:27:13.080 --> 00:27:14.680
Brett, anything else you want to throw out there while you're here?

00:27:14.680 --> 00:27:19.100
That's probably all the great Python ideas that I have at the moment.

00:27:19.100 --> 00:27:20.200
All right, super.

00:27:20.200 --> 00:27:20.880
How about a joke?

00:27:20.980 --> 00:27:21.580
Yeah, how about a joke?

00:27:21.580 --> 00:27:23.220
I actually have a couple of jokes for you.

00:27:23.220 --> 00:27:27.000
A programming joke and then just an adulting joke following up on that.

00:27:27.000 --> 00:27:29.580
So it's more of, I guess, more of an assessment.

00:27:29.580 --> 00:27:34.800
A good programmer is someone who always looks both ways before crossing a one-way street.

00:27:34.800 --> 00:27:38.740
Does that connect with you, Brian, as a tester?

00:27:38.740 --> 00:27:39.580
Yes, definitely.

00:27:39.580 --> 00:27:46.800
Having just gotten back from wandering around in London and always looking the wrong way when crossing a one-way street, that resonates with me.

00:27:46.800 --> 00:27:47.620
That's awesome.

00:27:47.620 --> 00:27:50.100
Yeah, I'm always paranoid when I'm in London or in Australia.

00:27:50.320 --> 00:27:52.640
Like, I'm like double checking both directions.

00:27:52.640 --> 00:27:54.100
They're like, you just got to look that way.

00:27:54.100 --> 00:27:56.040
I'm like, no, that's what you say now.

00:27:56.040 --> 00:27:59.920
Then there's going to be the time I look the wrong way and one of those big red buses is going to crush me.

00:27:59.920 --> 00:28:05.220
And I'm just, you know, so I'm just like a paranoid squirrel trying to cross the street in the UK.

00:28:05.220 --> 00:28:05.640
It's great.

00:28:05.640 --> 00:28:06.460
Yeah.

00:28:06.700 --> 00:28:14.080
So then related to that, not quite programming, but adulthood is like looking both ways before crossing the street and then getting hit by an airplane.

00:28:14.080 --> 00:28:17.300
I want to throw one more in there, though.

00:28:17.300 --> 00:28:17.880
Oh, go ahead, Brian.

00:28:17.880 --> 00:28:19.200
No, I think that's good.

00:28:19.200 --> 00:28:19.860
That's funny.

00:28:19.860 --> 00:28:21.440
It's a little too real to be funny, though.

00:28:21.440 --> 00:28:23.220
Like, we aren't laughing like, yeah, that hurt.

00:28:24.800 --> 00:28:25.240
All right.

00:28:25.240 --> 00:28:27.340
So, Brett, you started this one.

00:28:27.340 --> 00:28:29.880
So I'm going to throw it out here for everyone.

00:28:29.880 --> 00:28:30.980
Little Bobby Tables.

00:28:30.980 --> 00:28:32.920
Brian, do you know about Little Bobby Tables?

00:28:32.920 --> 00:28:35.160
Well, I remember it, but I probably couldn't explain it.

00:28:35.160 --> 00:28:35.380
Yeah.

00:28:35.480 --> 00:28:36.780
So it's XKCD.

00:28:36.780 --> 00:28:38.340
And here, I'll just read it.

00:28:38.340 --> 00:28:39.860
We'll just leave it out there for folks.

00:28:39.860 --> 00:28:44.140
It's a mom answering the phone and says, hi, this is your son's school.

00:28:44.140 --> 00:28:46.180
We're having some computer trouble.

00:28:46.180 --> 00:28:47.140
Oh, dear.

00:28:47.140 --> 00:28:47.960
Did he break something?

00:28:47.960 --> 00:28:48.760
In a way.

00:28:48.760 --> 00:28:55.720
Did you really name your son Robert, quote, parentheses, semicolon, drop table students, quote, semicolon, dash, dash?

00:28:55.720 --> 00:28:57.120
Oh, yes.

00:28:57.120 --> 00:28:58.300
Little Bobby Tables, we call them.

00:28:58.300 --> 00:29:00.880
Well, we've lost years of student records.

00:29:00.880 --> 00:29:01.580
I hope you're happy.

00:29:01.580 --> 00:29:04.140
And I hope you've learned to sanitize your database input.

00:29:04.140 --> 00:29:14.060
The thing I really love about this idea is that she has saddled this child with this terrible name for this one opportunity, right?

00:29:14.060 --> 00:29:17.980
I mean, when he gets to be 24, it's never going to work again, right?

00:29:17.980 --> 00:29:19.960
I mean, I guess unless he goes on to be a teacher.

00:29:19.960 --> 00:29:22.840
Then he can just cause havoc wherever he goes for the rest of his life.

00:29:22.840 --> 00:29:27.280
It sounds crazy, but there's this pen tester, penetration tester, who has a Tesla.

00:29:27.280 --> 00:29:29.900
And in the app, you can change the name of your Tesla.

00:29:30.800 --> 00:29:35.020
He changed it to a JavaScript injection string.

00:29:35.020 --> 00:29:38.800
And it went off when his car had to go get some service.

00:29:38.800 --> 00:29:40.080
Yeah, I believe it.

00:29:40.080 --> 00:29:47.560
I just have to say, as a general aside about anything, as somebody who ran, you know, a PCI DSS compliant thing for a long time, get pen tested.

00:29:47.560 --> 00:29:52.020
Like, every time I got pen tested, those people came up with something creative and I learned something.

00:29:52.020 --> 00:29:57.420
You know, like that's like, take the first dollar that you have to spend on security and hire a pen tester.

00:29:57.560 --> 00:29:59.180
Yeah, that sounds like good advice for sure.

00:29:59.180 --> 00:29:59.620
All right.

00:29:59.620 --> 00:30:00.500
Well, that looks like it.

00:30:00.500 --> 00:30:01.540
That's it for us, you guys.

00:30:01.540 --> 00:30:03.200
Brian, thanks as always.

00:30:03.200 --> 00:30:04.700
And Brett, thank you for coming this time.

00:30:04.700 --> 00:30:05.200
My pleasure.

00:30:05.200 --> 00:30:05.940
Yeah, thank you.

00:30:05.940 --> 00:30:06.180
Yep.

00:30:06.180 --> 00:30:06.600
Bye, everyone.

00:30:06.600 --> 00:30:06.900
Bye-bye.

00:30:06.900 --> 00:30:08.900
Thank you for listening to Python Bytes.

00:30:08.900 --> 00:30:11.440
Follow the show on Twitter via at Python Bytes.

00:30:11.440 --> 00:30:14.300
That's Python Bytes as in B-Y-T-E-S.

00:30:14.300 --> 00:30:17.540
And get the full show notes at pythonbytes.fm.

00:30:17.540 --> 00:30:21.740
If you have a news item you want featured, just visit pythonbytes.fm and send it our way.

00:30:21.740 --> 00:30:24.460
We're always on the lookout for sharing something cool.

00:30:24.840 --> 00:30:27.560
On behalf of myself and Brian Okken, this is Michael Kennedy.

00:30:27.560 --> 00:30:30.980
Thank you for listening and sharing this podcast with your friends and colleagues.

