Flask is now eight years old, and until recently had been going along pretty steady state.
It had been hanging around at version 0.11 and 0.12 for some time.
After a year-long effort, the web framework has now been updated to Flask 1.0.
David Lord is here to share the big news with us.
He's the maintainer of Flask, and we dive into the new features,
as well as the future directions of Flask with him.
This is Talk Python to Me, episode 177, recorded August 30th, 2018.
Welcome to Talk Python to Me, a weekly podcast on Python,
the language, the libraries, the ecosystem, and the personalities.
This is your host, Michael Kennedy. Follow me on Twitter, where I'm @mkennedy.
Keep up with the show and listen to past episodes at talkpython.fm,
and follow the show on Twitter via at Talk Python.
This episode is brought to you by Linode and 10x Agent On Demand.
Please check out what they're offering during their segments. It really helps support the show.
David, welcome to Talk Python.
Hello. Thanks for having me.
Hello. Yeah, it's great to have you here.
It's really good to see lots of vibrant activity around Flask,
and I know you're at the heart of much of this activity,
and I'm super excited about diving into it with you.
Yeah, let's get started.
Yeah, for sure. And so we're going to dive into Flask and the news that Flask 1.0 is now out.
That's a big deal, but let's get started with just your background.
How do you get into programming in Python?
Let's see. So I've been programming most of my life.
I got into it probably around like second grade or so.
Got a book about HTML, started making websites.
Nice.
Where I really like started and what I thought I wanted to do,
and I think this is the story for a lot of people,
is I thought I wanted to make video games when I grew up,
because I started with a game maker when I was in like middle school and everything,
making like 2D games.
I wish I had saved now, but I didn't know about Git back then,
so I didn't know about this back then maybe.
So they faded into the digital dust?
Yeah, unfortunately.
So yeah, I got started that way and then went to college for computer science
and eventually just kind of settled on like, oh, web apps are pretty cool.
Like I started making like some small things for groups I was involved with,
and eventually that's how I got into Python also.
There was like a Python course in college, but even before that,
I started thinking like, hmm, what can I do next?
Because I'm just doing Java here and it's not that exciting.
So I went one summer and I was looking at how to make a web application
and I came across Ruby on Rails and Django.
So I looked at both of them.
Two very different directions that could have gone great.
Yes.
I looked at both of them.
Looking at the growth curves and popularity curves of these two languages,
you know, 10 years out or whatever,
you probably got a good choice on the fork in the road there.
Yeah.
I mean, I'm sure there's plenty of good stuff you can do with Ruby also,
but back when I was starting, I looked at both of them,
looked at the code and said, not knowing Python or Ruby,
hey, I can read this Python.
It makes sense.
And so I just started using that.
Picked up the Django tutorial back when I think it was like 0.8 or so.
And I think Flask may have just come out or was going to come out the next year.
So it was like 2008, 2009 around that.
And so that's how I got started.
It just kind of went from there.
Yeah, that's awesome.
So I guess one of the interesting follow-up things is like,
how do you go from Django to Flask?
Like I just interviewed some folks for the Python survey done with the PSF
and JetBrains collaboratively.
And the number one framework,
the most popular framework that anybody picks up for anything in Python is Django.
And so it's certainly really popular.
So you've strayed.
You've strayed from Django.
How did you get over to Flask?
It's funny.
I want to touch on those most popular things also.
I don't want to start a fight with Django or anything.
But we'll go into how I did Flask first.
So for my job after college, I got put on a contract where it was basically open-ended.
Like they wanted this.
I mean, this is literally the line I got the first day I walked into the client's office was,
we have this spreadsheet.
Can we put it online?
Like an Excel spreadsheet.
And so the company I was working at, and I still work for them,
they were a Java shop.
And that's what my previous projects had been in.
But I was the only person on this contract over at the client's office.
I said, yeah, we can put that spreadsheet online in Django,
which I've been learning, which I was learning before I started here.
And I did it before anybody could say anything, you know.
You know, the best way to quiet dissenting voices in those situations
is to show them something working.
They're like, oh, you should use Java.
Wait, that works.
You're already done.
Okay.
Well, I guess, all right, fine.
You can do that, right?
Did it go something like this?
By the time they checked in a couple weeks later,
we already had like a working prototype.
And, you know, we've gone beyond the spreadsheet at that point.
Yeah.
Have they been using like the spreadsheet as like almost a web app database?
Were they like mailing it around?
What was the story?
I don't know how many details I want to give like publicly.
Yeah, yeah, sure.
It was basically they were keeping track of how secure their computers were for various audits that they needed to do.
And everybody was just basically reporting about their computers and somebody was filling out a spreadsheet.
And then they would go and look at the statistics every now and then.
So they wanted some way to people can like report that automatically.
They can get the reports about compliance automatically.
So it's kind of like just a data collection and reporting.
Yeah, I just I asked because it seems like there's just so many sort of holes like that that Excel fills.
That was just a little bit of skill.
You know, like a much better solution would be in place.
Yeah.
Well, the contract ended up lasting like three years and far outgrew what Excel would ever have done.
But it started from pretty humble beginnings.
Nice.
Okay, so that's Django.
So how'd you get to Flask?
Right, right.
So we were on Django.
And so we made this prototype and it was working well.
And they're like, well, we want to start using this every, you know, for the company now.
And so we deployed it and it ended up being too slow.
Now, I'm not saying Django is too slow.
That's probably partially on me.
Like I was still learning and everything.
But at the time, you know, it was a SQLite database.
The templates were kind of slowing down in rendering.
And the biggest problem was the ORM at the time.
And I know you can do clever things even in the Django ORM.
But I like was trying to do all these reports and aggregates and everything.
And it was kind of finding Django.
So I started looking for something, you know, alternatives.
I found SQLAlchemy.
And I found Flask, which SQLAlchemy was used with a lot.
So I said, okay, I'm just going to rewrite the whole thing in Flask and see what happens.
And that's about how it happened.
I just had a Django site and I needed more performance and more customizability.
And so I switched to Flask.
Yeah.
And was it pretty easy?
Was it like a couple days?
This is like six years ago now.
But yeah, it was pretty straightforward.
And like I said, like, I think I probably could have accomplished the same thing in Django eventually.
I knew a lot less at the time also.
And so I was more just exploring what was out there.
But it was definitely, we built something on it for three years after that.
Yeah.
So it was a really good foundation in the end, huh?
Yeah.
I'm a fan of the micro framework style.
You know, take a small web framework, pick the ORM and other tools that you want to use for that situation and put them together.
I don't know.
That's my style.
So I'm a fan of that style as well.
Yeah.
I'm not biased or anything, but I'm definitely a fan of that also.
For sure.
Yeah.
So we're going to talk a lot about Flask, but let's start at a more higher level umbrella style angle here.
So when I went to look about Flask, it's now under this Palette Project umbrella.
And a couple of years ago, I don't think it was.
So what is Palette and how did Flask get there?
So Palette is, it's like basically the new organization that's managing Flask and the other projects related to Flask.
So VerkZoik, Jinja, Click, MarkupSafe, It's Dangerous.
And there was a previous organization called Poku, which your listeners are probably familiar with,
because when you go to the Flask documentation, you're still going to flask.poku.org.
Right.
That was Armin Roeneker's stuff, right?
It was him and some of his friends.
They had started various projects and Flask came out of that.
Spinks came out of that.
Other projects came out of it that I'm remembering off the top of my head.
But everybody just kind of ended up moving on eventually.
And so it had become just Armin managing all these projects himself.
And he wanted to open it up more to the community.
And so he created this new Palettes website and said, okay, everything belongs to this organization now.
And I'm going to try to get more community involved.
And so that's how I kind of, that's about the same time that I got into the project as well.
And honestly, we haven't really picked up a lot more maintainers since then or anything.
It's still just a couple of maintainers going at things.
But it was like more of a significant like, it's not Armin's project anymore.
Right.
I was going to say, it kind of got Flask out of the shadow of Armin.
Right.
And he's still there.
Like I chat with him about like, hey, do we want to do things like this?
Or he still manages a lot of the assets behind the scenes like servers and that sort of thing.
But day to day, it's me and the contributors that I kind of have gotten on board.
All right.
Right.
Are you looking for more contributors?
Absolutely.
I don't know if you want to go in depth on that now.
Yeah, sure.
Let's talk about it just a little bit.
Because I know a lot of listeners will reach out to me and say, hey, I'm getting into open source.
I'm getting into this whole Python world.
And I would like to contribute to something.
But I feel like they contemplate creating something for themselves.
And like, well, I could build this thing, but I don't really have a great use case for it.
Or I'm not sure it'll be popular.
And then they look at contributing to other projects.
We talked about Django.
Django is really like a big polished project that is super hard and approachable for people to get into.
And so they're like, well, I can't get into these major projects because they're too advanced or too, you know, widely used.
Whereas the small, simple stuff, I don't think it's going to make a lot of sense.
So they ask you, well, what projects could I get involved with?
And like, where can I help out?
So if there's like a good place for people getting started or people who love Flask and want to get more involved, that'd be great.
Yeah.
So we're definitely looking for more contributors in all of the projects that I mentioned earlier.
So Flask, Berkswake, Jinja, everything out there.
The biggest success I have at finding contributors is at PyCon.
And I'll run the sprints and I'll find people who are interested.
You know, they'll come to me basically.
And I get to walk through everything in person, which is really helpful.
But I am trying to, I do get contacted occasionally, like saying, hey, can I contribute to Flask?
And I'm like, absolutely.
Do you want to write documentation?
Do you want to write tests?
Do you want to make sure our configurations are consistent across all six projects?
Do you want to triage issues and see, can you reproduce things?
Can you get more information out of people?
Can you identify where a problem is?
Right.
Triage all the issues that come rolling in, right?
Right.
So like, even if you're not comfortable, like writing code yet, and you should be, you absolutely
can contribute code to any of our projects.
But there's plenty of non-code related contributions out there that are really helpful to me.
So they give me more time to focus on the code.
Yeah, that's awesome.
Do you feel like it's a little easier to contribute to Flask because it's like six projects?
And each project is a little easier to hold conceptually in your mind?
It might be.
I mean, there are really, there's four main projects.
Flask, VarxSoy, Jinja, and Click are all pretty large code bases in themselves.
And they're pretty distinct use cases.
So there's not too much to do actually in Flask specifically anymore.
1.0 kind of said like, acknowledge, you know, here we're stable and we have the features we want
at this point.
So like, in terms of like bug fixes, like there's some bug fixes every now and then,
but a lot of the work is in VarxSoy and Click especially.
There's a lot of stuff behind the scenes that people don't see when they use Flask every day,
but it affects them.
I think a lot fewer people are aware of those also.
So like, people just being aware of those projects and looking at them also and not just Flask would
be really helpful.
And there's always tutorials and documentation that could use upkeep, right?
Like I went through and just for Flask 1.0, rewrote the entire Flask tutorial from scratch,
just kind of based on the questions and stuff I had experienced answering questions on Stack
Overflow, answering, helping people at meetups or conferences.
And so identifying those kinds of things like, hey, this didn't work for me in the docs, you know, or this could have been clearer and going and contributing there.
Yeah, that's cool.
I often think of like, every time there's a question about something that I thought was explained well,
but then it turns out there's a question about it.
You're kind of like, ah, it's almost like an issue on that explanation, right?
Most of the issues in Flask right now, the open issues on the bug tracker are documentation, really.
Like people have brought up, like, this is confusing or this could be clearer.
And if you're looking for even more issues, just go on Stack Overflow, go to the Flask tag and sort by most voted questions.
And just look at the top one, see if it's documented.
Look at the next one.
Yeah, that's a really good point, actually.
So it occurs to me that it might be worthwhile to spend just a moment talking about these projects that you discussed.
So we just quickly ran through it, like there's Flask and there's Jinja and there's Vexoig and stuff like that.
And could you maybe give us a rundown of like what each one of those actually is so people know what they're about?
Sure.
So, yeah, Flask is definitely the most popular.
But if you're using Flask, you're using the five other libraries also behind the scenes.
Like, so every time you pip install Flask, you get all these also.
And Flask, honestly, is just a wrapper around all these other libraries.
It's using what's provided there and just putting a nice framework around it.
So Vexoig is the closest to what Flask is doing.
It's also a WSGI library, but it's dealing with kind of a lower level than what Flask is.
So Flask is providing like an application framework and Vexoig is providing all the parts for taking a HTTP request and a WSGI request and parsing out the headers and producing some data structure,
like a request that we can use and look at and turning our response into something that our server can understand.
Jinja is a templating library, which means you write text files with special syntax in it that kind of looks like Python.
It actually compiles to Python behind the scenes.
And then you can render these templates and produce different web pages, for example, different HTML pages with user information or different details about different objects.
Click is the most recent Palettes project, but it's four years old at this point.
So it's not that recent, I guess.
It's probably also the one used most independently.
Yeah, that's true.
I wish I could name more projects off the top of my head that used it, but I do know PIPend uses it, Cookie Cutter uses it, and Flask uses it, obviously.
And that's our command line tool.
So it's kind of like Flask in a sense, but for command line applications instead.
So you use decorators to turn functions into commands that you can run with options and arguments and produce terminal output.
Right. Nice.
And there's all sorts of...
Click is kind of unique.
It tries to be very correct about how it interacts with the environment it's running in, in terms of encodings for the terminal, for the file system, for user input.
And it actually, I think, I don't know the full history, but I think in part influenced some recent changes in Python 3.7, where Python now handles UTF-8 encodings better, detecting those on Linux machines.
Because Click would actually complain, like, your system is not configured right, and I'm not going to try to get...
Right.
Which led to a lot of headaches for people writing tools.
But it did make people...
Yeah.
...better.
Yeah, yeah.
So one thing I want to highlight, and I'm not sure if people are aware of this, that GitHub recently added dependency computations or dependency reports for Python.
That used to be just for Ruby and JavaScript.
But if you go to, like, palette slash Click on GitHub and go to Insights, then Dependency Graph, and then Dependents, you can see there are 82,408 repositories and 4,774 packages that depend on Click.
And there's the list of them.
Okay.
Wow.
I haven't actually...
I remember vaguely seeing that they had released that, and I haven't looked at it yet.
That's really surprising.
It's really cool.
Dependency Graph.
I'm looking at it right now.
Oh, yeah.
Yeah.
It's good to draw you in, right?
And you can also see the dependencies, like, in reverse.
So it's good for, like, saying, what does this project depend upon if you're going to try to decide if you want to use it, right?
But I think the other one is interesting for people like you who create these packages and then other people depend upon them.
And you'll see, like, well, what else is out there?
Yeah, it's really cool.
It's just, like, an absolute number.
The other package I use for getting statistics like that is PyPinfo.
I don't know if anybody's discussed that on your podcast before.
No, I don't think we talked about it.
Yeah, you have, they have all the statistics about PyPI downloads, and you can just query that through Google BigQuery.
That's why I was questioning your, Django's the most popular earlier, because if you go look at it month to month, it's not like I monitor this every month or anything.
But Flask and Django are neck and neck.
Really?
And some months, Flask will be higher by a couple tens of thousands, even, and sometimes Django will be higher.
It's really surprising, though, because despite them being downloaded the same amount, if you look at statistics like number of questions asked on Stack Overflow, Django has, like, probably, I think, like 50,000 times more questions.
It's like a ridiculous number.
Yeah.
Well, I wonder if that's a micro framework versus sort of, I think of, like, Lego building block frameworks like Django.
Like, you wouldn't ask so much, you wouldn't say tie a question about SQLAlchemy to Flask because it's about SQLAlchemy.
But you very much, it's very common that you might do that for, say, Django ORM being tied to Django, even though it's the data, because it's more like grouped together.
I don't know.
Yeah, I'm not sure if you can even read anything into that.
Like, it's maybe there's just a bigger community, and so there's bigger awareness of Django that people think to ask questions about in the first place.
Yeah, but I think maybe the main takeaway is Flask and Django are both well up there as some of the most popular frameworks for Python.
Sure.
Okay, so let's see.
We talked about Flask, Jinja, Vixoy, Vixoy.
Yeah, thank you.
And we just touched on Click.
So we got MarkupSafe and It's Dangerous.
Right.
So MarkupSafe is kind of used internally by Jinja, and it is just a very fast implementation of escaping unsafe characters in HTML.
So basically...
Like, if you're going to take something from a database and plunk it into the web page as a string, you're going to HTML encode that before you do that so it doesn't get owned.
Right, right.
So if you have user input or anything like that, you're going to make sure it's safe to display to people without them being able to inject unsafe code into their browser.
And so it's just a very fast implementation of that.
And plenty of other projects use it behind the scenes.
Okay, that's interesting.
But I think Django might even use it.
Yeah, you can go to the Insights on GitHub now.
Or just their requirements at DXT.
But yeah, and then we have It's Dangerous as well, right?
Yeah, so It's Dangerous is the last one.
And that's just a way to securely sign messages.
And I know there's other solutions out there now, like JWT, that sort of thing.
But those didn't really exist at the time this was written.
And this is a lot simpler than JWT.
So basically, it's kind of like JSON.dumpS.
Yeah.
Just throw out some data, and it will dump it into a JSON string.
Then it will also securely sign that string so that you know that it can't be tampered with.
Right, tamper-proof marker.
But they can't edit it.
So we use it for our secure cookies and for signing things like login tokens and preset tokens.
Yeah.
Yeah, you don't want people tampering with that stuff.
This portion of Talk Python to me is brought to you by Linode.
Are you looking for bulletproof hosting that's fast, simple, and incredibly affordable?
Look past that bookstore and check out Linode at talkpython.fm/Linode.
That's L-I-N-O-D-E.
Plans start at just $5 a month for a dedicated server with a gig of RAM.
They have 10 data centers across the globe.
So no matter where you are, there's a data center near you.
Whether you want to run your Python web app, host a private Git server, or file server, you'll get native SSDs on all the machines, a newly upgraded 200-gigabit network, 24-7 friendly support, even on holidays, and a seven-day money-back guarantee.
Do you need a little help with your infrastructure?
They even offer professional services to help you get started with architecture, migrations, and more.
Get a dedicated server for free for the next four months.
Just visit talkpython.fm/Linode.
Then there's a few other projects that are not directly under Flask, but are under the palettes or related to palettes, right?
Yeah, there's plenty of extensions.
There's some that I'm involved with.
Flask SQLAlchemy, which is the kind of official extension for tying SQLAlchemy's sessions with Flask sessions.
There's Flask WTF, which is a wrapper around WTForms, which is a form library that lets people interact with data submitted from web pages and render those forms that submit that data, do validation, that sort of thing.
So the other things I'm involved with, I wrote this library called Flask Alembic, which is kind of like Flask SQLAlchemy.
It takes Alembic, which is the migration library for SQLAlchemy and wraps that in kind of the Flask configuration.
That's really cool.
So I don't believe we've talked about Alembic very much.
We've mentioned SQLAlchemy plenty of times, but I feel like Alembic, if you're doing real production relational database stuff with SQLAlchemy, you should know about Alembic to be using it.
Maybe give people a quick overview of what Flask Alembic does to that whole mix.
Yeah.
So I never just use SQLAlchemy unless it's just like a really quick example project.
What Alembic does is it does something called migrations.
So if you write your model in SQLAlchemy and you create a table in your database, if you want to change that model, the only thing SQLAlchemy lets you do is drop the table completely and then recreate it.
Instead, you can run migrations, which lets you add or move columns or change data and just kind of keep version control over what your database looks like.
Right. Because with these ORMs, the structure and schema of your database has to at least be a superset of exactly what you have in your SQLAlchemy definition.
So if you add like a column or field to your SQLAlchemy class, it can no longer talk to your database without also adapting the database schema.
Right.
Right. So you need some way to tell the database there is this new column that you need to know about.
And that's what Alembic does.
So Flask Alembic just kind of ties Alembic, which comes with its own CLI, for example, into Flask's CLI and moves the configuration from Alembic into Flask.
Just kind of a...
I think so it's kind of like a wrapper.
Yeah, it's a wrapper around it.
Just like, I mean, mainly like Flask SQLAlchemy is for SQLAlchemy.
There's another library out there called Flask Migrate, which is another wrapper around Alembic.
And that one's developed by Miguel Grinberg.
And we basically, from what I remember, because I developed, it was like four years ago now, but I think we developed them at basically the exact same time.
Really, something like a month of each other, completely independently.
His is a lot more of a direct wrapper around Alembic, which a lot of people, for a lot of people, is exactly what they need.
And it's a lot more straightforward a lot of the time.
Mine, on the other hand, I wanted to like be able to dig into all the internals of Alembic and like introspect exactly what was going on at any time.
So it's more of a very opinionated framework on my end.
And people can choose.
Yeah.
It's good to have options.
That's really cool.
Let's spend a little time talking about maybe the biggest news for Flask and that it went from, what was it, like 0.12 to 1.0?
Yeah, 0.12.4 to 1.0.
Well, here's a major open source project going to 1.0, which is actually, I think, really, really positive.
And I think it's, I'm just super excited to see that you guys did that because it's time, I think.
Oh, it was absolutely time.
I mean, I was, I had been working on that, getting that happening for about a year prior to it, at least.
We joked about it, this at PyCon, because Mamuta Shemi had come out with this thing called ZeroVert for ZeroVert.
And making fun of projects that were still on like Zero, not something that were 10 years old and Flask was on that list.
Yeah, that was actually, I didn't find out about that until after I released 1.0.
And then people were like, oh, it was because of ZeroVert.
No.
I've been doing it.
You set the record straight.
This is going a lot longer before that.
Yeah.
ZeroVert.
I was very amused by it.
I was like, yeah, this is, and I actually got them to put us on the Emeritus list.
Aha.
Nice.
So we're, we're graduated now on their website.
But yeah, I've been working on it for a while.
And we always have people asking like, hey, this is, this is 0.12.
My boss doesn't want me to use it because it's not software.
And we kept having to tell people, this has been stable for years.
Nothing's really going to change.
Nothing's going to change.
There's no breaking bugs or anything.
It's more just a number.
I think for a long time I told them, just tell them it's version 12 and we misplaced to zero or something.
Yeah.
But yeah, we finally got it.
They are.
I mean, that is the impression for a lot of people, especially people coming from commercial oriented software backgrounds.
I'm thinking like Microsoft shops, you know, .NET folks.
I'm thinking Java and those types of people.
They're just like, well, I mean, I think they even have a rule of the Microsoft shops.
Like you can't use this whole version three because the first two are messed up.
Right.
And I just think there's so many large organizations that at least some of the folks in there have that mindset.
And I think having this become one O is like a pretty big step to just sort of sidestep that conversation.
Yeah.
And I mean, it feels, it feels significant, even if like the actual stability of the software hasn't changed or, you know, the, the, the acceptability to use it in production environments hasn't changed really.
But, you know.
But there are some major changes.
Oh, yeah.
I mean, there's, the list is not trivial.
Right.
I was kind of surprised when I made that release slot or those release notes, just how much it changed.
It's a lot of small things, honestly, like, but it adds up.
Right.
You want to talk us through some of the changes, some of the major changes?
So, yeah, we dropped support for Python 2.6 and Python 3.3, which made me really happy.
That's really nice.
I was looking at, I was trying to use the PyPI info, which I mentioned earlier, to figure out stats about how people were using it.
And I think less than 0.1% of installs were on Python 2.6.
Yeah, 3.3 itself went unsupported, right?
Yeah.
It, like, 2.6 itself is unsupported.
And in the future, I'm definitely going to be sticking with, as soon as Python drops support for a release, I'm going to drop support for it.
Yeah, that makes sense.
That doesn't mean we're going to, like, rip out support and, like, it's suddenly going to break.
But we're not going to test on it.
You know, we're going to...
Not going to inject breaking changes to force it to not work.
But you're going to no longer run tests and not care if it breaks it.
Right.
And actually, Flask 1.0 secretly supports Python 2.6.
Even though I removed it a couple months before we made the release, I kept testing it internally because I wanted to give people who were deployed at least one chance to be on 1.0 before they had to make a bigger upgrade.
Yeah, that was generous.
Yeah, I probably shouldn't have done it in retrospective, but it's done.
You talked about the versioning going 1.0, like, in the comparison to Django.
Django is now in sort of this 1.0.2.0 versioning as well.
And they dropped support for Python 2 altogether.
Do you have plans for that outside of the deadline of 2020?
Yeah.
As soon as 2020 comes around, I am dropping support for Python 2.
Yeah, and I think that's basically what Django said.
It was like their end of life was, it was pretty far out before you could, you're fully unsupported on like an older version of Django or something.
Yeah, I'm looking forward to that day.
I mean, we'll still be supporting from, I think, 3.4 and up at that point.
Sure.
So we're still a little behind in terms of features that we're allowed to use.
Right, like async and await, for example.
Yeah, that's a whole other discussion that we'll get into.
Yeah, yeah, for sure.
Actually, it is, isn't it?
But do you think it will reduce the amount of code that you have to write?
Do you think it'll be easier for people to contribute if you don't have to do version checks or compatibility?
I haven't really considered it in a while.
I think it will cut down on, I think mostly it'll just cut down on mental overhead.
Like people don't have to think about it as much.
When I write code at this point, I'm so used to doing it for Flask that I just kind of, by default, write code that is compatible with both.
And occasionally get a mistake that CI catches.
But just having less surface to have to remember and to test, I think will be beneficial.
But for the most part, there's, I mean, there's cool features that come out.
But clearly all our code can be written in Python 2.7 and compatible code.
Yeah, I think what's more important is that people that use Flask get to use the new features where and how they want, you know?
Oh, well, people writing applications in Flask can already use Python 3.7 if they want.
And they can use f-strings and what was the controversial change that got into 3.7?
It's coming in 3.8.
It was PEP 572, the like assignment equality thing, the inline assignment.
Yeah.
Hey, I'm looking forward to when Flask only supports 3.8 and up because I'm going to switch all my code to that also.
I personally like the change.
Yeah.
Yeah, I do as well.
Yeah, very nice.
Okay, so another major change is the CLI.
Tell us about the changes there.
Yeah, so I'll talk about the CLI in a second.
But basically like all the changes that are, a lot of the significant changes that went into 1.0 are, were basically me trying to make things easier for people.
So easier for people to learn, easier for people to understand.
So a lot of this stuff is improving documentation, better error messages, and then a better CLI also.
So we did a lot of work on improving how the Flask command, which is like the recommended way to run the development server while you're working, how it detects your application.
So when you write code, you just write app equals Flask somewhere in your code.
And there's even a common pattern called the factory, the application factory, where you write a function that creates your application.
So you never actually have an instance of your application where you code.
That's what the server is in charge of setting up.
And so we did a lot of work to improve how the CLI can detect where your application is, what it's called, how it should be imported, and if it's behind a factory or not.
So that the command can just, like everything will just work when you're writing it, instead of having to set up some extra glue in between.
Yeah, that's cool.
So you no longer have to say set the Flask underscore EMV, no, the Flask debug rather, or the Flask app environment variables, right?
It can detect some of that stuff automatically.
Yeah.
A lot of the times for like really for simple applications, which is really useful for tutorials, especially like Flask app will just know that you have an app, you have a file called app.py.
That's where your application is.
I'll just look there.
You do still have to set Flask app in most significant cases.
Like once you're writing a big application, you know, a more significant application, you'll probably have to tell it like at least where the, which files are important, but nothing.
This portion of Talk Python to Me is brought to you by 10x Agent On Demand.
Here's a guess.
If you're listening to my podcast, you're likely a Python pro.
You may be even pretty well paid to code in it.
Here's another guess.
You likely aren't being paid what you're worth.
Why?
Because negotiating isn't your thing.
Even the best tech talent can get taken advantage of when negotiating their comp packages.
Don't let this happen to you.
10x Agent On Demand has negotiated more than $50 million worth of deals for senior level tech talent just like you.
When you've got a job offer at hand or expecting one soon, contact 10x and they'll help you level the playing field.
Just visit talkpython.fm/10x when you're ready to roll and mention Python for a three 30-minute consultation.
10x Agent On Demand.
You handle the tech, they'll handle the negotiation.
Another thing, actually, I think this was a, wasn't a warning message.
It was like an info message when I ran Flask recently that I had a virtual environment named .env.
And it said, hey, we think we can help you with some files that are hanging out in this .env thing.
Yeah.
So maybe tell us about the python.env.
Yeah.
So as part of the CLI improvements, we also, previously when you were using the CLI, you had to kind of type these environment variables in every time you opened a terminal.
So you had to tell it like export Flask app equals, you know, my app, export Flask app equals development.
And so we integrated python.env, which is a library that reads these .env files and automatically sets up your environment variables based on it.
So people can just have one of these sitting in their project.
And they won't have to set up their terminal every time they start working on the project again.
Yeah, that's really cool.
One thing I recently learned is the script that activates virtual environments.
You can export stuff from there.
You know, you set every virtual environment.
Go in there and sort of configure your virtual environment.
So in addition to just having the packages you want, it also kind of kicks off with the right environment variables, which is handy.
The downside of that, and we do have that listed in our CLI documentation.
Like this is an option.
You're using virtual lines, go edit your activate script.
But the downside of that is if you have multiple people developing or if you're on multiple machines, you know, and you recreate your virtual line.
If you suddenly don't have that stuff and so it doesn't work again.
Right.
It's a pain in the CLI, sorry, in continuous integration.
And also you can check your .flask env into source control, whereas you can't, you shouldn't check your virtual environment into.
Yeah.
If you've managed to check your virtual env into Git and it works somewhere else, that's amazing.
Yeah, exactly.
A lot of stuff has to line up just so for that dork, right?
Nice.
Okay.
Another one, another big change.
I thought this was pretty cool is it's got to help people when they're testing for performance.
And how's my app going to behave when I ship it to production?
Is the development server is now multi-threaded by default?
Yeah.
So the development server actually had threading previously pretty much for its entire existence, but you had to explicitly enable it.
So you had to say like when you were starting, you had to say like threading equals true or something.
Right.
And so now people were just always running into things like, hey, I'm trying to serve some media and like make an API request at the same time.
And suddenly it's hanging.
Well, that's because the dev server would only handle one request at a time.
But we decided to go, let's just enable threading by default.
It makes some things more difficult to reason about, but debuggers nowadays are pretty good at figuring out, you know, what threads are running and where to do breakpoints and all that.
I think it's a good change.
I mean, we're living in a multi-threaded world, right?
A multi-core world.
That's actually one of the big kind of hidden bugs that needs, or not bugs, but things that needs to be improved in Fairkzweig now.
Because we're threaded by default, Fairkzweig has this nice debugger that pops up the traceback and lets you interact with it when there's an error.
But it only works in single threaded environments.
It'll still output correctly.
But if you have multiple requests going on at the same time and you try to interact with the traceback, you might just get like junk data back.
And so figuring out how to get that working in a threaded environment is actually on my to-do list.
It still works for us.
Yeah.
It's not like a huge issue.
Yeah.
How many people are actually interacting with the debugger and hitting concurrency at, you know, exactly that moment, right?
Probably.
Very few.
I think we got a couple people who reported it.
And I just said, you know, you just kind of try to make your thing synchronous when you're debugging a list.
Right, right.
Use this command line that makes it not threaded.
Yeah.
So there's still things to be fixed, but we're basically trying to improve the 80% case, right?
Like the 80% of the time you're going to have this and then we can fix the, or whatever that's saying is, 90, 90, 10 or something.
Yeah, yeah.
Get people to fall into the best case scenario most of the time.
Right.
So another thing that changed is accessing missing keys from request.form.
Yes.
That was...
That's one of your error message type things, right?
Right.
Yeah.
So we had a couple of things.
So basically the way Flask looked up error handlers and reported errors was improved.
So it's more consistent in more cases.
And as part of that, I noticed that...
And this is an issue that comes up on Stack Overflow all the time is like, hey, I tried to access, you know, request.form name and I got a 400 error.
Why?
Well, the answer is because you didn't submit a form field called name.
But we don't tell you that we...
Like the dev server never told you that.
I guess if you're deeply familiar with status codes, you would know that 400 means something is wrong with the data you submitted, but it's still not even obvious there, right?
Yeah.
So now when you're running in debug mode, the error, we still raise the same error, but I inject some extra information into it about like, hey, you tried to access this key and it wasn't there.
So go check your HTML and see if it's...
If you're sending what you expect.
Yeah.
That's cool.
Like that could be the difference from...
Oh yeah, of course.
I'll check my HTML versus hunting Stack Overflow.
Yeah.
Now I know like Stack Overflow probably isn't the best metric for this, but like we still get plenty of questions about like,
why am I getting a 400 error?
Like I've even gotten questions with the error message saying you're missing this key right there in the question.
So like I'm not going to, you know, solve everybody's problems, but it's a lot clearer.
And that was basically the number one problem that I always saw.
Yeah.
I'm seeing it less at least.
Yeah, it'll definitely be less.
That's cool.
I mean, you're never going to solve the problem of somebody just sees it doesn't work.
I'm just going to Stack Overflow and pasting the error and not reading through it and thinking through it.
Or, you know, maybe they're just so new they don't make sense of...
They don't see what should be obvious.
Sure.
I mean, there's still a lot of information, even if that's at the bottom, you know.
So I understand, obviously.
Yeah.
Yeah, yeah.
For sure.
Let's see.
You changed error handlers a little bit.
Like the thing that will run if, say, there's a 400 bad request or a 404 or something like that?
That's more of an internal change.
Like, I don't think most people noticed.
But technically, when you've raised...
You can register error handlers on Flask and on the blueprints inside of it so that when certain errors are raised, they'll be handled by those instead of causing a 500 exception, you know, to be sent to the browser.
And in certain cases or for certain types of exceptions, the behavior was just kind of inconsistent.
And so we kind of...
We just went back and looked, like, how is this actually working?
Oh, there's, like, this mess of different if statements.
Well, let's just, like, simplify that.
So there's, like, a strict set of rules that it goes through now and it's documented and all that.
Yeah, that's cool.
So one thing that you just mentioned that I think is worth touching on a little bit for the listeners, a lot of the frameworks, it's a little easier to partition your view methods into different files and categorize them and stuff.
Because you just take a static decorator that comes out of, say, like, Pyramid.
You say, at view config and you just drop it there.
In Flask, you create the app and then you say app.route.
And so in order to split that stuff apart, you have to pass that app around in certain ways.
But then you also have blueprints, which really simplify that.
Do you want to just tell people real quickly who maybe only know about app.route, about blueprints and, like, that problem solves?
Yeah.
So I mentioned the application factory pattern earlier, where you don't actually ever have an instance of your application when you're coding.
You have a function that creates it.
And that's actually the recommended way to use Flask in the official tutorial now is use an application factory because it solves a lot of problems that people run into, even if it's a little more confusing.
But one of the problems with using that is, well, you can't just decorate your function, view function, with at app.route anymore because you don't have app.
So instead, Flask has this thing called blueprints, which are basically ways to defer calling app.route.
So you call blueprint.route.
And that just kind of registers, like, hey, this is here.
And now later, when you have your application and you register the blueprint with your application, take all those deferred registrations and perform them now.
And so you don't have to have access to the application.
You can split your code up into different modules so that all the stuff about users is over here and all the stuff about blog posts is over here.
You don't have to worry about circular imports or any of that.
Right.
And that has been tricky.
And I think the blueprint stuff is really beautiful.
It just makes it so much easier to partition your code in a more healthy way for large apps.
Yeah, it's a really good pattern.
And that's why I tried to...
It's something that confuses a lot of users.
I think they expect more of it than it actually does.
Like you said, it's a pretty straightforward, or it's a pretty simple pattern.
It just defers calls.
Yeah.
So people are doing Flask and they don't know about blueprints.
They should go spend the five minutes and learn about it.
Yeah.
Read the official tutorial.
Flask.poku.org slash docs slash tutorial.
It'll walk you through an application factory, making a blueprint, all that.
Yeah.
Very cool.
Another thing that changed in Flask 1.0 is the testing got a little easier.
Testing.
A test client having a JSON request and then also get JSON for response, right?
This was kind of like another one of those like, hey, there's an inconsistency here.
You could test JSON before.
I mean, there's a lot of people did.
But the request object that Flask gives you, like when requests come into your views, has this
JSON property.
And it basically automatically parses JSON from the request.
Right.
A dictionary pops out if it has JSON text inside.
And so people kept expecting that to work when they were testing.
So they would make a request with the test client, get a response object back.
And unlike for the request object, the response object didn't have that.
And so they'd call JSON.
It wouldn't work.
And then they would have to like go get the raw bytes and pass it to JSON.loads.
And some people would use Flask JSON implementation.
Some people would use Pythons.
So we just made it consistent.
So you can now get JSON from the response just like you can get it from the request body.
And similarly, a lot of people expected.
So we have this test client where you can just make a request.
Like you can make a fake request without running the server.
And it'll generate like the correct environment behind the scenes.
And so you just say like I'm going to request, you know, slash users.
And I'm going to pass, you know, name equals David to the form.
But there was no clear way to.
So it looked kind of like Python requests, the library, right?
Like so you would make it like requests.get, you know, data equals name equals David, right?
But so people were expecting it to kind of work like requests, be able to pass JSON equals, which you couldn't do.
So you had to encode the JSON yourself.
And so now you can just, if you want to test your JSON API, you can use the test client and just do JSON equals this data structure.
Yeah, that's cool.
Another thing around that is the test CLI runner.
Oh, right.
Yeah.
So, so there's another testing thing.
So we have this test client, which makes requests, but we didn't really ever document how to test CLI commands.
And I mean, one of the, one of the selling points of the Flask CLI is that you can add your own commands.
So if you want to like add a user management command, like, hey, have a create user command that I can run on the background to like add the admin user when I'm deploying.
There was no way to really test that.
Like it was documented in clicks documentation.
But even with that, it wasn't really clear how to get Flask, Flask's like CLI object working in a test framework.
So we have, you know, have this test CLI runner that kind of mirrors the test client.
So you can test the CLI code.
Yeah, that's great.
So I feel like that's the main items that I saw that are pretty interesting.
Anything else that you want to tell people about 1.0?
I think that was the big stuff.
Yeah, I think so as well.
I mean, you can go look at the full changelog.
It's pretty impressive.
I think it's like two pages long on my screen vertically.
That's awesome.
But yeah, these seem like a lot of great changes.
And what do you say for people who are thinking about upgrading, like maybe they've got Flask
equal equal, you know, 0.11.
They're afraid of change.
And they don't want to change it.
Should they change?
And what would they get from doing so?
They should absolutely upgrade, especially if they're on 0.11, because that's a couple of
years.
I was thinking of a pretty out of date version.
Yeah.
When I said that.
Yeah, one of the reasons to upgrade if nothing else is just to continue to get support.
Just kind of due to the size of our organization, we don't really offer support on old versions.
Like I will do security fixes for 0.12 until 1.1 comes out.
But nothing besides that.
Right.
So if there's a problem and somebody has a 0.11, the official answer is you want to fix
that, make that problem go away, you install one, right?
Yes, install one.
And even if you're on 0.12, there's no real reason to stay on it at this point.
Luckily, what I've heard from various users, like when I was at PyCon, Flask 1.0 had just
been released and people were already telling me, yeah, I upgraded.
And it was literally just changing the version number.
Everything worked.
Right.
There are some things that changed a little bit, but they're rarer cases and it's documented
on the change log and it's pretty obvious when it fails, like, oh, this thing got renamed.
Right.
So there's not a whole lot of work to upgrading.
No.
All right.
Excellent.
That's good to hear.
So one of the things that I thought was interesting is you talked about on the Pallet's organization
website about being part of the PSF's fiscal sponsorship program.
If people want to support Flask, maybe you want to tell them about that program and how
they can help.
Sure.
It's really cool.
It's also really new.
So I might not be the best spokesperson for it yet.
I hadn't heard of it before.
I'm like, oh, we should talk about this just so people know it's out there.
Yeah.
So, I mean, this is a little bit of advertising for the PSF also, but they have this program
called the fiscal sponsorship program.
They were mostly using it for meetups at the time that I tried to get in.
And basically what it is, is you submit your organization and they accept you.
Or if they accept you, you become part of the PSF essentially.
So you gain their, their nonprofit status.
They will help you out with certain logistics and they will also set up a donation page for
you and a bank account for you that they'll manage, which was great for me because it's
not something that I have any experience with.
And, but I did want to be able to start taking donations for Flask.
So yeah, I've reached out to them because I saw that somebody pointed out this program.
And when I reached out to them almost a year and a half ago now, I think they only, they
didn't have this set up for developer organizations like pallets yet.
So we were kind of their test project and we got into this program right as a, right before
PyCon.
And then I think they've accepted a couple more projects since then or kind of like in parallel
with us.
So we now have a donations page.
You can go to palletsprojects.com slash donate, and that'll redirect you to the right place.
Let's see, take PayPal or checks to one time or recurring payments.
And we're basically just trying to raise money to support the community.
And I'm not a hundred percent sure what that means yet.
I have some vague plans.
We want to be able to support maybe if you want to have a meetup that sprints on Flask,
for example, we can sponsor that.
You know, maybe we sponsored pizza or something, right?
Or recognizing people, you know, outstanding contributors in the community, sort of like Google
does, right?
So Google has that.
I don't know the name of the program, but they recognize developers every year.
And so we were thinking that would be a cool way to do it.
And maybe, you know, further down the line, being able to have a Flask conference.
And besides...
Really good.
Yeah.
So those are kind of like outward facing.
And then the other thing donations would support be getting the current maintainers to more conferences
so we can run sprints in person and supporting our infrastructure and all that sort of thing.
Yeah.
I know.
I'm pretty sure it was NumPy that had this, like one of the scientific groups basically...
Oh no, I think it was PyPy.
Anyway, one of these groups, basically a lot of contributors had never met and they had taken
their donations and they use it to get the contributors physically together.
Maybe like you said, at like another conference, like PyCon US or EuroPython or something.
And it seemed like it made a really big difference.
That's absolutely something I want to do eventually.
Like I've never met Armin or Adrian or Marcus in person who are the other core contributors,
mostly because they're in Europe and I'm over in California.
So it's a little difficult to find the time and money to do that.
And being able to get us all in the same room, I think would be very productive.
Yeah, I think so as well.
And let me just put a plea out there or a comment out there for folks who work for companies
that are large, successful companies that depend on their technology and that technology
significantly involves Flask.
I think there's so many large, multi-billion dollar companies that are built on Python and
some of its libraries and they don't necessarily contribute anything back.
If those companies could all just contribute, it's a very, very small amount of what they
pay their developers to keep the projects they depend upon healthy.
That would go a huge, huge way.
So people are out there in that situation.
I'm not, but if they can make that happen, that'd be awesome.
Absolutely.
I was reaching out.
That was basically my entire PyCon when I wasn't in open spaces or sprints was being on
the floor going to, I actually printed out business cards, not for myself, but for pallets
with the donate, the donate link on it.
And I was handing them out to every single company and like saying like, Hey, do you use
Flask?
Turns out like 80% of the companies at PyCon use Flask or Jinja or Click.
Yeah.
And if they all just recurrently added a hundred or a thousand dollars, right?
Like that would just change, change things dramatically.
I'm sure.
Oh, sure.
If everybody added a hundred thousand dollars, that'd be great.
A hundred or a thousand.
Obviously.
I don't know what we would do with that much.
Gosh.
Don't do that all at once.
Let me, give me a year to ramp up.
Yeah, exactly.
It's you'll find David on an eye, his own personal Island.
He's no longer working on Flask.
No, just kidding.
Now that'd be awesome.
If we got more support for Flask and other projects that are in the same, same boat,
basically.
Absolutely.
I think it's really important just to recognize the tools you're using and, you know, support
those, support the maintainers that are already working really hard on them.
And so, yeah, we're, we're starting that we've gotten, I didn't really advertise it that much
after PyCon, but we've gotten a significant number of donations already just from personal
donations.
And it's really cool to see those notifications come in.
You know, I see a little notification, like $5 was donated every time it happens.
And it's, it's really nice to see that.
Cause a lot of the times my experience with maintaining is, oh,
there's a new bug, go fix it and stuff.
You know, it's never anything like really positive.
Somebody being impatient and frustrated and then they've gotten to you finally.
And now you're frustration.
Right.
Yeah.
I hear you.
So let me ask, I guess sort of a few closing thoughts here.
Like what's next?
Like you've got one out now, now where are you headed?
I think I said this earlier, but Flask one, Oh, all the features that I want at least
are in there.
And I think most of the features that people ask for are easy to do with extensions at this
point.
That's not to say we're not going to like add anything to Flask or, but you know, it's
mostly like, like I said, how can we improve people's experience with Flask?
How can we make it easier for them to learn and work with it on a day-to-day basis?
So improving documentation, identifying better error messages, writing more tutorials, writing
better tests.
That's what a lot of the focus on Flask is.
There's still a lot of focus on Verixdweig and Click and Jinja for actual bugs and features
to get in.
Verixdweig is just never ending because there's always more HTTP RFCs coming out, you know,
changes in subtle ways.
It's my favorite.
I've gotten so good at reading RFCs now and I'm still, I still don't like it, but.
I'm sure.
It's pretty dry stuff.
So I guess the final question around this is when will I be able, if, will I ever be able
to write, let me rephrase it that way.
Will I ever be able to write async def index?
You know, app route, async def index.
Yes.
I've committed to this kind of publicly, but in other places, but yes, we do want to have
async support in Flask and Verixdweig.
That's awesome.
Getting there is going to be really difficult because we also want to maintain compatibility
with Python 2.7 for at least another year and a half.
We want to maintain compatibility with Python 3.4.
And I think if what you told people was you have to wait until we drop support for 2.7
and 3.4, that just knowing that it is coming actually would probably.
I mean, honestly, even if we don't say that it's probably going to take that long to get
there.
There's a lot of work to do.
Verixdweig is very, it makes a lot of assumptions behind the scenes about the WSGI environment.
I have gotten some contributors who are interested in working on that.
So there's an effort in Verixdweig to make it sans IO, which means separating the IO from
the parsing so that we can kind of plug in different.
Right.
Then you can plug in an async layer maybe right there without really changing much.
Right.
And then on the Flask side of things, we're looking at ways to kind of look kind of like
the two to three migration tool.
We're trying to look at some sort of async to sync migration tool where we can write async
code and get a version that can also work with sync code.
Yeah.
I think there's been some work on that in your all lib3.
Nice.
Have you seen the work they're doing with Quart?
Yeah.
So I actually reached out to Philip, who's the author of that, a couple weeks ago and said
like, hey, you know, Quart can still be its own thing.
But I know you were trying to be Flask compatible.
Would you be interested in just making Flask async?
And he was on board with that.
I've met with him a couple of times.
He's still working on Quart, obviously, but he's going to at least be there giving input
about how we can get Flask to be in that same place.
So yeah, it's definitely a cool project and excited to work on it.
Yeah.
If that sounds interesting, people don't know anything about it.
I interviewed Philip Jones about Quart on episode 147 a little while ago.
So check it out.
Okay.
Yeah.
I've played with it a little bit and it's pretty solid.
It seems like if you could take kind of what he's doing and where you're going and blend it.
Yeah.
The nice thing he has going for him is he can just say, I only want to support Python 3.6
and above.
Yep.
And I don't want to support sync at all.
Or like I'll support sync in, you know, some worker threat executors, but I'm all async.
And that's just not like we have to be a lot more deliberate about how we handle backwards
compatibility in Flask.
We will get there.
Well, I'm really encouraged to hear that you're on that path, even if that path is a long journey.
Yeah.
And so that's definitely if some people are interested in contributing or using async code and want it in Flask,
like that's definitely a place where I could use more contributors also.
So.
Okay.
Check it out.
Awesome.
All right.
Well, I think that's probably, we're going to leave it for Flask, but it's been great to get caught up with what you're up to.
Yeah.
Thanks for having me.
You bet.
You're not out of here without answering the two final questions though.
First of all, if you're going to write some, some Flask code, what editor do you use?
PyTerm.
Professional.
I love it.
I'm right there with you.
All right.
And then notable PyPI package.
We talked about six already.
Flask, Vexoeg, and so on.
Other ones that maybe people don't know about it.
You're like, oh, you should totally check out this.
So yeah, I gave this one a little bit of thought.
I don't actually have the opportunity to use a lot of PyPI packages, but the ones that have
been kind of in my awareness lately are one called Authlib.
Okay.
A-U-T-H-Lib.
Yeah.
And that's like a new, very thorough implementation of OAuth and OpenID and OAuth2 client and server
for Flask and Django and has all sorts of integrations with different existing OAuth implementations
on different social sites.
And so-
Oh yeah.
That looks cool.
It's pretty cool.
If you go look at the documentation, it's pretty incredible how thorough it is in terms
of what standards it's supporting and all that.
And the other one I'm looking at is Flask Talisman, which is basically-
I don't know that one.
What's that about?
This one's really important.
I think a lot of people don't really think about what it solves.
And what it does is there's all these different headers that you can send in your responses to
browsers that will tell the browser how to be secure.
What stuff it's allowed to do and what stuff it should block from happening.
And there's a lot of them out there.
There's like maybe not 20, but close to 20 different headers and different configurations
of them.
Flask Talisman will set all this up for you for the most part and tell you like, it'll give
you the secure defaults.
And all you do basically is just wrap your application in the Talisman extension and it's done.
Your application is just more secure.
And I really like that.
I'm just plugging it into all my applications now.
Oh, that's cool.
It looks like it comes from Google as well, which is pretty nice.
Those are two really great recommendations there.
And I'm definitely going to play a little more with AuthLab.
I got to get some single sign on stuff going on.
So that'll be great.
Final call to action.
People now know there's a Flask 1.0.
What should they do?
There's Flask 1.0.
Go upgrade.
Watch us on GitHub and start contributing to issues.
Donate.
Go to palletsprojects.com slash donate and help the maintainers all meet up maybe.
That's awesome.
All right.
David, thanks for sharing all of what you've been up to.
It's really great work.
And I'm super excited to see Flask moving forward like it is.
Yeah.
Thanks for having me on, Michael.
You bet.
Talk to you later.
This has been another episode of Talk Python to Me.
Our guest on this episode has been David Lord, and it's been brought to you by Linode and 10x Agent on Demand.
Linode is bulletproof hosting for whatever you're building with Python.
Get four months free at talkpython.fm/Linode.
That's L-I-N-O-D-E.
When you've got a job offer in hand or are expecting one soon, contact 10x Agent on Demand, and they'll help you get the salary you deserve.
Just visit talkpython.fm/10x and mention Python.
Want to level up your Python?
If you're just getting started, try my Python jumpstart by building 10 apps or our brand new 100 days of code in Python.
And if you're interested in more than one course, be sure to check out the Everything Bundle.
It's like a subscription that never expires.
Be sure to subscribe to the show.
Open your favorite podcatcher and search for Python.
We should be right at the top.
You can also find the iTunes feed at /itunes, Google Play feed at /play, and direct RSS feed at /rss on talkpython.fm.
This is your host, Michael Kennedy.
Thanks so much for listening.
I really appreciate it.
Now, get out there and write some Python code.