Skip to content

Commit

Permalink
fix: handle Optional type recursive models (#584)
Browse files Browse the repository at this point in the history
  • Loading branch information
adhtruong authored Sep 19, 2024
1 parent 9a83ad6 commit 135d7fe
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 4 deletions.
6 changes: 4 additions & 2 deletions polyfactory/factories/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -716,8 +716,10 @@ def get_field_value( # noqa: C901, PLR0911, PLR0912

# `None` is removed from the children when creating FieldMeta so when `children`
# is empty, it must mean that the field meta is an optional type.
if children:
return cls.get_field_value(cls.__random__.choice(children), field_build_parameters, build_context)
if not children:
return None

return cls.get_field_value(cls.__random__.choice(children), field_build_parameters, build_context)

if BaseFactory.is_factory_type(annotation=unwrapped_annotation):
if not field_build_parameters and unwrapped_annotation in build_context["seen_models"]:
Expand Down
6 changes: 4 additions & 2 deletions tests/test_recursive_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,19 @@ class PydanticNode(BaseModel):
value: int
union_child: Union[PydanticNode, int] # noqa: UP007
list_child: List[PydanticNode] # noqa: UP006
optional_child: Union[PydanticNode, None] # noqa: UP007
optional_union_child: Union[PydanticNode, None] # noqa: UP007
optional_child: Optional[PydanticNode] # noqa: UP007
child: PydanticNode = Field(default=_Sentinel) # type: ignore[assignment]


@pytest.mark.parametrize("factory_use_construct", (True, False))
def test_recursive_pydantic_models(factory_use_construct: bool) -> None:
factory = ModelFactory.create_factory(PydanticNode)
factory = ModelFactory[PydanticNode].create_factory(PydanticNode)

result = factory.build(factory_use_construct)
assert result.child is _Sentinel, "Default is not used" # type: ignore[comparison-overlap]
assert isinstance(result.union_child, int)
assert result.optional_union_child is None
assert result.optional_child is None
assert result.list_child == []

Expand Down

0 comments on commit 135d7fe

Please sign in to comment.