Home > Blockchain >  update_forward_refs() fails for dynamically-created model
update_forward_refs() fails for dynamically-created model

Time:07-13

When I create a pydantic model dynamically via create_model() then in some situations update_forward_refs() can't find the relevant definition.

This works:

from typing import List, Union
from pydantic import BaseModel
class Foo(BaseModel):
    foo: List["Bar"]

Bar = Union[Foo, int]
Foo.update_forward_refs()

But the following, which I believe should be equivalent, fails with a NameError:

from typing import List, Union
from pydantic import create_model, BaseModel
Foo = create_model("Foo", foo=(List["Bar"], ...))
Bar = Union[Foo, int]
Foo.update_forward_refs()

resulting in:

Traceback (most recent call last):
  File "test_forward_ref.py", line 11, in <module>
    Foo.update_forward_refs()
  File "pydantic\main.py", line 832, in pydantic.main.BaseModel.update_forward_refs
  File "pydantic\typing.py", line 382, in pydantic.typing.update_field_forward_refs
    or class checks.
  File "pydantic\typing.py", line 62, in pydantic.typing.evaluate_forwardref
    'MutableSet',
  File "C:\Users\Ian\.conda\envs\tso\lib\typing.py", line 518, in _evaluate
    eval(self.__forward_code__, globalns, localns),
  File "<string>", line 1, in <module>
NameError: name 'Bar' is not defined

It is significant that "Bar" is refered to within a List in the annotation for field foo. If the annotation of field foo is directly "Bar" then there is no problem.

Can someone please me towards fixing this please? What else do I need to do?

Python 3.8 and pydantic 1.8.2

CodePudding user response:

update_forward_refs() admits a **localns: Any parameter. It seems that in this case you can pass Bar=Bar to update_forward_refs() and it will work:

from typing import List, Union

from pydantic import create_model

Foo = create_model("Foo", foo=(List["Bar"], ...))
Bar = Union[Foo, int]
Foo.update_forward_refs(Bar=Bar)

print(Foo(foo=[1, Foo(foo=[2])]))

Output:

foo=[1, Foo(foo=[2])]
  • Related