WEBVTT

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

00:00:05.120 --> 00:00:10.540
This is episode 285, recorded May 24th, and I'm Brian Okken.

00:00:10.540 --> 00:00:11.660
I'm Michael Kennedy.

00:00:11.660 --> 00:00:12.780
And I'm Mark Little.

00:00:12.780 --> 00:00:13.880
I'm Ben Cosby.

00:00:13.880 --> 00:00:16.000
Nice. Welcome, Ben. Welcome, Mark.

00:00:16.000 --> 00:00:20.160
So, Michael, you have this story of why you brought Mark and Ben on.

00:00:20.160 --> 00:00:22.120
Yeah, I did bring Mark and Ben on.

00:00:22.120 --> 00:00:25.660
Mark and I have been really good friends for a long time, but that's not why he's here.

00:00:25.740 --> 00:00:30.780
He's here because he's been sharing this Python journey that he and Ben have both been on.

00:00:30.780 --> 00:00:38.060
They come from law, like being lawyers and bankers and stuff, and they've found their way over to writing software in Python.

00:00:38.060 --> 00:00:40.060
And it's been so fun to watch you guys come along.

00:00:40.060 --> 00:00:46.520
And you recently showed me the release of one of your SaaS products built with Python and Pyramid and other things.

00:00:46.520 --> 00:00:47.840
And I thought it was just super cool.

00:00:47.840 --> 00:00:56.060
So, I thought you could maybe share just a little bit of that before we kick off the main topics to kind of inspire people who are not, you know, traditional CS folks.

00:00:56.060 --> 00:00:57.960
And they can still build amazing things.

00:00:57.960 --> 00:01:01.540
You want to tell us a bit about yourself and then tell us a bit about your thing?

00:01:01.540 --> 00:01:04.660
I'll say first that I'm strictly the hobbyist.

00:01:04.660 --> 00:01:10.200
So, it's definitely been a collaboration and quite a journey.

00:01:10.200 --> 00:01:14.520
And Ben, I'll talk a little bit about how we got started because you play an instrumental role in that, Michael.

00:01:14.520 --> 00:01:20.300
So, we've released this product called LexChart that builds corporate organizational structures automatically.

00:01:20.300 --> 00:01:22.680
And these charts are kind of weird.

00:01:22.680 --> 00:01:30.200
They're sort of like, you know, human resources organizational charts, except that for legal entities, they're much more complicated.

00:01:30.200 --> 00:01:39.140
And so, we've built some automation in Python principally in the server side that generates these hierarchies automatically.

00:01:39.140 --> 00:01:40.780
And they can be quite elaborate.

00:01:40.780 --> 00:01:47.720
So, for example, some of them we release publicly and we've been building these things with our own app and releasing them.

00:01:47.720 --> 00:01:50.020
So, here's one for Elon Musk, for example.

00:01:50.020 --> 00:01:54.060
This is before the early stages of his Twitter acquisition.

00:01:54.060 --> 00:01:57.780
But our app does a lot of this layering automatically.

00:01:57.780 --> 00:02:02.860
And those things can be quite stunningly complicated.

00:02:03.060 --> 00:02:09.120
So, here's one, for example, with, you know, thousands of legal entities in the corporate structure of Blackstone.

00:02:09.120 --> 00:02:15.580
And so, we've actually got some Python that sort of automates the presentation and structure of all that.

00:02:15.580 --> 00:02:20.500
And then, as you say, it's using Pyramid and Chameleon and SQLAlchemy.

00:02:21.340 --> 00:02:26.260
And then, a lot of, you know, legal and business finance expertise as well.

00:02:26.260 --> 00:02:28.280
But it's been quite an exciting journey.

00:02:28.280 --> 00:02:38.380
And so, you know, we were excited to share this with you and look forward to sort of talking about some of the piece parts that are in the product that might be useful to the broader community as well.

00:02:38.380 --> 00:02:39.200
Yeah, yeah, exactly.

00:02:39.200 --> 00:02:44.380
Some of the stuff you guys are going to cover today as our main topics sort of were extracted out of the building of this, right?

00:02:44.380 --> 00:02:44.920
Yeah.

00:02:45.140 --> 00:02:48.160
Ben, anything you want to add to that and maybe just tell people about yourself real quick?

00:02:48.160 --> 00:02:56.080
As you pointed out, and Mark, too, you know, whenever I'm trying to explain to somebody what I do now, I always say, well, I'm a reformed barbarian at the gate.

00:02:56.080 --> 00:03:05.380
I created buyouts and IPOs in a suit on Wall Street or, you know, code in my office at home and in my pajamas kind of thing.

00:03:05.860 --> 00:03:10.180
And, but we've, as Mark talked about, we've kind of merged those couple of things together.

00:03:10.180 --> 00:03:20.080
And so, these days, I spend a lot of my time with Python on the front end and JavaScript, sorry, JavaScript on the front end and Python on the back end and DevOps and all sorts of things, you know, sort of have to do it all.

00:03:20.080 --> 00:03:27.300
But I also wanted to say kind of as part of our journey for your listeners, I'd be remiss if I didn't even know I didn't warn you beforehand I was going to do this.

00:03:27.300 --> 00:03:48.320
But, you know, along this way of kind of, you know, going from, you know, suits and deals and IPOs and things like that, you know, Michael's Talk Python Training for, I'm sure lots of people on this podcast are familiar, but if you're not, you know, those courses were pretty instrumental for us and for those we've worked with in, you know, evolving and making Python.

00:03:48.320 --> 00:03:52.980
Python now is completely central to our business and what we do.

00:03:52.980 --> 00:03:54.860
So, it's been fun to get here.

00:03:54.860 --> 00:03:56.720
Thanks for the shout out, Ben.

00:03:56.720 --> 00:03:57.460
I appreciate it.

00:03:57.460 --> 00:04:05.720
I would just say, too, we've been able to leverage that and, like, we've got some pretty complex math and graph theory, like, in the core of our app.

00:04:05.720 --> 00:04:18.880
So, we've been able to, like, take, you know, Michael's classes and really sort of leverage them in a much bigger way than I think a lot of people expect or imagine they can when they start some of these online classes.

00:04:18.880 --> 00:04:21.560
So, you know, your training in particular has been exceptional.

00:04:21.560 --> 00:04:22.720
Thanks, Mark.

00:04:22.720 --> 00:04:28.940
I just think what you guys have built looks so much more polished than a couple of guys who taught themselves programming a few years ago.

00:04:28.940 --> 00:04:30.000
And I just, I love it.

00:04:30.000 --> 00:04:31.580
So, super good work.

00:04:31.720 --> 00:04:33.080
Brian, should we kick it off?

00:04:33.080 --> 00:04:34.760
This is just great.

00:04:34.760 --> 00:04:36.560
I'm blown away.

00:04:36.560 --> 00:04:37.440
It looks awesome.

00:04:37.440 --> 00:04:39.040
So, yeah, let's kick it off.

00:04:39.040 --> 00:04:40.360
Yeah, I was, too.

00:04:40.360 --> 00:04:45.140
And I think some of the stuff that we're going to talk about is going to certainly be part of that.

00:04:45.460 --> 00:04:46.120
So, let's talk.

00:04:46.120 --> 00:04:47.240
Oh, whoop.

00:04:47.240 --> 00:04:47.380
Yeah.

00:04:47.380 --> 00:04:47.660
Nope.

00:04:47.660 --> 00:04:48.300
Wrong one.

00:04:48.300 --> 00:04:49.900
I'm up next, right, Brian?

00:04:49.900 --> 00:04:50.540
Yeah.

00:04:50.540 --> 00:04:51.020
Sorry.

00:04:51.020 --> 00:04:51.700
All right.

00:04:51.700 --> 00:04:54.420
I have a whole bunch of extras, folks.

00:04:54.420 --> 00:04:59.140
So, let me just, I'm going to start with, like, a quick one for one of our main topics here that maybe.

00:04:59.140 --> 00:05:00.840
We may have to cut you off.

00:05:00.840 --> 00:05:01.820
I know.

00:05:01.820 --> 00:05:03.000
You might have to cut me off.

00:05:03.000 --> 00:05:04.300
So, check this out, Brian.

00:05:04.300 --> 00:05:09.160
If I go over to PyPI.org and I go look for something like, let me look at Beanie.

00:05:09.160 --> 00:05:10.520
I don't know if I get that right.

00:05:10.520 --> 00:05:12.160
Actually, I don't think that's going to help me right.

00:05:12.160 --> 00:05:15.880
Let me look for SwitchLang, which is my Switch implementation.

00:05:15.880 --> 00:05:18.220
I added to Python, I don't know, a couple years ago.

00:05:18.220 --> 00:05:21.260
So, if you look over here on the left, oh, I think it's being blocked.

00:05:21.260 --> 00:05:27.920
But over here, it says, here's your avatar from Gravatar for M. Kennedy.

00:05:27.920 --> 00:05:31.400
But my little, I don't know, my browser settings are blocking that or whatever.

00:05:31.600 --> 00:05:34.620
But, so, this is a thing you see a lot of the times.

00:05:34.620 --> 00:05:37.860
And, like, where do you get these little Gravatar, right?

00:05:37.860 --> 00:05:41.740
So, if you have users and you have users who have emails, you want to show something about them,

00:05:41.740 --> 00:05:49.540
there's a chance that over in Gravatar, there's going to be some profile for them,

00:05:49.540 --> 00:05:51.680
different images, things like that.

00:05:51.680 --> 00:05:56.740
So, if you're in Python and you want to add Gravatar features to your site,

00:05:56.740 --> 00:05:59.740
it is ridiculous using this thing called LibGravatar.

00:05:59.740 --> 00:06:00.600
Oh, wow.

00:06:00.700 --> 00:06:06.760
So, all you got to do with LibGravatar is you go and you create an instance of one of these objects, Gravitars.

00:06:06.760 --> 00:06:07.840
You pass it an email.

00:06:07.840 --> 00:06:09.160
And you can say, get image.

00:06:09.160 --> 00:06:15.000
You give it a size and potentially a file extension if you want to control that or anything

00:06:15.000 --> 00:06:16.560
or whether or not you want to use SSL.

00:06:16.560 --> 00:06:24.740
And then it gives you back this non-reversible URL that is the image of that person based on the size that you asked for,

00:06:24.740 --> 00:06:25.980
who they are, and so on.

00:06:25.980 --> 00:06:30.780
And if they don't exist, you get the standard Gravatar logo, just like a little circle type thing.

00:06:30.780 --> 00:06:36.660
And so, this is some kind of hash algorithm that you have to follow based on their email address to pull them back and so on.

00:06:36.700 --> 00:06:44.340
But if you want to add that kind of Gravatar look and feel, then like literally, Gravatar object, give it the email address, dot get image.

00:06:44.340 --> 00:06:45.300
And that's pretty neat.

00:06:45.300 --> 00:06:49.000
It goes from 1 to 248 pixels on the image size.

00:06:49.100 --> 00:06:50.680
So, I'm not sure one's super useful.

00:06:50.680 --> 00:06:52.600
Like, you get one dot.

00:06:52.600 --> 00:06:58.540
But, you know, maybe you want it to be kind of like a particular, like a shade of the person is all you're going to get, I guess.

00:06:58.540 --> 00:07:02.780
Like a 5x5 would be fun, you know, just a few pixels.

00:07:02.780 --> 00:07:03.580
It would.

00:07:03.580 --> 00:07:08.420
So, you can do a get profile, which will then give you access to the user and see all of their email addresses,

00:07:08.420 --> 00:07:10.780
all of their information about them, and so on.

00:07:10.780 --> 00:07:12.020
So, there's a little bit more that you can actually.

00:07:12.020 --> 00:07:12.780
Social security.

00:07:12.780 --> 00:07:13.480
Oh, yeah, yeah.

00:07:13.480 --> 00:07:17.880
There's this whole shadow profile that's built up by, like, you know, the surveillance ad tech industry.

00:07:18.240 --> 00:07:19.240
It's only 5 bucks a use.

00:07:19.240 --> 00:07:19.760
No, just kidding.

00:07:19.760 --> 00:07:23.560
But you can get, like, more details about them through their profile if you really want.

00:07:23.560 --> 00:07:29.040
But basically, the main use case is, given an email, can I get a picture without hassling this person to upload a picture?

00:07:29.040 --> 00:07:29.680
Maybe.

00:07:29.680 --> 00:07:35.200
And just so, if anybody's not familiar with Gravatar, it's owned by Automatic, who does WordPress.

00:07:35.200 --> 00:07:37.680
So, all the WordPress people use it.

00:07:37.680 --> 00:07:41.840
And that's why it's, like, well-supported and it's not too evil or anything like that.

00:07:41.840 --> 00:07:42.380
Yeah.

00:07:42.380 --> 00:07:44.400
And like I said, PyPI.org uses it.

00:07:44.400 --> 00:07:45.520
So, that's the start.

00:07:45.520 --> 00:07:46.780
Mark, Ben, what do you guys think?

00:07:46.900 --> 00:07:49.120
Do you have user pictures in your app?

00:07:49.120 --> 00:07:50.100
Are you worried about this kind of stuff?

00:07:50.100 --> 00:07:51.120
We don't.

00:07:51.120 --> 00:07:52.860
We don't in Let's Chart.

00:07:52.860 --> 00:08:03.540
But it's funny because at the very beginning of our journey, we implemented a little question-answer app as, like, a demo to make sure that, you know, we could, like, justify going down to Python.

00:08:03.540 --> 00:08:05.440
And I used Gravatar in there.

00:08:05.440 --> 00:08:07.700
This actually is a pretty cool library.

00:08:07.700 --> 00:08:10.300
Because I remember in that app, I really was just focused on Python.

00:08:10.300 --> 00:08:15.820
But I had to, you know, fall back on some JavaScript in order to put the Gravatar icons in there.

00:08:15.820 --> 00:08:16.560
But it is great.

00:08:16.560 --> 00:08:18.140
Gravatar is really useful.

00:08:18.140 --> 00:08:21.020
I'd encourage your listeners if you're looking for something.

00:08:21.020 --> 00:08:25.860
Because the nice thing, as you said, is it'll just generate, like, this automatic little drawing, even if they don't have an image.

00:08:25.860 --> 00:08:33.220
So you can kind of create a nice look and feel for your site, for your user profiles, where everybody gets some sort of a graphic, even if they haven't uploaded anything.

00:08:33.220 --> 00:08:35.240
It's kind of a nice little tool.

00:08:35.640 --> 00:08:36.320
Yeah, absolutely.

00:08:36.320 --> 00:08:43.260
Kim Van Weck out in the audience says, when pixel Gravitars might be useful for building images, like displaying contributors and stuff.

00:08:43.260 --> 00:08:45.620
Maybe not one, but you could do, like, 10 by 10.

00:08:45.620 --> 00:08:49.320
And you could build up, you know, a montage of all the people or something that people.

00:08:49.320 --> 00:08:55.100
And you also, Ben, you also have some cheering folks in the audience, which is lovely.

00:08:55.100 --> 00:08:57.880
So go, Ben.

00:08:57.880 --> 00:08:59.020
Good to have you here.

00:08:59.020 --> 00:08:59.360
All right.

00:08:59.360 --> 00:09:01.400
Brian, over to you.

00:09:01.400 --> 00:09:03.400
I'm very excited about it.

00:09:03.400 --> 00:09:05.320
When I first saw this, I'm like, oh, you don't really need that.

00:09:05.980 --> 00:09:06.860
Pydantic does this on.

00:09:06.860 --> 00:09:08.380
Oh, wait, no, this is amazing.

00:09:08.380 --> 00:09:08.820
Tell me.

00:09:08.820 --> 00:09:09.080
Tell me.

00:09:09.080 --> 00:09:10.900
So this is so cool.

00:09:10.900 --> 00:09:14.280
It's a little thing that was suggested by Chun Li.

00:09:14.280 --> 00:09:16.940
It's a JSON to Pydantic converter.

00:09:16.940 --> 00:09:24.220
And Chun said, this awesome JSON to Pydantic is so useful.

00:09:24.220 --> 00:09:28.960
It literally saves me days of work with complex nested JSON schema.

00:09:29.400 --> 00:09:35.740
So the idea is you've got basically it's just this website with, like, you know, a JSON side and a Pydantic side.

00:09:35.740 --> 00:09:37.580
And I've got one prepared.

00:09:37.580 --> 00:09:39.600
I went and copied one from somewhere.

00:09:39.600 --> 00:09:45.500
And so if we go over and just replace the simple one with, like, a more complex one, paste it in there.

00:09:45.500 --> 00:09:48.960
And then it just generates the Pydantic model.

00:09:48.960 --> 00:09:51.180
And it's pretty awesome.

00:09:51.180 --> 00:09:52.960
There's a couple of options.

00:09:52.960 --> 00:09:56.860
So for people who are listening, it's not that it converts JSON to Pydantic.

00:09:56.860 --> 00:09:59.040
It converts JSON to Pydantic code.

00:09:59.700 --> 00:10:04.600
It writes the code that you would have to write for the Pydantic to understand what you put.

00:10:04.600 --> 00:10:05.460
It's amazing.

00:10:05.460 --> 00:10:06.100
I love it.

00:10:06.100 --> 00:10:06.640
Right.

00:10:06.640 --> 00:10:08.820
And then some of the options are cool.

00:10:08.820 --> 00:10:12.020
You might not use it for everything, but just knowing the syntax for it.

00:10:12.020 --> 00:10:19.240
So if you drop a give them optional, it'll tell you where to put optional in your model to make it all work right.

00:10:19.240 --> 00:10:21.940
And it's like this one's only just showing up at the bottom.

00:10:21.940 --> 00:10:22.920
So anyway.

00:10:23.500 --> 00:10:27.380
And then the last one is aliasing camel case.

00:10:27.380 --> 00:10:28.580
I didn't know you could do this.

00:10:28.580 --> 00:10:30.840
Aliasing camel case for snake case.

00:10:30.840 --> 00:10:35.900
So if you're using, I guess, both camel case and snake case, you can have them work.

00:10:35.900 --> 00:10:36.240
I don't know.

00:10:36.240 --> 00:10:43.860
A lot of times if you're consuming a JSON API that's written in another language, the variable names are idiomatic to that language.

00:10:43.860 --> 00:10:49.900
So like C# would be or JavaScript would represent this one where you've got like the camel casing.

00:10:49.900 --> 00:10:52.360
But that would not be how you would want to call it in Python.

00:10:52.360 --> 00:10:56.540
So you can say, well, give me the Python version, but allow Pythonic to find the other size.

00:10:56.540 --> 00:10:57.760
Okay, cool.

00:10:57.760 --> 00:10:58.140
Yeah.

00:10:58.140 --> 00:11:03.920
Then one of the neat things about this that I really love is it's an open source project.

00:11:03.920 --> 00:11:05.900
So at the bottom, there's a link.

00:11:05.900 --> 00:11:10.160
It takes you to the to the just the open source page.

00:11:10.160 --> 00:11:15.500
And this is built with FastAPI and create react app, which is pretty cool.

00:11:15.500 --> 00:11:17.840
And then a data model code generator.

00:11:17.840 --> 00:11:20.520
So it's like that's doing the most of the work.

00:11:20.520 --> 00:11:26.580
So if you want to do this yourself somewhere else by, you know, embed it within your tool

00:11:26.580 --> 00:11:28.300
chain or something like that, you can do this.

00:11:28.300 --> 00:11:31.820
So I don't know why you'd regenerate it all the time, though.

00:11:31.820 --> 00:11:38.440
But it's just super kind of fun to just drop drop some JSON, a JSON example of a good one

00:11:38.440 --> 00:11:39.480
in there and drop it in.

00:11:39.480 --> 00:11:40.540
It's fantastic.

00:11:40.540 --> 00:11:44.300
If you're going to consume an API and you say, here's a specification of what I'm going

00:11:44.300 --> 00:11:44.820
to get back.

00:11:44.820 --> 00:11:45.340
Boom.

00:11:45.340 --> 00:11:46.440
You're halfway there.

00:11:46.440 --> 00:11:47.580
Or you're a consultant.

00:11:47.580 --> 00:11:48.960
You pick up somebody else's code.

00:11:48.960 --> 00:11:50.540
And you're like, I want to use Pythonic here.

00:11:50.540 --> 00:11:51.000
This is great.

00:11:51.000 --> 00:11:53.420
Anthony on the audience is, oh, come on.

00:11:53.420 --> 00:11:54.620
I could use this last week.

00:11:54.620 --> 00:11:58.860
You guys, what do you think of this?

00:11:59.340 --> 00:12:00.140
That's really cool.

00:12:00.140 --> 00:12:04.860
We have a project where we're looking at migrating from a different tech stack to Python.

00:12:04.860 --> 00:12:07.500
And, you know, one of our output sources there is JSON.

00:12:07.500 --> 00:12:11.180
So I'm looking at this and, you know, wondering, you know, Ben, this might be an opportunity for

00:12:11.180 --> 00:12:15.600
us to, you know, get there a little quicker for some of that data.

00:12:15.600 --> 00:12:16.980
That is cool.

00:12:16.980 --> 00:12:21.400
Especially for prototyping or something where, you know, you just want to see and you want

00:12:21.400 --> 00:12:24.540
to spend three days seeing what it's going to look like.

00:12:24.540 --> 00:12:25.720
This is pretty cool.

00:12:26.180 --> 00:12:28.360
Yeah, it's very cool.

00:12:28.360 --> 00:12:33.100
Also another, I mean, we get this all the time, but I just want to remind people, this

00:12:33.100 --> 00:12:34.640
was a suggestion from a listener.

00:12:34.640 --> 00:12:39.120
And that's one of the neat things about the podcast is people can find cool things and

00:12:39.120 --> 00:12:40.880
send them in and then we can share it with everybody.

00:12:40.880 --> 00:12:41.500
It's nice.

00:12:41.500 --> 00:12:42.680
Absolutely.

00:12:42.680 --> 00:12:45.320
That's like half of our topics are that, right?

00:12:45.320 --> 00:12:46.980
All right, Mark, you're up with the next one.

00:12:46.980 --> 00:12:48.020
Awesome.

00:12:48.020 --> 00:12:54.560
So this is not a Python library and it's probably well known to most of your listeners, but I

00:12:54.560 --> 00:13:00.280
wanted to just talk about a few Tailwind CSS things that people, if you're only sort of

00:13:00.280 --> 00:13:03.480
casually aware of Tailwind, might help you jumpstart.

00:13:03.480 --> 00:13:09.060
We are an aggressive user of Tailwind and some of the components.

00:13:09.060 --> 00:13:14.300
The other piece I want to talk about is Tailwind UI, which is not open source.

00:13:14.300 --> 00:13:18.060
So Tailwind CSS is completely free from Tailwind Labs.

00:13:18.280 --> 00:13:23.740
But Tailwind UI is behind a paywall.

00:13:23.740 --> 00:13:27.200
But these are pre-built components by the creators of Tailwind.

00:13:27.200 --> 00:13:29.620
So there are lots of people building components for Tailwind.

00:13:29.620 --> 00:13:34.940
But Tailwind UI is specifically built by the people who created Tailwind in the first instance.

00:13:34.940 --> 00:13:36.960
And it's interesting to me.

00:13:36.960 --> 00:13:42.980
I know that both of you have a lot of interest in user interface design around Python and web

00:13:42.980 --> 00:13:45.800
apps and Tailwind certainly is a part of that theme.

00:13:45.800 --> 00:13:51.340
And it's also interesting for the business model piece about how to turn sort of open source

00:13:51.340 --> 00:13:53.380
into sort of a revenue generating model.

00:13:53.380 --> 00:13:56.360
So you can use Tailwind and never need Tailwind UI.

00:13:56.360 --> 00:14:02.960
But if you need examples or references, Tailwind UI is a fantastic resource.

00:14:02.960 --> 00:14:08.600
And so I thought I would just show they've got widgets, basically pre-built components around

00:14:08.600 --> 00:14:11.980
marketing or app UIs and then a new sort of e-commerce section.

00:14:11.980 --> 00:14:15.340
And to give you an example, there's really low-level granular stuff.

00:14:15.340 --> 00:14:19.500
Like if you want a little stats component, you can come in here.

00:14:19.500 --> 00:14:20.740
They'll show you what it looks like.

00:14:20.740 --> 00:14:22.560
They've designed several options.

00:14:22.560 --> 00:14:26.080
You can see what they are like responsibly.

00:14:26.080 --> 00:14:27.660
And then you can actually see the code.

00:14:28.120 --> 00:14:31.760
And they'll give you the code in raw HTML, React, or Vue.

00:14:31.760 --> 00:14:35.660
And some of them need JavaScript as well.

00:14:35.660 --> 00:14:39.280
They'll give you hints around what to do with the JavaScript if that's necessary.

00:14:39.280 --> 00:14:45.500
But this is an example of that little stats widget with all of the sort of Tailwind classes

00:14:45.500 --> 00:14:47.900
built in there that you can grab and reuse.

00:14:48.860 --> 00:14:54.780
And we have found it really useful for creating this sort of really professional sort of user

00:14:54.780 --> 00:14:56.040
interface experience.

00:14:56.040 --> 00:15:03.480
And our app, so for example, if I just quickly create one, like our toolbar here is a couple

00:15:03.480 --> 00:15:08.940
of chameleon templates with Tailwind running around each of these buttons to keep them consistent,

00:15:08.940 --> 00:15:13.400
which also means that at different resolutions, the buttons will look different.

00:15:13.400 --> 00:15:17.460
So if I'm on a larger screen, there will actually be help text underneath each of these buttons.

00:15:17.640 --> 00:15:18.460
They get smaller.

00:15:18.460 --> 00:15:20.440
All that's done really nicely in Tailwind.

00:15:20.440 --> 00:15:25.860
And then we can, because it's a chameleon template running in our Python stack, we can use those

00:15:25.860 --> 00:15:31.520
toolbars in a variety of circumstances and have really granular, nice, intuitive control of them.

00:15:31.520 --> 00:15:37.360
So, you know, between Tailwind CSS and Tailwind UI, these are sort of great resources to get

00:15:37.360 --> 00:15:38.960
familiar and up and running with it.

00:15:38.960 --> 00:15:40.300
There have been a few people.

00:15:40.300 --> 00:15:41.980
This is so, Mark, this is so nice.

00:15:41.980 --> 00:15:46.420
Just to give people a sense of like some of the size of the building blocks is we've all gone to the

00:15:46.420 --> 00:15:50.600
websites where you click pricing, for example, and it's got like the three columns and one's

00:15:50.600 --> 00:15:53.060
a little bigger and it says, this is the most common or whatever.

00:15:53.060 --> 00:15:53.840
Yeah.

00:15:53.840 --> 00:15:55.640
That is just a drop-in element.

00:15:55.640 --> 00:15:56.680
Yes.

00:15:56.680 --> 00:15:59.700
And it's so beautiful, right?

00:15:59.700 --> 00:16:00.280
Yeah.

00:16:00.460 --> 00:16:06.560
And this is the best thing about Tailwind from my perspective is it's built principally by Adam

00:16:06.560 --> 00:16:08.120
Wathen and Steve Schroger.

00:16:08.120 --> 00:16:14.540
And Adam, I'm probably grossly oversimplifying this, would be the technical component of this.

00:16:14.540 --> 00:16:15.840
And Steve is the design element.

00:16:15.840 --> 00:16:17.400
And they have some great resources.

00:16:17.400 --> 00:16:22.640
If you just, Steve Schroger has some wonderful videos where he sort of recomposes user interfaces

00:16:22.640 --> 00:16:28.160
and he's got a book out on refactoring UI that I think you can add to the show notes.

00:16:28.160 --> 00:16:31.400
But you're basically standing on the shoulders of these giants, right?

00:16:31.400 --> 00:16:33.780
These are fantastic design principles.

00:16:33.780 --> 00:16:34.500
Yes.

00:16:34.500 --> 00:16:38.860
I'm sure there are people that are better than me at doing this, but I know that Steve and

00:16:38.860 --> 00:16:41.340
Adam have done a fantastic job in using these components.

00:16:41.460 --> 00:16:43.780
Even if I need to tweak them, I learn a lot.

00:16:43.780 --> 00:16:48.140
There are a lot of comments that people will learn a lot about CSS, just watching them work

00:16:48.140 --> 00:16:50.080
and seeing how these components are built.

00:16:50.080 --> 00:16:53.780
Tailwind automatically handles lots of cool edge cases.

00:16:53.780 --> 00:16:58.820
And you see that when you look at these components and they're, you know, everything is built to

00:16:58.820 --> 00:17:02.580
be responsive from the beginning and they're just lovely to work with.

00:17:02.580 --> 00:17:03.420
Yeah.

00:17:03.420 --> 00:17:04.980
It's also super fast.

00:17:04.980 --> 00:17:06.120
So there are a bunch of components.

00:17:06.120 --> 00:17:10.400
Their latest release has made their just-in-time compiler native.

00:17:10.640 --> 00:17:11.600
So it's built in.

00:17:11.600 --> 00:17:18.880
It does generate a lot of CSS, but it will only do that if you're actually using, you

00:17:18.880 --> 00:17:20.320
know, certain classes or components.

00:17:20.320 --> 00:17:23.600
And so it's just been fantastic to work with.

00:17:23.600 --> 00:17:26.720
I will also say we used this in a recent project.

00:17:26.720 --> 00:17:32.940
You can actually drop Tailwind into an existing project and avoid conflicts with existing CSS.

00:17:32.940 --> 00:17:36.700
There's a way to have a custom prefix on all the Tailwind classes.

00:17:37.340 --> 00:17:43.420
And both PyCharm and VS Code will, their Tailwind plugins will adapt to that prefixing.

00:17:43.420 --> 00:17:49.460
So for example, instead of it, you know, if you need padding, you just append or pre-pinned

00:17:49.460 --> 00:17:54.600
TW hyphen to the classes, to the Tailwind classes.

00:17:54.600 --> 00:17:58.000
And VS Code and PyCharm will pick up that prefix.

00:17:58.000 --> 00:18:00.520
They'll still give you all the helps and prompts for Tailwind.

00:18:00.960 --> 00:18:03.320
And you'll avoid all the conflicts with your existing CSS.

00:18:03.320 --> 00:18:04.120
Yeah.

00:18:04.120 --> 00:18:04.720
It's amazing.

00:18:04.720 --> 00:18:08.240
And then finally, I'd say it's just, it's great with, you know, template languages.

00:18:08.240 --> 00:18:14.100
So whether it's Chameleon or Jinja or Mako, it's really nice because you're just looking

00:18:14.100 --> 00:18:16.400
at that little bit of HTML in those templates.

00:18:16.400 --> 00:18:22.480
And you can just put the classes right there in the HTML and have a high confidence in what

00:18:22.480 --> 00:18:23.260
that's going to look like.

00:18:23.260 --> 00:18:24.480
Brian, have you played with this any?

00:18:24.480 --> 00:18:33.260
No, but one of the things I was having a, did a little consult with a, somebody trying

00:18:33.260 --> 00:18:34.400
to get a startup off the ground.

00:18:34.780 --> 00:18:37.940
And I was looking at their site and I was like, man, your site looks awesome.

00:18:37.940 --> 00:18:38.740
Did you hire somebody?

00:18:38.740 --> 00:18:41.520
And they said, no, I'd use Tailwind UI.

00:18:41.520 --> 00:18:48.620
And actually, so that's the thing, the sweet spot, I think, is somebody that like maybe took

00:18:48.620 --> 00:18:52.000
the Michael's entrepreneurial course or something.

00:18:52.000 --> 00:18:55.620
And just like one or two people that are trying to get a business off the ground.

00:18:55.620 --> 00:18:56.900
You don't have any money.

00:18:56.900 --> 00:18:58.180
You can't hire somebody.

00:18:58.180 --> 00:19:01.420
Or maybe you do, but often you don't.

00:19:01.420 --> 00:19:04.860
Or it might just be too early to worry about that, right?

00:19:04.860 --> 00:19:05.380
Yeah.

00:19:05.380 --> 00:19:11.260
So starting off the ground with a professional looking site, I think that's a great way to

00:19:11.260 --> 00:19:11.660
start.

00:19:11.660 --> 00:19:16.660
And yes, it's not free, but it's also not out of the realm of a small startup.

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

00:19:17.280 --> 00:19:19.640
I would add, we've used a lot of frameworks.

00:19:19.640 --> 00:19:22.020
We've used Bootstrap, of course, Semantic.

00:19:22.020 --> 00:19:24.180
We've used a lot of these things.

00:19:24.180 --> 00:19:28.320
And what Tailwind is nice, particularly Tailwind UI, Tailwind in general, but Tailwind UI as

00:19:28.320 --> 00:19:31.240
well, is they will give you full page references.

00:19:31.240 --> 00:19:35.720
So if I scroll down here, you'll see, for example, there's this page example.

00:19:35.720 --> 00:19:40.880
So if you need a landing page, they will show you what an entire landing page looks like.

00:19:40.880 --> 00:19:44.240
But you don't have to take the entire page.

00:19:44.240 --> 00:19:49.840
If you want to assemble these components individually into your own page structure, you can certainly

00:19:49.840 --> 00:19:50.480
do that.

00:19:50.480 --> 00:19:52.700
So here's a feature section.

00:19:53.260 --> 00:19:57.220
It doesn't include any of the other stuff, but these are, if you like this feature presentation,

00:19:57.220 --> 00:20:00.080
you can go grab just this bit and mix and match it.

00:20:00.080 --> 00:20:05.360
So unlike a lot of the theme kind of frameworks where you have this entire theme that just sort

00:20:05.360 --> 00:20:12.260
of stomps all over your design, you can actually get a custom looking output with Tailwind that's

00:20:12.260 --> 00:20:13.100
still consistent.

00:20:13.100 --> 00:20:18.440
So it's a nice balance between pretty modular granular control, but still a consistent look

00:20:18.440 --> 00:20:20.080
of the entire app or website.

00:20:20.540 --> 00:20:25.080
And I have no doubt that like the stuff behind it, like how much CSS is there and the

00:20:25.080 --> 00:20:30.100
size, it's probably going to be a heavier site than having somebody custom write all this

00:20:30.100 --> 00:20:32.040
stuff, but it's also going to be cheaper.

00:20:32.040 --> 00:20:33.080
Yeah.

00:20:33.080 --> 00:20:34.860
And that is true.

00:20:34.860 --> 00:20:39.020
What they have done, they have a just-in-time compiler that really minimizes the amount of

00:20:39.020 --> 00:20:40.040
CSS they produce.

00:20:40.040 --> 00:20:44.280
And then, of course, you can do, they recommend using post-CSS and a number of other things like

00:20:44.280 --> 00:20:47.600
CSS Nano to sort of reduce the size of those files.

00:20:47.600 --> 00:20:49.620
We still get very high performance.

00:20:49.820 --> 00:20:54.000
So keep in mind, sort of our app is built entirely with Tailwind, plus we're doing a lot of math

00:20:54.000 --> 00:20:55.480
on the server side.

00:20:55.480 --> 00:21:01.960
And we get, you know, very small sub-second returns on our pages as a result, even with

00:21:01.960 --> 00:21:02.540
all that stuff.

00:21:02.540 --> 00:21:03.440
Yeah.

00:21:03.440 --> 00:21:04.260
That's cool.

00:21:04.260 --> 00:21:09.520
You've definitely inspired me, Mark, to think about rewriting a lot of what I've been doing

00:21:09.520 --> 00:21:10.400
in Tailwind.

00:21:10.400 --> 00:21:11.220
And it'll get there.

00:21:11.220 --> 00:21:12.020
I'm just not there yet.

00:21:12.020 --> 00:21:14.260
I've got other stuff to work on first.

00:21:15.260 --> 00:21:15.760
All right.

00:21:15.760 --> 00:21:19.300
Before we move on, Brian, can I take a moment and tell you all about our sponsor?

00:21:19.300 --> 00:21:20.120
Yes.

00:21:20.120 --> 00:21:20.760
Yeah.

00:21:20.820 --> 00:21:25.700
So this week, the show is brought to you by Compiler, the Compiler podcast from Red Hat.

00:21:25.700 --> 00:21:30.680
Just like everyone on the show and everyone listening, Brian and I are fans of podcasts.

00:21:30.680 --> 00:21:33.180
And I'm super happy to share Compiler with you.

00:21:33.180 --> 00:21:38.900
It comes to you from Red Hat, a well-respected open source company we all know of, I'm sure.

00:21:39.320 --> 00:21:43.440
So with more and more of us working from home, it's important to keep our human connection

00:21:43.440 --> 00:21:44.420
with technology.

00:21:44.420 --> 00:21:50.300
And Compiler unravels industry topics and trends, things you've always wanted to know about in

00:21:50.300 --> 00:21:54.220
tech, all the way up to interviews with people who know it best.

00:21:54.220 --> 00:21:59.320
So on Compiler, you'll hear a course of perspectives from diverse communities behind the code.

00:21:59.320 --> 00:22:03.940
Conversations include questions like, what is technical debt or what are tech managers

00:22:03.940 --> 00:22:04.940
actually looking for?

00:22:04.940 --> 00:22:08.060
And do you have to know how to code to get an open source?

00:22:08.480 --> 00:22:12.120
I was actually a guest on Red Hat's previous podcast, Command Line Heroes.

00:22:12.120 --> 00:22:16.520
And Compiler is following along in that same tradition of being an excellent produced and

00:22:16.520 --> 00:22:17.340
polished show.

00:22:17.340 --> 00:22:23.540
So actually, the show that they just released, When Should Data Die, I think is one of those

00:22:23.540 --> 00:22:27.940
cool sort of philosophical questions of, you know, should data have a lifetime?

00:22:27.940 --> 00:22:30.080
Should your data be able to outlive you?

00:22:30.080 --> 00:22:31.560
All those kinds of things are pretty interesting.

00:22:31.560 --> 00:22:33.540
So I recommend people check it out.

00:22:33.540 --> 00:22:35.740
Just visit pythonbytes.fm/compiler.

00:22:35.740 --> 00:22:38.040
The link is in your podcast show notes.

00:22:38.040 --> 00:22:41.240
I know we're all smart developers who are listening.

00:22:41.240 --> 00:22:44.680
You can just search for Compiler in your podcast player, but please sign up by clicking that

00:22:44.680 --> 00:22:46.280
link and then clicking your podcast player.

00:22:46.280 --> 00:22:47.800
It'll help them know it came from us.

00:22:47.800 --> 00:22:50.980
So thank you to Red Hat and Compiler for supporting the show.

00:22:50.980 --> 00:22:51.960
All right.

00:22:51.960 --> 00:22:53.500
I guess I'm still up, huh, Brian?

00:22:53.500 --> 00:22:54.840
So let's talk peps.

00:22:55.400 --> 00:22:57.160
This PEP is pretty interesting.

00:22:57.160 --> 00:22:58.800
This comes to us from Itamar.

00:22:58.800 --> 00:23:03.700
It's by Jermaine Bravo and Carl Meyer, sponsored by Barry Warsaw.

00:23:03.700 --> 00:23:09.880
And it's something, honestly, I'm surprised it hasn't been covered or addressed yet.

00:23:09.960 --> 00:23:15.920
I think this comes out of Meta's sender project where they're trying to do a whole bunch of

00:23:15.920 --> 00:23:18.560
performance improvements, but I'm not 100% sure.

00:23:18.560 --> 00:23:20.040
So I think that with a grain of salt.

00:23:20.040 --> 00:23:25.620
Basically, the idea is right now what happens when I write some Python code, I'll write at

00:23:25.620 --> 00:23:29.760
the top import requests, import Beanie, import FastAPI.

00:23:29.760 --> 00:23:31.600
What happens when I import Beanie?

00:23:31.600 --> 00:23:35.560
Well, inside Beanie, it says import motor, import Pydantic.

00:23:35.560 --> 00:23:37.300
What happens inside motor?

00:23:37.300 --> 00:23:37.900
It says import.

00:23:37.900 --> 00:23:43.300
It's just this transitive closure of at the top of all of these projects, each one of them

00:23:43.300 --> 00:23:48.940
is importing something and like parsing and compiling the Python code as in, you know, into

00:23:48.940 --> 00:23:52.040
abstract syntax trees into memory and stuff like that.

00:23:52.040 --> 00:23:54.900
All of that happens when I write one import line, right?

00:23:54.900 --> 00:23:56.200
That's a lot.

00:23:56.200 --> 00:24:01.660
But what if there's different paths in my code and only some of the time, maybe I'm using

00:24:01.660 --> 00:24:06.820
Pydantic or only later in the app am I actually using FastAPI, but not right away.

00:24:06.820 --> 00:24:09.900
And sometimes you might not use them at all, right?

00:24:09.900 --> 00:24:14.480
I could do a bunch of data science imports, but only if a certain function runs do I care.

00:24:14.480 --> 00:24:21.040
So this PEP, this PEP 690 says, well, let's not do that.

00:24:21.240 --> 00:24:27.140
Let's not preload every possible path that you might run when you're going to use a library.

00:24:27.140 --> 00:24:28.720
Let's wait until you use it.

00:24:28.720 --> 00:24:33.960
So that import FastAPI kind of just hangs there until I say FastAPI dot.

00:24:33.960 --> 00:24:37.580
And soon as the first line of code runs there, then the import happens.

00:24:37.580 --> 00:24:43.320
So you don't have this transitive closure of all these imports if you're not actually going

00:24:43.320 --> 00:24:43.760
to use them.

00:24:43.760 --> 00:24:48.840
So it helps with startup time and it also maybe helps with overall performance if not

00:24:48.840 --> 00:24:50.200
every bit of code runs.

00:24:50.200 --> 00:24:51.480
I want this.

00:24:51.480 --> 00:24:53.580
Me too.

00:24:53.580 --> 00:24:55.300
It looks cool, right?

00:24:55.300 --> 00:24:59.360
Yeah, you can spend a lot of time in startup just because of all the import statements.

00:24:59.780 --> 00:25:05.220
Yeah, one of the things that I face a lot with helping people is with pytest.

00:25:05.220 --> 00:25:07.540
So pytest imports your code.

00:25:07.540 --> 00:25:13.640
So it does when it's, well, it imports your tests and then the tests will import your code

00:25:13.640 --> 00:25:14.740
to run your code.

00:25:14.740 --> 00:25:20.760
But if you're running, if you're going to like, for instance, stop on the first failure, you're

00:25:20.760 --> 00:25:23.080
not going to hit a whole bunch of that code.

00:25:23.080 --> 00:25:28.540
And so avoiding those and getting to start earlier, it would help that.

00:25:28.540 --> 00:25:32.860
And that's just one example of startup time being helped.

00:25:32.860 --> 00:25:41.580
Now, I'm curious about if it'll affect runtime early on otherwise, you know, at post-startup.

00:25:41.580 --> 00:25:44.460
There's some conversations about compatibility.

00:25:44.460 --> 00:25:50.360
So what could happen is there could be side effects that happen because of the import, right?

00:25:50.360 --> 00:25:55.460
You're not supposed to make changes to the system, but that's arbitrary code running during

00:25:55.460 --> 00:25:56.460
your import statement, right?

00:25:56.460 --> 00:25:58.240
So it could have an effect.

00:25:58.240 --> 00:26:01.540
So theoretically, this could change things.

00:26:01.540 --> 00:26:04.540
And they refer to the not the lazy ones as eager imports.

00:26:04.540 --> 00:26:11.080
But they do talk about how some of these, you'll have to pass a runtime flag to the Python

00:26:11.080 --> 00:26:14.720
interpreter or set an environment variable for this to happen by default.

00:26:14.720 --> 00:26:15.960
It won't happen by default.

00:26:15.960 --> 00:26:17.240
It's off by default.

00:26:17.760 --> 00:26:20.620
So for better or worse, maybe someday that'll change.

00:26:20.620 --> 00:26:21.480
But right now.

00:26:21.480 --> 00:26:22.940
That's pretty cool.

00:26:22.940 --> 00:26:23.740
I like it.

00:26:23.740 --> 00:26:24.000
Yeah.

00:26:24.000 --> 00:26:24.880
Yep.

00:26:24.880 --> 00:26:25.460
Indeed.

00:26:25.460 --> 00:26:27.620
Ben, Mark, you guys have thoughts on this?

00:26:27.620 --> 00:26:29.060
Yeah, I agree.

00:26:29.060 --> 00:26:33.600
I think this is really interesting from the front end world where I spend a lot of time

00:26:33.600 --> 00:26:33.800
too.

00:26:33.800 --> 00:26:36.040
I mean, there's a billion analogs for this.

00:26:36.040 --> 00:26:40.140
We do all kinds of jumping through hoops, you know, from the old day code splitting in the

00:26:40.140 --> 00:26:44.940
old days and all kinds of, you know, web back and a million other roll up and all sorts

00:26:44.940 --> 00:26:49.080
of ways of, you know, trying to take advantage of this on the client side, you know, because

00:26:49.080 --> 00:26:49.440
the browser.

00:26:49.440 --> 00:26:55.780
But I can actually imagine a lot of situations using Python where, you know, what in one app,

00:26:55.780 --> 00:26:58.980
you know, maybe it is just limited to, you know, that moment of startup.

00:26:58.980 --> 00:27:03.040
But I can imagine a lot of situations where the way that your app or your service is being

00:27:03.040 --> 00:27:11.120
used is causing that, you know, initial run event to, you know, to be an experience that

00:27:11.120 --> 00:27:15.320
the user is having on a more frequent basis, you know, based on what you're doing or what

00:27:15.320 --> 00:27:15.880
you've constructed.

00:27:15.880 --> 00:27:17.680
So that's actually really cool.

00:27:17.680 --> 00:27:20.140
And I haven't thought much about this, but I kind of agree with you.

00:27:20.140 --> 00:27:21.880
Sort of surprised now that I see it.

00:27:22.700 --> 00:27:24.280
I should have always done this, right?

00:27:24.280 --> 00:27:25.180
I've been in a more conversation before.

00:27:25.180 --> 00:27:26.900
Yeah, absolutely.

00:27:26.900 --> 00:27:34.720
And I also wonder if it allows you to have code that can be less, have more optional dependencies

00:27:34.720 --> 00:27:35.380
installed.

00:27:35.380 --> 00:27:38.620
So like, for example, I think it was a FastAPI.

00:27:39.100 --> 00:27:44.360
There's some support for form stuff you have to install as a separate pip dependency.

00:27:44.360 --> 00:27:49.080
And here you could just write that code and unless you actually run it, it doesn't matter

00:27:49.080 --> 00:27:53.840
if you have import that thing that's missing because not until does it try to use it, is

00:27:53.840 --> 00:27:54.460
it going to be a problem?

00:27:54.460 --> 00:27:56.140
So it might allow you to write simpler code.

00:27:56.140 --> 00:27:57.300
Let's see out in the audience.

00:27:57.300 --> 00:28:02.220
Eddie Bergman says, I feel like with it opt in, many people won't know to use it, but making

00:28:02.220 --> 00:28:05.380
it opt out could break so many systems depending on the behavior.

00:28:05.380 --> 00:28:08.360
So yeah, it's I don't know what the right choice is.

00:28:08.360 --> 00:28:11.620
So I guess the safe one is to just opt out or to make people opt in.

00:28:11.620 --> 00:28:18.460
And Beanie, the author of, sorry, Roman Wright, the author of Beanie, gives it definitely a

00:28:18.460 --> 00:28:19.520
thumbs up for this idea as well.

00:28:19.520 --> 00:28:21.980
So support for some framework authors there as well.

00:28:21.980 --> 00:28:24.680
All right, Brian, what do you got for your last one here?

00:28:24.680 --> 00:28:26.260
Hope it's something rich for us.

00:28:26.260 --> 00:28:29.520
Well, I've got a couple of things that a couple of these are small.

00:28:29.520 --> 00:28:32.260
So it's sort of a multi-grab bag.

00:28:32.260 --> 00:28:33.680
pytest Rich.

00:28:33.680 --> 00:28:37.300
So this is a plugin for pytest that uses Rich.

00:28:37.560 --> 00:28:42.620
Not much more to say other than it's kind of cool to use Rich to have some nice output.

00:28:42.620 --> 00:28:50.800
This was done by Bruno Oliveira, who is he's one of the core people on pytest and also the

00:28:50.800 --> 00:28:55.060
only other person on the planet that I know of that has written a book focused on pytest.

00:28:55.060 --> 00:28:56.500
But cool guy.

00:28:58.100 --> 00:29:02.520
He said this is a proof of concept and he'd love for somebody else to take it over.

00:29:02.520 --> 00:29:05.300
But it doesn't look like it's like dead or anything.

00:29:05.300 --> 00:29:05.780
It's good.

00:29:05.780 --> 00:29:06.560
It's some activity.

00:29:06.560 --> 00:29:08.780
So anyway, I think this is fun.

00:29:08.780 --> 00:29:13.200
So cool opportunity for people to jump in if they want to.

00:29:13.200 --> 00:29:13.700
Thanks.

00:29:13.700 --> 00:29:17.120
The question from the audience, Ryan, how's it compared to pytest sugar?

00:29:17.540 --> 00:29:21.040
I haven't used sugar for a really long time.

00:29:21.040 --> 00:29:23.480
But you can look at the image.

00:29:23.480 --> 00:29:26.020
So it looks like similar to sugar.

00:29:26.020 --> 00:29:29.740
But sugar doesn't have these cool rich tracebacks in it.

00:29:29.740 --> 00:29:31.280
So there's that.

00:29:31.280 --> 00:29:31.720
Yeah, indeed.

00:29:31.720 --> 00:29:37.400
So the next thing I wanted to talk about before we move on to somebody else is a short little thing.

00:29:37.480 --> 00:29:42.940
This was a recommended by actually the pytest rich was recommended by Brian Skin.

00:29:42.940 --> 00:29:43.680
Thanks, Brian.

00:29:43.680 --> 00:29:54.220
And then this is recommended by Henrik Finsberg is a video by Anthony Sotilli on how to get images and read me.

00:29:54.220 --> 00:29:55.860
And I guess I didn't know how to do this.

00:29:55.860 --> 00:30:06.200
We encourage and I wanted to bring this up because we encourage everybody to put pictures and animated GIFs and all that sort of stuff in your read me so that when we review stuff, we can see what it does.

00:30:06.720 --> 00:30:07.440
It helps.

00:30:07.440 --> 00:30:09.420
But it's not hard.

00:30:09.420 --> 00:30:14.840
So Anthony goes through this little thing of like, you don't have to put the image in your repo.

00:30:14.840 --> 00:30:20.340
You just have to drop it into a comment field or in a repo edit field.

00:30:20.340 --> 00:30:25.580
And then GitHub will just put it on a CDN somewhere.

00:30:25.580 --> 00:30:27.020
So the image is just there.

00:30:27.020 --> 00:30:28.660
So some magic there.

00:30:28.660 --> 00:30:32.120
Kind of trick GitHub into uploading it and then not actually.

00:30:32.120 --> 00:30:36.540
Well, I mean, since the read me supports it, it's interesting.

00:30:36.680 --> 00:30:48.160
Anthony talks about going using the using a edit a comment field of your issues to drop a picture in and then you get the URL from that.

00:30:48.160 --> 00:30:56.640
But if you just go into your read me in within GitHub on the web interface and edit there, you can also drop it there.

00:30:56.640 --> 00:30:58.480
And it just works fine.

00:30:58.840 --> 00:31:02.760
I guess maybe he's thinking that you're probably not going to edit your read me directly.

00:31:02.760 --> 00:31:05.260
You'll probably edit it locally and push it in.

00:31:05.260 --> 00:31:06.240
You can still do that.

00:31:06.240 --> 00:31:07.480
But anyway.

00:31:07.480 --> 00:31:08.040
It's neat.

00:31:08.040 --> 00:31:08.560
Yeah.

00:31:08.560 --> 00:31:08.920
Very nice.

00:31:08.920 --> 00:31:09.140
That's cool.

00:31:09.940 --> 00:31:10.300
Yeah.

00:31:10.300 --> 00:31:15.480
People should definitely have pictures and explanations and charts and all sorts of stuff in there.

00:31:15.480 --> 00:31:16.100
They're reading me.

00:31:16.100 --> 00:31:16.660
So this is great.

00:31:16.660 --> 00:31:16.800
Yeah.

00:31:16.800 --> 00:31:23.940
I would just add more generally, you know, docs and tutorials can be a strategic asset when done well.

00:31:23.940 --> 00:31:26.040
You know, Tailwind does this amazingly well.

00:31:26.040 --> 00:31:27.320
EdgeDB does it really well.

00:31:27.320 --> 00:31:31.400
DigitalOcean is off the chart in the comprehensiveness and thoroughness of there.

00:31:31.400 --> 00:31:33.520
And those things become an asset for the business.

00:31:33.580 --> 00:31:38.440
Instead of an annoyance, you know, that you have to do, the docs actually become valuable for the project or the business.

00:31:38.440 --> 00:31:39.080
Yeah.

00:31:39.080 --> 00:31:42.320
Do you want to be there or do you regret that you have to go there, right?

00:31:42.320 --> 00:31:43.300
Right.

00:31:43.300 --> 00:31:43.960
Exactly.

00:31:43.960 --> 00:31:45.500
All right.

00:31:45.500 --> 00:31:47.940
Ben, you want to take us out of here with your final main topic?

00:31:47.940 --> 00:31:48.500
Yeah.

00:31:48.500 --> 00:32:01.680
So, you know, as you mentioned, part of our latest project, LexChart, that Mark's talked a little bit about, you know, one of the things that we had to do, despite the fact that, you know, as we were getting close to it,

00:32:01.680 --> 00:32:12.060
I realized you can use LexChart for a lot of things that maybe, you know, we didn't think about when my 12-year-old daughter sent me, and I spun her up an account so she could tinker with it,

00:32:12.060 --> 00:32:17.120
so I could kind of get an interesting test case out of somebody that has, like, no connection to what we're doing.

00:32:17.120 --> 00:32:25.040
And she sent me a little organization chart of Encanto characters and their family tree from the movie Encanto.

00:32:25.620 --> 00:32:31.340
So I wasn't expecting, but she's not really our typical user.

00:32:31.340 --> 00:32:40.920
And with our target audience, who looks a lot like, you know, I did in my former life, you know, security is a big, big deal with our clients.

00:32:41.380 --> 00:32:47.040
And so one of the things we obviously had to look at is, you know, we need to implement some multi-factor authentication.

00:32:47.760 --> 00:32:53.740
And, you know, initially, my, you know, knee-jerk reaction to that was, okay, yeah, we'll just do what everybody does,

00:32:53.740 --> 00:32:59.680
and, you know, we'll set it up, and you'll get an SMS message on your phone and all that kind of stuff.

00:32:59.680 --> 00:33:08.800
But as I looked at that more and thought about some of the conversations we'd had with clients of some of our other software,

00:33:09.040 --> 00:33:12.440
you know, I wondered, how long is that really going to last?

00:33:12.440 --> 00:33:19.780
Because there's a number of kind of real security issues with SMS, not least of which is, you know,

00:33:19.780 --> 00:33:21.040
just the way voice networks are built.

00:33:21.040 --> 00:33:22.880
Everything's sent in clear text.

00:33:22.880 --> 00:33:25.900
It's actually really not that hard to, you know.

00:33:25.900 --> 00:33:28.740
Yeah, it works, but people do look down upon it a little bit.

00:33:28.740 --> 00:33:31.500
They're like, oh, this is not quite real security.

00:33:31.500 --> 00:33:33.640
This is better than nothing but, right?

00:33:34.000 --> 00:33:34.980
Yeah, exactly, right?

00:33:34.980 --> 00:33:37.440
And it's not to say, you know, you make me a point.

00:33:37.440 --> 00:33:39.400
It's everywhere.

00:33:39.400 --> 00:33:40.520
Everyone's using it.

00:33:40.520 --> 00:33:42.900
And, you know, by the way, yeah, absolutely.

00:33:42.900 --> 00:33:47.960
You know, password, bless MFA, even with SMS, is great.

00:33:47.960 --> 00:33:51.060
It's so much better than the password only from a security standpoint.

00:33:51.060 --> 00:33:52.660
So it's not a knock on it.

00:33:52.660 --> 00:33:58.180
You know, I just, well, maybe we need to step one more step forward here and see if there's some other things.

00:33:58.180 --> 00:34:02.700
And so, you know, I was looking for a library that could help us with one-time password stuff,

00:34:02.700 --> 00:34:08.280
and specifically one that could help us with time-based one-time password implementations,

00:34:08.280 --> 00:34:13.100
which is something that I think Google really ultimately started this way back.

00:34:13.100 --> 00:34:17.120
And that's why a lot of people associate this with the Google Authenticator app.

00:34:17.120 --> 00:34:19.500
But there's actually a lot of authenticators.

00:34:19.500 --> 00:34:20.520
It's an open standard.

00:34:20.520 --> 00:34:26.880
And it really is closely connected to what's happening when you do it with SMS or with email.

00:34:27.040 --> 00:34:33.840
Both of those are similar in that, you know, both of these approaches, they just lean on a moving factor.

00:34:33.840 --> 00:34:38.680
So in the case of your SMS, that moving factor is just usually like a counter in the database, right?

00:34:38.680 --> 00:34:40.460
Just kind of clicking for it and whatever.

00:34:40.460 --> 00:34:48.580
And that's, you know, along with all the other secret sauces, you know, generating, you know, these temporary codes, if you will.

00:34:48.840 --> 00:34:50.640
In time-based, the moving factor is time.

00:34:50.640 --> 00:34:57.900
And so what that allows you to do is, you know, have an authenticator app where you don't actually have to communicate with that at all.

00:34:57.900 --> 00:35:06.940
But, you know, based on a shared secret, again, same as how you do with SMS, you're able to, you know, sync up these passwords.

00:35:06.940 --> 00:35:10.060
And then they have like kind of a, they sort of explode, if you will, right?

00:35:10.060 --> 00:35:13.140
You know, so they last for like 30 seconds and all that kind of thing.

00:35:13.140 --> 00:35:19.240
And so, yeah, the library you're highlighting here is PyOTP, which I guess lets you do this really easy in Python, huh?

00:35:19.240 --> 00:35:19.980
It does.

00:35:19.980 --> 00:35:21.760
Yeah, it makes it really, really straightforward.

00:35:21.760 --> 00:35:33.580
So, you know, I've, in the notes, you know, people will be able to see, I put a couple of representative, you know, functions that you could use to do this.

00:35:33.580 --> 00:35:35.920
But it's a very small amount of code.

00:35:35.920 --> 00:35:39.260
Basically, you generate a secret, you store it with your user credentials.

00:35:40.140 --> 00:35:47.640
Then, you know, when you're actually verifying somebody, you know, they come in, you have the shared secret in there.

00:35:47.640 --> 00:35:52.180
They, you know, pull up their little authenticator app on their phone.

00:35:52.180 --> 00:35:59.720
You know, I think most people know what this looks like, but we'll do this there.

00:35:59.720 --> 00:36:02.340
So that's the Google Authenticator app.

00:36:02.340 --> 00:36:08.380
And so it gives you a little code and you can see it ticking down and all that kind of stuff.

00:36:08.560 --> 00:36:14.880
And so instead of getting your SMS, you just pull up your code, you hit your app, you type it in, and then your user's putting that.

00:36:14.880 --> 00:36:17.100
And then you're just running that through the verifier.

00:36:17.100 --> 00:36:20.140
And based on this shared secret, it says, yeah, you're the real guy.

00:36:20.140 --> 00:36:20.540
Great.

00:36:20.540 --> 00:36:22.240
And every 30 seconds, those go away.

00:36:22.240 --> 00:36:28.600
So even if somebody, you know, just looked at mine for my Google Authenticator, you know, you got, you know, 30 seconds to figure out my password.

00:36:28.600 --> 00:36:29.800
Exactly.

00:36:30.320 --> 00:36:34.260
See if you can get into that test account that I'm showing you that for.

00:36:34.260 --> 00:36:37.500
But yeah, it's super, super simple to implement.

00:36:37.500 --> 00:36:45.780
The only thing, you know, for the Python crowd here is that it is helpful from a setup standpoint to do a little bit of front-end work.

00:36:47.120 --> 00:36:50.740
Because the easiest way for users to set this up is to scan a QR code.

00:36:51.420 --> 00:37:00.480
And so we have that implement on the front-end where you can see, you know, that QR code and scan it from a setup.

00:37:00.480 --> 00:37:04.860
But those little functions I put in the show notes, you know, you just spin up a little URI.

00:37:05.580 --> 00:37:11.860
You can put that into any kind of QR code generator, including Python-based generators if you actually want to do that.

00:37:11.860 --> 00:37:13.740
Store the image on the server and then serve it up.

00:37:13.740 --> 00:37:16.400
In our case, I actually do that on the JavaScript side.

00:37:16.400 --> 00:37:18.620
And I put a little link to QR code.

00:37:18.620 --> 00:37:23.680
It's just kind of one of the most widely used, you know, npm packages for that purpose.

00:37:23.680 --> 00:37:25.400
Display that to users.

00:37:25.400 --> 00:37:26.040
They scan it.

00:37:26.040 --> 00:37:26.700
They set it up.

00:37:26.700 --> 00:37:27.700
They pair that first time.

00:37:27.700 --> 00:37:30.440
And then, you know, it takes a little getting used to for the user.

00:37:30.440 --> 00:37:36.020
I think, you know, at the end of the day, SMS is a little more user-friendly just because people are a little bit more familiar with it.

00:37:36.020 --> 00:37:37.780
This isn't a big leap.

00:37:37.780 --> 00:37:44.080
So we went here instead of something like WebOften, which is, you know, even probably better from a security standpoint.

00:37:44.080 --> 00:37:46.300
But I think a bigger leap for users.

00:37:46.300 --> 00:37:48.360
So I just think it's a cool little library.

00:37:48.360 --> 00:37:48.860
It's easy.

00:37:48.860 --> 00:37:49.640
It's purpose-built.

00:37:49.640 --> 00:37:55.360
Literally those few lines of code that I put in the show notes, it's almost everything that you would need to implement this on the back end.

00:37:55.360 --> 00:37:56.440
There really isn't anything else.

00:37:56.440 --> 00:37:57.580
It's amazing.

00:37:57.760 --> 00:38:01.140
I've always avoided doing this because I'm like, ah, it's probably kind of complicated.

00:38:01.140 --> 00:38:02.940
I don't want to screw it up and unlock people out.

00:38:02.940 --> 00:38:06.580
But it looks really simple and fantastic and straightforward.

00:38:06.580 --> 00:38:08.680
So, yeah, this is a great suggestion for people.

00:38:08.680 --> 00:38:09.280
Yeah.

00:38:09.280 --> 00:38:09.760
Cool.

00:38:09.760 --> 00:38:11.220
Brian, have you had to do any of this?

00:38:11.220 --> 00:38:13.180
No.

00:38:13.180 --> 00:38:19.140
But I do have, like, a SaaS app in the works that, like, I don't think I'll get that complicated.

00:38:19.140 --> 00:38:25.160
Because I think for somebody, like, with GitHub, we have to use it, like, something like that for GitHub now.

00:38:25.160 --> 00:38:26.080
Or you can.

00:38:26.240 --> 00:38:27.340
And I have set it up.

00:38:27.340 --> 00:38:33.380
But some people, for some kind of apps, it depends on your audience.

00:38:33.380 --> 00:38:35.460
Some audiences aren't really going to want that.

00:38:35.460 --> 00:38:35.720
Sure.

00:38:35.720 --> 00:38:37.920
It also depends on what you're protecting.

00:38:37.920 --> 00:38:39.320
Yeah, exactly.

00:38:39.320 --> 00:38:43.320
Most of our clients, you know, are B2B, large corporations, sort of all over the world.

00:38:43.320 --> 00:38:45.820
And many of them already have these authenticator apps.

00:38:45.980 --> 00:38:48.960
And the nice thing about this solution is it works with any of them.

00:38:48.960 --> 00:38:54.840
So you don't have to, as a business, you don't have to direct your clients to use a particular authenticator app.

00:38:54.840 --> 00:39:02.580
So if you're using Microsoft or Google or Twilio's Authy or any others, you know, you can just plug this in and just use it.

00:39:03.060 --> 00:39:07.740
You know, we test and validate on those three, but it'll likely work on any of them.

00:39:07.740 --> 00:39:10.920
And so it's really nice in that corporate environment just to slide in.

00:39:11.280 --> 00:39:17.640
Yeah, and I should have emphasized for this audience, one of the great things about this is SMS is not expensive, but this is free.

00:39:17.640 --> 00:39:21.320
It's free for you from a developer standpoint, and it's free for your users.

00:39:21.320 --> 00:39:23.520
These authenticator apps are free downloads.

00:39:23.520 --> 00:39:27.380
This isn't, you know, you're not imposing any friction on your users from that standpoint.

00:39:27.380 --> 00:39:30.200
Just a tiny bit of a learning curve for them.

00:39:30.200 --> 00:39:37.260
But I think what you find, like you said, GitHub, you can link an authenticator app to GitHub if you want to add MFA to your GitHub login,

00:39:37.260 --> 00:39:40.440
which, you know, I would say most of your listeners probably are familiar with.

00:39:40.520 --> 00:39:43.300
And so, you know, if you're wondering about it, I'd encourage you just try that.

00:39:43.300 --> 00:39:46.720
Download Google Authenticator, Microsoft Authenticator, implement their MFA.

00:39:46.720 --> 00:39:52.700
You'll see what the experience is like, and you'll probably find that not really probably a big hard sell with your clients.

00:39:52.700 --> 00:39:56.400
If, in fact, MFA is something you need, as you say, you don't need it, you don't need it.

00:39:56.400 --> 00:39:57.920
But if you do, you know you do.

00:39:57.920 --> 00:40:05.860
And, you know, this is a solution I think people should consider because I think SMS, you know, is fine and great.

00:40:06.020 --> 00:40:11.320
But obviously, the more widespread it becomes, you know, the more likely, you know, people are to attack it.

00:40:11.320 --> 00:40:13.600
And the hacks on this are not hard.

00:40:13.600 --> 00:40:21.140
My favorite one is using a cell signal booster, which, you know, some of you heard of, especially some of your listeners that don't live in urban areas and whatever.

00:40:21.140 --> 00:40:24.120
And, you know, I'm not encouraging this.

00:40:24.180 --> 00:40:28.800
But if you poke around just a little bit, it's not going to be very hard for you to figure out how to hack a cell signal booster.

00:40:28.800 --> 00:40:30.400
People don't even know they're attached to it.

00:40:30.400 --> 00:40:33.820
And you can listen to everything and record all their texts and all that.

00:40:33.820 --> 00:40:35.800
So, yeah, that's just.

00:40:35.800 --> 00:40:36.440
That's a nervous.

00:40:36.440 --> 00:40:37.620
Brian is getting ideas.

00:40:37.620 --> 00:40:40.760
I got to go, guys.

00:40:40.760 --> 00:40:43.760
I love having this.

00:40:43.760 --> 00:40:45.300
I use Authy and I just checked.

00:40:45.300 --> 00:40:50.540
My Authy has 45 different accounts doing 2FA, MFA, which is fantastic.

00:40:50.540 --> 00:40:52.220
Yeah, I like Authy as well.

00:40:52.220 --> 00:40:54.560
Brian, what else we got?

00:40:54.560 --> 00:40:56.700
Well, I've got a few extras.

00:40:56.700 --> 00:40:58.220
Do you have any extras?

00:40:58.220 --> 00:40:59.980
You know I do.

00:40:59.980 --> 00:41:00.260
All right.

00:41:00.260 --> 00:41:02.160
Yeah, I'll do mine first.

00:41:02.160 --> 00:41:04.740
So let's start with some real quick ones.

00:41:04.740 --> 00:41:17.480
First of all, Mac Rumors points out that the machine learning framework PyTorch, traditionally these have been like mainstream GPU, these machine learning training frameworks,

00:41:17.480 --> 00:41:23.160
and especially focused on NVIDIA, which if you're on a Mac is a problem because you don't have NVIDIA.

00:41:23.160 --> 00:41:28.440
Not even before the M1 stuff, you had Radeon chips and stuff.

00:41:28.440 --> 00:41:32.020
So doing hardware-based machine acceleration was really tricky.

00:41:32.020 --> 00:41:41.580
They are now supporting Metal on Apple, which means you get GPU-accelerated training on the new Apple Silicon Macs, including the M1 Ultra and all that stuff.

00:41:41.740 --> 00:41:45.100
So if people are on M1, they may check that out.

00:41:45.100 --> 00:41:45.720
That sounds good.

00:41:45.720 --> 00:41:46.520
Let's see.

00:41:46.520 --> 00:41:49.240
I got a message from Harry.

00:41:49.720 --> 00:41:57.600
This is a 15-year-old kid who said, hey, I built this learning platform and a bunch of tutorials with my cousin, Anna, who's 14.

00:41:57.600 --> 00:42:01.520
And they built this app, which I'll link into, called Mission Encodable.

00:42:01.520 --> 00:42:08.460
And you come in and you can do little tutorials and you've got like little lessons and achievements to do after and stuff.

00:42:08.460 --> 00:42:14.040
So anyway, I just thought I'd give them a shout out because it's really cool that a 15 and a 14-year-old put this together for people.

00:42:14.040 --> 00:42:15.200
Yeah, very cool.

00:42:15.560 --> 00:42:15.720
Yeah.

00:42:15.720 --> 00:42:16.380
All right.

00:42:16.380 --> 00:42:18.160
Two real quick things as well.

00:42:18.160 --> 00:42:19.520
I use Calendly.

00:42:19.520 --> 00:42:20.740
Calendly.

00:42:20.740 --> 00:42:21.900
Not stating that.

00:42:21.900 --> 00:42:22.600
That's how it's supposed to be.

00:42:22.600 --> 00:42:27.000
Calendly.com, which is great for like sharing your available free time.

00:42:27.000 --> 00:42:28.940
People can sign up and book slots with you.

00:42:29.160 --> 00:42:36.380
I recently learned about Cal.com, which is an open source parallel or equivalent to Calendly.com.

00:42:36.380 --> 00:42:43.180
So if you can self-host it or you have a free version, you can even have them host it for more pro things if you want.

00:42:43.180 --> 00:42:44.680
But I just thought it was kind of cool.

00:42:44.680 --> 00:42:47.400
There's an open source Cal.com, which is Calendly.

00:42:47.620 --> 00:42:56.080
And on the same vein, if you heard about Firebase, which is kind of like the back-end platform for so many mobile apps and stuff.

00:42:56.080 --> 00:43:02.700
So you don't have to have a website and an API and a database and users like this would handle all of those things for Firebase.

00:43:03.140 --> 00:43:10.000
I also heard about Supabase, like super but without the R, Supabase, which is the open source equivalent of that.

00:43:10.000 --> 00:43:17.260
So you can have sort of like the back-end cloud for free for your open source for your mobile things if you care about that.

00:43:17.260 --> 00:43:23.080
And yeah, so those are my – oh, I have one more extra I want to share with you.

00:43:23.080 --> 00:43:27.960
So we've all heard about PyScript, right?

00:43:27.960 --> 00:43:28.960
PyScript is awesome.

00:43:28.960 --> 00:43:35.700
This comes from Anaconda, takes the CPython runtime and turns it into WebAssembly and then runs it in your browser.

00:43:35.700 --> 00:43:41.960
And I've been looking at the PyScript.net website, and they've got all sorts of cool stuff in there.

00:43:41.960 --> 00:43:46.940
And if you go to PyScript slash examples, there's actually a bunch of examples.

00:43:46.940 --> 00:43:49.180
You showed the one – you covered this last time.

00:43:49.180 --> 00:43:50.740
I think it was last time or time before.

00:43:50.740 --> 00:43:53.960
You covered the anti-gravity one and those kinds of things, right?

00:43:53.960 --> 00:43:58.180
What's lacking from here is anything that looks like a regular application, right?

00:43:58.840 --> 00:43:59.120
Yeah.

00:43:59.120 --> 00:44:01.060
So I said, well –

00:44:01.060 --> 00:44:02.000
It was the ToDo app.

00:44:02.000 --> 00:44:04.680
The ToDo app is not a regular – you got it.

00:44:04.680 --> 00:44:05.660
Come on, man.

00:44:05.660 --> 00:44:08.140
No, no.

00:44:08.140 --> 00:44:08.880
You're right, though.

00:44:08.880 --> 00:44:10.820
That is the absolute closest by far.

00:44:10.820 --> 00:44:14.060
But everything here says data science, data science.

00:44:14.060 --> 00:44:17.900
I want Jupyter in the browser but not with a server.

00:44:17.900 --> 00:44:18.840
Run it in the browser.

00:44:18.840 --> 00:44:19.980
And that's fine.

00:44:19.980 --> 00:44:23.800
But that comes, I think, far short of the potential, okay?

00:44:24.140 --> 00:44:24.320
Yeah.

00:44:24.320 --> 00:44:28.060
So this weekend, I'm like, I'm going to fix this.

00:44:28.060 --> 00:44:33.380
And the way I'm fixing it is with this project and a video that I was working on right before we jumped on.

00:44:33.380 --> 00:44:34.580
I'll publish it later today.

00:44:34.800 --> 00:44:38.640
It's called the PyScript PWA weather app.

00:44:38.640 --> 00:44:39.740
So check this out.

00:44:39.740 --> 00:44:40.980
See this thing here on the screen?

00:44:40.980 --> 00:44:45.260
This is an application that installs in your dock offline.

00:44:45.260 --> 00:44:46.580
It installs in your dock.

00:44:46.700 --> 00:44:52.600
It's written in Python and PyScript and with Python on the front end and has no back-end stuff locally.

00:44:52.600 --> 00:44:54.240
It's got like Electron or something like that.

00:44:54.240 --> 00:44:55.880
It's a progressive web app.

00:44:55.880 --> 00:45:02.800
It downloads all the files, including the 15 megabytes of the Pyodide runtime in PyScript, puts it offline.

00:45:02.800 --> 00:45:06.040
And when you run it, it just starts instantly.

00:45:06.220 --> 00:45:11.240
So from a cold launch until you have this thing up and running, it's about two seconds.

00:45:11.240 --> 00:45:15.780
And it goes out and it talks to an API and gets this cool weather here.

00:45:15.780 --> 00:45:17.320
And you can have a little button.

00:45:17.320 --> 00:45:18.420
You press this refresh button.

00:45:18.420 --> 00:45:19.800
It goes pop, pop, pop, and it'll refresh.

00:45:19.800 --> 00:45:24.440
It's as you click it, it's instantaneous the way it sort of interacts with it.

00:45:24.440 --> 00:45:34.700
And all of it is written on the front end using stuff that you would recognize, stuff that looks like requests and JSON and Python classes and try accept and everything.

00:45:35.240 --> 00:45:35.740
That's pretty cool.

00:45:35.740 --> 00:45:36.460
It is.

00:45:36.460 --> 00:45:39.060
Here, let me actually pull up a little bit of code really quick just to show you all.

00:45:39.060 --> 00:45:40.320
So check it out.

00:45:40.320 --> 00:45:41.400
We've got our regular code.

00:45:41.400 --> 00:45:42.280
Here's our flask bit.

00:45:42.280 --> 00:45:45.380
But if I go to static, there's now a Python folder in static.

00:45:45.380 --> 00:45:47.800
And you can go to the weather API.

00:45:47.800 --> 00:45:50.040
And let me make that bigger for the screen.

00:45:50.040 --> 00:45:51.360
See this code right here?

00:45:51.360 --> 00:45:52.740
It's download a report.

00:45:52.740 --> 00:45:54.060
Type in, goes to report.

00:45:54.060 --> 00:46:00.020
It has this thing that comes back from calling this URL, turns into JSON, does the URL.

00:46:00.020 --> 00:46:00.880
It's hardly any code.

00:46:00.880 --> 00:46:01.580
That.

00:46:01.580 --> 00:46:01.900
Nice.

00:46:02.540 --> 00:46:09.120
That is running in the browser in the CPython runtime, all of it locally with no download and no slow startup.

00:46:09.120 --> 00:46:09.620
So.

00:46:09.620 --> 00:46:10.060
Pretty cool.

00:46:10.060 --> 00:46:11.440
Anyway, I'm going to do a video on that.

00:46:11.440 --> 00:46:13.140
And I'll, yeah, what do you guys think?

00:46:13.140 --> 00:46:13.900
Neat, huh?

00:46:13.900 --> 00:46:14.540
Yeah.

00:46:14.540 --> 00:46:15.240
PyScript is.

00:46:15.240 --> 00:46:16.920
And that's cool what you've done too.

00:46:16.920 --> 00:46:18.180
PyScript's interesting to me.

00:46:18.380 --> 00:46:21.000
I'm interested to see how that evolves.

00:46:21.000 --> 00:46:27.640
I'm sure, you know, like you said, I think most people are using it maybe from a data science standpoint or waiting for it to, you know, mature or whatever.

00:46:27.840 --> 00:46:33.560
But there's some kind of odd analogs between, you know, how React and some of those things got started here.

00:46:33.560 --> 00:46:35.560
Obviously, you angled a different audience.

00:46:36.000 --> 00:46:42.120
But I think, you know, there's some really cool things that could be done with this, you know, as, as you evolve.

00:46:42.580 --> 00:46:51.740
And interesting that you mentioned this on the show today, because if you look in the repo for PyScript, Tailwind is one of their core dependencies.

00:46:51.740 --> 00:46:52.760
Oh, nice.

00:46:52.760 --> 00:46:53.460
How interesting.

00:46:53.460 --> 00:46:54.440
Yeah, it's all coming together.

00:46:54.440 --> 00:46:58.240
So I'll talk more about it when I release the video later.

00:46:58.240 --> 00:47:00.380
But I think that this, and the source code is out.

00:47:00.380 --> 00:47:01.580
It's linking to GitHub.

00:47:01.580 --> 00:47:03.360
People can check it out and install it.

00:47:03.360 --> 00:47:05.160
It's really neat.

00:47:05.160 --> 00:47:06.320
And I think it opens the door.

00:47:06.320 --> 00:47:08.660
I can see people writing like a Vue.js wrapper.

00:47:08.840 --> 00:47:12.920
So you create a Python class that sort of parallels Vue or React or something like that.

00:47:12.920 --> 00:47:17.300
And you could create really neat stuff in this offline sort of progressive web app mode.

00:47:17.300 --> 00:47:18.220
So we'll see.

00:47:18.220 --> 00:47:19.200
All right.

00:47:19.200 --> 00:47:20.000
That's it for my extras.

00:47:20.000 --> 00:47:21.100
Okay.

00:47:21.100 --> 00:47:21.980
I've got a few.

00:47:21.980 --> 00:47:27.680
The videos for PyCon US 2022 are up.

00:47:27.680 --> 00:47:28.580
So, yay.

00:47:28.580 --> 00:47:29.780
You can watch them now.

00:47:29.780 --> 00:47:31.460
I'll have a link in the show notes.

00:47:31.460 --> 00:47:34.660
But you can also just look on YouTube and search for PyCon US.

00:47:34.660 --> 00:47:36.400
Yeah.

00:47:36.400 --> 00:47:37.680
So I'm looking forward to it.

00:47:37.680 --> 00:47:39.600
I've got a whole stack of ones I want to watch.

00:47:39.600 --> 00:47:42.400
I unfortunately didn't get a chance to make it this year.

00:47:42.400 --> 00:47:45.340
So I'm looking forward to participating in this way.

00:47:45.340 --> 00:47:49.220
Second thing I wanted to bring up is another podcast.

00:47:49.220 --> 00:47:52.680
So there's another Python podcast out there called the Sad Python Girls Club.

00:47:52.680 --> 00:47:56.200
So far they have two episodes.

00:47:56.200 --> 00:47:58.020
The second episode they interviewed Brett Cannon.

00:47:58.020 --> 00:47:59.380
And it's good.

00:47:59.380 --> 00:48:01.680
They're not actually sad.

00:48:01.680 --> 00:48:06.440
The sad comes from that they used to be emo people when they were young.

00:48:06.440 --> 00:48:08.380
So I thought that was interesting.

00:48:08.380 --> 00:48:11.520
So I listened to a lot of the same music.

00:48:11.520 --> 00:48:12.860
Nice.

00:48:12.860 --> 00:48:13.100
All right.

00:48:13.100 --> 00:48:14.360
Congrats to them for starting that.

00:48:14.360 --> 00:48:14.620
That's cool.

00:48:14.620 --> 00:48:15.240
Yeah.

00:48:15.240 --> 00:48:20.680
Third thing was is I'm going to do this publicly to try to get me motivated to finish it.

00:48:20.680 --> 00:48:21.900
The pytest course.

00:48:22.480 --> 00:48:25.940
So yes, I've started work on a pytest course.

00:48:25.940 --> 00:48:31.000
And it will be through the Talk Python Michael Kennedy thing.

00:48:31.000 --> 00:48:33.080
Unless, you know, unless it's really terrible.

00:48:33.080 --> 00:48:34.600
And then he probably won't want to do it.

00:48:36.340 --> 00:48:37.520
No, it'll be great, Brian.

00:48:37.520 --> 00:48:38.400
I'm looking forward to it.

00:48:38.400 --> 00:48:39.800
Yeah.

00:48:39.800 --> 00:48:47.380
So I, man, a couple of days ago, I recorded like 20 minutes for the video with the mic off.

00:48:47.380 --> 00:48:51.240
I've done that.

00:48:51.240 --> 00:48:53.320
Or two mics on where there's a weird echo.

00:48:53.320 --> 00:48:55.340
It's offset by 20 milliseconds.

00:48:55.340 --> 00:48:56.120
And no.

00:48:56.360 --> 00:49:00.660
But I'm looking forward to getting that out because a lot of people have asked for it.

00:49:00.660 --> 00:49:02.160
So that's in the works.

00:49:02.160 --> 00:49:03.140
Fantastic.

00:49:03.140 --> 00:49:04.160
I think that's cool, Brian.

00:49:04.160 --> 00:49:05.260
You need to finish it.

00:49:05.260 --> 00:49:08.960
We're all a little, none of us, none of us write enough tests.

00:49:08.960 --> 00:49:10.740
We need more.

00:49:10.740 --> 00:49:11.620
We can use the course.

00:49:11.620 --> 00:49:15.020
That's all for me.

00:49:15.020 --> 00:49:15.900
Mark, either of you guys.

00:49:15.900 --> 00:49:16.120
Yeah.

00:49:16.120 --> 00:49:18.460
You got anything else you want to give a shout out to before we wrap it up?

00:49:18.460 --> 00:49:19.880
I guess I better shout out.

00:49:19.880 --> 00:49:20.960
Go ahead, Mark.

00:49:20.960 --> 00:49:24.880
No, I said I better shout out since you highlighted the cheerleaders earlier.

00:49:25.120 --> 00:49:29.240
I'm pretty sure that was my daughter, Isabel, and a friend, Olivia, and Jess listening.

00:49:29.240 --> 00:49:33.800
So if they've hung with us this long through Python podcast, then I better shout out to them.

00:49:33.800 --> 00:49:34.300
Thanks.

00:49:34.300 --> 00:49:35.260
Right on.

00:49:35.260 --> 00:49:35.680
That's cool.

00:49:35.680 --> 00:49:45.980
And I would just say, if you're interested in any sort of public company, complicated organizational structures like Tesla or Apple or anything, we have some of them on our website on LexChart.

00:49:45.980 --> 00:49:50.020
And if you want others, just drop us a line and we'll build them.

00:49:50.020 --> 00:49:50.700
Nice.

00:49:50.700 --> 00:49:51.440
Yeah, that's very cool.

00:49:51.440 --> 00:49:52.420
All right.

00:49:52.420 --> 00:49:53.980
Shall we close out with a joke, Brian?

00:49:53.980 --> 00:49:55.020
Yes.

00:49:55.480 --> 00:50:03.760
I wanted to come up with something that I felt was a little bit associated with learning to code and being somewhat beginner, even though what these guys built is not at all beginner.

00:50:03.760 --> 00:50:05.620
But I know that they've been on that path recently.

00:50:05.620 --> 00:50:06.800
So here we go.

00:50:07.180 --> 00:50:14.080
So this one is an animated GIF of a very frustrated person carrying their computer out, throwing it in the dumpster in the back.

00:50:14.080 --> 00:50:20.860
It says, programmers, when they finally fix all their syntax errors in their code, just to be confronted with a bug.

00:50:21.240 --> 00:50:21.860
I don't know about you.

00:50:21.860 --> 00:50:23.920
I remember when I was learning C++.

00:50:23.920 --> 00:50:26.960
I was so happy when I got my complicated code to compile.

00:50:26.960 --> 00:50:30.960
And then I realized, no, that's just the beginning of the hair pulling part.

00:50:31.980 --> 00:50:32.400
Yeah.

00:50:32.400 --> 00:50:33.760
It's Ron Swanson.

00:50:33.760 --> 00:50:34.160
Yeah.

00:50:34.160 --> 00:50:34.360
Yeah.

00:50:34.360 --> 00:50:34.720
Yeah.

00:50:34.720 --> 00:50:39.160
Yeah.

00:50:39.160 --> 00:50:39.800
Yeah.

00:50:39.800 --> 00:50:40.360
Absolutely.

00:50:40.360 --> 00:50:41.340
All right.

00:50:41.340 --> 00:50:42.520
Thanks a lot.

00:50:42.520 --> 00:50:43.380
That's all I got, Brian.

00:50:43.380 --> 00:50:44.040
Excellent.

00:50:44.040 --> 00:50:44.680
That was fun.

00:50:45.220 --> 00:50:47.340
Thanks, Ben and Mark for showing up.

00:50:47.340 --> 00:50:48.760
And thanks, Michael, as always.

00:50:48.760 --> 00:50:49.580
It's been fun.

00:50:49.580 --> 00:50:50.200
Thank you, guys.

00:50:50.200 --> 00:50:50.780
You bet.

00:50:50.780 --> 00:50:51.400
Bye, everyone.

00:50:51.400 --> 00:50:52.080
Bye.

00:50:52.080 --> 00:50:52.740
Cheers.

