WEBVTT

00:00:00.001 --> 00:00:09.400
The release of Pydantic 2.0, its partial rewrite in Rust, and its refactoring into Pydantic Core and top-level Pydantic in Python is big news.

00:00:09.400 --> 00:00:12.320
In fact, the alpha of Pydantic 2 was just released.

00:00:12.320 --> 00:00:22.160
Of course, these changes will have potentially wide-ranging and positive effects on the libraries that are built upon Pydantic, such as FastAPI, Beanie, and others.

00:00:22.160 --> 00:00:32.560
That's why this chance I had to catch up with Samuel Colvin from Pydantic and Sebastian Ramirez from FastAPI together, live from PyCon 2023, was really timely.

00:00:32.560 --> 00:00:36.100
It's a super fun and wide-ranging interview I'm sure you'll enjoy.

00:00:36.100 --> 00:00:38.600
Plus, there's a bit of an Easter egg in the middle.

00:00:38.600 --> 00:00:47.020
This is Talk Python To Me, episode 415, recorded on location at PyCon in Salt Lake City on April 23rd, 2023.

00:00:47.020 --> 00:01:02.980
Welcome to Talk Python To Me, a weekly podcast on Python.

00:01:02.980 --> 00:01:04.720
This is your host, Michael Kennedy.

00:01:04.720 --> 00:01:12.180
Follow me on Mastodon, where I'm @mkennedy, and follow the podcast using @talkpython, both on fosstodon.org.

00:01:12.180 --> 00:01:14.800
Be careful with impersonating accounts on other instances.

00:01:14.800 --> 00:01:15.740
There are many.

00:01:15.740 --> 00:01:20.640
Keep up with the show and listen to over seven years of past episodes at talkpython.fm.

00:01:20.640 --> 00:01:24.060
We've started streaming most of our episodes live on YouTube.

00:01:24.060 --> 00:01:31.500
Subscribe to our YouTube channel over at talkpython.fm/youtube to get notified about upcoming shows and be part of that episode.

00:01:31.500 --> 00:01:34.060
This episode is sponsored by Sentry.

00:01:34.060 --> 00:01:36.020
Don't let those errors go unnoticed.

00:01:36.020 --> 00:01:36.800
Use Sentry.

00:01:36.800 --> 00:01:39.980
Get started today at talkpython.fm/sentry.

00:01:39.980 --> 00:01:42.200
And it's brought to you by InfluxDB.

00:01:42.540 --> 00:01:49.540
InfluxDB is a database purpose-built for handling time series data at a massive scale for real-time analytics.

00:01:49.540 --> 00:01:53.060
Try it for free at talkpython.fm/InfluxDB.

00:01:53.460 --> 00:01:56.500
Samuel, Sebastian, super nice to see you here at PyCon.

00:01:56.500 --> 00:01:57.500
Welcome to the show.

00:01:57.500 --> 00:01:59.140
Thank you very much for having us.

00:01:59.140 --> 00:02:03.500
It's strange and exciting to do this live and to see you.

00:02:03.500 --> 00:02:04.100
Yes, I know.

00:02:04.100 --> 00:02:09.440
Normally it's remote over screen share over half the world or something like that.

00:02:09.440 --> 00:02:11.080
Yeah, I've been able to talk with you directly.

00:02:11.080 --> 00:02:12.420
Also with Samuel here.

00:02:12.420 --> 00:02:14.220
It's super cool, super cool to hear you.

00:02:14.220 --> 00:02:15.240
Yeah, thank you very much.

00:02:15.240 --> 00:02:16.080
Yes, it's great to be here.

00:02:16.080 --> 00:02:19.660
It's really fun being at PyCon and then doing this is like, yeah, even more fun.

00:02:19.660 --> 00:02:23.840
I've done my talk, so I'm much more relaxed than I would have been if it had been this time yesterday.

00:02:23.840 --> 00:02:30.480
I was just thinking, talking to someone else, like one of the best parts about giving a talk is that when it's over, you can really relax.

00:02:30.720 --> 00:02:33.320
You know what I mean? You're like, okay, now I can enjoy the conference.

00:02:33.320 --> 00:02:34.060
Absolutely, yeah.

00:02:34.060 --> 00:02:36.860
And the parties, because you can't go too big on the parties if you've got to talk.

00:02:36.860 --> 00:02:38.420
I feel like all the best ones were last night.

00:02:38.420 --> 00:02:41.380
I'm afraid. We were at a pretty good one last night, weren't we?

00:02:41.380 --> 00:02:41.880
Yeah.

00:02:41.880 --> 00:02:42.300
Yeah.

00:02:42.300 --> 00:02:43.560
But that was excellent.

00:02:43.560 --> 00:02:46.480
All right, well, really good to have you both at the show.

00:02:46.480 --> 00:02:49.060
I guess you hardly need introductions.

00:02:49.060 --> 00:02:51.320
You both are doing such cool work.

00:02:51.320 --> 00:02:53.380
We've had you on the show several times each.

00:02:53.380 --> 00:02:55.940
So maybe just let's start with a catch up.

00:02:55.940 --> 00:02:57.740
Like you both have lots of big news.

00:02:57.740 --> 00:03:00.240
Don't want to necessarily spoil too much, but you know.

00:03:00.500 --> 00:03:01.140
What have you been up to?

00:03:01.140 --> 00:03:03.820
Yeah, so I raised money earlier this year.

00:03:03.820 --> 00:03:05.320
Well, it was all sorted last year.

00:03:05.320 --> 00:03:06.680
Money came in in January this year.

00:03:06.680 --> 00:03:08.240
Started a company around Pydantic.

00:03:08.240 --> 00:03:10.120
So I've been busy hiring.

00:03:10.120 --> 00:03:12.020
Got a team of seven now.

00:03:12.020 --> 00:03:13.620
One more going to join in June.

00:03:13.620 --> 00:03:18.580
And yeah, currently we're working full-time on Pydantic version 2, getting that released.

00:03:18.580 --> 00:03:21.400
And then after that, we're going to move on to the commercial plans,

00:03:21.400 --> 00:03:25.280
which I'm not talking about too much, mostly because they're up in the air a bit.

00:03:25.340 --> 00:03:28.200
Also because if you start talking about them, you have to finish talking about them.

00:03:28.200 --> 00:03:30.500
And then that's like, I'll just like take over the whole podcast.

00:03:30.500 --> 00:03:35.000
So I'll say that, yeah, working on Pydantic V2 for now and then moving on soon.

00:03:35.000 --> 00:03:36.940
Well, first from the whole community, congratulations.

00:03:36.940 --> 00:03:38.160
You must be really thrilled.

00:03:38.600 --> 00:03:39.600
Yeah, it's amazing.

00:03:39.600 --> 00:03:41.260
It's very surreal, right?

00:03:41.260 --> 00:03:43.820
Because I was going to say, did you see this coming?

00:03:43.820 --> 00:03:44.460
No, I didn't.

00:03:44.460 --> 00:03:49.860
My plan had been to start a different company once Pydantic V2 was done.

00:03:49.860 --> 00:03:55.740
And then in November, Bogomil from Sequoia, who Sebastian knew, Sebastian recommended,

00:03:55.740 --> 00:03:56.500
he chatted to me.

00:03:56.500 --> 00:03:57.400
We had a call.

00:03:57.400 --> 00:03:58.660
We had another call two weeks later.

00:03:58.660 --> 00:04:02.680
And then he said, let's have the final meeting with like a few more partners to decide whether

00:04:02.680 --> 00:04:03.900
to invest in two weeks time.

00:04:03.900 --> 00:04:06.540
So I thought, oh, I should probably go and speak to some other VCs.

00:04:07.140 --> 00:04:08.920
So Sebastian very kindly got me lots of intros.

00:04:08.920 --> 00:04:10.560
My girlfriend also got me some intros.

00:04:10.560 --> 00:04:12.580
I had like five meetings lined up.

00:04:12.580 --> 00:04:17.020
And then the like floodgates opened and I got another like 20 or so VCs emailing me being

00:04:17.020 --> 00:04:17.840
like, please, can I call?

00:04:17.840 --> 00:04:20.860
Starting to hear about, oh, why are we not part of this?

00:04:20.860 --> 00:04:21.440
Right.

00:04:21.440 --> 00:04:23.080
And then I got COVID.

00:04:23.080 --> 00:04:27.020
So I spent a week like locked in the bedroom upstairs doing VC calls.

00:04:27.020 --> 00:04:29.860
Most of them with the like camera off feeling absolutely horrific.

00:04:29.860 --> 00:04:35.080
And yeah, and then came back full circle back and had the big call with Sequoia and took

00:04:35.080 --> 00:04:35.400
their money.

00:04:35.400 --> 00:04:36.280
They've been amazing.

00:04:36.440 --> 00:04:37.660
So it was Sequoia that invested.

00:04:37.660 --> 00:04:37.940
Yeah.

00:04:37.940 --> 00:04:38.460
Wow.

00:04:38.460 --> 00:04:38.900
Awesome.

00:04:38.900 --> 00:04:40.680
That's a big name to have behind you.

00:04:40.680 --> 00:04:45.560
So Sequoia and Partec who are the smaller VC who are like French American and then Irregular

00:04:45.560 --> 00:04:51.040
Expression, which is this really cool CTO network based kind of again, like New York and Paris.

00:04:51.040 --> 00:04:52.500
And then a bunch of angels.

00:04:52.500 --> 00:04:53.060
Yeah.

00:04:53.060 --> 00:04:56.820
Last time we spoke, it was about Pydantic V2 and then all of this broke.

00:04:56.820 --> 00:04:57.260
Yeah.

00:04:57.260 --> 00:04:57.780
Yeah.

00:04:57.780 --> 00:05:02.120
So I feel like I'm just back up to, as in problem was, although I was doing it to speed

00:05:02.120 --> 00:05:06.060
up, that was there were then two months of basically doing meetings and doing legals.

00:05:06.060 --> 00:05:09.400
So I think I've now got a team sufficiently that I'm like caught up to where I would have

00:05:09.400 --> 00:05:11.780
been if I had just sat there and written code all along.

00:05:11.780 --> 00:05:12.340
Yeah.

00:05:12.340 --> 00:05:14.840
That's how it goes, right?

00:05:14.840 --> 00:05:15.060
Yeah.

00:05:15.060 --> 00:05:19.800
You got to put a little more sand in the gears to grow, I guess.

00:05:19.800 --> 00:05:21.340
And Sebastian, how about you?

00:05:21.340 --> 00:05:22.540
What do you, what have you been up to?

00:05:22.540 --> 00:05:22.900
How have you been?

00:05:22.900 --> 00:05:24.360
Oh, I've been good.

00:05:24.360 --> 00:05:24.800
I've been good.

00:05:24.800 --> 00:05:25.180
Yeah.

00:05:25.180 --> 00:05:29.440
Very excited about like what they are doing at Pydantic is like the team they are assembling

00:05:29.440 --> 00:05:30.800
is like just amazing.

00:05:30.800 --> 00:05:36.860
And like, yeah, just like recently working a bunch in FastAPI and like Typer and actually

00:05:36.860 --> 00:05:43.540
like in also some of the low level things of FastAPI and also not just FastAPI, but like

00:05:43.540 --> 00:05:44.960
the things that go underneath.

00:05:44.960 --> 00:05:50.020
Right now, like one of the things that I am pushing for is having documentation of the

00:05:50.020 --> 00:05:54.720
API reference of the reference of the, each one of the parameters for what it is for each

00:05:54.720 --> 00:05:56.020
one of the methods, like all that stuff.

00:05:56.020 --> 00:05:56.340
Yeah.

00:05:56.340 --> 00:06:01.380
And I want to do it in a, in a better way that is more maintainable and that I can test

00:06:01.380 --> 00:06:06.740
the actual documentation for those parameters and consistency between like, there's a bunch

00:06:06.740 --> 00:06:08.080
of things that I'm trying to do.

00:06:08.080 --> 00:06:12.120
And like, it also goes to the low levels of like typing and interacting with the people

00:06:12.120 --> 00:06:16.340
that is handling typing and like all the stuff that is super cool, super exciting.

00:06:16.340 --> 00:06:21.240
But like, I think it can work and it can, it can make these things have like, you know,

00:06:21.240 --> 00:06:26.320
like the API reference for the tools is something that a lot of people have been requesting and

00:06:26.320 --> 00:06:31.440
like being able to have that in a way that is easy to maintain and that can work well and

00:06:31.440 --> 00:06:32.240
that I can handle.

00:06:32.240 --> 00:06:34.260
Like, I think that's, that's super exciting on that side.

00:06:34.360 --> 00:06:38.520
And on the other side, of course, like the integration with Pydantic V2 is super exciting

00:06:38.520 --> 00:06:41.220
now that they have like the first alpha available.

00:06:41.220 --> 00:06:42.380
It is.

00:06:42.380 --> 00:06:45.780
I mean, here you are going along working on FastAPI.

00:06:45.780 --> 00:06:49.100
Everyone I talked to was just universally impressed with it.

00:06:49.100 --> 00:06:54.100
You know, honestly, like I've never heard a bad thing about FastAPI and people are really

00:06:54.100 --> 00:06:54.580
enjoying it.

00:06:54.580 --> 00:06:59.620
And then here comes Samuel just changing the foundation, changing up Pydantic.

00:07:00.260 --> 00:07:02.500
No, no, no.

00:07:02.500 --> 00:07:03.040
I'm just teasing.

00:07:03.040 --> 00:07:07.340
So how much work is that actually going to be to kind of make the change?

00:07:07.340 --> 00:07:09.080
Is it kind of nothing or is it some work?

00:07:09.080 --> 00:07:11.000
No, like there will be some working FastAPI.

00:07:11.000 --> 00:07:15.520
The thing is for final users, it will be like almost transparent.

00:07:15.520 --> 00:07:15.940
Right.

00:07:15.940 --> 00:07:21.660
They will probably like, if they are doing like weird stuff, complex things like that touches

00:07:21.660 --> 00:07:25.000
the corner cases or things like that, like they will probably have to update some things.

00:07:25.000 --> 00:07:29.320
But for most of the use cases, it will be pretty much transparent for people.

00:07:29.660 --> 00:07:33.000
And they will just like get like the, like, I don't know, like 10, 20x performance from

00:07:33.000 --> 00:07:33.660
Pydantic v2.

00:07:33.660 --> 00:07:35.220
And also like the...

00:07:35.220 --> 00:07:37.220
I was going to say, just on the performance, I'm sorry to interrupt you.

00:07:37.220 --> 00:07:42.120
One of the big things that we will be able to, you'll be able to drop from FastAPI is the,

00:07:42.120 --> 00:07:44.160
I'm going to call it a hack, but it's not your fault.

00:07:44.160 --> 00:07:44.740
It's my fault.

00:07:44.740 --> 00:07:48.700
Of like, don't ask the type problem of serialization.

00:07:48.700 --> 00:07:54.060
So I think that the like speed up on serialization in FastAPI could exceed, like, you know,

00:07:54.060 --> 00:07:54.880
could be even bigger than that.

00:07:54.940 --> 00:07:59.420
I don't know that yet, but I'm really hopeful for some like massive improvements because of

00:07:59.420 --> 00:08:03.040
fixes in Pydantic that make FastAPI simpler and more elegant.

00:08:03.040 --> 00:08:03.620
Yeah.

00:08:03.620 --> 00:08:07.580
And since they're turning up the lights, we'll see how long we last here.

00:08:07.580 --> 00:08:10.260
We'll stay as long as we can.

00:08:10.260 --> 00:08:13.920
If you hear any noise in the background, that's because they're trying to tear down PyCon,

00:08:13.920 --> 00:08:14.760
but we're going to...

00:08:14.760 --> 00:08:16.120
They're tearing down PyCon around us, it seems.

00:08:16.120 --> 00:08:17.620
We will not let it be torn out.

00:08:17.620 --> 00:08:18.480
It will live on.

00:08:19.020 --> 00:08:20.620
It's not because of Pydantic V2.

00:08:20.620 --> 00:08:24.940
So, yeah, we may have to pause and move, but we'll find out.

00:08:24.940 --> 00:08:32.260
Anyway, from a user for Pydantic, Samuel, if you haven't gone to like deeply gone into like

00:08:32.260 --> 00:08:36.460
root object validation and all that kind of stuff, it's probably you won't even know, right?

00:08:36.460 --> 00:08:38.080
So I think the hardest thing...

00:08:38.080 --> 00:08:38.440
Yeah, you're right.

00:08:38.440 --> 00:08:42.140
The vast majority of your code will either continue to work or we'll have a...

00:08:44.140 --> 00:08:49.420
If you get run over by a forklift, it's going to really slow down the development of Pydantic,

00:08:49.420 --> 00:08:49.920
by the way.

00:08:49.920 --> 00:08:55.460
We're going to have a mod tool to change the name of methods.

00:08:55.460 --> 00:09:00.280
So with luck, the vast majority of the changes should be automated.

00:09:00.280 --> 00:09:05.440
I suspect that, and I was saying this earlier in the open space, the hardest thing is probably

00:09:05.440 --> 00:09:11.600
going to be where your API subtly changes in its restrictions because of effectively edge

00:09:11.600 --> 00:09:12.880
cases that Pydantic has fixed.

00:09:13.200 --> 00:09:17.240
So for example, in Pydantic v1, we would coerce a int to a string.

00:09:17.240 --> 00:09:21.800
If you passed a string to an int to a string field, we would coerce it.

00:09:21.800 --> 00:09:23.800
I think that that's wrong and we shouldn't have done it.

00:09:23.800 --> 00:09:24.620
And so now we don't.

00:09:24.620 --> 00:09:29.500
But I was saying in the example, if for some reason you stored your IDs as strings and therefore

00:09:29.500 --> 00:09:34.200
your API had the ID field as a string, but your user was just like pumping them into your

00:09:34.200 --> 00:09:38.040
API as integers because that seemed to make sense to them, that's going to break.

00:09:38.040 --> 00:09:41.700
And you probably haven't gotten a unit test that test that because you know your ID field

00:09:41.700 --> 00:09:42.140
is a string.

00:09:42.260 --> 00:09:44.100
So I feel sorry for those people.

00:09:44.100 --> 00:09:50.720
And my biggest request would be if you're a user, try Pydantic v2 as soon as possible.

00:09:50.720 --> 00:09:54.640
I know if you use it via FastAPI, you can't yet, but like all the other libraries.

00:09:54.640 --> 00:09:59.700
But the sooner you can try it, the sooner you can tell us and the more easily we can fix things.

00:09:59.700 --> 00:10:02.320
And we are prepared to add compatibility shims.

00:10:02.860 --> 00:10:03.040
Okay.

00:10:03.040 --> 00:10:06.640
Well, there, I mean, in Python, we have sort of a from futures import.

00:10:06.640 --> 00:10:10.800
Well, there'd be from a, from history import type of like reverse thing.

00:10:10.800 --> 00:10:14.760
Just slow that down or is it going to be a deprecation or is it just...

00:10:14.760 --> 00:10:19.040
So we're doing deprecation warnings everywhere we can or deprecation errors saying this has

00:10:19.040 --> 00:10:19.420
gone away.

00:10:19.420 --> 00:10:20.880
You probably want to replace it with this thing.

00:10:20.880 --> 00:10:22.320
We're working really hard on that.

00:10:22.320 --> 00:10:28.820
We haven't got a like from future import or a compact layer yet for actual like validation

00:10:28.820 --> 00:10:29.260
logic.

00:10:29.420 --> 00:10:30.580
But if we have to, we will.

00:10:30.580 --> 00:10:31.060
Yeah.

00:10:31.060 --> 00:10:31.600
Okay.

00:10:31.600 --> 00:10:32.560
You'll see, right?

00:10:32.560 --> 00:10:34.240
See how much screaming...

00:10:34.240 --> 00:10:38.420
What we didn't want to do was try and guess at what the problems were and build a compatibility

00:10:38.420 --> 00:10:39.560
layer that people didn't need.

00:10:39.560 --> 00:10:40.380
Yeah, of course.

00:10:40.380 --> 00:10:41.940
So that's why we're doing it this way.

00:10:41.940 --> 00:10:42.420
Yeah.

00:10:42.420 --> 00:10:43.620
That makes a lot of sense.

00:10:43.620 --> 00:10:48.700
You want to go as minimal backwards trying to fill those gaps as possible, right?

00:10:48.700 --> 00:10:53.020
And if I'm brutal about it, if insert name of big bank that use Pydantic locks and never

00:10:53.020 --> 00:10:57.760
engage with the open source community, get stung by this, they never paid me a penny and they've

00:10:57.760 --> 00:11:02.260
never engaged, then like, I'm sorry for them, but I'm not as sorry as I would be if they

00:11:02.260 --> 00:11:05.700
had like come and reported an issue and tried to like help along the way.

00:11:05.700 --> 00:11:06.080
Yeah.

00:11:06.080 --> 00:11:06.320
Yeah.

00:11:06.320 --> 00:11:08.700
Like, can we work with you to just like smooth this over?

00:11:08.700 --> 00:11:13.640
And, you know, worst case, can it be, you know, equal, equal, Pydantic, equal, equal,

00:11:13.640 --> 00:11:14.600
1.10?

00:11:14.600 --> 00:11:18.520
I think we'll carry on supporting critical security fixes for a year.

00:11:18.520 --> 00:11:19.040
Okay.

00:11:19.040 --> 00:11:21.480
So there's something of an LTS type of thing you're thinking?

00:11:21.480 --> 00:11:21.880
Yeah.

00:11:21.880 --> 00:11:22.740
For a while.

00:11:22.740 --> 00:11:23.380
We have to, right?

00:11:23.380 --> 00:11:24.120
For a while.

00:11:24.120 --> 00:11:25.240
And yeah, we'll see.

00:11:25.240 --> 00:11:27.120
Look at the download numbers and play it by ear.

00:11:27.120 --> 00:11:27.580
Yeah.

00:11:27.580 --> 00:11:28.200
All right.

00:11:28.200 --> 00:11:28.440
Cool.

00:11:28.440 --> 00:11:33.660
While we're talking about compatibility, if people are like doing a lot of the overriding

00:11:33.660 --> 00:11:37.380
functions and stuff in their Pydantic models, like what do they, what should they expect?

00:11:37.380 --> 00:11:38.940
Too many changes are pretty similar.

00:11:38.940 --> 00:11:45.400
One of the biggest changes is that the init method of a model is now no longer called when

00:11:45.400 --> 00:11:47.140
you're, unless you literally call init.

00:11:47.140 --> 00:11:53.380
So if you call model validate, or if your model is nested inside another model, init is no longer

00:11:53.380 --> 00:11:53.720
called.

00:11:53.720 --> 00:11:58.360
The solution for that is to use a wrap validator or a model validator, but that's going to

00:11:58.360 --> 00:12:00.140
be one of the pain points for people.

00:12:00.140 --> 00:12:04.380
But there's just, it turns out with the Rust API, it's literally impossible without a massive

00:12:04.380 --> 00:12:05.340
performance hit to do that.

00:12:07.340 --> 00:12:10.240
This portion of Talk Python To Me is brought to you by Sentry.

00:12:10.240 --> 00:12:14.480
You know that Sentry captures the errors that would otherwise go unnoticed.

00:12:14.480 --> 00:12:18.820
Of course, they have incredible support for basically any Python framework.

00:12:18.820 --> 00:12:25.660
They have direct integrations with Flask, Django, FastAPI, and even things like AWS Lambda and

00:12:25.660 --> 00:12:26.120
Celery.

00:12:26.720 --> 00:12:30.320
But did you know they also have native integrations with mobile app frameworks?

00:12:30.320 --> 00:12:36.140
Whether you're building an Android or iOS app, or both, you can gain complete visibility into

00:12:36.140 --> 00:12:40.600
your application's correctness both on the mobile side and server side.

00:12:40.600 --> 00:12:46.800
We just completely rewrote Talk Python's mobile apps for taking our courses, and we massively

00:12:46.800 --> 00:12:50.160
benefited from having Sentry integration right from the start.

00:12:50.680 --> 00:12:55.540
We used Flutter for our native mobile framework, and with Sentry, it was literally just two

00:12:55.540 --> 00:12:58.860
lines of code to start capturing errors as soon as they happen.

00:12:58.860 --> 00:13:02.840
Of course, we don't love errors, but we do love making our users happy.

00:13:02.840 --> 00:13:08.920
Solving problems as soon as possible with Sentry on the mobile Flutter code and the Python server

00:13:08.920 --> 00:13:12.760
side code together made understanding error reports a breeze.

00:13:12.760 --> 00:13:19.500
So whether you're building Python server side apps or mobile apps or both, give Sentry a try

00:13:19.500 --> 00:13:22.220
to get a complete view of your app's correctness.

00:13:22.220 --> 00:13:27.120
Thank you to Sentry for sponsoring the show and helping us ship more reliable mobile apps

00:13:27.120 --> 00:13:27.900
to all of you.

00:13:27.900 --> 00:13:30.580
Do you already have a roadmap?

00:13:30.580 --> 00:13:33.460
Have you already tried the alpha on FastAPI?

00:13:33.460 --> 00:13:35.180
Like, what's the story for you guys?

00:13:35.180 --> 00:13:36.520
So, like...

00:13:36.520 --> 00:13:37.120
Pedantic-wise.

00:13:37.120 --> 00:13:37.980
Yeah, yeah, yeah.

00:13:37.980 --> 00:13:42.300
So, like, we have actually been interacting a lot, like, with what are the changes that are

00:13:42.300 --> 00:13:42.480
needed?

00:13:42.480 --> 00:13:43.600
Like, what is it going to be?

00:13:43.600 --> 00:13:48.180
And like, as someone was saying, like, I have a lot of code that is quite hacky.

00:13:48.500 --> 00:13:51.460
I was actually surprised it didn't break much.

00:13:51.460 --> 00:13:52.780
It just, like, really worked.

00:13:52.780 --> 00:13:58.240
And like, it's for this particular use case where you can have, like, they are so loud.

00:13:58.240 --> 00:13:59.840
They really want to tear us down.

00:13:59.840 --> 00:14:00.300
I know.

00:14:00.300 --> 00:14:02.220
We might have to be weird to say it.

00:14:02.220 --> 00:14:02.680
But let's go ahead.

00:14:02.680 --> 00:14:03.320
Let's finish this up.

00:14:03.320 --> 00:14:03.500
Yeah.

00:14:03.880 --> 00:14:08.620
So, like, validation error.

00:14:08.620 --> 00:14:09.460
Can it concentrate?

00:14:09.460 --> 00:14:13.280
So, imagine this use case where you have user model.

00:14:13.280 --> 00:14:16.240
And then this, you want to return this user model.

00:14:16.460 --> 00:14:22.360
But then you have an authenticated user model, as you were showing in the talk, in the PyCon talk.

00:14:22.360 --> 00:14:26.080
And then this authenticated user model has a field that is a password.

00:14:26.080 --> 00:14:33.860
If you return that use, the authenticated user directly, FastAPI does a lot of tricks to make

00:14:33.860 --> 00:14:38.600
sure that what you receive in the client side is the actual user without the password.

00:14:38.600 --> 00:14:41.080
That is the thing that you declared that you were going to return.

00:14:41.080 --> 00:14:46.000
But by default, if you don't do it through FastAPI, but you do it with just plain Pydantic,

00:14:46.000 --> 00:14:48.480
it will just check, like, hey, is this an instance of the other?

00:14:48.580 --> 00:14:50.700
And then it will include the field.

00:14:50.700 --> 00:14:54.860
Because, like, you know, because in thinking about types, it makes sense.

00:14:54.860 --> 00:14:56.920
Like, oh, this is a subclass of that.

00:14:56.920 --> 00:14:58.400
So, it makes sense that it's valid.

00:14:58.400 --> 00:15:02.280
But when you think about data in an API, it doesn't make sense that it will include more

00:15:02.280 --> 00:15:03.460
data than what it should.

00:15:03.460 --> 00:15:04.760
Right, right, right.

00:15:04.760 --> 00:15:10.320
Because you don't want to either have a mass injection attack on the inbound data or an

00:15:10.320 --> 00:15:12.740
over-exposure on the way out, right?

00:15:12.740 --> 00:15:14.740
You know, give away the password from users.

00:15:14.740 --> 00:15:15.220
Is that bad?

00:15:15.220 --> 00:15:16.780
I think it's pretty bad.

00:15:16.780 --> 00:15:17.620
Okay, yeah, all right.

00:15:18.320 --> 00:15:23.160
Like, you know, for example, like, some months ago or years or something, like, I remember

00:15:23.160 --> 00:15:28.500
that Kaggle, the Kaggle API was returning, like, some of the hashes of the experiments.

00:15:28.500 --> 00:15:33.420
So, like, you know, it's like, it's a mistake and a bit, but it's sad that it will end up

00:15:33.420 --> 00:15:36.360
just, like, filtering more data than what it should be returning.

00:15:36.360 --> 00:15:38.040
And it's something that can happen very easily.

00:15:38.040 --> 00:15:43.240
It can happen very easily to FastAPI applications if people don't specify what is the response

00:15:43.240 --> 00:15:45.260
model, the thing that they want to return.

00:15:45.260 --> 00:15:47.280
And they just return a bunch of data directly.

00:15:47.700 --> 00:15:52.860
So FastAPI does a lot of things to make sure that when you declare a response model that

00:15:52.860 --> 00:15:55.460
should filter this data, the data is filtered.

00:15:55.460 --> 00:15:58.480
But that's a lot of code in FastAPI to make it compatible.

00:15:58.480 --> 00:16:02.280
With the new Pydantic V2, that's going to be pretty much transparent.

00:16:02.280 --> 00:16:03.780
So that's amazing.

00:16:03.780 --> 00:16:04.620
That is amazing.

00:16:04.620 --> 00:16:04.800
Yeah.

00:16:04.800 --> 00:16:08.080
There's going to be, like, a bunch of things that require, like, some refactoring and

00:16:08.080 --> 00:16:14.560
also making sure that the Pydantic V1 and V2 are compatible at the same time in some way

00:16:14.560 --> 00:16:16.740
so that people can have, like, a migration path.

00:16:16.740 --> 00:16:21.460
But yeah, like, we have been making sure that, like, all the things that need to be changed

00:16:21.460 --> 00:16:25.320
or that need to be updated or, like, all the things that need to be exposed from the Pydantic

00:16:25.320 --> 00:16:26.620
side are actually available.

00:16:26.620 --> 00:16:29.180
Yeah, it's awesome that you guys are working so closely together on this.

00:16:29.180 --> 00:16:30.280
I mean, it's going to make it.

00:16:30.280 --> 00:16:31.060
Yeah, absolutely.

00:16:31.060 --> 00:16:34.100
So in my mind, these two projects are pretty closely tied.

00:16:34.100 --> 00:16:36.520
I know that they're not, but that's a big use case.

00:16:36.520 --> 00:16:37.360
Yeah, I think that's true.

00:16:37.360 --> 00:16:40.720
And we know that FastAPI is by far our biggest dependent.

00:16:41.120 --> 00:16:46.980
But also Django Ninja, which is, I think, now second or third, maybe third after SQL model

00:16:46.980 --> 00:16:51.900
by Starz, is, like, Vitaly, who maintains that, has been engaging a lot with us on V2.

00:16:51.900 --> 00:16:54.280
So yeah, lots of other projects are interested in it.

00:16:54.280 --> 00:16:57.820
And I think, yeah, lots of people will be able to remove messy code because of that problem.

00:16:57.820 --> 00:17:01.500
Because, yeah, like, the invariance of the response interface problem.

00:17:01.500 --> 00:17:02.160
That's fantastic.

00:17:02.160 --> 00:17:04.480
Coming back to your previous question about...

00:17:04.480 --> 00:17:06.760
Before we go to that, I think we should probably find it.

00:17:06.760 --> 00:17:07.240
What do you think?

00:17:07.240 --> 00:17:08.120
Yeah, I think you might be right.

00:17:08.120 --> 00:17:11.840
Not even necessarily, I think the audio may be okay, but just for a concentration, it's

00:17:11.840 --> 00:17:13.340
very loud with the trucks around us.

00:17:13.340 --> 00:17:16.000
I feel like I'm on the deck of that aircraft carrier, so I throw things off the side.

00:17:16.000 --> 00:17:17.660
Yeah, okay, let's pause this for a moment.

00:17:17.660 --> 00:17:18.160
We'll be back.

00:17:18.160 --> 00:17:18.540
Hold on.

00:17:18.540 --> 00:17:22.400
So we have survived the disassembly.

00:17:22.400 --> 00:17:24.320
We have returned to continue.

00:17:24.320 --> 00:17:29.500
We were talking about the integration of FastAPI and Pydantic, and that was really cool.

00:17:29.500 --> 00:17:34.340
I think something I'd like to kind of move to real quick is this big announcement, alpha

00:17:34.340 --> 00:17:35.540
of version two.

00:17:35.540 --> 00:17:40.120
Samuel, last time you were on the show, we spoke about the plan for version two, and

00:17:40.120 --> 00:17:41.920
now you're released in an alpha stage.

00:17:41.920 --> 00:17:43.480
Tell people where we are with this.

00:17:43.480 --> 00:17:47.520
Yeah, so we're, yeah, we've had two alphas, maybe three alphas now out.

00:17:47.520 --> 00:17:54.060
We're basically pretty close to a feature freeze, and the plan is to release the package, release

00:17:54.060 --> 00:17:58.800
a beta, and effectively, we hope that we can then release the full release, say two weeks

00:17:58.800 --> 00:17:59.240
after that.

00:17:59.240 --> 00:18:01.880
But there'll be bugs, and we'll fix them, and we'll have more betas.

00:18:01.880 --> 00:18:06.460
But effectively, once we get to beta, the plan is that active development is stopping

00:18:06.460 --> 00:18:07.800
bar fixing bugs.

00:18:07.800 --> 00:18:09.860
Now it's performance and bugs, right?

00:18:09.860 --> 00:18:10.100
Yeah.

00:18:10.100 --> 00:18:13.480
And obviously, one of the big things will be once that's out, there'll be a lot more work

00:18:13.480 --> 00:18:16.020
on, say, FastAPI, Django Ninja, et cetera, et cetera.

00:18:16.020 --> 00:18:18.600
And that might come back with, we really need this thing.

00:18:18.600 --> 00:18:23.340
Either this is broken, or we really need that to make it, you know, to reduce the overhead

00:18:23.340 --> 00:18:24.340
of upgrading.

00:18:24.340 --> 00:18:30.420
One of the things I did for Pydantic 1.10, which was super valuable in beta, was to go

00:18:30.420 --> 00:18:35.320
through packages that use Pydantic, initially sorting by star, but then looking at what they

00:18:35.320 --> 00:18:37.260
actually do, and trying to upgrade them.

00:18:37.260 --> 00:18:41.240
And that, like, found me a bunch of bugs in either libraries or in Pydantic.

00:18:41.240 --> 00:18:46.300
So we're not promising we're going to go and upgrade the whole of GitHub to Pydantic V2,

00:18:46.680 --> 00:18:50.240
but we'll do a bit of that mostly to try and find bugs.

00:18:50.240 --> 00:18:54.620
One of the things that would be really useful is if anyone has an application that uses Pydantic,

00:18:54.620 --> 00:18:59.480
preferably without FastAPI or another library, that they would like help upgrading, we would

00:18:59.480 --> 00:19:00.840
love to come and help.

00:19:00.840 --> 00:19:05.880
And it might be a really powerful way of us, again, seeing the real pain points and identifying

00:19:05.880 --> 00:19:07.200
bugs before we get to V2.

00:19:07.200 --> 00:19:07.720
Yeah.

00:19:07.720 --> 00:19:12.120
And I guess another thing to mention that is a real headline, and I also want to get your

00:19:12.120 --> 00:19:15.040
thoughts on this, Sebastian, is the performance numbers, right?

00:19:15.100 --> 00:19:19.280
I mean, you put out some pretty impressive performance numbers, and Sebastian gets to

00:19:19.280 --> 00:19:20.440
piggyback on that, right?

00:19:20.440 --> 00:19:20.920
Yeah.

00:19:20.920 --> 00:19:23.740
I mean, yeah, I'm really proud of it, right?

00:19:23.740 --> 00:19:24.820
Yeah, you should be.

00:19:24.820 --> 00:19:30.580
I think to go in a change of release, in a bump of release, to be in the ballpark of 22

00:19:30.580 --> 00:19:35.660
times faster, not 22%, but 22 times faster, I don't know of another package that's made

00:19:35.660 --> 00:19:37.780
an upgrade of that kind of order of magnitude.

00:19:37.780 --> 00:19:41.160
What's crazy is it's not numerical computing, right?

00:19:41.160 --> 00:19:41.920
It's general purpose.

00:19:42.020 --> 00:19:46.040
If you look at the example I gave in my talk earlier, it's a completely standard Pynantic

00:19:46.040 --> 00:19:47.000
model with four fields.

00:19:47.000 --> 00:19:50.920
And that's where we're seeing that kind of like 22 times speed up.

00:19:50.920 --> 00:19:51.940
So I think it's going to be massive.

00:19:51.940 --> 00:19:57.140
I have my own cynicism about people who hype about performance as being the most important

00:19:57.140 --> 00:19:57.340
thing.

00:19:57.340 --> 00:20:01.240
I don't think most applications, it's actually the thing that matters most.

00:20:01.240 --> 00:20:02.300
But I think it matters.

00:20:02.660 --> 00:20:05.160
A, it matters to everyone, and everyone wants it to go in the same direction.

00:20:05.160 --> 00:20:10.420
And two, it matters to the whole world and to the whole community that we effectively reduce

00:20:10.420 --> 00:20:14.320
the energy that we consume, like doing compute, basically.

00:20:14.320 --> 00:20:14.560
Right.

00:20:14.560 --> 00:20:15.740
That's absolutely true.

00:20:15.740 --> 00:20:20.000
And also, even if people don't actually need it, there's a group of people who are like,

00:20:20.000 --> 00:20:22.500
well, I'm going to leave for Go because it's not fast enough.

00:20:22.500 --> 00:20:24.200
I can't do enough concurrency or whatever.

00:20:24.660 --> 00:20:28.440
And if they don't have that feeling, even if they didn't actually need that percentage

00:20:28.440 --> 00:20:30.640
increase, that's still really good for the Python community.

00:20:30.640 --> 00:20:36.720
Even me, I was saying I had a gigabyte of data from web analytics that I needed to load

00:20:36.720 --> 00:20:38.180
into a Polars data frame.

00:20:38.180 --> 00:20:43.940
And for that, I needed to A, extract some attributes from nested fields and B, parse dates and things

00:20:43.940 --> 00:20:44.240
like that.

00:20:44.240 --> 00:20:45.460
And I used Pynantic V2.

00:20:45.460 --> 00:20:49.060
And it was vastly faster with V2.

00:20:49.060 --> 00:20:51.700
It went from like toodling, what's the word I'm looking for?

00:20:51.700 --> 00:20:56.840
Twiddling your thumbs to like it happens virtually instantly, right?

00:20:56.840 --> 00:20:57.400
And that's fantastic.

00:20:57.400 --> 00:21:01.760
And that'll be even more true when you have an order of magnitude or two orders of magnitude

00:21:01.760 --> 00:21:02.300
more data.

00:21:02.300 --> 00:21:03.220
Yeah, for sure.

00:21:03.220 --> 00:21:04.600
Sebastian, how about you?

00:21:04.600 --> 00:21:06.440
What's the knock-on effect for FastAPI?

00:21:06.440 --> 00:21:11.180
So I think one of the coolest things is that people won't have to change the code to get

00:21:11.180 --> 00:21:12.160
that performance benefit.

00:21:12.160 --> 00:21:13.720
It's just going to be like a bump suddenly.

00:21:13.720 --> 00:21:19.180
And because of the new ways that Pynantic can handle the data, we're going to be able

00:21:19.180 --> 00:21:21.660
to, there's something that needs to be done in FastAPI, but we're going to

00:21:21.660 --> 00:21:28.620
be able to let the parsing of the data, let Pynantic handle that in the Rust site.

00:21:28.620 --> 00:21:34.360
So Pynantic will be able to just read the JSON bytes instead of reading them in the Python

00:21:34.360 --> 00:21:35.740
site and let Pynantic do that.

00:21:35.740 --> 00:21:39.120
And then Pynantic give the models back to the rest of the code of FastAPI.

00:21:39.120 --> 00:21:41.600
That alone will boost performance a lot.

00:21:41.600 --> 00:21:45.600
But the fact that it's being done in Rust, in the Rust site, it's just going to be amazing.

00:21:45.600 --> 00:21:46.000
Yeah.

00:21:46.300 --> 00:21:50.820
Like one of the other things that I want to do that is on the plans is to let users

00:21:50.820 --> 00:21:55.180
define how they want to serialize data and not have like, this is just like by default,

00:21:55.180 --> 00:21:58.880
it's just like Pynantic models and like it converts automatically to JSON.

00:21:59.060 --> 00:22:03.880
But I want to allow users to decide how to serialize the objects and the data so that

00:22:03.880 --> 00:22:04.600
they can just...

00:22:04.600 --> 00:22:06.300
Like data classes or something like that?

00:22:06.300 --> 00:22:06.600
Yeah.

00:22:06.600 --> 00:22:10.500
For example, they can say like, oh, I don't want to serialize with the standard JSON serializer.

00:22:10.500 --> 00:22:13.020
I want to serialize with our JSON, which is like the...

00:22:13.020 --> 00:22:14.040
I see.

00:22:14.040 --> 00:22:16.740
Rust based implementation to serialize JSON.

00:22:17.020 --> 00:22:21.020
Or they can say like, I want Pynantic to be the one that serializes this because I know

00:22:21.020 --> 00:22:22.740
that this is just a model that can handle that.

00:22:22.740 --> 00:22:23.980
They can also like...

00:22:23.980 --> 00:22:25.880
And this is one of the things that I think is super cool.

00:22:25.880 --> 00:22:27.880
They can also create...

00:22:27.880 --> 00:22:33.960
They will be able to create a way to say, I want to serialize this response to XML or something

00:22:33.960 --> 00:22:38.880
like that or to YAML and to let Pynantic handle the validation, but then like do the serialization

00:22:38.880 --> 00:22:43.400
in a way that they can customize the whole thing without having to do it directly in the code.

00:22:43.400 --> 00:22:47.100
Maybe even some of these crazy stream buffer type of protocols.

00:22:47.100 --> 00:22:51.920
You know, like, yeah, like protocol buffers with GRPC or like even message pack or like,

00:22:51.920 --> 00:22:56.220
you know, like a bunch of these things that there's no obvious way and there's no native

00:22:56.220 --> 00:23:00.060
way to have support for that, for reading the data and for exporting the data.

00:23:00.060 --> 00:23:02.900
And like, that's one of the things that I have like implants.

00:23:02.900 --> 00:23:06.800
I like, I'm probably saying too much and then I'm going to account all the pieces of the code.

00:23:06.800 --> 00:23:07.800
And now they're like, you know what?

00:23:07.800 --> 00:23:08.620
You promised this.

00:23:08.620 --> 00:23:09.860
You did promise it.

00:23:09.860 --> 00:23:10.400
Well.

00:23:10.400 --> 00:23:12.340
Can I just come back on serialization for a minute?

00:23:12.340 --> 00:23:12.640
Yeah, please.

00:23:12.640 --> 00:23:12.760
Yeah, please.

00:23:13.100 --> 00:23:13.240
Yeah.

00:23:13.240 --> 00:23:19.120
So what we've, I've worked from October, quite like putting to one side, the whole funding

00:23:19.120 --> 00:23:21.860
round in the middle of it was working solidly on serialization.

00:23:21.860 --> 00:23:26.080
So we have, there's almost as much code in Pynantic core now for serialization as there

00:23:26.080 --> 00:23:26.760
is for validation.

00:23:26.760 --> 00:23:27.340
Yeah.

00:23:27.340 --> 00:23:32.800
Well, we can serialize directly to, to Jason using the same underlying library that, or Jason

00:23:32.800 --> 00:23:38.280
uses using Serdi, but one, and also we can, you can customize how your serialization

00:23:38.280 --> 00:23:42.900
goes on a per field basis rather than on a per type basis, which is like incredibly powerful.

00:23:42.900 --> 00:23:46.380
But we also allow you to effectively serialize to Python.

00:23:46.380 --> 00:23:51.040
So not just what used to be the dict method, but basically do JSONable Python.

00:23:51.040 --> 00:23:55.820
So you effectively set the mode when serializing to Python, to Jason, and you will only get the

00:23:55.820 --> 00:24:00.240
like, whatever it is, seven primitive Jason types in Python, which is super valuable if you

00:24:00.240 --> 00:24:04.220
want your output to be XML, because then you know your XML encoder only needs to bother,

00:24:04.220 --> 00:24:07.900
needs to take in dictionaries, list, ints, floats, none, bool.

00:24:08.220 --> 00:24:08.400
Yeah.

00:24:08.400 --> 00:24:11.220
Rather than whatever complex data you have.

00:24:11.220 --> 00:24:15.760
So there's an, or I, yeah, I'm like super proud of lots of the advantages of serialization.

00:24:15.760 --> 00:24:20.620
My 45 minute talk earlier, I was able to touch about half of the big new features, which

00:24:20.620 --> 00:24:23.180
kind of talks about quite how much has changed.

00:24:23.180 --> 00:24:23.720
Yeah.

00:24:23.720 --> 00:24:24.540
That's really exciting.

00:24:24.540 --> 00:24:28.500
I think we definitely, I was saying earlier, if I had known how long it was going to take,

00:24:28.500 --> 00:24:30.220
I would never have set out on this journey.

00:24:30.360 --> 00:24:33.880
So the best thing about it is I didn't, I didn't think about how long it was going to

00:24:33.880 --> 00:24:36.020
take because we didn't try and do a bit more.

00:24:36.020 --> 00:24:38.040
We tried to do everything or I tried to do everything.

00:24:38.040 --> 00:24:40.020
And that's how it's disadvantaged.

00:24:40.020 --> 00:24:41.820
It's taken longer than we had hoped, but.

00:24:41.820 --> 00:24:42.680
But here you are.

00:24:42.680 --> 00:24:43.300
You're pretty much here.

00:24:43.300 --> 00:24:43.920
That's really good.

00:24:43.920 --> 00:24:44.580
That's really good.

00:24:44.580 --> 00:24:49.440
And so when you think about performance, right, obviously the 22 times faster is awesome.

00:24:49.440 --> 00:24:51.660
The FastAPI speedup is awesome.

00:24:51.660 --> 00:24:58.100
But if you do something like SQL model and FastAPI or Beanie and FastAPI, you're getting

00:24:58.100 --> 00:25:03.600
on both ends, you're getting that Beanie or the Pydantic benefits with the Beanie integration

00:25:03.600 --> 00:25:04.220
and the fast.

00:25:04.220 --> 00:25:08.280
So you, you're kind of putting Pydantic in both those layers.

00:25:08.280 --> 00:25:11.800
And so those speedups are like twice as good or something like that.

00:25:11.800 --> 00:25:12.160
Yeah.

00:25:12.160 --> 00:25:12.340
Right.

00:25:12.340 --> 00:25:16.420
I think you, well, they're probably, yeah, they're like, they're the same relatively,

00:25:16.420 --> 00:25:17.780
but more in absolute terms.

00:25:17.780 --> 00:25:18.160
Yeah.

00:25:18.160 --> 00:25:18.560
Yeah.

00:25:18.560 --> 00:25:19.260
Yeah, absolutely.

00:25:19.260 --> 00:25:21.640
So, yeah, I think it's, you know, the fact that it's a lot of people,

00:25:21.640 --> 00:25:26.860
so many things have been built upon Pydantic means you've just sped up a bunch of projects

00:25:26.860 --> 00:25:28.880
without them doing too much.

00:25:28.880 --> 00:25:29.080
Yeah.

00:25:29.080 --> 00:25:30.060
We get the, like the win.

00:25:30.060 --> 00:25:32.540
It's like CPython itself getting faster, helps everyone.

00:25:32.540 --> 00:25:36.320
This is like the next layer down, but we, you know, as a dependency of lots of packages,

00:25:36.320 --> 00:25:41.160
we get to speed up lots of the community with one package, like one person devoting a year

00:25:41.160 --> 00:25:41.400
to it.

00:25:41.400 --> 00:25:44.280
Does this surprise you to see all these projects coming out?

00:25:44.280 --> 00:25:48.380
Like here's another project based on Pydantic plus, you know, name your other thing that

00:25:48.380 --> 00:25:51.480
it's been crazy, particularly in the like machine learning space where,

00:25:51.620 --> 00:25:56.280
you know, LangChain, who are one of the like big names right now in these like big language

00:25:56.280 --> 00:25:59.480
models, large language models, all based on Pydantic, right?

00:25:59.480 --> 00:25:59.940
Yeah.

00:25:59.940 --> 00:26:04.020
You were saying, I think on Twitter, that OpenAPI use a bunch of FastAPI, right?

00:26:04.020 --> 00:26:04.660
OpenAI?

00:26:04.660 --> 00:26:05.680
Sorry.

00:26:05.680 --> 00:26:06.120
Yeah.

00:26:06.120 --> 00:26:07.340
OpenAI, not OpenAPI.

00:26:08.940 --> 00:26:11.880
Marvin from, I think from Prefect is built on Pydantic again.

00:26:11.880 --> 00:26:16.720
So like the wave of machine learning stuff seems to have leveraged Pydantic a whole lot.

00:26:16.720 --> 00:26:18.700
Docker array being another, another big example.

00:26:18.700 --> 00:26:21.180
Some for Elastic and some other things as well.

00:26:24.100 --> 00:26:28.760
This portion of Talk Python To Me is brought to you by Influx Data, the makers of Influx

00:26:28.760 --> 00:26:28.980
DB.

00:26:28.980 --> 00:26:35.980
Influx DB is a database purpose built for handling time series data at a massive scale for real

00:26:35.980 --> 00:26:36.780
time analytics.

00:26:36.780 --> 00:26:42.320
Developers can ingest, store, and analyze all types of time series data, metrics, events,

00:26:42.320 --> 00:26:44.140
and traces in a single platform.

00:26:44.700 --> 00:26:46.600
So dear listener, let me ask you a question.

00:26:46.600 --> 00:26:51.660
How would boundless cardinality and lightning fast SQL queries impact the way that you develop

00:26:51.660 --> 00:26:52.800
real-time applications?

00:26:52.800 --> 00:26:58.900
Influx DB processes large time series data sets and provides low latency SQL queries, making

00:26:58.900 --> 00:27:04.340
it the go-to choice for developers building real-time applications and seeking crucial insights.

00:27:04.340 --> 00:27:10.040
For developer efficiency, Influx DB helps you create IoT analytics and cloud applications

00:27:10.040 --> 00:27:13.440
using timestamped data rapidly and at scale.

00:27:13.860 --> 00:27:18.780
It's designed to ingest billions of data points in real-time with unlimited cardinality.

00:27:18.780 --> 00:27:24.700
Influx DB streamlines building once and deploying across various products and environments from

00:27:24.700 --> 00:27:27.160
the edge, on-premise, and to the cloud.

00:27:27.160 --> 00:27:31.200
Try it for free at talkpython.fm/influxDB.

00:27:31.200 --> 00:27:33.620
The link is in your podcast player show notes.

00:27:33.620 --> 00:27:36.780
Thanks to Influx Data for supporting the show.

00:27:36.780 --> 00:27:42.960
I'm sure one of the big things you're thinking going forward with FastAPI is like how do you

00:27:42.960 --> 00:27:44.920
guys work together and make this a seamless change?

00:27:44.920 --> 00:27:45.860
What else you got?

00:27:45.860 --> 00:27:46.960
What else are you working on?

00:27:46.960 --> 00:27:48.160
What else do you see in the future?

00:27:48.160 --> 00:27:49.500
I have a bunch of things.

00:27:49.500 --> 00:27:51.780
Are they secret or can you tell us?

00:27:51.780 --> 00:27:52.180
No, no, no.

00:27:52.180 --> 00:27:52.780
I can't tell.

00:27:52.780 --> 00:27:54.180
Most of it I can't tell.

00:27:54.180 --> 00:27:57.500
I just feel the accountability.

00:27:57.500 --> 00:27:59.160
But I can't tell.

00:27:59.440 --> 00:28:04.100
So like I have a bunch of projects and like the funny thing is that in some way it's kind

00:28:04.100 --> 00:28:07.040
of a dependency graph of things that I should work on.

00:28:07.040 --> 00:28:12.060
So for example, I have this project generator for FastAPI to generate a project with a SQL

00:28:12.060 --> 00:28:12.460
database.

00:28:12.460 --> 00:28:15.880
I haven't updated it in a long time and it uses SQLAlchemy.

00:28:16.040 --> 00:28:19.660
I built SQL model for that project to use it there.

00:28:19.660 --> 00:28:23.480
But I haven't updated it there because first I want to upgrade more things in SQL model.

00:28:23.480 --> 00:28:26.500
I want to finish the documentation, finish the story about migration.

00:28:26.500 --> 00:28:30.720
But then for the story about migration, I need typer for SQL model.

00:28:30.720 --> 00:28:32.520
So I need to update things in typer.

00:28:32.520 --> 00:28:36.580
And then for typer, I want to add support for annotated, which is actually one of the big

00:28:36.580 --> 00:28:36.880
things.

00:28:36.880 --> 00:28:41.300
One of the recent big things in FastAPI is that now there's support for annotated.

00:28:41.300 --> 00:28:44.220
So annotated is this feature from Python.

00:28:44.220 --> 00:28:46.400
It's like standard Python typings.

00:28:46.400 --> 00:28:52.120
You import from typing, from typings import annotated, and then you can use that to meet

00:28:52.120 --> 00:28:54.940
information to the types that you define for parameters.

00:28:54.940 --> 00:28:55.460
Like what?

00:28:55.460 --> 00:28:56.040
I haven't used this.

00:28:56.040 --> 00:28:56.680
I love typing.

00:28:56.680 --> 00:28:57.400
I use it all the time.

00:28:57.400 --> 00:28:59.220
And here I'm learning more about typing.

00:28:59.220 --> 00:29:04.260
The thing is it exists there in the standard library, but it doesn't have like a canonical

00:29:04.260 --> 00:29:05.520
use in Python itself.

00:29:05.680 --> 00:29:09.080
It's there mainly for FastAPI and Pydantic to use it.

00:29:09.080 --> 00:29:13.200
You know, like it's just that like I haven't, I hadn't pushed for that before.

00:29:13.200 --> 00:29:19.340
But the thing is you import from typings, import annotated, and then you create a function that

00:29:19.340 --> 00:29:20.420
takes like a username.

00:29:20.420 --> 00:29:23.560
And then this function will normally be of type string.

00:29:23.560 --> 00:29:28.080
So it will be like the parameter of the function will be username colon str.

00:29:28.080 --> 00:29:33.900
Now you can say username colon annotated, and then open square brackets as if it was like

00:29:33.900 --> 00:29:35.360
a list or like a dict or something.

00:29:35.480 --> 00:29:36.400
Open square brackets.

00:29:36.400 --> 00:29:38.820
And then the first thing that you put there, that's the actual type.

00:29:38.820 --> 00:29:40.700
So you will say annotated string.

00:29:40.700 --> 00:29:41.280
Ah, okay.

00:29:41.280 --> 00:29:43.780
And then you can pass additional metadata afterwards.

00:29:43.780 --> 00:29:48.200
And the additional metadata is the thing that you will use to tell FastAPI this will be extracted

00:29:48.200 --> 00:29:50.880
from the query parameters or from the cookies or from headers.

00:29:51.380 --> 00:29:57.100
Before, and like up to recently in FastAPI, the only way to do that was using the default value of the parameter.

00:29:57.100 --> 00:29:57.400
Right.

00:29:57.400 --> 00:29:59.940
You would set the default to like a depends or...

00:29:59.940 --> 00:30:04.300
Yeah, to depends or equals a cookie or equals header or something like that.

00:30:04.300 --> 00:30:08.860
And then FastAPI can take the information from that to give you the data in your function.

00:30:08.860 --> 00:30:13.860
But the thing is, if you call that function manually somewhere else, the editor and Python

00:30:13.860 --> 00:30:16.940
won't complain that you are not passing some parameter that is required.

00:30:16.940 --> 00:30:20.680
And then you're going to end up with some strange value internally that is just for FastAPI.

00:30:20.680 --> 00:30:21.100
Right.

00:30:21.180 --> 00:30:24.120
Or the type checker complains, you're not passing a depends.

00:30:24.120 --> 00:30:25.500
Like, no, I'm passing a string.

00:30:25.500 --> 00:30:26.480
That's what it's supposed to be.

00:30:26.480 --> 00:30:26.960
But that's...

00:30:26.960 --> 00:30:27.520
Yeah, exactly.

00:30:27.520 --> 00:30:28.140
Some weird thing like that.

00:30:28.140 --> 00:30:28.440
Exactly.

00:30:28.440 --> 00:30:29.000
Yeah, okay.

00:30:29.000 --> 00:30:32.880
So for those cases, having annotated, like all the type is exactly what it is.

00:30:32.880 --> 00:30:37.520
And if it has a default value, it's the actual default value instead of like some strange

00:30:37.520 --> 00:30:40.000
internal concept in FastAPI.

00:30:40.000 --> 00:30:45.560
And having support for that allows having like much better support for typings, for editors,

00:30:45.560 --> 00:30:47.120
autocompletion, inline errors, all these things.

00:30:47.120 --> 00:30:49.180
It's reusing the same functions in other places.

00:30:49.840 --> 00:30:54.820
And it will also, having support for that in typer, will allow users to have the same

00:30:54.820 --> 00:31:01.060
function being used for FastAPI and typer, having the custom metadata necessary for each

00:31:01.060 --> 00:31:04.160
one of the parameters for FastAPI and for typer and things like that.

00:31:04.160 --> 00:31:06.900
So it's something that is super powerful and super interesting.

00:31:06.900 --> 00:31:07.520
Yeah.

00:31:07.520 --> 00:31:09.660
I'm going to come in on annotated because I'm excited about it too.

00:31:09.660 --> 00:31:13.240
So Pydantic V2, we use annotated for all of our custom types.

00:31:13.240 --> 00:31:16.880
So for example, positive int type is just annotated of int.

00:31:17.200 --> 00:31:22.680
And then we use the annotated types package, which is some reusable metadata for annotated.

00:31:22.680 --> 00:31:28.000
So we would use like positive int is annotated of int and then greater than zero.

00:31:28.000 --> 00:31:33.200
And what's even cooler is that will be used by Pydantic, of course.

00:31:33.200 --> 00:31:36.260
Hypothesis is going to get support for that really soon.

00:31:36.360 --> 00:31:40.380
So it will only pass a positive value in if it sees greater than zero there.

00:31:40.380 --> 00:31:44.880
And then typer, I guess, could like, even if it's still based on click, it can go and take

00:31:44.880 --> 00:31:47.760
that greater than and infer it as, you know, must be greater than zero.

00:31:47.760 --> 00:31:52.480
So I think it was one of the things that typing guys, when they first created annotated, hoped

00:31:52.480 --> 00:31:56.780
was going to build a rich network of libraries that interchanged metadata.

00:31:56.780 --> 00:31:59.780
It's taken a bit longer than they expected, but we're getting there.

00:31:59.780 --> 00:32:02.360
Here the two of you are kind of doing that a little bit, right?

00:32:02.360 --> 00:32:02.860
That's cool.

00:32:02.860 --> 00:32:03.640
That's really cool.

00:32:03.640 --> 00:32:08.740
One of the areas where I feel like typing is a little janky is on ORMs and ODMs.

00:32:08.740 --> 00:32:15.800
When you define a class, you say, for example, it's like a SQLAlchemy column, or it's a beanie

00:32:15.800 --> 00:32:17.280
column or something like that.

00:32:17.280 --> 00:32:21.980
And the type is it's a string column, but really it's a string.

00:32:21.980 --> 00:32:22.980
It's not a string column.

00:32:22.980 --> 00:32:28.600
And so there's this weirdness of using types to kind of drive behavior.

00:32:28.840 --> 00:32:31.000
That's a perfect case for using annotated.

00:32:31.000 --> 00:32:31.600
That's what I was thinking.

00:32:31.600 --> 00:32:31.840
Yeah.

00:32:31.840 --> 00:32:36.420
What it doesn't do is the other case where there is a context where you'd want to get the

00:32:36.420 --> 00:32:40.000
column object of some sort rather than the integer in a row.

00:32:40.000 --> 00:32:44.680
So it does mean two different things, the kind of dot objects in the Django context.

00:32:44.680 --> 00:32:45.500
But yeah, absolutely.

00:32:45.500 --> 00:32:46.020
Yeah.

00:32:46.020 --> 00:32:48.300
It's there precisely to solve this kind of problem.

00:32:48.300 --> 00:32:52.240
And it's also because like currently, as far as I remember, there's no way.

00:32:52.240 --> 00:32:55.760
So the thing is that this is all based on something called descriptors.

00:32:55.760 --> 00:33:01.860
And it's that when you call like, I don't know, class user dot name, it's actually the

00:33:01.860 --> 00:33:02.800
attribute in the class.

00:33:02.800 --> 00:33:07.300
But when you create an instance of that user and then say user dot name, that is the attribute

00:33:07.300 --> 00:33:08.460
on the actual instance.

00:33:08.460 --> 00:33:14.020
And the way that these ODMs or ORMs or these things work is that they have a special way

00:33:14.020 --> 00:33:18.160
to say like when someone calls the actual class, this is a different thing than when someone

00:33:18.160 --> 00:33:20.160
calls an instance attribute.

00:33:20.160 --> 00:33:20.640
Right.

00:33:20.960 --> 00:33:22.680
And there's sort of two behaviors.

00:33:22.680 --> 00:33:22.980
Yeah.

00:33:22.980 --> 00:33:23.300
Yeah.

00:33:23.300 --> 00:33:24.740
And like it's super powerful.

00:33:24.740 --> 00:33:26.140
That's how SQLAlchemy works.

00:33:26.140 --> 00:33:29.940
And it's super powerful because then like all the queries and all the stuff is actually

00:33:29.940 --> 00:33:32.580
like consistent with how Python works.

00:33:32.580 --> 00:33:36.740
And you can say like greater than or equals to using Python syntax, which is great.

00:33:36.740 --> 00:33:41.340
But then currently, as far as I know, there's no way to define that with type annotations

00:33:41.340 --> 00:33:42.000
in a standard way.

00:33:42.000 --> 00:33:45.000
I think it's something that will probably be improvable.

00:33:45.000 --> 00:33:46.380
But I think there's currently no way.

00:33:46.380 --> 00:33:47.720
There will probably be a way at some point.

00:33:47.720 --> 00:33:53.120
But to be able to say like, hey, this SQLAlchemy column is a column when it's accessed

00:33:53.120 --> 00:33:54.220
at the class level.

00:33:54.220 --> 00:33:57.960
But this is going to be a string when it's accessed at the instance level.

00:33:57.960 --> 00:34:01.840
A scope level in the annotated, you know, the class is this and this.

00:34:01.840 --> 00:34:03.740
And it's the instance is that and that.

00:34:03.740 --> 00:34:03.940
Yeah.

00:34:03.940 --> 00:34:04.920
That's really interesting.

00:34:04.920 --> 00:34:09.500
While we're talking types, and I know you both are really big fans because it's such a

00:34:09.500 --> 00:34:11.220
central part, both your libraries.

00:34:11.220 --> 00:34:13.040
What do you want to see coming?

00:34:13.040 --> 00:34:15.000
It feels like this is an area of Python changing fast.

00:34:15.000 --> 00:34:19.060
But is there something like they just if they could just and I have another question on types

00:34:19.060 --> 00:34:20.000
by the way after that.

00:34:20.000 --> 00:34:20.400
If I remember.

00:34:20.400 --> 00:34:23.500
So I gave a talk at the typing summit asking for certain things.

00:34:23.500 --> 00:34:28.320
So now we're going to test my can I remember PEP numbers challenge, which I'm going to fail

00:34:28.320 --> 00:34:28.520
in.

00:34:28.520 --> 00:34:36.820
But pep472 is that keyword args to so one option would be to allow keyword arguments to get

00:34:36.820 --> 00:34:40.720
item, which would make annotated even more powerful because then you could use keyword arguments

00:34:40.720 --> 00:34:44.660
to describe the meaning of your metadata, rather than having to have these kind of identifier

00:34:44.660 --> 00:34:49.240
types like greater than one of the big things that I hope we're going to persuade.

00:34:49.240 --> 00:34:52.840
So I think one of the things that's happened recently is that everyone gets that runtime

00:34:52.840 --> 00:34:54.820
use of type hints is a legitimate thing.

00:34:54.820 --> 00:34:58.100
They might not want to do it themselves, but they get that like, it's a legitimate thing

00:34:58.100 --> 00:34:58.380
to do.

00:34:58.380 --> 00:35:01.300
How much pushback was there when you first came out by Tandic there?

00:35:01.300 --> 00:35:03.360
I think we were like the black sheep of Python.

00:35:03.360 --> 00:35:04.640
I was a black sheep of Python.

00:35:04.640 --> 00:35:05.760
This is supposed to have no meaning.

00:35:05.860 --> 00:35:06.580
What are you doing?

00:35:06.580 --> 00:35:07.500
You're doing it wrong.

00:35:07.500 --> 00:35:10.780
And I think nowadays that's changed and everyone gets it's a real thing.

00:35:10.780 --> 00:35:16.700
But so for example, the hash of a union is independent of the order of the members of the union.

00:35:16.700 --> 00:35:21.620
That makes sense in the context of static typing, where the union of int float is exactly the

00:35:21.620 --> 00:35:23.160
same as a union of float int.

00:35:23.160 --> 00:35:27.380
It turns out in static typing, particularly when you're doing coercion, there are some cases

00:35:27.380 --> 00:35:28.760
where that is not the case.

00:35:28.760 --> 00:35:34.800
And so it's really difficult right now that effectively when you unions are fine on their

00:35:34.800 --> 00:35:34.940
own.

00:35:34.940 --> 00:35:40.160
But if you have a union, say within a string, the capital string square brackets, it will

00:35:40.160 --> 00:35:45.600
the order will be match the order that the first time you call that not what you actually call

00:35:45.600 --> 00:35:49.800
unless you use lowercase string when it is the right order, except there's a PR open right

00:35:49.800 --> 00:35:53.420
now to break it on string to string as well.

00:35:53.420 --> 00:35:56.740
So anyway, we are on lowercase lists as well.

00:35:58.040 --> 00:36:02.020
Anyway, so things like that, where I do think that we'll see what happens on that particular

00:36:02.020 --> 00:36:02.300
case.

00:36:02.300 --> 00:36:07.620
But I feel like the voice of people doing runtime use of types, we're not the only people, are

00:36:07.620 --> 00:36:08.260
being heard better.

00:36:08.260 --> 00:36:11.560
And yeah, I think things are going to continue to improve.

00:36:11.560 --> 00:36:17.020
Yeah, there was a PEP that proposed an optimization for typing that kind of broke the runtime behaviors

00:36:17.020 --> 00:36:18.620
of it a little bit for both of y'all.

00:36:18.620 --> 00:36:20.520
Yeah, it did in some edge cases.

00:36:20.520 --> 00:36:24.100
And that's going to be fixed soon by the successor pep.

00:36:24.100 --> 00:36:24.660
Absolutely.

00:36:24.660 --> 00:36:25.800
So that's really good.

00:36:26.200 --> 00:36:30.240
Generic alias is another thing that kills us internally in Pydantic.

00:36:30.240 --> 00:36:31.920
I won't go into all of the details of it.

00:36:31.920 --> 00:36:38.800
But yeah, the high-level takeaway is that the typing community seemed happy with the idea

00:36:38.800 --> 00:36:41.680
that they might make a change to typing to make it easier for us.

00:36:41.680 --> 00:36:44.480
And I think that's also for the Pydantic team to engage better.

00:36:44.480 --> 00:36:46.340
And instead of spending ages...

00:36:46.340 --> 00:36:46.780
Problem is, right?

00:36:46.780 --> 00:36:47.460
You have a problem.

00:36:47.460 --> 00:36:49.180
You see a solution in typing.

00:36:49.180 --> 00:36:50.400
You submit the PR.

00:36:50.660 --> 00:36:54.640
Even if it gets accepted in a week, which it won't, you wait five years before we can

00:36:54.640 --> 00:36:56.840
remove the code that deals with the other case.

00:36:56.840 --> 00:37:00.880
So it's very tempting not to engage with typing, but just go and write the work around where

00:37:00.880 --> 00:37:04.820
we should be better Python citizens and go and submit the PR to see Python to try and fix

00:37:04.820 --> 00:37:05.340
it properly.

00:37:05.340 --> 00:37:05.820
Yeah.

00:37:05.820 --> 00:37:07.060
What's your wish list for typing?

00:37:07.060 --> 00:37:11.280
So, well, the first thing is like this thing that I have been trying to work on and like

00:37:11.280 --> 00:37:15.780
trying to do to have like better ways to do documentation of the APIs that's also related

00:37:15.780 --> 00:37:17.600
to typing and to the annotations.

00:37:17.600 --> 00:37:19.360
Like, let's see if I can pull it off.

00:37:19.900 --> 00:37:23.400
The other thing is like, it's actually not that necessarily that related to the things

00:37:23.400 --> 00:37:28.060
that we have been talking about, but it's quite relevant for the data science and machine

00:37:28.060 --> 00:37:28.820
learning community.

00:37:28.820 --> 00:37:35.440
That is that there are many, many APIs for many libraries that decorate in some way, some

00:37:35.440 --> 00:37:36.040
function.

00:37:36.040 --> 00:37:41.620
And then the function is expected to give some types of values to the body of the function

00:37:41.620 --> 00:37:45.500
internally, but to be able to receive different types of values.

00:37:45.500 --> 00:37:51.360
That sounds a bit abstract, but like that's the core idea that is like replicated across

00:37:51.360 --> 00:37:52.280
several libraries.

00:37:52.280 --> 00:37:56.620
And this will apply to, for example, to Ray, the distributed machine learning or computing

00:37:56.620 --> 00:38:00.920
system, to Dask, to, I think, Dagster also uses something like that.

00:38:00.920 --> 00:38:06.300
Monad, this system for deploying workloads and machine learning and things like that, also uses

00:38:06.300 --> 00:38:07.220
these types of ideas.

00:38:07.220 --> 00:38:12.400
So there are many of these libraries that like the way that they are designed is that you create

00:38:12.400 --> 00:38:16.460
some function and then you are going to tell something to call this function.

00:38:16.460 --> 00:38:19.440
And then in the function, you say, I want to expect this value.

00:38:19.440 --> 00:38:23.260
And instead of you calling all the functions that will generate that value, you tell it like,

00:38:23.260 --> 00:38:25.640
hey, distributed system, blah, blah, blah.

00:38:25.640 --> 00:38:26.900
Give me this value.

00:38:26.900 --> 00:38:27.960
Execute this for me.

00:38:27.960 --> 00:38:34.340
But that means that you will have or no type annotations or invalid type annotations or red

00:38:34.340 --> 00:38:39.360
squiggly lines in some places or no auto completion or auto completion for the wrong things, just

00:38:39.360 --> 00:38:45.100
because there's currently no way to define this specific thing of saying, hey, this function after

00:38:45.100 --> 00:38:49.600
being decorated is going to be able to receive a different type.

00:38:49.600 --> 00:38:50.440
Oh, yeah.

00:38:50.440 --> 00:38:52.520
Than what it's going to give to internal.

00:38:52.520 --> 00:38:57.140
So I think that's something that, and it's probably quite challenging and like a big thing to tackle,

00:38:57.140 --> 00:39:01.500
but it's something that is replicated across several libraries, in particular for these things

00:39:01.500 --> 00:39:04.580
that do distributed processing of data.

00:39:04.680 --> 00:39:07.320
I think that's something that will be great to improve.

00:39:07.320 --> 00:39:09.940
Does paramspec fix some of that?

00:39:10.720 --> 00:39:18.700
It's very close, but the paramspec only does it for being able to sort of copy the params

00:39:18.700 --> 00:39:20.300
that come from one function to another.

00:39:20.300 --> 00:39:24.360
And actually, I use all that for, for example, for async and for other things to be able to

00:39:24.360 --> 00:39:30.000
get like auto completion for the decorated function or for the generated function or things like

00:39:30.000 --> 00:39:30.400
that.

00:39:30.520 --> 00:39:35.260
And it will probably like the change will probably be somewhere around paramspec to

00:39:35.260 --> 00:39:40.900
be able to say like, not just the paramspec, but like this function will not only have the

00:39:40.900 --> 00:39:45.640
paramspec, but will receive a modification like this of the parameters.

00:39:45.640 --> 00:39:47.340
Almost making paramspec generic.

00:39:50.040 --> 00:39:50.680
All right.

00:39:50.680 --> 00:39:52.380
One more typing question.

00:39:52.380 --> 00:39:56.200
Do you all think typing is going too far with like the generic stuff?

00:39:56.200 --> 00:39:59.680
And is it going too much like C++ and C# and Java?

00:39:59.680 --> 00:40:02.000
Or is it, is it still, still good?

00:40:02.000 --> 00:40:07.000
I think it's, I think the way Python is growing is super interesting because like,

00:40:07.000 --> 00:40:12.200
we all have to agree that Python 3.12 is not the same Python 2.7.

00:40:12.200 --> 00:40:12.600
Yeah.

00:40:12.600 --> 00:40:13.960
It's quite different.

00:40:13.960 --> 00:40:15.700
And I think it's a different in a good way.

00:40:15.700 --> 00:40:20.980
The users are different and the light, the focus of the runtime is different.

00:40:20.980 --> 00:40:26.680
And like the things that we can do with types now, and like the fact that in Python, we can

00:40:26.680 --> 00:40:31.620
access these types at runtime, which means like, I don't know, I was always confused with the

00:40:31.620 --> 00:40:32.140
term runtime.

00:40:32.140 --> 00:40:33.520
It's like, what does that mean?

00:40:33.520 --> 00:40:38.480
And it's like, when you execute Python, the same Python code can inspect and like see what

00:40:38.480 --> 00:40:39.000
are those types.

00:40:39.000 --> 00:40:40.580
That's what FastAPI and Pydantic do.

00:40:40.580 --> 00:40:42.240
It's just like seeing like, what are those types?

00:40:42.240 --> 00:40:43.640
We can do that in Python.

00:40:43.640 --> 00:40:48.140
You cannot do that in things like TypeScript, or you cannot do it in Java.

00:40:48.140 --> 00:40:49.560
You cannot do it in many other languages.

00:40:49.560 --> 00:40:53.700
You get access to this typing information to be able to do additional things with that, like

00:40:53.700 --> 00:40:56.960
validation, data serialization, documentation, all that stuff.

00:40:56.960 --> 00:41:00.260
So I think that's, to start, that's super powerful in Python.

00:41:00.260 --> 00:41:06.240
The language in Python for typings is not as powerful as, for example, TypeScript.

00:41:06.240 --> 00:41:08.980
That is just like so much stuff that you can do with that.

00:41:09.560 --> 00:41:14.580
Nevertheless, I feel that in Python is just like, is growing and is growing organically.

00:41:14.580 --> 00:41:16.820
And like, we have growing pains, you know?

00:41:16.820 --> 00:41:21.500
Like, there are some things that is like, oh, this little thing here is slightly incorrectly

00:41:21.500 --> 00:41:22.180
named.

00:41:22.180 --> 00:41:23.100
Yeah.

00:41:23.100 --> 00:41:26.480
But like, now there's a better way to do that in Python 3.10.

00:41:26.480 --> 00:41:29.620
So we don't care much about that slightly incorrect name.

00:41:29.620 --> 00:41:30.220
Things like that.

00:41:30.480 --> 00:41:34.740
Yeah, I feel like there's some tensions of people who are in the mypy side, and they want

00:41:34.740 --> 00:41:39.780
perfect validation of, I want to prove my code hangs together like a static compiler.

00:41:39.780 --> 00:41:46.420
And folks like you all who are like, we want to leverage typing to make it behave in interesting

00:41:46.420 --> 00:41:46.880
ways.

00:41:46.880 --> 00:41:51.520
And maybe that behavior expression doesn't exactly match what it looks statically like, but

00:41:51.520 --> 00:41:52.160
it is.

00:41:52.160 --> 00:41:55.720
Everybody wants it, but it might trip up mypy.

00:41:55.720 --> 00:41:57.860
And I feel like there's this tension between those two things.

00:41:57.860 --> 00:41:59.600
That's kind of what I was thinking when I asked that question.

00:41:59.600 --> 00:42:04.980
I guess there's a little bit of that, but at the same time, there's, is much less than

00:42:04.980 --> 00:42:05.600
you could imagine.

00:42:05.600 --> 00:42:11.020
There are so many people that are so close to, you know, core mypy and these things that are

00:42:11.020 --> 00:42:13.440
actually very excited about the things that we are doing.

00:42:13.440 --> 00:42:17.640
So they're like, you know, like the, it's actually quite friendly, all the communication.

00:42:17.640 --> 00:42:22.160
It's just that there is some people that just don't really care about runtime types and

00:42:22.160 --> 00:42:22.640
that's fine.

00:42:22.640 --> 00:42:28.380
But like, I feel like it's much more, you know, much more closer together and like much more

00:42:28.380 --> 00:42:30.140
stronger the relationship, I think.

00:42:30.140 --> 00:42:30.400
Yeah.

00:42:30.400 --> 00:42:30.640
Yeah.

00:42:30.640 --> 00:42:30.920
That's great.

00:42:30.920 --> 00:42:31.340
Yeah.

00:42:31.340 --> 00:42:35.380
I think actually we've gone in the, we've, typing's got better for someone who's not

00:42:35.380 --> 00:42:38.720
like, it's actually got less verbose, cleaner, easier to understand.

00:42:38.720 --> 00:42:40.340
You don't have to import union.

00:42:40.340 --> 00:42:41.740
You can do pipe operator.

00:42:41.740 --> 00:42:44.040
You don't have to import list from typing.

00:42:44.040 --> 00:42:46.140
You can use list, which makes complete sense.

00:42:46.140 --> 00:42:51.980
Any is an unfortunate one, but I also understand why the any function might, it would not make

00:42:51.980 --> 00:42:52.180
sense.

00:42:52.180 --> 00:42:52.700
I give up.

00:42:52.700 --> 00:42:54.180
I just, I can't deal with this part.

00:42:54.180 --> 00:42:54.640
So yeah.

00:42:54.640 --> 00:42:57.580
No, in general, I think it's got much better.

00:42:57.580 --> 00:43:03.640
I do think that the interchange between runtime, so there's a PEP open now to add to data class

00:43:03.640 --> 00:43:06.020
transforms, a converter function.

00:43:06.020 --> 00:43:11.720
I forget exactly how it works, but I think that is awareness in the static typing space

00:43:11.720 --> 00:43:15.640
that data gets converted when you construct something that looks like a data class.

00:43:15.640 --> 00:43:18.340
So no, I think, I think it's really positive.

00:43:18.340 --> 00:43:23.080
I think we're incredibly lucky that we're like, I could say TypeScript is the other, is in some

00:43:23.080 --> 00:43:25.740
ways the best untyped language typing system.

00:43:25.860 --> 00:43:29.120
But the fact that they're not available at runtime means we're, we're killing it.

00:43:29.120 --> 00:43:35.140
I think I spoke to someone who maintains a library that does a type analysis at runtime in

00:43:35.140 --> 00:43:40.160
TypeScript and all his types are strings and like they're valid TypeScript, but they're

00:43:40.160 --> 00:43:40.500
strings.

00:43:40.500 --> 00:43:44.080
And that's, you know, he was saying that doesn't matter and it's all fine.

00:43:44.080 --> 00:43:46.620
I tend to feel like it probably does a bit.

00:43:46.620 --> 00:43:48.500
We're really lucky to have them at runtime.

00:43:48.500 --> 00:43:51.120
Then you go to the other end where I've been writing a lot of Rust.

00:43:51.120 --> 00:43:52.760
I am like, Rust's great.

00:43:52.760 --> 00:43:55.840
It has many advances, but if you want to just get something done and not have to,

00:43:55.840 --> 00:43:58.200
think too hard about what the types are, it's really nice.

00:43:58.200 --> 00:44:01.160
I write a lot of Python that's untyped when I'm just trying to get something to, something

00:44:01.160 --> 00:44:01.620
to work.

00:44:01.620 --> 00:44:05.040
I'm not a like, everything must have a type on it kind of person.

00:44:05.040 --> 00:44:06.840
So no, I think we're in a really great place.

00:44:06.840 --> 00:44:09.560
And I think most of the advantages are actually cleaning it up.

00:44:09.560 --> 00:44:18.220
So the new six something, 649, the new generics syntax to me, 695.

00:44:18.220 --> 00:44:25.480
There are people who know the names of their numbers of their peps and there's everyone

00:44:25.820 --> 00:44:26.440
everyone's saying.

00:44:26.440 --> 00:44:30.660
That for me, it cleans up generics, right?

00:44:30.660 --> 00:44:32.580
Yes, it's a fundamental change to the language.

00:44:32.580 --> 00:44:36.740
Yes, it makes the syntax of a function look a bit more like Rust or something.

00:44:36.740 --> 00:44:41.240
But like, if you look at it independently of our experience, it's a heck of a lot more elegant

00:44:41.240 --> 00:44:42.640
than importing type var.

00:44:42.640 --> 00:44:43.220
All right.

00:44:43.220 --> 00:44:43.680
Yeah.

00:44:43.680 --> 00:44:43.960
Yeah.

00:44:44.140 --> 00:44:48.580
Let me ask you one that's, this is purely theoretical because I don't think it'll get adopted,

00:44:48.580 --> 00:44:50.600
but we have int, pipe, none.

00:44:50.600 --> 00:44:51.920
We have optional of int.

00:44:51.920 --> 00:44:55.600
A lot of languages have question mark for nullable types.

00:44:55.600 --> 00:44:56.380
Like it'd be int.

00:44:56.380 --> 00:44:57.680
You could even say it like int.

00:44:57.680 --> 00:44:58.480
I'm not sure.

00:44:58.480 --> 00:44:59.080
Is it an int?

00:44:59.080 --> 00:44:59.680
It could be an int.

00:44:59.680 --> 00:45:00.580
It might be nullable.

00:45:00.580 --> 00:45:01.420
I don't know.

00:45:01.420 --> 00:45:01.700
Right?

00:45:01.900 --> 00:45:03.040
Or use int as an int.

00:45:03.040 --> 00:45:03.540
You just know.

00:45:03.540 --> 00:45:04.520
There's no question mark.

00:45:04.520 --> 00:45:08.460
And those types, what are your thoughts about null, call us, annual care?

00:45:08.460 --> 00:45:12.760
I'm really happy with the new situation and not having the optional that isn't optional.

00:45:12.760 --> 00:45:14.300
That's been a problem for a long time.

00:45:14.420 --> 00:45:19.040
So not needing to use optional is being able to use pipe none is great.

00:45:19.040 --> 00:45:23.540
I actually think one of the things that's going to happen with, particularly with the advent

00:45:23.540 --> 00:45:29.500
of the match syntax and with increased use of type dict, we're going to need a new union

00:45:29.500 --> 00:45:32.360
type that operates much more like an enum in Rust.

00:45:32.360 --> 00:45:38.120
So basically a union that keeps track of which member of the enum you have an instance of.

00:45:38.120 --> 00:45:40.920
I keep meaning to build a package to demonstrate what I mean.

00:45:40.920 --> 00:45:43.980
And I haven't got around to it, but like if you have a union.

00:45:44.240 --> 00:45:46.440
Type dict, which is a legitimate thing to do.

00:45:46.440 --> 00:45:50.740
It's effectively impossible without starting to do effectively validation to work out which

00:45:50.740 --> 00:45:51.340
member you're on.

00:45:51.340 --> 00:45:55.740
So I think we need, and it would be really neat if you could use a match expression to process

00:45:55.740 --> 00:45:57.120
each branch of your union.

00:45:57.120 --> 00:45:57.780
Sebastian?

00:45:57.780 --> 00:45:58.940
You already said everything.

00:45:58.940 --> 00:46:04.940
No, but like, you know, like I feel, I feel that way, I was saying that like, I feel

00:46:04.940 --> 00:46:08.000
Python is just like growing and like the typing system is growing.

00:46:08.000 --> 00:46:12.320
I feel it's growing in a very healthy way because it's not, you know, it's not like just some,

00:46:12.320 --> 00:46:17.220
some, some academics hidden in some corners somewhere saying like, this is how it should

00:46:17.220 --> 00:46:17.320
be done.

00:46:17.320 --> 00:46:19.820
I did my thesis on this type system and here we are.

00:46:19.820 --> 00:46:19.820
Yeah.

00:46:19.820 --> 00:46:21.500
And then like everyone should just use it.

00:46:21.500 --> 00:46:26.600
It's just like a lot of hearing everyone and just receiving the feedback from everyone

00:46:26.600 --> 00:46:29.100
and just like growing in the ways that it should grow.

00:46:29.100 --> 00:46:30.000
I think that's amazing.

00:46:30.120 --> 00:46:35.980
I think like we are, you know, it's like a kind of renaissance of like typing in Python

00:46:35.980 --> 00:46:37.680
and like how we can build all these things.

00:46:37.680 --> 00:46:38.460
I think that's amazing.

00:46:38.460 --> 00:46:39.680
I think it absolutely is.

00:46:39.680 --> 00:46:39.860
All right.

00:46:39.860 --> 00:46:41.340
I think we're pretty much out of time.

00:46:41.340 --> 00:46:44.920
We've used up all the various places we've escaped to at a shutting down conference here.

00:46:44.920 --> 00:46:46.460
Final question for you both.

00:46:46.460 --> 00:46:47.620
Just, you know, what's your big takeaway?

00:46:47.620 --> 00:46:49.140
What's the experience like here at PyCon?

00:46:49.140 --> 00:46:51.020
Like how's it been 2023?

00:46:51.020 --> 00:46:52.920
For me, it's been amazing.

00:46:52.920 --> 00:46:54.740
It's my first PyCon in the US.

00:46:55.080 --> 00:46:55.560
Oh, it is.

00:46:55.560 --> 00:46:55.880
Yeah.

00:46:55.880 --> 00:46:57.880
Like I have never been in a PyCon in the US.

00:46:57.880 --> 00:47:00.800
I have been in PyCons in like many other places, but not in the US.

00:47:00.800 --> 00:47:06.640
And like I got to see, I got to put faces to so many handles in Twitter and GitHub.

00:47:06.640 --> 00:47:08.240
I got to meet you in person.

00:47:08.240 --> 00:47:09.100
That's amazing.

00:47:09.100 --> 00:47:09.380
Wow.

00:47:09.380 --> 00:47:09.800
It's great.

00:47:09.800 --> 00:47:14.220
Like a bunch of other people that I only knew, you know, just like on the internet,

00:47:14.220 --> 00:47:16.340
a bunch of core developers and like, that's so cool.

00:47:16.340 --> 00:47:16.960
They are so cool.

00:47:16.960 --> 00:47:20.760
Like I knew they were super cool, but just like, you know, talking on Twitter and like

00:47:20.760 --> 00:47:21.580
didn't see me in person.

00:47:21.580 --> 00:47:23.000
That's amazing.

00:47:23.480 --> 00:47:25.120
It's my favorite part of the whole conference.

00:47:25.120 --> 00:47:27.760
It's just the people and the getting together.

00:47:27.760 --> 00:47:28.240
Definitely.

00:47:28.240 --> 00:47:31.040
I think I attended like two talks.

00:47:31.040 --> 00:47:34.160
I was just on the hallways talking to everyone.

00:47:34.160 --> 00:47:35.440
You feel the hallway track.

00:47:35.440 --> 00:47:35.760
Yeah.

00:47:35.760 --> 00:47:38.040
I was all the way on the hallway track.

00:47:38.040 --> 00:47:38.300
Awesome.

00:47:38.300 --> 00:47:38.900
Well, that's great.

00:47:38.900 --> 00:47:39.360
Yeah.

00:47:39.360 --> 00:47:40.200
I absolutely love it.

00:47:40.200 --> 00:47:44.020
I remember Sebastian and I joined the Language Summit remotely two years ago, the year when

00:47:44.020 --> 00:47:44.700
there was no PyCon.

00:47:44.700 --> 00:47:49.200
And the most interesting bit of the like four hours Zoom call was the five minutes between

00:47:49.200 --> 00:47:50.400
talks when people just chatted.

00:47:50.860 --> 00:47:54.760
And I remember then thinking how cool PyCon must be to have that same group of people

00:47:54.760 --> 00:47:57.120
like in a room rather than on a Zoom call.

00:47:57.120 --> 00:47:58.900
So no, I love it.

00:47:58.900 --> 00:48:00.460
I think it's, I've really enjoyed it.

00:48:00.460 --> 00:48:01.960
Last year was my first year.

00:48:01.960 --> 00:48:03.160
This year is even more fun.

00:48:03.160 --> 00:48:03.420
Yeah.

00:48:03.420 --> 00:48:03.980
I really enjoy it.

00:48:03.980 --> 00:48:04.460
Awesome.

00:48:04.460 --> 00:48:04.680
Yeah.

00:48:04.680 --> 00:48:06.100
It's been great to meet you both in person.

00:48:06.100 --> 00:48:07.340
Meeting you has been the best bit of all.

00:48:07.340 --> 00:48:08.140
Thank you very much.

00:48:08.140 --> 00:48:08.520
No, no.

00:48:08.520 --> 00:48:10.380
It's been really great to spend some time with you all here.

00:48:10.500 --> 00:48:12.360
Thanks for coming on the podcast.

00:48:12.360 --> 00:48:14.960
Part two now here to wrap things up.

00:48:14.960 --> 00:48:18.740
So it's, thanks for taking the time and congrats both on the success of your projects.

00:48:18.740 --> 00:48:19.480
They're amazing.

00:48:19.480 --> 00:48:20.300
Thanks so much.

00:48:20.300 --> 00:48:21.180
Thank you very much.

00:48:21.180 --> 00:48:21.960
Thanks for having us.

00:48:21.960 --> 00:48:23.020
Thanks for seeing us.

00:48:23.020 --> 00:48:23.340
Yeah.

00:48:23.340 --> 00:48:23.680
Bye guys.

00:48:24.020 --> 00:48:26.540
This has been another episode of Talk Python To Me.

00:48:26.540 --> 00:48:27.920
Thank you to our sponsors.

00:48:27.920 --> 00:48:29.520
Be sure to check out what they're offering.

00:48:29.520 --> 00:48:30.940
It really helps support the show.

00:48:30.940 --> 00:48:32.640
Take some stress out of your life.

00:48:32.640 --> 00:48:38.120
Get notified immediately about errors and performance issues in your web or mobile applications with

00:48:38.120 --> 00:48:38.420
Sentry.

00:48:38.420 --> 00:48:43.020
Just visit talkpython.fm/sentry and get started for free.

00:48:43.020 --> 00:48:46.500
And be sure to use the promo code talkpython, all one word.

00:48:46.500 --> 00:48:49.580
InfluxData encourages you to try InfluxDB.

00:48:49.580 --> 00:48:53.880
InfluxDB is a database purpose built for handling time series data

00:48:53.880 --> 00:48:56.440
at a massive scale for real-time analytics.

00:48:56.440 --> 00:49:00.300
Try it for free at talkpython.fm/InfluxDB.

00:49:00.300 --> 00:49:01.600
Want to level up your Python?

00:49:01.600 --> 00:49:05.640
We have one of the largest catalogs of Python video courses over at Talk Python.

00:49:05.640 --> 00:49:10.720
Our content ranges from true beginners to deeply advanced topics like memory and async.

00:49:10.720 --> 00:49:13.360
And best of all, there's not a subscription in sight.

00:49:13.360 --> 00:49:16.260
Check it out for yourself at training.talkpython.fm.

00:49:16.260 --> 00:49:20.740
Be sure to subscribe to the show, open your favorite podcast app, and search for Python.

00:49:20.740 --> 00:49:22.000
We should be right at the top.

00:49:22.220 --> 00:49:26.900
You can also find the iTunes feed at /itunes, the Google Play feed at /play,

00:49:26.900 --> 00:49:31.080
and the direct RSS feed at /rss on talkpython.fm.

00:49:31.080 --> 00:49:33.700
We're live streaming most of our recordings these days.

00:49:33.700 --> 00:49:37.100
If you want to be part of the show and have your comments featured on the air,

00:49:37.100 --> 00:49:41.460
be sure to subscribe to our YouTube channel at talkpython.fm/youtube.

00:49:41.700 --> 00:49:43.000
This is your host, Michael Kennedy.

00:49:43.000 --> 00:49:44.300
Thanks so much for listening.

00:49:44.300 --> 00:49:45.460
I really appreciate it.

00:49:45.460 --> 00:49:47.320
Now get out there and write some Python code.

00:49:47.320 --> 00:49:48.500
I'll see you next time.

00:49:48.500 --> 00:49:48.500
Bye.

00:49:48.500 --> 00:49:48.500
Bye.

00:49:48.500 --> 00:49:48.500
Bye.

00:49:48.500 --> 00:49:49.500
Bye.

00:49:49.500 --> 00:49:50.500
Bye.

00:49:50.500 --> 00:49:50.500
Bye.

00:49:50.500 --> 00:49:50.500
Bye.

00:49:50.500 --> 00:49:51.500
Bye.

00:49:51.500 --> 00:49:52.500
Bye.

00:49:52.500 --> 00:49:52.500
Bye.

00:49:52.500 --> 00:49:52.500
Bye.

00:49:52.500 --> 00:49:53.500
Bye.

00:49:53.500 --> 00:49:54.500
Bye.

00:49:54.500 --> 00:49:54.500
Bye.

00:49:54.500 --> 00:49:54.500
Bye.

00:49:54.500 --> 00:49:54.500
Bye.

00:49:54.500 --> 00:49:54.500
Bye.

00:49:54.500 --> 00:49:54.500
Bye.

00:49:54.500 --> 00:49:54.500
Bye.

00:49:54.500 --> 00:49:54.500
Bye.

00:49:54.500 --> 00:49:55.500
Bye.

00:49:55.500 --> 00:49:55.500
Bye.

00:49:55.500 --> 00:49:55.500
Bye.

00:49:55.500 --> 00:49:55.500
Bye.

00:49:55.500 --> 00:49:56.500
Bye.

00:49:56.500 --> 00:49:57.500
Bye.

00:49:57.500 --> 00:49:58.500
Bye.

00:49:58.500 --> 00:49:59.500
Bye.

00:49:59.500 --> 00:50:00.500
Bye.

00:50:00.500 --> 00:50:01.500
Bye.

00:50:01.500 --> 00:50:02.000
you

00:50:02.000 --> 00:50:02.500
you

00:50:02.500 --> 00:50:05.380
Thank you.

