WEBVTT

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

00:00:05.200 --> 00:00:10.340
This is episode 202, recorded September 30th, 2020.

00:00:10.340 --> 00:00:11.860
I'm Brian Okken.

00:00:11.860 --> 00:00:12.860
And I'm Michael Kennedy.

00:00:12.860 --> 00:00:16.680
Yeah. And this episode is brought to you by Datadog. So thanks, Datadog.

00:00:16.680 --> 00:00:19.160
Yeah. Thank you, Datadog. It's good to have you back, Brian.

00:00:19.160 --> 00:00:19.760
It's good to be back.

00:00:19.760 --> 00:00:20.280
We missed you.

00:00:20.280 --> 00:00:23.160
Yeah. I had a little bit of a heart scare, but I'm all better now.

00:00:23.160 --> 00:00:25.000
That's good to hear.

00:00:25.000 --> 00:00:32.520
We're recording this September 30th, but by the time this comes out, we might have a new Python. So did you know that?

00:00:32.520 --> 00:00:41.100
I did not know that, but I'm very excited that you're covering that first. Yeah. So usually there's about a week delay and that's about when Python 3.9 should be, right?

00:00:41.100 --> 00:00:50.940
Yeah. So Python 3.9, there is a RC2 or Release Canada 2 was released September 17th. The final is scheduled for release October 5th.

00:00:50.940 --> 00:00:57.240
Of course, you know, it's software, so things can come up, but we're looking forward to starting using 3.9 right away.

00:00:57.240 --> 00:01:08.420
We're linking to the changelog. There's a lot of different lists for what is in 3.9, but I wanted to highlight a few features that I pulled out from the changelog.

00:01:08.420 --> 00:01:25.340
The first couple I think I'm most excited about, there's a dictionary merge and update operators. So the merge operator is just the bar. So you can have two dictionaries and do a bar to merge them together. And the bar equal for the update.

00:01:25.800 --> 00:01:34.380
The update kind of means, it doesn't mean append. It means like, if there's new stuff, add it to the other dictionary. But if there's changes, change it.

00:01:34.380 --> 00:01:42.820
So I think this is just, when I first read about this, I thought, why don't we already have this? This just seems obvious. So I'm glad to have a merge operator.

00:01:42.820 --> 00:01:54.240
Yeah, I thought this, there's already a way to accomplish this with the curly bracket, star, star, dictionary, star, star, dictionary, star, star, dictionary, which has the same effect. It's a little bit longer.

00:01:54.240 --> 00:02:00.120
I think this is for consistency with other container objects like sets that have a pipe behavior.

00:02:00.120 --> 00:02:01.860
So it's like, oh, you can just do it to dictionaries.

00:02:01.860 --> 00:02:02.160
Yeah.

00:02:02.160 --> 00:02:02.940
I think.

00:02:03.020 --> 00:02:14.960
That's nice. I had to read a little bit. The next one is a remove prefix and remove suffix has been added to strings and also added to bytes, byte array and collections user string, which is cool.

00:02:14.960 --> 00:02:16.080
I'm most excited about this one.

00:02:16.080 --> 00:02:16.320
Are you?

00:02:16.320 --> 00:02:16.760
Yeah.

00:02:16.760 --> 00:02:22.060
Because this actually, when you look at like the workarounds to do something, the workarounds are ugly.

00:02:22.060 --> 00:02:28.160
If you just want to, it's just, I have like this string that might be at the beginning of my, of another string.

00:02:28.240 --> 00:02:36.460
I want to remove it. Like if I'm just this prepended stuff that happens all the time. So like spaces or things like that. What would you use it for?

00:02:36.460 --> 00:02:42.480
Well, yeah, the same thing. There's a lot of times there's like, oh, there's this string that always starts at the beginning of this line and I just don't want it.

00:02:42.480 --> 00:02:56.060
Right. But the trim, trim, start, trim, end, trim. If you give it characters, it doesn't mean remove that string. It remains remove, like take each one of those characters and remove all of them until you don't run into any more of those characters.

00:02:56.440 --> 00:03:02.800
And so if one of the characters of your string happens to be the first character of the stuff that's left, it'll also get ripped.

00:03:02.800 --> 00:03:07.260
Yeah. You just want a specific string to get removed. A set of strings.

00:03:07.260 --> 00:03:16.320
Right. If I'm like, I want this substring off the front, you know, if it exists, but not if it doesn't, right? You don't do the test. And anyway, it's just, it cleans it up and makes it a little more predictable.

00:03:16.320 --> 00:03:33.160
Okay. Yeah. Next thing is type annotations have a change that you can now use the built-in collection types, such as list and dict as generic types, instead of having to import typing or from typing import capital list or capital dict. I'm really excited about this.

00:03:33.280 --> 00:03:35.880
Wait, I did get back. I'm more excited about this than remove prints.

00:03:35.880 --> 00:03:46.400
Yeah. Cause I'm always annoyed when I have to like, cause I'm, I, I'm starting to use type hinting for a, you know, for interfaces and you don't need to import anything to do that.

00:03:46.400 --> 00:03:54.600
Except for if you have a list or a dictionary or set or something like that. And now you don't have to do that anymore. And I'm very happy.

00:03:54.600 --> 00:04:01.260
I'm still waiting for the optional operator, the question mark or something rather than capital O optional.

00:04:01.260 --> 00:04:03.260
Yeah, that'd be good.

00:04:03.260 --> 00:04:04.100
Yeah.

00:04:04.100 --> 00:04:12.760
We've talked about the peg parser before, but the three, nine is where the new peg parser comes in. I don't know if it'll affect anybody, but it's neat.

00:04:12.760 --> 00:04:24.480
Yeah. It's supposed to make extending the language with more complicated behaviors and more nuanced syntax easier, but it won't affect you or me probably writing code day to day. I'm not going to touch that thing.

00:04:24.480 --> 00:04:42.520
Yeah, I'm not. I was intrigued by this. Any valid expression can now be used as a decorator. This is PEP 614. I haven't quite wrapped my head around it, but I think this will change the way we use decorators, but I think we need a few tutorials to be written to people to figure out how to use this.

00:04:42.520 --> 00:04:49.740
So maybe we should just make decorators like a lambda expression because I know you have later in the show some really cool uses of lambda expression. So we can come back to that.

00:04:49.740 --> 00:05:03.800
Oh my gosh. A huge lambda expression could be a decorator. Yeah, that'd be cool. Or really bad. Anyway, the other thing, last thing I wanted to mention, zone info is a new module that comes in, which is cool.

00:05:03.800 --> 00:05:14.180
Python has IANA time zone databases support. That's part of the standard library now. And there's a whole bunch of other stuff too. So we're going to link to the change log and people should check that out.

00:05:14.180 --> 00:05:17.820
Yeah, very cool. Exciting. We're going to have a new Python and Python comes faster now.

00:05:17.820 --> 00:05:18.360
It does.

00:05:18.520 --> 00:05:20.800
I think they changed the release cycle to 12 months.

00:05:20.800 --> 00:05:21.320
Oh yeah.

00:05:21.320 --> 00:05:22.600
So it's a year month.

00:05:22.600 --> 00:05:26.180
310 or whatever the next thing is should be out soon.

00:05:26.180 --> 00:05:29.660
Yeah, we'll just put it on our calendar. First week in October, we should expect a new Python.

00:05:29.660 --> 00:05:32.560
That's right. What happens in October? Halloween and Python.

00:05:32.560 --> 00:05:34.600
And black. Black cats.

00:05:34.740 --> 00:05:44.260
Black. Yeah, because you want to go out into your costumes and your scary costumes at night when it's dark. It's no fun to do Halloween in the day because it looks fake.

00:05:44.260 --> 00:05:49.600
Or maybe you just have a Jupyter notebook and you're a fan of black, but you would like to format it.

00:05:49.600 --> 00:05:58.420
So Mary Hong sent over a cool recommendation based on some stuff we had over on Talk Python.

00:05:58.420 --> 00:06:10.940
So in Talk Python, I did an auto racing episode with Kane Replical and his pick for a PyPI package recommendation was Black Cell Magic, which I think we covered on the show as well.

00:06:10.940 --> 00:06:11.480
I'm pretty sure.

00:06:11.480 --> 00:06:13.900
She said you should check out Jupyter Black.

00:06:13.900 --> 00:06:21.540
And Jupyter Black is kind of like the same thing, but instead of having to type into the cells, you can just press.

00:06:21.540 --> 00:06:24.640
It gives you a toolbar button. You can press and off it goes.

00:06:24.640 --> 00:06:26.500
So that looks really cool.

00:06:26.500 --> 00:06:34.180
It gives you a toolbar button and a couple of hotkey shortcuts, keyboard shortcuts to format single cells and format all the cells.

00:06:34.180 --> 00:06:38.800
Okay, that was going to be my question. Can you just have it do the whole shebang at once?

00:06:38.800 --> 00:06:40.300
Exactly. And that's what was...

00:06:40.300 --> 00:06:42.560
You can also just run...

00:06:42.560 --> 00:06:47.000
Instead of running black in your CI, you can run J Black or as a pre-commit hook or something like that.

00:06:47.000 --> 00:06:47.240
Okay.

00:06:47.240 --> 00:06:55.080
So I believe with the Black Cell Magic that I talked about previously, you had to type it into the notebook and it would do it, which is cool.

00:06:55.080 --> 00:06:57.200
But this is more of a...

00:06:57.200 --> 00:07:02.100
And I talked about there being an extension that would kind of do it for the whole notebook, but it had a huge message.

00:07:02.100 --> 00:07:03.460
Like, this is no longer supported.

00:07:03.460 --> 00:07:05.080
So I'm not so sure.

00:07:05.080 --> 00:07:11.120
So this gives you both a CLI and hotkeys for the whole notebook, which seems cool.

00:07:11.120 --> 00:07:12.280
Yeah, it does seem neat.

00:07:12.280 --> 00:07:13.660
Definitely need to check that out.

00:07:13.660 --> 00:07:14.180
Yeah, absolutely.

00:07:14.180 --> 00:07:15.400
Quick and simple.

00:07:15.580 --> 00:07:20.680
But to me, that's one of the huge shortcomings of Jupyter on multiple levels.

00:07:20.680 --> 00:07:23.240
I think the auto-formatting...

00:07:23.240 --> 00:07:25.380
Like, Jupyter should format that code as I type.

00:07:25.380 --> 00:07:29.880
I shouldn't have to, like, run command line things against it to get formatted code.

00:07:29.880 --> 00:07:32.540
Like, you know, Visual Studio Code, PyCharm.

00:07:32.540 --> 00:07:34.240
It gives you that support as you go.

00:07:34.240 --> 00:07:36.080
You're not, like, spacing around, tapping around.

00:07:36.300 --> 00:07:39.880
The other I really wish Jupyter did better was autocomplete.

00:07:39.880 --> 00:07:40.280
Yeah.

00:07:40.280 --> 00:07:44.220
Yes, if you hit dot, nothing happens.

00:07:44.220 --> 00:07:45.880
But if you hit tab, it will come up.

00:07:45.880 --> 00:07:47.660
And I think there's a lot of...

00:07:47.660 --> 00:07:49.320
You know, compare that to the other modern editors.

00:07:49.320 --> 00:07:51.680
There's a lot of room to make improvements on those areas.

00:07:51.680 --> 00:08:00.320
But, you know, this, at least having a keyboard shortcut, like, reformat document, you know, command shift B or whatever, control shift B, that seems really like a good start.

00:08:00.460 --> 00:08:03.600
Do you know if JupyterLab has any different support or is it...

00:08:03.600 --> 00:08:04.220
I don't think so.

00:08:04.220 --> 00:08:08.160
I think JupyterLab just has more other UI elements.

00:08:08.160 --> 00:08:11.460
Like, you have an ability to get to the terminal and do other stuff.

00:08:11.460 --> 00:08:12.840
It's not just the notebook.

00:08:12.840 --> 00:08:16.260
But I don't think the fundamental editor experience changed.

00:08:16.260 --> 00:08:16.840
I could be wrong.

00:08:16.840 --> 00:08:19.300
I don't compare them that often, but I don't think so.

00:08:19.300 --> 00:08:19.620
Well, we could...

00:08:19.620 --> 00:08:22.180
I mean, if they get to that point, it wouldn't be an IDE.

00:08:22.180 --> 00:08:23.820
It would be a JDE, right?

00:08:23.820 --> 00:08:25.160
Jupyter development.

00:08:25.160 --> 00:08:26.220
That's right, a JDE.

00:08:26.220 --> 00:08:27.360
Exactly.

00:08:27.360 --> 00:08:28.240
Good one.

00:08:28.240 --> 00:08:28.680
All right.

00:08:28.800 --> 00:08:30.520
Another cool thing is Datadog.

00:08:30.520 --> 00:08:33.560
This episode of Python Bytes is brought to you by Datadog.

00:08:33.560 --> 00:08:35.260
Let me ask you a question.

00:08:35.260 --> 00:08:38.540
Do you have an app in production that is slower than you like?

00:08:38.540 --> 00:08:40.480
Is its performance all over the place?

00:08:40.480 --> 00:08:42.080
Sometimes fast, sometimes slow.

00:08:42.080 --> 00:08:44.160
Now, here's an important question.

00:08:44.160 --> 00:08:45.220
Do you know why?

00:08:45.220 --> 00:08:46.660
With Datadog, you will.

00:08:46.660 --> 00:08:50.400
You can troubleshoot your app's performance with Datadog's end-to-end tracing.

00:08:50.400 --> 00:08:56.480
Use the detailed flame graphs to identify bottlenecks and latency in that finicky app of yours.

00:08:57.100 --> 00:09:00.560
Be the hero that got the app back on track for your company.

00:09:00.560 --> 00:09:05.040
Get started today with a free trial at pythonbytes.fm/Datadog.

00:09:05.040 --> 00:09:05.400
Awesome.

00:09:05.400 --> 00:09:06.120
Thank you, Datadog.

00:09:06.120 --> 00:09:07.480
You know what's not awesome?

00:09:07.480 --> 00:09:08.440
DDoS.

00:09:08.440 --> 00:09:11.400
Denial of service against your web app.

00:09:11.400 --> 00:09:11.760
Yeah.

00:09:12.040 --> 00:09:15.780
So, this is the next couple of things I've got are listener suggestions.

00:09:15.780 --> 00:09:22.080
And unfortunately, since I've kind of been out of commission for a week, I forgot who suggested this.

00:09:22.080 --> 00:09:25.560
So, my apologies to the listener who brought this to their attention.

00:09:25.900 --> 00:09:34.140
There's an article written by Jacob Kaplan Moss called Understanding and Preventing Denial of Service on Web Applications.

00:09:34.360 --> 00:09:41.320
I saw it, but I kind of dismissed it right away because I thought it was just another, like, about all languages.

00:09:41.320 --> 00:09:45.720
But this one is focused on Python and has some specifics on Django.

00:09:45.720 --> 00:09:57.800
So, I think it starts off with a good discussion of what denial of service is and then sort of kind of what to do about it and how to prevent it from happening and fix things with your application.

00:09:58.300 --> 00:10:01.800
But it kind of led me down a rabbit hole and I kind of enjoyed it.

00:10:01.800 --> 00:10:12.660
Anyway, there's one example that it lists as a, I think I've heard, Bev, I don't remember if we've talked about it on the show, which is called a RedOS, which is a regular expression denial of service.

00:10:12.660 --> 00:10:14.000
We talked about this?

00:10:14.000 --> 00:10:14.320
Do you know?

00:10:14.320 --> 00:10:15.340
I don't think so.

00:10:15.340 --> 00:10:25.240
But, yeah, there's certain types of, like, computationally expensive things that are not going to match or useless or whatever you can send over to regular expressions that will cause all sorts of trouble.

00:10:25.240 --> 00:10:36.440
And what's interesting is, so, it says RedOS bugs occur when certain types of strings can cause improperly crafted regular expressions to form extremely, perform poorly.

00:10:36.440 --> 00:10:38.740
And I'm talking, like, really poorly.

00:10:38.740 --> 00:10:42.800
What's interesting is they're not even complicated or regular expressions.

00:10:42.800 --> 00:10:54.700
They're just, like, for instance, a match, a set containing, like, one or more characters or zero or more characters, followed by another zero or more characters, followed by a B.

00:10:54.700 --> 00:10:56.280
Or something like that.

00:10:56.280 --> 00:11:02.600
And there's, like, a little graphic on one of the links on this page that shows how slow this is.

00:11:02.600 --> 00:11:06.300
It has to match all these different things, and it's bad.

00:11:06.300 --> 00:11:13.040
Anyway, some languages have stuff put in place to try to thwart this sort of a thing, but Python does not.

00:11:13.040 --> 00:11:15.360
But we have a solution.

00:11:15.360 --> 00:11:24.580
So, this article links to another article called Finding Python Redos Bugs at Scale Using DLint, which I was like, DLint?

00:11:24.580 --> 00:11:25.460
What's that?

00:11:25.460 --> 00:11:27.520
So, I went and looked there.

00:11:27.520 --> 00:11:30.140
DLint is a Flake 8 plugin.

00:11:30.140 --> 00:11:36.720
So, you can check for denial of service vulnerabilities when you're checking everything else with Flake.

00:11:36.720 --> 00:11:37.380
Oh, that's interesting.

00:11:37.380 --> 00:11:39.440
I'd never heard of that one.

00:11:39.440 --> 00:11:45.120
Yeah, so this, I was thinking, it's a security plugin, a sort of linter for Python.

00:11:45.120 --> 00:11:48.540
I mean, I was thinking, is there a difference between that and Bandit?

00:11:48.540 --> 00:11:51.680
And the authors of DLint were expecting that.

00:11:51.680 --> 00:11:55.220
So, the first FAQ is, what about Bandit?

00:11:55.220 --> 00:11:57.720
So, there's a discussion about whether or not to use Bandit.

00:11:57.720 --> 00:12:02.440
But the TLDR is, it checks for different things than Bandit.

00:12:02.440 --> 00:12:06.540
So, you can run both of them and they run perfectly fine on the same code base.

00:12:06.540 --> 00:12:07.640
Yeah, super cool.

00:12:07.640 --> 00:12:08.880
DDoS is no fun.

00:12:08.880 --> 00:12:11.060
Distributed DDoS, a whole lot less fun.

00:12:11.060 --> 00:12:13.480
So, having to deal with that.

00:12:13.480 --> 00:12:18.460
I've had to deal with that before and managed to get ahead of it.

00:12:18.460 --> 00:12:26.140
But if there's thousands of computers trying to do bad stuff to your website all at the same time from different locations, it's not easy.

00:12:26.960 --> 00:12:29.980
You've had to do that for maybe Talk Python or something?

00:12:29.980 --> 00:12:31.540
For Talk Python training, yeah.

00:12:31.540 --> 00:12:32.060
Lame.

00:12:32.060 --> 00:12:37.380
People, thousands of computers were trying to do all sorts of stuff at the same time.

00:12:37.380 --> 00:12:40.740
So, even things like, let's just block this IP address.

00:12:40.740 --> 00:12:48.780
Or let's put in checks that if this IP address does five bad actions, we're going to block it for an hour or a day or permanently.

00:12:48.780 --> 00:12:53.700
None of that would work because it was so many different computers or devices or whatever.

00:12:53.700 --> 00:12:55.060
Anyway, not fun?

00:12:55.060 --> 00:12:56.780
It'll definitely get your attention.

00:12:56.780 --> 00:13:00.020
Another thing that'll get your attention is pictures.

00:13:00.020 --> 00:13:00.920
We love pictures.

00:13:01.660 --> 00:13:08.040
So, Shomik Chowduri sent over a project that he's working on that I think is pretty cool.

00:13:08.040 --> 00:13:09.060
So, I decided to cover it.

00:13:09.060 --> 00:13:11.940
It reminds me of something I'd worked on a long time ago.

00:13:11.940 --> 00:13:14.000
So, he works with computer vision.

00:13:14.000 --> 00:13:15.260
And now, this is not just about...

00:13:15.260 --> 00:13:18.120
I think this is useful beyond computer vision, which is why I'm covering it.

00:13:18.120 --> 00:13:20.400
But especially for computer vision.

00:13:20.400 --> 00:13:32.200
What he has to work with a lot is there's an image and you're trying to find all the people and maybe the bicycle or all the cars and the things the car needs to worry about if it's a self-driving car.

00:13:32.200 --> 00:13:32.620
Right?

00:13:33.040 --> 00:13:36.280
So, you want to put little pictures around it.

00:13:36.280 --> 00:13:40.540
And say, the computer vision and the ML algorithm said, this is a car.

00:13:40.540 --> 00:13:41.520
Where is that?

00:13:41.520 --> 00:13:42.160
Duck over there.

00:13:42.160 --> 00:13:42.800
That's not a car.

00:13:42.800 --> 00:13:43.160
Right?

00:13:43.660 --> 00:13:46.080
So, you want to label them visually.

00:13:46.080 --> 00:13:52.360
So, often what they do is they put boxes around them and they put some text to say, this is a person, this is a car, this is a duck.

00:13:52.360 --> 00:14:02.380
And drawing those boxes with the picture, with the label lined up just right or affixed to the edge of the box or sort of an arrow pointing down to it or things like that.

00:14:02.380 --> 00:14:03.780
You know, kind of tedious.

00:14:03.780 --> 00:14:17.400
So, he wrote a thing called bbox visualizer, which lets you just say, here's an image file like a PNG and here is the coordinates of this box and the label I want you to put on it.

00:14:17.400 --> 00:14:24.660
And boom, it draws like a nice fancy little box around the object that you talk about and puts a well-oriented label on it.

00:14:24.900 --> 00:14:36.840
So, if you're doing any sort of science stuff or image analysis where you want to put, like, here's what the computer thought is over here and here's what we're calling it, you know, for all sorts of analysis.

00:14:36.840 --> 00:14:38.780
This is a handy little library.

00:14:38.780 --> 00:14:39.960
Yeah, this is cool.

00:14:39.960 --> 00:14:40.300
Yeah.

00:14:40.300 --> 00:14:41.920
Not everyone's going to need it.

00:14:41.920 --> 00:14:44.340
You don't need it for like a fancy web app or whatever.

00:14:44.340 --> 00:14:49.800
But I think if you're trying to do this kind of work, here's a super simple like two or three lines of code.

00:14:49.800 --> 00:14:54.120
Put a nice bunch of bounding boxes on top of things and pictures with nice labels.

00:14:54.120 --> 00:14:54.780
That seems cool.

00:14:54.780 --> 00:15:07.260
Yeah, I can also see like lots of different like student projects where they're using, working with images and algorithms around it to be able to highlight a particular area that they're working on or something like that.

00:15:07.260 --> 00:15:08.020
I think uses.

00:15:08.020 --> 00:15:08.460
For sure.

00:15:08.460 --> 00:15:10.560
I can see a lot of science that are doing it.

00:15:10.560 --> 00:15:13.320
Like we just, we detected this as a star here.

00:15:13.320 --> 00:15:14.080
This is a star.

00:15:14.080 --> 00:15:15.680
Here's the name of the star or whatever.

00:15:15.680 --> 00:15:16.000
Yeah.

00:15:16.000 --> 00:15:20.100
And to just sort of lump all of the drawing the box stuff into a library.

00:15:20.100 --> 00:15:20.620
This is cool.

00:15:20.620 --> 00:15:21.360
I like it.

00:15:21.360 --> 00:15:22.280
Yeah, for sure.

00:15:22.600 --> 00:15:27.420
You've got some nice fancy code examples, like taking your Pythonic code to the next level.

00:15:27.420 --> 00:15:28.140
Tell us about it.

00:15:28.140 --> 00:15:28.880
To the next level.

00:15:28.880 --> 00:15:34.400
I was debating as to, I've got like a devilish streak in me, I think, as to why I'm bringing this in.

00:15:34.400 --> 00:15:36.980
This also was another listener suggestion.

00:15:36.980 --> 00:15:38.760
My apologies to whoever sent it.

00:15:38.760 --> 00:15:39.300
I forget.

00:15:39.300 --> 00:15:41.060
I think it's a gist.

00:15:41.060 --> 00:15:42.400
GitHub gist, I'm pretty sure.

00:15:42.740 --> 00:15:45.380
And it's how to never use lambdas.

00:15:45.380 --> 00:15:50.060
So I'm like just chuckling even at the name.

00:15:50.060 --> 00:15:56.240
It starts off with a brief example showing how to rewrite a power function as a lambda.

00:15:57.000 --> 00:16:10.100
And, you know, anybody sort of familiar with lambdas, that's kind of a common use case is I've got a little like a single one or two argument function that I need to pass in as an expression instead.

00:16:10.100 --> 00:16:12.060
And I can't pass in functions.

00:16:12.060 --> 00:16:16.660
So I pass in a lambda as it's kind of a bound function sort of thing.

00:16:16.780 --> 00:16:16.920
Right.

00:16:16.920 --> 00:16:20.680
I want to do a sort on a list and I want to sort by all users.

00:16:20.680 --> 00:16:22.260
I want to sort by their login date.

00:16:22.260 --> 00:16:27.400
So, you know, lambda U goes to U dot login date or something super simple like that, right?

00:16:27.400 --> 00:16:28.260
That seems good.

00:16:28.260 --> 00:16:32.760
And anybody scared of lambdas, if you look at the initial example, that's a good simple thing.

00:16:32.760 --> 00:16:34.080
They're not scary.

00:16:34.080 --> 00:16:36.220
They're just basically functions without names.

00:16:36.220 --> 00:16:38.220
But they have to be expressions.

00:16:38.220 --> 00:16:40.380
So first one, no problem.

00:16:40.380 --> 00:16:42.960
But then he jumps right into some crazy code.

00:16:42.960 --> 00:16:43.640
I'm saying he.

00:16:43.640 --> 00:16:45.280
I don't know who wrote it.

00:16:45.660 --> 00:16:49.680
But the crazy code right away is some code with import statements.

00:16:49.680 --> 00:16:51.980
So how do you get around import statements?

00:16:51.980 --> 00:17:04.020
Will you somehow it's a using a dunder import and referencing the library you want to import as an expression has to as in the value of that past as an argument to another lambda.

00:17:04.020 --> 00:17:06.020
And these are nested lambdas.

00:17:06.020 --> 00:17:09.620
So right off the bat, first bad example is horrible.

00:17:09.620 --> 00:17:10.900
So don't do that.

00:17:10.900 --> 00:17:13.900
This is almost like a decorator lambda.

00:17:15.260 --> 00:17:15.860
Thing.

00:17:15.860 --> 00:17:17.040
It's so weird.

00:17:17.040 --> 00:17:17.880
It starts off frightening.

00:17:17.880 --> 00:17:21.620
And then it shows an example of a class definition.

00:17:21.620 --> 00:17:25.580
And then how to lambify a class definition.

00:17:25.580 --> 00:17:26.680
Yeah.

00:17:26.680 --> 00:17:30.440
So you can have a lambda expression be an entire class definition.

00:17:30.440 --> 00:17:31.460
Weird.

00:17:32.020 --> 00:17:41.540
And then the last example, which is my favorite is an entire working flask application as a single lambda expression.

00:17:41.540 --> 00:17:43.240
It's truly horrible stuff.

00:17:43.240 --> 00:17:45.660
You should not do this, but it's amusing to read about.

00:17:45.840 --> 00:17:51.320
Well, if your goals have fewer lines of code, like one line for an entire flask application.

00:17:51.320 --> 00:17:51.960
That's impressive.

00:17:51.960 --> 00:17:53.440
I think it has two.

00:17:53.440 --> 00:17:55.340
Yeah, it has two routes, not just one.

00:17:55.340 --> 00:17:56.300
Impressive.

00:17:57.240 --> 00:17:57.680
Yeah.

00:17:57.680 --> 00:17:58.960
Yeah, it's great.

00:17:58.960 --> 00:17:59.600
Cool.

00:17:59.600 --> 00:18:04.220
Some of the, sometimes of these, like, let's see these ideas taken to extreme are pretty interesting.

00:18:04.220 --> 00:18:06.100
And definitely that's the lambda equivalent there.

00:18:06.100 --> 00:18:11.720
Yeah, one good use case of this, I think, maybe I might get struck by lightning by suggesting this.

00:18:11.720 --> 00:18:24.600
But if you're in, if you got a CS student and you're doing really good, you've got like 110% in the class, maybe turn in a homework assignment that's just entirely lambda expressions.

00:18:25.880 --> 00:18:34.380
Or if you're just feeling really mischievous and you get some homework assignment you're super frustrated with, you're like, you know what?

00:18:34.380 --> 00:18:36.700
You're going to ask me to do something silly.

00:18:36.700 --> 00:18:39.000
And you said, as long as it works, it counts.

00:18:39.000 --> 00:18:40.020
You're getting this back.

00:18:40.020 --> 00:18:43.160
Anyway, yeah, I'll probably get.

00:18:43.160 --> 00:18:44.100
Yeah, don't do that.

00:18:44.100 --> 00:18:44.520
That's mean.

00:18:44.520 --> 00:18:45.720
I'll probably get hate mail for that.

00:18:45.720 --> 00:18:46.540
So, sorry.

00:18:46.540 --> 00:18:49.440
What's not mean is contributing to open source, generally speaking.

00:18:49.440 --> 00:18:50.180
Yeah, that's not mean.

00:18:50.180 --> 00:18:50.720
That's nice.

00:18:50.720 --> 00:18:56.020
Yeah, so Alexander, one of the listeners, sent over an article or blog post by Vincent Wanderman.

00:18:56.020 --> 00:19:02.320
And it's called Uncommon Contributions, Making an Impact Without Touching the Core of a Library.

00:19:02.320 --> 00:19:13.360
I think this is one of the challenges, paradoxes that you might run into is like, you find these libraries that are very popular and you love them and you want to contribute to them.

00:19:13.360 --> 00:19:15.660
Like, I love Django, so I want to contribute to it.

00:19:15.660 --> 00:19:17.200
I love Flask, I want to contribute to it.

00:19:17.200 --> 00:19:19.280
I love Request, I want to contribute to it.

00:19:19.280 --> 00:19:20.200
Well, guess what?

00:19:20.200 --> 00:19:30.820
Although those things are highly polished and they have a lot of different use cases, it's very hard to make changes to them because any little change will have a potentially huge effect on a lot of software, right?

00:19:30.820 --> 00:19:34.840
Yeah, and it's also just intimidating to touch the code for a large project, too.

00:19:34.840 --> 00:19:36.100
Yeah, exactly.

00:19:36.100 --> 00:19:41.100
So, here are a bunch of ideas of things that are low danger, low stress.

00:19:41.100 --> 00:19:44.080
Probably a lot of people haven't taken advantage of them.

00:19:44.080 --> 00:19:48.140
I'll just go through a couple that Vincent works through.

00:19:48.140 --> 00:19:50.520
One of them is just providing better information.

00:19:50.520 --> 00:19:53.820
So, he contributed to this project called Rasa.

00:19:53.820 --> 00:19:55.700
And I don't know what Rasa does.

00:19:55.700 --> 00:19:56.700
I forgot to check out.

00:19:56.700 --> 00:19:58.380
So, it has a CLI.

00:19:58.380 --> 00:19:59.360
You say Rasa.

00:19:59.360 --> 00:20:01.500
You can say Rasa --version.

00:20:02.040 --> 00:20:04.840
And what it would say would be like 1.2.7.

00:20:04.840 --> 00:20:06.160
Okay.

00:20:06.160 --> 00:20:07.480
That seems totally legit.

00:20:07.480 --> 00:20:09.160
Like, that feature is implemented, right?

00:20:09.160 --> 00:20:22.380
But then, and by the way, if you look at this article, if you open up the actual article, Brian, you'll see like each one of these has like a beautiful like XKCD style picture talking about the story.

00:20:22.380 --> 00:20:26.880
So, for like the info one, it says to debug this, like somebody says, hey, Rasa's not working.

00:20:26.880 --> 00:20:27.260
Like, all right.

00:20:27.260 --> 00:20:33.900
Well, in order for me to debug this, you got to give me your Python version, your operating system, all the versions of the packages that you have.

00:20:33.900 --> 00:20:36.820
Like, are you running out of a virtual environment, et cetera, et cetera.

00:20:37.220 --> 00:20:48.220
So, what he did was said, all right, when you say --version, now you're going to get the version of Python, the path to your virtual environment, the version of related packages that Rasa depends upon, things like that.

00:20:48.220 --> 00:20:48.620
Nice.

00:20:48.620 --> 00:20:49.440
That's easy to do.

00:20:49.440 --> 00:20:54.240
That's not a challenging, you know, too difficult sort of implementation there.

00:20:54.240 --> 00:21:04.500
The next one is to set up a cron job to run tests checking the dependencies haven't affected a package.

00:21:05.220 --> 00:21:08.860
So, I know you know about continuous integration, right?

00:21:08.860 --> 00:21:13.600
Check in, changes come, going to rerun your unit tests.

00:21:13.600 --> 00:21:14.400
That's great, right?

00:21:14.400 --> 00:21:21.240
But what happens if an underlying package has an underlying dependency?

00:21:21.240 --> 00:21:25.360
So, the dependency of the dependency, is that a grand dependency?

00:21:25.360 --> 00:21:25.920
I don't know.

00:21:25.920 --> 00:21:31.880
Underlying dependency has a change that potentially makes something operate differently.

00:21:32.380 --> 00:21:36.540
What is going to trigger your CI if you don't make any changes to your code there?

00:21:36.540 --> 00:21:36.940
Yeah.

00:21:36.940 --> 00:21:37.400
Right?

00:21:38.160 --> 00:21:40.820
So, he actually ran into this.

00:21:40.820 --> 00:21:44.700
scikit-lego is a package that Vincent works on.

00:21:44.700 --> 00:21:51.800
And he discovered that it wasn't working for some reason because scikit-learn introduced a minor but breaking change.

00:21:51.800 --> 00:22:06.860
So, what he set up was a cron job with GitHub Actions to just run that once a day to say, hey, just in case something which we don't know about directly affects our repo, we still want to run those tests again just to make sure, like, yeah, things are still good.

00:22:06.860 --> 00:22:07.260
Yeah.

00:22:07.260 --> 00:22:08.020
What do you think about that?

00:22:08.020 --> 00:22:08.200
That's good.

00:22:08.200 --> 00:22:15.420
And I also wonder if the breaking change was that they changed what the version output produced.

00:22:15.420 --> 00:22:18.120
Yeah, I did think about that, actually.

00:22:18.120 --> 00:22:24.120
If somewhere in there, there's, like, a test, you know, someone has something that's just test that, calling that on the command line.

00:22:24.120 --> 00:22:25.340
All right.

00:22:25.340 --> 00:22:25.980
Spell check.

00:22:25.980 --> 00:22:27.380
Spell check is easy.

00:22:27.380 --> 00:22:27.840
Oh, yeah.

00:22:27.840 --> 00:22:29.860
There's always spelling errors in code.

00:22:30.660 --> 00:22:31.360
Always, yeah.

00:22:31.360 --> 00:22:34.180
Because a lot of times the symbols we use are not proper words.

00:22:34.180 --> 00:22:43.440
But I do really appreciate things like PyCharm that will find misspellings inside of various things.

00:22:43.440 --> 00:22:44.140
Right?

00:22:44.200 --> 00:22:49.820
Like, if you've got a function, check login and I and inner switch, it'll say login is misspelled.

00:22:49.820 --> 00:22:51.420
But, you know, it's still.

00:22:51.420 --> 00:22:52.540
Or grammar checks.

00:22:52.540 --> 00:22:57.020
Grammar checking people's doc strings or comments in code and stuff like that.

00:22:57.020 --> 00:22:57.460
Exactly.

00:22:57.860 --> 00:23:06.940
So, there's a nice example in there about looking for a country, I think, where it was Spain, but Spain was misspelled, you know, as a doc string example.

00:23:06.940 --> 00:23:09.240
So, that's definitely something easy to do.

00:23:09.240 --> 00:23:11.000
Just run a spell checker on the doc string.

00:23:11.000 --> 00:23:15.240
One that I'm a real big proponent of is having better error messages.

00:23:15.240 --> 00:23:15.860
Oh, yeah.

00:23:15.860 --> 00:23:18.220
So, it's so frustrating.

00:23:18.220 --> 00:23:19.300
Like, just today.

00:23:19.300 --> 00:23:20.540
Yesterday?

00:23:20.540 --> 00:23:21.320
I don't know.

00:23:21.320 --> 00:23:21.820
I was asleep.

00:23:21.820 --> 00:23:23.680
I was not sure exactly when I got this.

00:23:23.680 --> 00:23:28.420
But I got a message from a student taking the Excel course.

00:23:28.420 --> 00:23:31.140
It says, hey, I tried to run cookie cutter.

00:23:31.140 --> 00:23:36.400
Because during the Excel course, we talk about setting up, like, a cookie cutter template that gets everyone started.

00:23:36.400 --> 00:23:39.640
It says, I tried to run cookie cutter and it didn't work.

00:23:39.640 --> 00:23:41.100
Here's the message.

00:23:41.100 --> 00:23:46.460
And it just says something about the Git clone that cookie cutter internally tries to use failed.

00:23:46.460 --> 00:23:50.280
And it doesn't say anything about, you know, is Git not installed?

00:23:50.280 --> 00:23:52.680
Did Git, what was the error from Git?

00:23:52.860 --> 00:23:53.940
Like, it just, nope.

00:23:53.940 --> 00:23:56.060
It failed, right?

00:23:56.060 --> 00:23:58.100
You know, just like a random, like, this command failed.

00:23:58.100 --> 00:23:58.480
Like, great.

00:23:58.480 --> 00:24:05.200
So, if there was a better error message, like, we tried to do that, but you don't have permission to write where you tried to clone this thing to.

00:24:05.200 --> 00:24:06.620
Or Git is not installed.

00:24:06.620 --> 00:24:07.740
Or something like that.

00:24:07.740 --> 00:24:09.400
They could have gone, oh, I need to install Git.

00:24:09.400 --> 00:24:10.080
Right?

00:24:10.080 --> 00:24:11.700
They would have been much better off.

00:24:11.700 --> 00:24:12.700
So, error messages.

00:24:12.700 --> 00:24:16.820
So, they work on, Vincent works on something called Whatley's.

00:24:16.820 --> 00:24:19.680
And it allows for optional dependencies.

00:24:19.680 --> 00:24:25.760
Like, it has some of its functionality, but you might have to pip install Whatley's bracket something else.

00:24:25.760 --> 00:24:26.840
Like, here's tfhub.

00:24:26.840 --> 00:24:27.580
Right?

00:24:27.740 --> 00:24:33.980
And in order to use a certain part of that that depends on that optional dependency, you have to have that installed.

00:24:33.980 --> 00:24:35.640
But you don't have to install it to use the library.

00:24:35.640 --> 00:24:35.860
Right?

00:24:35.860 --> 00:24:39.180
So, you could run into this problem where you try to use a feature that doesn't have a dependency.

00:24:39.180 --> 00:24:39.640
Yeah.

00:24:39.640 --> 00:24:44.640
So, instead of just going, none object has no attribute whatever, right?

00:24:44.640 --> 00:24:45.880
Or whatever's going to happen there.

00:24:45.880 --> 00:24:48.380
Or no library such and such.

00:24:48.380 --> 00:24:57.700
It's a, now the error is, in order to use convert, convert language, you'll need to install, pip install Whatley's bracket tfhub.

00:24:57.700 --> 00:24:59.500
See installation guide here.

00:24:59.500 --> 00:25:00.320
And there's the URL.

00:25:00.320 --> 00:25:01.680
Like, that is a proper error message.

00:25:01.680 --> 00:25:02.040
Yeah, that's great.

00:25:02.040 --> 00:25:04.120
Telling people how to fix the error.

00:25:04.420 --> 00:25:04.820
Yeah.

00:25:04.820 --> 00:25:08.580
And, you know, it's just, it's not that much work, but just finding these problems.

00:25:08.580 --> 00:25:10.720
Like, how many times does it appear on Stack Overflow?

00:25:10.720 --> 00:25:14.700
Rather than just, like, let him go find it on Stack Overflow and give the message.

00:25:14.700 --> 00:25:17.220
So, I recently added something like this to FluentCheck.

00:25:17.220 --> 00:25:23.920
Remember when we talked, I think you brought this up, talked about using raise from on an exception.

00:25:23.920 --> 00:25:31.560
So, you could say raise an exception, but if you do that in a catch block, you get weird other issues, right?

00:25:31.560 --> 00:25:38.720
So, by default, it would say something like, during the handling of the above exception, another exception occurred.

00:25:38.720 --> 00:25:40.920
And that sounds like one thing broke another.

00:25:40.920 --> 00:25:47.020
But, like, in this library, it's supposed to find errors and then report them to you.

00:25:47.020 --> 00:25:53.740
So, if you use raise from, it'll say the above exception was a direct cause of the following exception.

00:25:53.740 --> 00:25:57.960
Which makes it sound like, okay, this is the source of the error, right?

00:25:57.960 --> 00:26:00.660
So, just simple changes like that are really nice.

00:26:00.660 --> 00:26:01.560
Get better error messages.

00:26:01.560 --> 00:26:03.040
Failing unit tests.

00:26:03.040 --> 00:26:07.280
And I'm not talking about going around and finding projects that have failing unit tests.

00:26:07.280 --> 00:26:15.040
But rather, if you want to make a contribution, or rather you find a bug, rather than just submitting a bug on a GitHub issue tracker saying,

00:26:15.040 --> 00:26:19.500
this doesn't work, I tried it, and then having a long conversation about it,

00:26:19.500 --> 00:26:25.220
submit along with it a failing, create a PR that has a failing unit test for that issue.

00:26:25.220 --> 00:26:25.920
Oh, that's awesome.

00:26:26.120 --> 00:26:26.960
Yeah, right?

00:26:26.960 --> 00:26:29.180
Just go, look, it's supposed to do this.

00:26:29.180 --> 00:26:29.680
This fails.

00:26:29.680 --> 00:26:31.640
If you make this pass, I'm happy, right?

00:26:31.640 --> 00:26:34.340
And then they can fold that into the unit test suite and so on.

00:26:34.340 --> 00:26:42.940
And then also, finally, there are some packages that might have names that result in import statements that are very confusing.

00:26:42.940 --> 00:26:48.000
So, for example, if you've got a package, and in the package there's a file.py, lowercase f,

00:26:48.080 --> 00:26:52.820
and within file.py, there's a capital file class.

00:26:52.820 --> 00:26:54.000
Those would be totally reasonable.

00:26:54.000 --> 00:26:55.700
What you can call the files, file.py.

00:26:55.700 --> 00:26:56.780
Create a class in it.

00:26:56.780 --> 00:27:06.600
Depending on how the package is set up, you could end up with something like from package import lowercase file and from package import uppercase file would both work,

00:27:06.600 --> 00:27:08.180
but obviously don't mean the same thing.

00:27:08.680 --> 00:27:14.780
So, in that case, they recommend renaming certain files that are really meant to be used internally as an option.

00:27:14.780 --> 00:27:15.360
Yeah.

00:27:15.360 --> 00:27:18.640
Like in the example, I don't even get what's different.

00:27:19.200 --> 00:27:21.300
I know, I just stared at it for a while as well.

00:27:21.300 --> 00:27:22.180
Okay.

00:27:22.180 --> 00:27:23.580
That's it for all those recommendations.

00:27:23.580 --> 00:27:25.320
But I think there's definitely some good ones in there.

00:27:25.320 --> 00:27:26.800
I like the error messages a lot.

00:27:26.800 --> 00:27:29.320
I like the failing unit tests as well.

00:27:29.320 --> 00:27:30.840
Those are my two faves.

00:27:30.840 --> 00:27:31.220
Yeah.

00:27:31.220 --> 00:27:33.320
I was just even thinking about all this stuff.

00:27:33.320 --> 00:27:35.300
Did it talk about documentation?

00:27:35.300 --> 00:27:36.900
Not about creating documentation.

00:27:36.900 --> 00:27:39.820
Just about the spell checking within documentation.

00:27:39.820 --> 00:27:40.420
Okay.

00:27:40.420 --> 00:27:41.680
Well, I would probably...

00:27:41.680 --> 00:27:43.160
Well, I guess that's doc strings.

00:27:43.160 --> 00:27:44.000
It's pretty limited.

00:27:44.000 --> 00:27:48.240
I'd add documentation to this because projects always are lacking.

00:27:48.580 --> 00:27:49.540
Or sometimes behind.

00:27:49.540 --> 00:27:51.880
So, the documentation might be great.

00:27:51.880 --> 00:27:54.120
Somebody was really gung-ho about it for a while.

00:27:54.120 --> 00:27:55.760
And then there's been improvements.

00:27:55.760 --> 00:28:00.500
But the new features just haven't made it into the documentation all over the place yet.

00:28:00.500 --> 00:28:00.720
Yeah.

00:28:00.720 --> 00:28:01.600
Or tutorials.

00:28:01.600 --> 00:28:04.980
There's no good tutorials showing this part of code.

00:28:04.980 --> 00:28:06.600
There's maybe a quick start.

00:28:06.600 --> 00:28:09.020
But then the advanced hard stuff, there's no examples.

00:28:09.020 --> 00:28:09.840
Yeah.

00:28:09.840 --> 00:28:10.520
Yeah, definitely.

00:28:10.520 --> 00:28:12.220
These are good.

00:28:12.220 --> 00:28:12.360
Cool.

00:28:12.360 --> 00:28:14.340
What extra you got for us?

00:28:14.340 --> 00:28:15.840
Well, I just learned about this morning.

00:28:15.840 --> 00:28:20.500
So, I was going to just not give a whole big thing, but just let people know.

00:28:20.500 --> 00:28:22.180
I saw somebody on Twitter.

00:28:22.180 --> 00:28:26.400
Of course, I'm obviously being really bad about referencing people.

00:28:26.400 --> 00:28:26.980
But sorry.

00:28:26.980 --> 00:28:28.020
A new thing.

00:28:28.020 --> 00:28:28.820
There's a...

00:28:28.820 --> 00:28:34.940
As of September, early in September, there was a collaboration between the people who do

00:28:34.940 --> 00:28:38.880
Wonder Woman and the Smithsonian Learning Lab and NASA and Microsoft.

00:28:39.780 --> 00:28:40.520
Nice.

00:28:40.520 --> 00:28:45.820
So, we're linking to an article that's Learn to Code with Wonder Woman, Smithsonian, and NASA.

00:28:45.820 --> 00:28:48.080
And so, there's a whole bunch of...

00:28:48.080 --> 00:28:49.380
The idea is that there's...

00:28:49.380 --> 00:28:53.180
One, there's a lot of schools that don't offer computer science education.

00:28:53.180 --> 00:28:57.080
And also, with COVID and everything, some people have kind of...

00:28:57.080 --> 00:28:59.200
That's kind of dropped off a little bit.

00:28:59.620 --> 00:29:03.460
And people are focusing on core classes, which is probably fair.

00:29:03.460 --> 00:29:09.220
But if you still want to have your kid learn programming, this might be a way to do it.

00:29:09.220 --> 00:29:10.720
And this is pretty cool.

00:29:10.720 --> 00:29:12.580
And it looks pretty neat.

00:29:12.580 --> 00:29:18.480
There's some Wonder Woman adventure stuff and NASA exploration.

00:29:18.480 --> 00:29:21.560
And there's even a little bit of Minecraft in there.

00:29:22.020 --> 00:29:23.120
It looks really fun.

00:29:23.120 --> 00:29:25.500
And at least some of the tutorials are in Python.

00:29:25.500 --> 00:29:28.680
I haven't checked out to see if all of them are Python or not.

00:29:28.680 --> 00:29:30.280
But there's a lot of Python in there.

00:29:30.280 --> 00:29:31.360
Some of them use Blocky.

00:29:31.360 --> 00:29:36.440
But some of them, like the Super Quiz from Wonder Woman uses Python.

00:29:36.440 --> 00:29:43.200
And then some of the NASA ones, which Cecil actually called out the NASA Microsoft partner ones last time.

00:29:43.200 --> 00:29:45.400
But not the Wonder Woman ones.

00:29:45.400 --> 00:29:45.960
So, yeah.

00:29:45.960 --> 00:29:46.420
It's a mix.

00:29:46.420 --> 00:29:47.000
But very cool.

00:29:47.000 --> 00:29:47.460
It's neat.

00:29:47.760 --> 00:29:50.620
Plus, I can't wait to see 1984.

00:29:50.620 --> 00:29:52.340
I'm looking forward to it.

00:29:52.340 --> 00:29:54.000
Yeah, definitely.

00:29:54.000 --> 00:29:55.060
All right.

00:29:55.060 --> 00:29:56.180
I have a quick thing as well.

00:29:56.180 --> 00:29:59.100
I'm going to be doing a presentation at IndiePy.

00:29:59.100 --> 00:30:00.980
So, virtual online, obviously.

00:30:00.980 --> 00:30:02.420
When is this?

00:30:02.420 --> 00:30:06.120
This is coming up on October 13th.

00:30:06.120 --> 00:30:10.540
So, there I'm going to be doing a Python memory deep dive.

00:30:10.540 --> 00:30:17.260
Both understanding some of the internals of Python memory as well as some optimizations that you can make to go faster and use less memory.

00:30:17.820 --> 00:30:20.120
So, you all can sign up for that and check it out if you like.

00:30:20.120 --> 00:30:20.260
Cool.

00:30:20.260 --> 00:30:20.960
A memory talk.

00:30:20.960 --> 00:30:21.820
And you forgot the date.

00:30:21.820 --> 00:30:22.400
That's funny.

00:30:22.400 --> 00:30:23.640
Yeah.

00:30:23.640 --> 00:30:24.120
I know.

00:30:24.120 --> 00:30:27.220
Maybe we should just have another joke.

00:30:27.220 --> 00:30:27.660
Yeah, let's do another joke.

00:30:27.660 --> 00:30:28.180
Finish it off.

00:30:28.180 --> 00:30:32.940
You know, I think we actually may have covered this a long time ago when it came out, but I'm not sure.

00:30:32.940 --> 00:30:34.480
I don't remember covering it.

00:30:34.480 --> 00:30:39.560
So, suggested by Tim Jacobson, Kelsey Hightower's project no code.

00:30:39.560 --> 00:30:43.940
This is a hilarious repo, but you kind of have to go look at it.

00:30:43.940 --> 00:30:48.620
So, the tagline is, no code is the best way to write secure and reliable applications.

00:30:48.620 --> 00:30:50.240
Write nothing, deploy nowhere.

00:30:51.240 --> 00:30:54.920
And you highlighted that the style guide was good, so I went and looked at that.

00:30:54.920 --> 00:30:56.980
It says, no code style guide.

00:30:56.980 --> 00:31:00.060
All no code programs are the same, regardless of use case.

00:31:00.060 --> 00:31:02.060
Any code you write is a liability.

00:31:02.060 --> 00:31:03.440
Yeah.

00:31:03.440 --> 00:31:05.140
This is beautiful.

00:31:05.140 --> 00:31:07.780
The style guide talks about file extensions.

00:31:07.800 --> 00:31:14.940
It says, no code is not stored in files, but if you must, use the .no file extension.

00:31:14.940 --> 00:31:17.000
Like, example, main.no.

00:31:17.000 --> 00:31:21.800
There are linters built right into your POSIX-based system, your Linux systems.

00:31:21.800 --> 00:31:32.000
So, for example, you can check by saying du-h space main.no, and if it outputs zero, then you have no code.

00:31:32.000 --> 00:31:33.500
What is du?

00:31:33.500 --> 00:31:34.140
Do you know?

00:31:34.140 --> 00:31:35.220
It's like a line count.

00:31:35.220 --> 00:31:36.960
Count the number of lines of text in this file.

00:31:36.960 --> 00:31:40.660
And then they have code reviews.

00:31:40.660 --> 00:31:45.680
The no code community has adopted the following conventions for reviewing code changes.

00:31:45.680 --> 00:31:51.560
When the code changes contains no code additions or modifications, LGTM looks good to me.

00:31:51.560 --> 00:31:58.220
When the code changes include code additions or modifications, C-I-A-L, code is a liability.

00:31:58.220 --> 00:32:02.300
That code change should be rejected immediately.

00:32:02.300 --> 00:32:10.440
And then the final kicker for me on this one is that there's 43,000 stars, 4,000 forks of it, which are funny.

00:32:10.440 --> 00:32:19.020
But the thing that made me laugh is there's 368 people watching for changes in the no code repository where there's supposed to be no changes.

00:32:22.080 --> 00:32:22.840
That's funny.

00:32:22.840 --> 00:32:22.860
That's funny.

00:32:22.860 --> 00:32:23.840
And there's 3.

00:32:23.840 --> 00:32:24.360
Yeah.

00:32:24.360 --> 00:32:26.000
Oh, it adds Docker support as well.

00:32:26.000 --> 00:32:28.300
There's 3.2,000 issues filed against it.

00:32:28.300 --> 00:32:28.920
Oh, my God.

00:32:28.920 --> 00:32:29.300
There are.

00:32:29.300 --> 00:32:30.320
What are they here for?

00:32:30.320 --> 00:32:33.100
Oh, yeah.

00:32:33.100 --> 00:32:39.320
Suspended Arctic code vault contributional reconstruction aviator chain generator keys.

00:32:39.320 --> 00:32:39.720
All right.

00:32:39.720 --> 00:32:41.780
No water in the water cooler is one of the issues.

00:32:42.780 --> 00:32:46.400
And then the contributing at the end of the readme says contributing.

00:32:46.400 --> 00:32:47.680
You don't.

00:32:47.680 --> 00:32:49.880
Sweet.

00:32:49.880 --> 00:32:50.980
All right.

00:32:50.980 --> 00:32:53.760
Well, that's a good one, Tim and Kelsey.

00:32:53.760 --> 00:32:55.400
Nice job on that project.

00:32:55.400 --> 00:32:58.280
Well, thanks a lot again for a lovely podcast.

00:32:58.280 --> 00:33:00.700
Thank you for listening to Python Bytes.

00:33:00.700 --> 00:33:03.160
Follow the show on Twitter at Python Bytes.

00:33:03.160 --> 00:33:06.200
That's Python Bytes as in B-Y-T-E-S.

00:33:06.200 --> 00:33:09.100
And get the full show notes at pythonbytes.fm.

00:33:09.320 --> 00:33:14.160
If you have a news item you want featured, just visit pythonbytes.fm and send it our way.

00:33:14.160 --> 00:33:16.200
We're always on the lookout for sharing something cool.

00:33:16.200 --> 00:33:17.380
This is Brian Okken.

00:33:17.380 --> 00:33:21.460
And on behalf of myself and Michael Kennedy, thank you for listening and sharing this podcast

00:33:21.460 --> 00:33:22.620
with your friends and colleagues.

00:33:22.620 --> 00:33:23.620
Thanks.

