-
-
Notifications
You must be signed in to change notification settings - Fork 8.5k
♻️ Update internal annotation usage for compatibilty with Pydantic 2.11 #13314
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
50e766c to
9a64c56
Compare
svlandeg
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the explanation and the fix! I've added your MRE to the test suite and confirmed that the unit test works on master with Pydantic 2.8.2 or 2.10.6 but breaks with 2.11.0a1. The failure with 2.11 is resolved with this PR though.
Will leave this to Tiangolo for a final review 🙏
|
Thanks @svlandeg for wrapping it up |
|
Just a friendly reminder that 2.11 is going to be released soon, in two weeks. If this isn't tackled it might cause issues in some projects (we had one report so far from an alpha release). |
|
Thanks for the note, @Viicos! Will do - Tiangolo is aware of this one. |
|
Thanks! I was hoping to get a failing small FastAPI app that is fixed by this, but I couldn't make one, and it seems the report you had on Pydantic was not really using FastAPI but extending internals in some way, I couldn't make a minimal breaking FastAPI app from that report. I tried building one using the textual description there, but it kept passing on Do you know in which use cases would it behave differently or how it could break a FastAPI app? I would like to have a test with that. The current test checks that an internal function returns some specific value, which is better than nothing (thanks @svlandeg!), but still, it seems it is only testing that an internal function returns a specific shape. But it could be refactored in the future and there wouldn't be a way to know what could be broken in an app if not done correctly. 🤔 |
|
I don't think this is reproducible only using FastAPI. The issue came from https://github.com/airtai/faststream, which is manually inspecting the FastAPI dependants to create a OpenAPI-like schema. |
|
Perhaps a better test would be to build an API route with |
|
I just noticed that on line 421 there's a Sad not being able to write a test of an app that would break, to prevent accidentally reverting it in the future. Also, because sometimes I prefer not to change things that could break other apps in unknown ways without at least knowing what the change would fix/improve. But anyway, I understand that the |
|
On a side note, the On a side note, is it expected for FastAPI to have the ParamDetails(
│ type_annotation=<class 'int'>,
│ depends=None,
│ field=ModelField(
│ │ field_info=Query(
│ │ │ annotation=int,
│ │ │ required=False,
│ │ │ default=<object object at 0x7033aa582700>,
│ │ │ alias='user',
│ │ │ json_schema_extra={},
│ │ │ metadata=[FieldInfo(annotation=NoneType, required=True, metadata=[Strict(strict=True)])]
│ │ ),
│ │ name='user',
│ │ mode='validation'
│ )
) |
|
So, the For most of the parts, if I remember correctly, FastAPI just gives that field (or series of fields) to Pydantic for:
But about the Side note: I struggle with GitHub notifications, I could miss these replies or tags, if I miss something, you could write to me or tag me on the Pydantic Slack. 🤓 |
|
So, there was indeed a use case that would break with this. 😅 #13440 I'll revert this PR for now. Meanwhile, @Viicos could you help me think what would be the right way to pass the data and metadata for Pydantic? You maybe know, but for completeness, the mismatch is mainly that in Pydantic the top level "thing" is normally a model class. But in FastAPI the top level "thing" is actually a field: a param name with a type annotation and maybe a default, the same thing that could go inside Pydantic classes, this allows me to for example support params of lists, with all the Pydantic validation, with no extra effort from users, for example, for query parameters. I suspect that if I supported Pydantic v2 only, maybe everything about each field could be around a TypeAdapter and that's it, but I need to support Pydantic v1 still, so I need to be able to create the If you have any ideas please let me know (and please ping me on Slack so I notice it). |
|
I reverted this PR here: #13442 There I also added a docs with a source example for the use case and tests for it. 🤓 |
|
Thanks @tiangolo for taking care of it. I wasn't expecting this to blow up badly. Unfortunately, I don't have any satisfying answer. The FastAPI logic around The Lines 106 to 108 in 3824664
And it uses the field info (in the case of FastAPI, the custom Lines 249 to 253 in 3824664
So perhaps an alternative fix could be to unwrap annotated in the We are also in weird state with 2.11 now: Lines 110 to 113 in 3824664
I really think that the proper fix would be to avoid having FastAPI relying (i.e. subclassing) on the |
|
Get it, thanks for the thorough review of the code and the detailed explanation! I see this might get complicated. For now, let's wait and see if people report problems. I'll save the effort to focus it on supporting both v2 and v2's |
Hi! Sorry for ping, but have you any plans about Pydantic V1 drop? Looks like the most tools already leave this version. Probably, users still stuck in v1 could stuck in older FastAPI version as well? |
In Pydantic 2.11 (expected release date March
31st10th), we removed an unnecessary step that would unpack theAnnotatedform inFieldInfo.__init__(see https://github.com/pydantic/pydantic/pull/11109/files#r1888512603).However, FastAPI relied on this extra step, meaning we get different results.
MRE:
On 2.10.6:
on 2.11.0a1:
Fixes pydantic/pydantic#11382.