WEBVTT

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

00:00:04.980 --> 00:00:09.320
It's episode 85, recorded on July 3rd, 2018.

00:00:09.320 --> 00:00:10.360
I'm Michael Kennedy.

00:00:10.360 --> 00:00:11.200
And I'm Brian Okken.

00:00:11.200 --> 00:00:11.920
Hey, Brian. How are you doing?

00:00:11.920 --> 00:00:13.160
I am doing great today.

00:00:13.160 --> 00:00:16.120
I know. It's another day in paradise here in the Pacific Northwest, isn't it?

00:00:16.120 --> 00:00:19.860
Yeah, as long as you're not driving, because it's the 3rd of July.

00:00:19.860 --> 00:00:22.660
That can be problematic. We do have our traffic issues, don't we?

00:00:22.660 --> 00:00:23.220
Yeah.

00:00:23.220 --> 00:00:27.380
Yeah. Well, yeah, before we get to items, I want to say thank you to DigitalOcean.

00:00:27.480 --> 00:00:29.820
They've been supporting the show in a major way.

00:00:29.820 --> 00:00:33.900
And so, you know, like I've said, our stuff runs on DigitalOcean, which is really great.

00:00:33.900 --> 00:00:39.700
If you want yours to run on it, you go to pythonbytes.fm/DigitalOcean, get $100 free credit for new users.

00:00:39.700 --> 00:00:47.220
I find myself, Brian, more and more loving the concept of limited use of type hints in just the right places.

00:00:47.220 --> 00:00:49.240
I was just typing that 15 minutes ago.

00:00:49.240 --> 00:00:49.600
Were you?

00:00:49.600 --> 00:00:49.920
Yeah.

00:00:49.920 --> 00:00:51.600
Yeah. Yeah. That's nice.

00:00:51.600 --> 00:00:54.080
The more I use them, the more I'm warming to them.

00:00:55.200 --> 00:00:59.820
And there's a couple of resources that came by just recently that I really enjoyed.

00:00:59.820 --> 00:01:04.820
So there's an article called The State of Type Hints in Python.

00:01:04.820 --> 00:01:12.400
And this is a fairly thorough article, but it pretty much like, okay, now it's 2018.

00:01:12.400 --> 00:01:14.680
What is it like to use type hints now?

00:01:15.700 --> 00:01:25.040
And especially, and I, okay, I'm, the article talks about if you want to use type hints in 2.7 and prior to 3.6 sort of stuff.

00:01:25.260 --> 00:01:35.780
And that's doable.

00:01:35.780 --> 00:01:36.400
Python 3.6.

00:01:36.400 --> 00:01:44.240
Because you can use commented type annotations in 2.7, I believe, because they're just comments.

00:01:44.240 --> 00:01:50.980
But adding the little arrows for the types and the colons and everything, it's more concise and it looks better.

00:01:50.980 --> 00:02:00.420
And I, my personal feeling is, unless you really are trying to convert a large code base, which I know some people are, I would switch to 3.1 first and then add type hints.

00:02:00.620 --> 00:02:02.740
If it was me, if you have that option.

00:02:02.740 --> 00:02:03.060
Yeah.

00:02:03.060 --> 00:02:07.340
And 3.6 is even better than 3.5 because you can put types on variables.

00:02:07.340 --> 00:02:10.580
You can, although I find my, I'm not really doing that.

00:02:10.580 --> 00:02:14.860
When I'm using type hints, I'm just mostly doing it for interface, to document interfaces.

00:02:15.160 --> 00:02:21.220
You know where I end up doing that is where there are core functions that I can't control.

00:02:21.220 --> 00:02:31.900
So I need to call a function and I know it returns something rich that I know what the type is and I would like to be able to get better editor experiences, better autocomplete.

00:02:32.160 --> 00:02:35.840
But it's a package function, not something I've created.

00:02:35.840 --> 00:02:36.300
Okay.

00:02:36.300 --> 00:02:41.200
So then you can say this variable is a, you know, SQLAlchemy session, for example.

00:02:41.200 --> 00:02:43.380
And then it's like, oh, I see.

00:02:43.380 --> 00:02:47.160
Now you've got add and delete and all this stuff and it's amazing, right?

00:02:47.160 --> 00:02:47.600
Yeah.

00:02:47.600 --> 00:02:59.900
And, you know, one of the things I like about the article and I agree with is the main point of a good reason to use type hints isn't, I mean, it is good to be able to catch all the, catch more bugs and incompatibilities.

00:02:59.900 --> 00:03:13.980
But it does, there's a lot of reasons why it makes your, makes your code more maintainable and more readable because there's, you just have that option to be able to document it right there to say, hey, this, this is the type that this function needs.

00:03:14.240 --> 00:03:22.840
So that there's so many things and the article walks through a few of them, like refactoring is easier, helping when you come back and read it later, it makes it more obvious.

00:03:22.840 --> 00:03:30.180
I mean, when you're writing, yes, there are some great polymorphic functions that can take multiple types of type, multiple types.

00:03:30.180 --> 00:03:33.760
But, you know, most of the code I write really does expect one type.

00:03:33.760 --> 00:03:38.260
It expects a list or maybe the most generic thing is it expects an iterable.

00:03:38.260 --> 00:03:42.460
And I'm actually still not sure how to write that in the type shed stuff.

00:03:42.460 --> 00:03:43.240
I'm sure there's a way.

00:03:43.820 --> 00:03:46.260
But yeah, this article does talk about things like unions.

00:03:46.260 --> 00:03:56.920
I ran my pie on my, on some of my code and I realized that I had some uninitial, some default values set to none, which I wanted to be okay.

00:03:56.920 --> 00:04:00.920
But if they're not none, they're strings or they're integers or something.

00:04:00.920 --> 00:04:05.040
And the type system allows you to add a union type.

00:04:05.040 --> 00:04:08.280
So you can say, well, it's, it's either none or it's a string.

00:04:08.720 --> 00:04:10.780
And it's pretty interesting.

00:04:10.780 --> 00:04:17.640
But this article talks about a lot of stuff that I really had forgotten about actually is like interface stub files.

00:04:17.640 --> 00:04:20.540
And I haven't worked with those at all yet.

00:04:20.540 --> 00:04:29.640
And I know that the type shed is around that allows these, that has these interface stub files for the standard library and a bunch of other popular libraries.

00:04:29.780 --> 00:04:32.060
But I haven't really used it yet.

00:04:32.060 --> 00:04:35.580
So, or maybe I have, but I just don't know about it.

00:04:35.580 --> 00:04:36.360
But I don't know.

00:04:36.360 --> 00:04:37.140
This is good.

00:04:37.140 --> 00:04:37.420
Yeah.

00:04:37.420 --> 00:04:43.040
You have an interesting quote in here that type hints should be used whenever unit tests are worth writing.

00:04:43.220 --> 00:04:44.300
What's the backstory on that?

00:04:44.300 --> 00:04:47.460
It's just one of the, in the conclusion of the article, it talked about that.

00:04:47.460 --> 00:04:51.200
It said, okay, all of this information, but when should you use it?

00:04:51.200 --> 00:04:57.980
I mean, if you're going to just write a little utility function for, I don't know, for your own use or something, do you need type hints then?

00:04:57.980 --> 00:05:03.400
And, and they just came up with this rule of thumb is if you're going to, I quoted it just as is.

00:05:03.400 --> 00:05:04.620
It says unit test.

00:05:04.740 --> 00:05:07.600
I personally would just say automated tests.

00:05:07.600 --> 00:05:13.860
If the code you're writing is worth having automated tests, it's worth putting, trying to think about where you're going to put type.

00:05:13.860 --> 00:05:25.600
The other thing I wanted to add was I was listening to, I got about halfway through it so far, but there's a recent seminar that Guido presented at Stanford called optional static typing for Python.

00:05:25.600 --> 00:05:34.280
And in part of that, it talks about mypy, but it talks about some of the beginnings of this, of like where this came from and how it came to be,

00:05:34.380 --> 00:05:35.160
what it is now.

00:05:35.160 --> 00:05:38.360
And so for, and what, how are we doing with it now?

00:05:38.360 --> 00:05:40.460
So it's a, it's about an hour and a half though.

00:05:40.460 --> 00:05:42.580
So it's, it's a chunk of time to watch, but.

00:05:42.580 --> 00:05:43.200
It's a commitment.

00:05:43.200 --> 00:05:43.720
Yeah.

00:05:43.720 --> 00:05:44.440
But it sounds interesting.

00:05:44.440 --> 00:05:44.800
Yeah.

00:05:44.800 --> 00:05:49.920
But I think I recommend even like the first 20 minutes for some of the backstory is, is interesting.

00:05:49.920 --> 00:05:50.280
Okay.

00:05:50.280 --> 00:05:50.700
Yeah.

00:05:50.700 --> 00:05:52.220
That's, that's really cool.

00:05:52.220 --> 00:05:54.640
I'm definitely a fan of it and I'm glad you're bringing it up.

00:05:54.640 --> 00:05:55.560
There's some nice stuff in there.

00:05:55.560 --> 00:06:00.260
So I have no idea how to transition from a type hints to MongoDB.

00:06:00.260 --> 00:06:02.640
So I guess that's a reasonable transition.

00:06:02.640 --> 00:06:03.280
That's it.

00:06:03.340 --> 00:06:06.060
So I've actually found a pretty interesting thing on MongoDB.

00:06:06.060 --> 00:06:08.100
People know that I'm a fan of course.

00:06:08.100 --> 00:06:14.200
And one of the big decision points, I think, when you're trying to decide, do I go with Django

00:06:14.200 --> 00:06:17.640
or do I go with one of these smaller web frameworks like Pyramid Flask?

00:06:17.640 --> 00:06:22.260
You know, many of the micro frameworks is the micro frameworks.

00:06:22.400 --> 00:06:23.720
You can pick the little pieces.

00:06:23.720 --> 00:06:24.840
I want SQL Alchemist here.

00:06:24.840 --> 00:06:26.560
And maybe this part's going to be Mongo.

00:06:26.560 --> 00:06:31.400
And this part's going to be this other aspect that I would like to bring into this framework

00:06:31.400 --> 00:06:32.720
for authentication or something.

00:06:32.720 --> 00:06:35.820
Whereas Django is more like, here are your big building blocks.

00:06:35.820 --> 00:06:37.180
Click them together.

00:06:37.180 --> 00:06:37.520
Right.

00:06:38.040 --> 00:06:42.080
And a big challenge there can be like the Django ORM and the admin stuff.

00:06:42.080 --> 00:06:43.320
It's all tied into that.

00:06:43.320 --> 00:06:47.040
And well, if you don't want to use that, then you're kind of out of luck, right?

00:06:47.040 --> 00:06:50.000
There's a lot of challenges of sort of bringing your own thing.

00:06:50.000 --> 00:06:53.000
You lose some of the value, at least, out of Django traditionally.

00:06:53.360 --> 00:07:00.720
So the Django ORM, it depends on a, not a particular SQL database, but it does assume a SQL database.

00:07:00.720 --> 00:07:01.380
Is that correct?

00:07:01.380 --> 00:07:02.480
Yeah, I believe so.

00:07:02.480 --> 00:07:03.280
I believe that's right.

00:07:03.280 --> 00:07:09.380
And things like the Django admin section, which is really valuable to some people, depends upon

00:07:09.380 --> 00:07:10.680
the Django ORM, right?

00:07:10.680 --> 00:07:12.660
So like there's these layers of stuff.

00:07:12.660 --> 00:07:14.980
And so if you pull out the bottom brick, there's problems.

00:07:14.980 --> 00:07:20.940
But I actually, this guy named Robin sent me a heads up about this thing on Twitter that

00:07:20.940 --> 00:07:26.280
I had never heard of, but it's pretty awesome, called Django MongoDB Connector.

00:07:26.280 --> 00:07:26.720
Cool.

00:07:26.720 --> 00:07:27.160
Yeah.

00:07:27.160 --> 00:07:34.120
So the idea is you continue to use the Django ORM just like you normally would, except it's

00:07:34.120 --> 00:07:36.700
now had its backend swapped out to be MongoDB.

00:07:36.700 --> 00:07:39.000
And that's pretty awesome.

00:07:39.000 --> 00:07:43.540
And at first you're like, okay, well, how much value am I going to get in that, right?

00:07:43.540 --> 00:07:49.040
Like if I give up, if I continue to use what is effectively a relational ORM, like you can't

00:07:49.040 --> 00:07:51.000
use the hierarchical documents, right?

00:07:51.000 --> 00:07:57.100
But what they've done, a little bit like MongoEngine, is the parameters that go into your query can

00:07:57.100 --> 00:07:58.960
be more interesting, right?

00:07:58.960 --> 00:08:04.120
So you would say, like imagine if you had a blog, you say blog.objects.filter, and you

00:08:04.120 --> 00:08:08.480
would pass like name equals something in traditional relational stuff.

00:08:09.180 --> 00:08:17.940
But in Mongo, you might want to traverse like into a blog object and then go find the name

00:08:17.940 --> 00:08:20.400
and then find that the name is contained in a set.

00:08:20.400 --> 00:08:26.140
And so you just pass different arguments to the filter parameter and boom, it becomes Mongo

00:08:26.140 --> 00:08:27.500
hierarchical enabled.

00:08:27.500 --> 00:08:27.980
It's beautiful.

00:08:27.980 --> 00:08:28.460
Wow.

00:08:28.460 --> 00:08:29.840
That's actually pretty cool.

00:08:29.840 --> 00:08:30.340
Isn't that cool?

00:08:30.340 --> 00:08:31.140
It's so simple.

00:08:31.140 --> 00:08:31.360
Yeah.

00:08:31.420 --> 00:08:31.580
Yeah.

00:08:31.580 --> 00:08:35.540
And it says you can also use it to connect third party apps like Django REST framework

00:08:35.540 --> 00:08:40.320
and Vueflow and other stuff, which heavily depend upon these Django models.

00:08:40.320 --> 00:08:43.360
They can now super easily be integrated with MongoDB as well.

00:08:43.360 --> 00:08:44.720
And it has a hilarious name.

00:08:44.720 --> 00:08:45.000
Yeah.

00:08:45.000 --> 00:08:46.680
What is his name?

00:08:46.680 --> 00:08:47.640
Django.

00:08:47.640 --> 00:08:47.960
Yeah.

00:08:47.960 --> 00:08:48.880
Or something like Django.

00:08:48.880 --> 00:08:53.300
The app, the official Django app you put in the settings file is Django.

00:08:53.300 --> 00:08:54.100
That's great.

00:08:54.100 --> 00:08:54.780
Yeah.

00:08:54.780 --> 00:08:56.080
Because for Django, I get it.

00:08:56.080 --> 00:08:56.860
Django, Mongo.

00:08:56.860 --> 00:08:57.820
Django, Mongo.

00:08:57.820 --> 00:08:58.900
Smushed together.

00:08:58.900 --> 00:08:59.440
Yeah, exactly.

00:09:00.040 --> 00:09:06.360
Another thing that's interesting is this is a Python 3.6 or higher only and Mongo 3.4 or

00:09:06.360 --> 00:09:09.700
higher, which is like, I don't know, a year, year and a half old, something like that.

00:09:09.700 --> 00:09:14.620
So it's not quite so new, but Python 3.6 is really quite new for the store.

00:09:14.620 --> 00:09:15.020
Yeah.

00:09:15.020 --> 00:09:19.200
But I mean, it just also seems like something you would start a project with.

00:09:19.200 --> 00:09:21.460
You probably wouldn't like rip apart an old project.

00:09:21.460 --> 00:09:22.520
Probably not.

00:09:22.520 --> 00:09:27.880
I mean, you may have an app you're trying to make better and migrate, but yeah, I would

00:09:27.880 --> 00:09:29.360
think you probably wouldn't really.

00:09:29.660 --> 00:09:30.260
Yeah.

00:09:30.260 --> 00:09:31.040
I'd throw that more in there.

00:09:31.040 --> 00:09:34.160
Just like it even has like a pretty high requirement for MongoDB.

00:09:34.160 --> 00:09:37.500
Just so if somebody's got like an older or something or another, you can't just jam it in there.

00:09:37.500 --> 00:09:39.620
You got to make sure you got the new goodness.

00:09:39.620 --> 00:09:40.100
Okay.

00:09:40.100 --> 00:09:43.960
So I was actually, so this is a not sort of related.

00:09:43.960 --> 00:09:50.140
I was talking to somebody about Mongo before and they asked me about migrations from if you're

00:09:50.140 --> 00:09:51.420
going to change the databases.

00:09:51.420 --> 00:09:53.340
Does Mongo have that sort of concept?

00:09:53.340 --> 00:09:54.780
It does have that concept.

00:09:55.100 --> 00:09:56.880
You do it a lot less often.

00:09:56.880 --> 00:10:01.920
Much of the time at what your migration is, is something like I'm adding an additional

00:10:01.920 --> 00:10:02.680
column here.

00:10:02.680 --> 00:10:05.120
I'm adding another table there, right?

00:10:05.120 --> 00:10:10.020
Like it's not that common that you're say deleting a column or you're renaming a column.

00:10:10.020 --> 00:10:13.420
It happens, but it's way less often than new column, new table.

00:10:13.420 --> 00:10:16.920
And in MongoDB, new column or new table is automatic.

00:10:16.920 --> 00:10:17.940
You don't do anything.

00:10:17.940 --> 00:10:19.820
It just, it just adapts, right?

00:10:19.820 --> 00:10:20.720
As you use it.

00:10:20.800 --> 00:10:24.400
So you don't actually run any scripts or migrations to do the common transformations.

00:10:24.400 --> 00:10:30.700
But if you're going to say like delete a column or reorganize your data, you would do the same

00:10:30.700 --> 00:10:32.500
thing and you would run a script against it.

00:10:32.500 --> 00:10:36.860
I don't think there's something like a limbic where there's like a framework for migrations,

00:10:36.860 --> 00:10:40.720
but the concept of like a migration with a script definitely exists, but it's not very

00:10:40.720 --> 00:10:41.000
common.

00:10:41.000 --> 00:10:41.400
All right.

00:10:41.400 --> 00:10:45.300
And I brought this up hopefully because if we're wrong about this, somebody can get ahold of

00:10:45.300 --> 00:10:46.660
us and tell us.

00:10:46.660 --> 00:10:49.240
So yeah, if there's some cool framework for doing that, let us know.

00:10:49.580 --> 00:10:51.180
Awesome.

00:10:51.180 --> 00:10:55.460
So what's this deal with Python idioms you got going on here?

00:10:55.460 --> 00:10:59.020
This was a tiny little article, which, you know, sometimes I like that.

00:10:59.020 --> 00:11:02.120
Just a small article of like, hey, I learned this thing and it's helpful.

00:11:02.120 --> 00:11:05.680
And here's a small blog post about it.

00:11:05.680 --> 00:11:09.040
And this was Amir Ratchnam.

00:11:09.040 --> 00:11:10.720
Why do I try to pronounce people's names?

00:11:10.720 --> 00:11:12.940
Anyway, multi-line strings.

00:11:12.940 --> 00:11:16.460
So the idiom he's talking about is multi-line strings.

00:11:16.460 --> 00:11:19.420
So if I've got, and we know this is like a triple quote.

00:11:19.420 --> 00:11:20.800
You can have strings.

00:11:20.800 --> 00:11:23.640
Strings can be multiple lines if you use triple quote.

00:11:23.640 --> 00:11:28.760
And we usually see these with doc strings, but it can be really anywhere.

00:11:28.760 --> 00:11:29.780
You're going to use a string.

00:11:29.780 --> 00:11:36.320
But if you're using it like in the middle of a function, it's awkward because it either,

00:11:36.900 --> 00:11:43.400
you have to, everything but the first line has to be, is like over on the left side of your page.

00:11:43.400 --> 00:11:45.720
And it's not indented the right place.

00:11:45.720 --> 00:11:50.140
And if you do indent it over, it's including all of those spaces in your string.

00:11:50.680 --> 00:11:55.800
But the way to get around it is to use a standard library function.

00:11:55.800 --> 00:12:00.020
The module or the package is textwrap and the function is ddent.

00:12:00.020 --> 00:12:01.960
So it's textwrap.ddent.

00:12:01.960 --> 00:12:04.940
And that will strip out.

00:12:04.940 --> 00:12:13.700
What it does is it takes, looks at all of the lines of the multi-line string and takes the common spacing at the beginning of it and just rips that off.

00:12:14.460 --> 00:12:16.220
So it's just automatic.

00:12:16.220 --> 00:12:23.700
And I was actually, I use this enough with, actually I use it, you know, generating tools and generating other things.

00:12:23.700 --> 00:12:30.340
And I can't think of a good example right now where I've used it, but I have used it enough times and I've looked this up that I want people to know about it.

00:12:30.340 --> 00:12:31.300
It's an easy trick.

00:12:31.300 --> 00:12:32.900
So it's good.

00:12:32.900 --> 00:12:33.660
Oh, I love it.

00:12:33.660 --> 00:12:34.460
I didn't know about it.

00:12:34.460 --> 00:12:34.840
Thank you.

00:12:34.840 --> 00:12:35.520
This is cool.

00:12:35.520 --> 00:12:41.000
So I've definitely had multi-line text strings because I've got some big formatted piece of text.

00:12:41.120 --> 00:12:49.200
And I'm like, all right, I, instead of trying to break this apart and turn it into something I can store in code, if I just, you know, triple quote it and put it in here, it's going to be golden.

00:12:49.200 --> 00:12:56.320
But you do get that weird, you've got to like indent it to the left outside of your function and it's all bizarro.

00:12:56.320 --> 00:13:03.580
So this lets you can keep your code looking really nice and it obviously puts the string to like visually into the block that it belongs in.

00:13:03.580 --> 00:13:04.080
It's really nice.

00:13:04.080 --> 00:13:04.420
I love it.

00:13:04.420 --> 00:13:04.620
Yeah.

00:13:04.620 --> 00:13:12.880
And I've also like tried to punt and like put, define a global variable or at least a file global variable so that I can get around it.

00:13:12.880 --> 00:13:15.040
But this is cleaner and it's good.

00:13:15.040 --> 00:13:16.060
It's a good thing.

00:13:16.060 --> 00:13:16.320
Yeah.

00:13:16.320 --> 00:13:16.800
I love it.

00:13:16.800 --> 00:13:17.180
That's awesome.

00:13:17.180 --> 00:13:19.480
Other good things include DigitalOcean.

00:13:20.480 --> 00:13:27.800
I definitely want to tell people about DigitalOcean because they're sponsoring the show in addition to just us being happy customers there.

00:13:27.800 --> 00:13:32.040
So you can go from zero to a customized server in 60 seconds.

00:13:32.040 --> 00:13:39.240
I've talked about how we've done cool stuff with virtual machines, how they've got spaces, how they've got other various things that are pretty awesome.

00:13:39.240 --> 00:13:41.700
Like the one click containers for like machine learning.

00:13:41.700 --> 00:13:45.500
One thing I haven't talked about yet is container distributions.

00:13:45.500 --> 00:13:57.260
So if you want to set up your own like Docker container, you can go click over there and create a core OS or Fedora atomic server, even a rancher OS, which I've never used, but it's got a cool icon.

00:13:57.260 --> 00:14:05.520
And you can just fire one of those up and it's like all ready to go to be your container host for all sorts of cool Docker stuff and Kubernetes.

00:14:05.520 --> 00:14:09.800
So definitely check them out over at pythonbytes.fm/DigitalOcean.

00:14:09.800 --> 00:14:12.680
Get a $300 credit to play around with those kinds of things.

00:14:12.680 --> 00:14:14.060
That's actually pretty cool.

00:14:14.060 --> 00:14:14.680
I like it.

00:14:14.680 --> 00:14:15.300
Yeah, I like it too.

00:14:15.300 --> 00:14:18.000
And I had a DigitalOcean accident the other day.

00:14:18.000 --> 00:14:18.880
Oh no, what happened?

00:14:18.880 --> 00:14:23.860
Well, I wore my favorite DigitalOcean t-shirt to work and I spilled coffee on it.

00:14:23.860 --> 00:14:28.220
But luckily it was a gray shirt and it didn't show up as a stain.

00:14:28.220 --> 00:14:29.080
So it's all good.

00:14:29.080 --> 00:14:30.000
It's pretty fail safe.

00:14:30.000 --> 00:14:30.380
Yeah.

00:14:30.380 --> 00:14:31.000
Unless you're painting.

00:14:31.000 --> 00:14:34.960
So how do you feel about your design skills, Brian?

00:14:34.960 --> 00:14:40.300
Are you a fan of shuffling around CSS and HTML and that kind of stuff?

00:14:40.300 --> 00:14:46.820
No, CSS is definitely one of those things where I either rely on a framework or I try to hire somebody.

00:14:46.820 --> 00:14:47.600
Nice.

00:14:47.600 --> 00:14:56.660
So something that you might be able to use if you're using Flask, and I know you've played around Flask recently, is this thing called Flaskerizer.

00:14:56.660 --> 00:14:57.420
Flaskerizer.

00:14:57.420 --> 00:14:59.580
Okay, I don't know what the name stands for.

00:15:00.220 --> 00:15:02.900
I guess to make Flask-ish or something.

00:15:02.900 --> 00:15:07.500
But the idea is you can go to one of these places that has Bootstrap themes.

00:15:07.500 --> 00:15:09.020
So Bootstrap is nice.

00:15:09.020 --> 00:15:11.880
Obviously it's a CSS front-end design framework.

00:15:11.880 --> 00:15:12.920
It's pretty well known.

00:15:13.320 --> 00:15:15.700
But what's really awesome about it are the themes.

00:15:15.700 --> 00:15:24.560
Like people make these pre-made themes, and for like $10 or even free a lot of times, you can get incredible web designs, and you just drop them in, right?

00:15:24.560 --> 00:15:27.660
You just put in your logic into the bits where it goes.

00:15:28.020 --> 00:15:39.460
So this Flaskerizer thing is what you can do is you can download the themes from certain locations that have a known format, and it will convert the static Bootstrap theme into a Flask app.

00:15:39.460 --> 00:15:40.440
Oh, that's cool.

00:15:40.440 --> 00:15:41.040
Yes.

00:15:41.040 --> 00:15:43.160
Isn't that sweet?

00:15:43.920 --> 00:15:48.000
So instead of worrying about how it all goes together, you just go, you know, command line, boom.

00:15:48.000 --> 00:15:51.380
Now I've got like a dynamic running Bootstrap theme in Flask.

00:15:51.380 --> 00:15:51.860
I like it.

00:15:51.860 --> 00:15:52.100
Yeah.

00:15:52.100 --> 00:15:55.160
So there's a couple of sites that they work with.

00:15:55.160 --> 00:16:01.500
I don't know how general this is because I don't know how common Bootstrap themes are, but I think it's pretty cool.

00:16:01.500 --> 00:16:07.720
And, of course, if you open up the website and you look around, you can tell that it's a proper design.

00:16:07.720 --> 00:16:17.220
This is the GitHub repo because they go from just plain white, like no design, no logo, to clearly a designer with a black turtleneck.

00:16:17.220 --> 00:16:21.220
Yeah, he's definitely a designer.

00:16:21.220 --> 00:16:21.820
Yeah, definitely.

00:16:21.820 --> 00:16:23.100
Dark black glasses, too.

00:16:23.100 --> 00:16:24.180
And a beard.

00:16:24.180 --> 00:16:24.820
Yeah, exactly.

00:16:24.820 --> 00:16:26.200
Oh, he's all good.

00:16:26.200 --> 00:16:27.600
He's got all the boxes checked.

00:16:27.600 --> 00:16:28.920
Very nice.

00:16:28.920 --> 00:16:37.340
So if you want to do a Flask site and you want a design to, you know, go pick a theme and just start working with that design, check out FlaskRiser.

00:16:37.340 --> 00:16:38.760
It could get you up and running really quick.

00:16:38.760 --> 00:16:39.680
Wow, interesting.

00:16:39.680 --> 00:16:40.720
I was reading down this.

00:16:40.720 --> 00:16:47.220
This is one of the few applications I've ever seen or the frameworks that uses Nose 2 as its testing.

00:16:47.220 --> 00:16:47.920
Oh, nice.

00:16:47.920 --> 00:16:49.180
What's the story with Nose 2?

00:16:49.180 --> 00:16:50.200
I only know about Nose.

00:16:50.200 --> 00:16:56.860
Well, so Nose was sort of kind of abandoned, but Nose 2 was a, well, I'll offend anybody that's still working on Nose.

00:16:57.100 --> 00:17:05.420
But Nose 2 was kind of trying to reboot it and redo a lot of the, make a backward compatibility break.

00:17:05.420 --> 00:17:10.280
So it doesn't do some of the things, but it does other neat things and clean up the code base.

00:17:10.280 --> 00:17:17.840
But still, it started kind of running, getting some steam at the same time pytest was sort of getting a lot of steam.

00:17:18.480 --> 00:17:23.260
So I think that there's not a lot of projects that use it, but I mean, it's still reasonable.

00:17:23.260 --> 00:17:30.480
It's just since there's not that many people working on it, getting fixes and stuff is sometimes an issue.

00:17:30.480 --> 00:17:31.160
Yeah, nice.

00:17:31.160 --> 00:17:32.560
Okay, well, very interesting.

00:17:32.560 --> 00:17:33.240
Very interesting.

00:17:33.240 --> 00:17:34.780
So are you learning Python now?

00:17:34.780 --> 00:17:36.160
Is this your next project?

00:17:37.760 --> 00:17:45.900
No, but I thought this was fun because I encourage every youth I meet and actually everybody I meet to learn Python.

00:17:45.900 --> 00:17:48.380
And I always tell them.

00:17:48.380 --> 00:17:48.800
Good advice.

00:17:48.800 --> 00:17:49.240
Good advice.

00:17:49.240 --> 00:17:49.500
Yeah.

00:17:49.500 --> 00:17:53.260
The reason I tell them the reason isn't so that you can become a programmer.

00:17:53.540 --> 00:17:59.400
It's so that you can, like, it's a power boost to what are the other skills you have.

00:17:59.400 --> 00:18:05.020
So if you're a biology student, also learn Python because now you're a biology student that knows Python.

00:18:05.020 --> 00:18:11.140
You're now the favorite person in the lab that can actually solve the problem with the data that they got in Excel or something, right?

00:18:11.140 --> 00:18:12.260
Yeah, and it doesn't matter.

00:18:12.260 --> 00:18:13.560
It's science or non-science.

00:18:13.560 --> 00:18:17.720
If you're an artist that also knows how to code, it's just going to help.

00:18:17.720 --> 00:18:19.120
There's no downside.

00:18:19.460 --> 00:18:27.540
And so a lot of times with code, people kind of have – they start writing code and it's precious to them and they don't want to throw it away because they worked really hard on it.

00:18:27.540 --> 00:18:31.140
And so I wanted to highlight this article because of its advice.

00:18:31.140 --> 00:18:34.380
This is – I think it's a real Python.

00:18:34.380 --> 00:18:35.660
Yeah, it's a real Python article.

00:18:35.660 --> 00:18:39.340
And it's called Learn Python the Methodical Way.

00:18:39.340 --> 00:18:41.260
And I'm just going to read the steps.

00:18:41.260 --> 00:18:51.340
The steps are make your way through a tutorial or a chapter from what you're learning, a book or something, that teaches you some discrete four to six-step skill.

00:18:51.340 --> 00:18:54.320
You're going to work through it while you're reading it.

00:18:54.320 --> 00:18:58.500
Now write down the steps as distinctly and generically as possible.

00:18:58.500 --> 00:19:09.460
Put the tutorial and chapter and its solutions away and build your project from scratch and peek at the solution and the steps only when you get stuck.

00:19:09.780 --> 00:19:12.660
Now erase the whole thing and do it again.

00:19:12.660 --> 00:19:19.340
And then go back, completely put it away, and then erase everything and do it again like a day or two later.

00:19:19.340 --> 00:19:28.960
And this sort of erasing and redoing it, I think at least a couple times is good for people because it gets rid of that preciousness.

00:19:28.960 --> 00:19:32.800
Because the second time you do something, it's always faster.

00:19:32.800 --> 00:19:34.880
Anyway, I just thought this was neat advice.

00:19:34.880 --> 00:19:35.740
So I thought I'd share it.

00:19:35.740 --> 00:19:36.260
I like it.

00:19:36.260 --> 00:19:37.440
It's pretty interesting.

00:19:38.440 --> 00:19:42.820
I definitely feel like when you're new, you feel like I put a lot of effort into that.

00:19:42.820 --> 00:19:44.880
And so there's no way I'm throwing that away.

00:19:44.880 --> 00:19:50.720
But the really valuable lesson is actually the second time, it's probably better.

00:19:50.720 --> 00:19:57.360
And the third time, you're like, whoa, this is really a much improved version of what I did.

00:19:57.360 --> 00:19:59.940
And it takes less and less time, of course, right?

00:20:00.060 --> 00:20:00.180
Yeah.

00:20:00.180 --> 00:20:04.400
And also, it's easier to throw away the cruft.

00:20:04.440 --> 00:20:10.880
And if it's just something you spend an hour working on, even if you had to redo the entire thing, it's only a wasted hour.

00:20:10.880 --> 00:20:15.000
And you realize that you can really do it again pretty fast.

00:20:15.180 --> 00:20:21.260
And so the one part I kind of disagree about is I never code without resources anymore.

00:20:21.920 --> 00:20:30.760
But I wouldn't say try to do it just for memory, but try to use the normal resources that you would otherwise, like Google or Stack Overflow or whatever.

00:20:30.760 --> 00:20:31.120
Right.

00:20:31.120 --> 00:20:31.480
Exactly.

00:20:31.480 --> 00:20:32.640
To look up things.

00:20:32.640 --> 00:20:33.440
You don't have...

00:20:33.440 --> 00:20:37.580
I think it's silly to try to memorize the order of parameters to a function.

00:20:37.580 --> 00:20:40.280
That's what code completion is for and stuff like that.

00:20:40.500 --> 00:20:40.820
Exactly.

00:20:40.820 --> 00:20:42.880
That's probably a type-ins, isn't it?

00:20:42.880 --> 00:20:43.580
Yeah.

00:20:43.580 --> 00:20:45.580
So I totally agree.

00:20:45.580 --> 00:20:52.160
I don't think these completely abstract, in isolation sorts of things make sense.

00:20:52.160 --> 00:20:59.220
But maybe the idea is don't just keep following these steps three times, but try to recreate it from your mind.

00:20:59.220 --> 00:21:03.360
And to me, recreating it is totally fine to go, but how do I actually insert that thing?

00:21:03.360 --> 00:21:05.220
What is the function I call it?

00:21:05.220 --> 00:21:06.960
That is a totally reasonable Google search.

00:21:06.960 --> 00:21:07.720
Yeah, definitely.

00:21:07.720 --> 00:21:08.520
Awesome.

00:21:08.520 --> 00:21:11.220
So we've talked about debuggers before.

00:21:11.220 --> 00:21:13.540
We talked about the breakpoint thing last time.

00:21:13.540 --> 00:21:28.740
One of the areas where doing proper debugging, and by proper I mean visual debugging, not command line debugging, but like visual debugging where you see all the state of the system and everything, that can be really tricky in Jupyter Notebooks, right?

00:21:28.740 --> 00:21:30.780
Because, you know, like attach to them.

00:21:30.780 --> 00:21:32.900
They're running in the notebook, in your web browser, right?

00:21:32.900 --> 00:21:33.820
Yeah, I've never tried.

00:21:33.820 --> 00:21:34.140
Yeah.

00:21:34.140 --> 00:21:37.800
So you can use PDB, but that's like a command line thing.

00:21:37.800 --> 00:21:39.940
It just happens to be the command line is a Jupyter cell.

00:21:39.940 --> 00:21:41.560
That's not the same, I don't think.

00:21:41.560 --> 00:21:45.280
However, there's this thing called Pixie Debugger.

00:21:45.280 --> 00:21:54.320
So the idea is you include this Pixie Debugger into your Jupyter Notebook, and then it becomes a visual debugger for each cell that you're working in.

00:21:54.320 --> 00:21:54.880
Oh, wow.

00:21:55.000 --> 00:21:55.520
It's pretty cool.

00:21:55.520 --> 00:21:58.960
And they have a really nice video, and they've got some nice screenshots of the thing I linked to.

00:21:58.960 --> 00:22:07.720
And so it has one of those, I don't know what the right word is, like a magic command for Jupyter that escapes out of Python and speaks to Jupyter, like the percent, percent.

00:22:08.440 --> 00:22:12.620
And you can just say percent, percent, debug this function or debug this cell.

00:22:13.000 --> 00:22:19.560
And then, boom, it just drops into a thing where you can, like, step over, step into, view all the states of all the variables.

00:22:19.560 --> 00:22:21.200
You can set little breakpoints.

00:22:21.200 --> 00:22:26.360
There's like a little command prompt REPL underneath when it's paused.

00:22:26.420 --> 00:22:32.480
And you can just ask it questions, like type in a variable, and it'll show you the value or even change the value of the variable, things like that.

00:22:32.480 --> 00:22:33.020
Oh, nice.

00:22:33.020 --> 00:22:34.420
Yeah, this is neat.

00:22:34.420 --> 00:22:36.460
Yeah, so if you're working in Jupyter, this is really cool.

00:22:36.460 --> 00:22:44.100
And it's interesting because it comes from the video that the guy did, David Tayeb.

00:22:44.100 --> 00:22:48.400
It was at the Watson data platform.

00:22:48.400 --> 00:22:52.760
So a Jupyter Notebook hosted on IBM Watson, which was pretty interesting.

00:22:52.760 --> 00:22:53.360
Oh, yeah.

00:22:53.460 --> 00:22:58.840
So I didn't even know that was a thing, but apparently the IBM Watson data platform is another one of these hosted notebooks.

00:22:58.840 --> 00:23:07.940
And the reason I bring that up is he's like, well, we needed a really good way to debug these things called, what do they call them, Pixie Apps, I believe.

00:23:07.940 --> 00:23:18.560
And a Pixie app is like a GUI interactive thing that you can put in a notebook that's kind of like a web app, but kind of like a desktop app, but in a notebook.

00:23:18.560 --> 00:23:19.840
It's kind of funky.

00:23:19.840 --> 00:23:21.080
So I don't know.

00:23:21.080 --> 00:23:23.000
Maybe I'll cover the Pixie apps as well.

00:23:23.040 --> 00:23:24.620
But that's also kind of an interesting thing.

00:23:24.620 --> 00:23:27.120
It's kind of like Flask running inside of a notebook.

00:23:27.120 --> 00:23:28.340
It's bizarre, but cool.

00:23:28.340 --> 00:23:29.120
Yeah, neat.

00:23:29.120 --> 00:23:29.440
Yeah.

00:23:29.520 --> 00:23:36.900
So anyway, anyone out there doing notebooks and wishing for a visual debugger, check out the video that I linked to at the end.

00:23:36.900 --> 00:23:40.080
It's only in like two or three minutes, and you'll know whether or not this is for you.

00:23:40.080 --> 00:23:41.060
It looks cool to me, though.

00:23:41.060 --> 00:23:41.320
Yeah.

00:23:41.320 --> 00:23:45.820
And having debugger tools available in any, wherever you're working is good.

00:23:45.820 --> 00:23:46.580
Yeah, I know.

00:23:47.260 --> 00:23:50.840
I always feel like I don't need a debugger until I'm like, geez, I really want a debugger for this.

00:23:50.840 --> 00:23:51.600
This is just not.

00:23:51.600 --> 00:23:53.520
Until you really need a debugger.

00:23:53.520 --> 00:23:53.820
Yeah.

00:23:54.240 --> 00:23:54.560
Exactly.

00:23:54.560 --> 00:23:54.920
Exactly.

00:23:54.920 --> 00:23:58.420
It's not that often, but when I do need it, I'm like, oh, my gosh, I'm so happy this is here.

00:23:58.420 --> 00:23:59.500
Awesome.

00:23:59.500 --> 00:23:59.760
All right.

00:23:59.760 --> 00:24:01.200
Well, Brian, thank you for sharing everything.

00:24:01.200 --> 00:24:03.820
Anything else you want to give a shout out to while we're talking?

00:24:03.820 --> 00:24:04.620
No, not today.

00:24:04.620 --> 00:24:04.980
Yeah.

00:24:04.980 --> 00:24:05.860
Not me either.

00:24:06.040 --> 00:24:08.500
So, well, have a happy 4th of July.

00:24:08.500 --> 00:24:11.100
It is probably exactly that day when this comes out.

00:24:11.100 --> 00:24:11.760
Oh, you too.

00:24:11.760 --> 00:24:12.360
Thanks.

00:24:12.360 --> 00:24:12.880
Yeah, thanks.

00:24:12.880 --> 00:24:13.160
Yeah.

00:24:13.160 --> 00:24:13.580
Bye, everyone.

00:24:13.580 --> 00:24:14.000
Bye.

00:24:14.000 --> 00:24:16.800
Thank you for listening to Python Bytes.

00:24:16.800 --> 00:24:19.380
Follow the show on Twitter via at Python Bytes.

00:24:19.380 --> 00:24:22.260
That's Python Bytes as in B-Y-T-E-S.

00:24:22.260 --> 00:24:25.660
And get the full show notes at Pythonbytes.fm.

00:24:25.660 --> 00:24:30.020
If you have a news item you want featured, just visit Pythonbytes.fm and send it our way.

00:24:30.020 --> 00:24:32.760
We're always on the lookout for sharing something cool.

00:24:33.400 --> 00:24:36.120
On behalf of myself and Brian Okken, this is Michael Kennedy.

00:24:36.120 --> 00:24:39.740
Thank you for listening and sharing this podcast with your friends and colleagues.

