Skip to content

Commit

Permalink
Resolve ForwardRef on Field.outer_type_ (#4249)
Browse files Browse the repository at this point in the history
* Add tests checking Field.outer_type_ ForwardRefs

* Update root ForwardRefs in field.outer_type_

* fix strings

* Add changes file
  • Loading branch information
JacobHayes committed Aug 9, 2022
1 parent a9c2732 commit b59a85a
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 7 deletions.
1 change: 1 addition & 0 deletions changes/4249-JacobHayes.md
@@ -0,0 +1 @@
Update `ForwardRef`s in `Field.outer_type_`
6 changes: 6 additions & 0 deletions pydantic/typing.py
Expand Up @@ -507,8 +507,14 @@ def update_field_forward_refs(field: 'ModelField', globalns: Any, localns: Any)
"""
Try to update ForwardRefs on fields based on this ModelField, globalns and localns.
"""
prepare = False
if field.type_.__class__ == ForwardRef:
prepare = True
field.type_ = evaluate_forwardref(field.type_, globalns, localns or None)
if field.outer_type_.__class__ == ForwardRef:
prepare = True
field.outer_type_ = evaluate_forwardref(field.outer_type_, globalns, localns or None)
if prepare:
field.prepare()

if field.sub_fields:
Expand Down
19 changes: 12 additions & 7 deletions tests/test_forward_ref.py
@@ -1,5 +1,5 @@
import sys
from typing import Optional, Tuple
from typing import Dict, List, Optional, Tuple

import pytest

Expand Down Expand Up @@ -131,15 +131,12 @@ def module():
from typing import Dict, List

from pydantic import BaseModel
from pydantic.typing import ForwardRef

Foo = ForwardRef('Foo')

class Foo(BaseModel):
a: int = 123
b: Foo = None
c: List[Foo] = []
d: Dict[str, Foo] = {}
b: 'Foo' = None
c: 'List[Foo]' = []
d: 'Dict[str, Foo]' = {}

Foo.update_forward_refs()

Expand All @@ -157,6 +154,14 @@ class Foo(BaseModel):
{'loc': ('c', 0, 'b'), 'msg': 'value is not a valid dict', 'type': 'type_error.dict'}
]

assert module.Foo.__fields__['a'].type_ is int
assert module.Foo.__fields__['b'].type_ is module.Foo
assert module.Foo.__fields__['b'].outer_type_ is module.Foo
assert module.Foo.__fields__['c'].type_ is module.Foo
assert module.Foo.__fields__['c'].outer_type_ == List[module.Foo]
assert module.Foo.__fields__['d'].type_ is module.Foo
assert module.Foo.__fields__['d'].outer_type_ == Dict[str, module.Foo]


def test_self_forward_ref_local(create_module):
@create_module
Expand Down

0 comments on commit b59a85a

Please sign in to comment.