Skip to content
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

Field metadata from Annotated is lost after a call to update_forward_refs #3282

Closed
3 tasks done
xx55tt opened this issue Oct 2, 2021 · 7 comments · Fixed by #7698
Closed
3 tasks done

Field metadata from Annotated is lost after a call to update_forward_refs #3282

xx55tt opened this issue Oct 2, 2021 · 7 comments · Fixed by #7698
Assignees
Labels
bug V1 Bug related to Pydantic V1.X

Comments

@xx55tt
Copy link

xx55tt commented Oct 2, 2021

Checks

  • I added a descriptive title to this issue
  • I have searched (google, github) for similar issues and couldn't find anything
  • I have read and followed the docs and still think this is a bug

Bug

Output of python -c "import pydantic.utils; print(pydantic.utils.version_info())":

             pydantic version: 1.8.2
            pydantic compiled: False
                 install path: /usr/lib/python3.9/site-packages/pydantic
               python version: 3.9.7 (default, Aug 31 2021, 13:28:12)  [GCC 11.1.0]
                     platform: Linux-5.14.8-arch1-1-x86_64-with-glibc2.33
     optional deps. installed: ['email-validator', 'typing-extensions']
from __future__ import annotations
from typing import Annotated

from pydantic import BaseModel, Field


class Works(BaseModel):
    foo: list[Foo] = Field(..., alias="bar")


class Fails(BaseModel):
    foo: Annotated[list[Foo], Field(alias="bar")]


class Foo(BaseModel):
    a: int


Works.update_forward_refs()
Fails.update_forward_refs()

json = '{"bar":[{"a":0}]}'

Works.parse_raw(json)
Fails.parse_raw(json)

With the postponed evaluation of annotations enabled, the Field metadata seems to be lost after the update_forward_refs call. Apart from that it seemed to be working fine, it parsed the JSON if the field name was foo. I also tried the allow_mutation argument, it was not working as well.

Without the from __future__ import annotations import, all of the following worked:

foo: "list[Foo]" = Field(..., alias="bar")
foo: List["Foo"] = Field(..., alias="bar")
foo: list[ForwardRef("Foo")] = Field(..., alias="bar")
foo: Annotated["list[Foo]", Field(alias="bar")]
foo: Annotated[List["Foo"], Field(alias="bar")]
foo: Annotated[list[ForwardRef("Foo")], Field(alias="bar")]
@xx55tt xx55tt added the bug V1 Bug related to Pydantic V1.X label Oct 2, 2021
@klaa97
Copy link
Contributor

klaa97 commented Oct 2, 2021

I reproduced your bug and debugged a little, and I 100% agree: the root of the problem is that the update_forward_refs method doesn't correctly parse the information from the FieldInfo of Annoted types.

I tried to propose a fix here: #3283

@dmontagu
Copy link
Contributor

It looks like this is now fixed in both v1 and v2

@mshonichev
Copy link

mshonichev commented Sep 28, 2023

Whoa! Why was this issue closed without merging the fix?
I find it is still reproducing at

pydantic==2.4.2
pydantic_core==2.10.1

reproducer is exactly the same:

from __future__ import annotations

class Foo(BaseModel):
    bar: Annotated[Bar | None, Field(alias="_bar")] = None

class Bar(BaseModel):
    foo: int | None = None


def test_model():
    data= '{"_bar": {"foo": 42}}'
    model = Foo.model_validate_json(data)
    assert model.bar.foo == 42

throws AttributeError: 'NoneType' object has no attribute 'foo'

but if we change the order of declarations, validation successfully loads the alias and test succeeds:


class Bar(BaseModel):
    foo: int | None = None

class Foo(BaseModel):
    bar: Annotated[Bar | None, Field(alias="_bar")] = None


def test_model():
    data= '{"_bar": {"foo": 42}}'
    model = Foo.model_validate_json(data)
    assert model.bar.foo == 42

@mshonichev
Copy link

@dmontagu could you please reopen this issue, or should I probably file a new one?

@dmontagu dmontagu reopened this Sep 28, 2023
@dmontagu
Copy link
Contributor

I'm not sure why I closed it, clearly it's still an issue. Apologies for that.

@dmontagu
Copy link
Contributor

dmontagu commented Sep 28, 2023

@mshonichev I think I've got a fix for it ready in #7698 (at least for pydantic v2), thanks for bringing this to my attention again, and apologies for closing it before when it wasn't actually fixed.

@dmontagu
Copy link
Contributor

Also @mshonichev, I added a different test in #7698, but I can confirm that your snippet above does not error with the change in that PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug V1 Bug related to Pydantic V1.X
Projects
None yet
4 participants