litestar-org/polyfactory

Bug: Infinite recursion error with discriminated unions

judahrand opened this issue · 6 comments

Description

This seems to occur when a Discriminated Union model has a Discriminated Union field. The first level of this problem was fixed in #76 but it is still broken for the next level down.

URL to code causing the issue

No response

MCVE

from typing import Literal, Union

from typing_extensions import Annotated

from pydantic import BaseModel, Field

class BlackCat(BaseModel):
    pet_type: Literal['cat']
    color: Literal['black']
    black_name: str
    pet: 'Pet'

class WhiteCat(BaseModel):
    pet_type: Literal['cat']
    color: Literal['white']
    white_name: str
    pets: 'Pet'

Cat = Annotated[Union[BlackCat, WhiteCat], Field(discriminator='color')]

class Dog(BaseModel):
    pet_type: Literal['dog']
    name: str
    pet: 'Pet'

Pet = Annotated[Union[Cat, Dog], Field(discriminator='pet_type')]
BlackCat.update_forward_refs()
WhiteCat.update_forward_refs()
Dog.update_forward_refs()

class Model(BaseModel):
    pet: Pet
    n: int

from polyfactory.factories.pydantic_factory import ModelFactory

class MyModelFactory(ModelFactory):
    __model__ = Model


# This will create a max recursion error
obj = MyModelFactory.build()

print(obj)

Steps to reproduce

1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

Screenshots

"In the format of: `![SCREENSHOT_DESCRIPTION](SCREENSHOT_LINK.png)`"

Logs

No response

Litestar Version

polyfactory==2.0.1

Platform

  • Linux
  • Mac
  • Windows
  • Other (Please specify in the description above)
Fund with Polar

I've got some fairly complex models and haven't identified the root cause of this, but I'm also getting infinite recursion errors with pydantic factories. The models themselves definitely don't recurse though.

Python 3.10, pydantic 1.10.7, polyfactory 2.1.0

Stack trace if it's useful:

.../test_ThingView.py:24: in <listcomp>
    things = [thing_factory.build() for i in range(10)]
/var/virtualenv/lib/python3.10/site-packages/polyfactory/factories/pydantic_factory.py:166: in build
    processed_kwargs = cls.process_kwargs(**kwargs)
/var/virtualenv/lib/python3.10/site-packages/polyfactory/factories/base.py:681: in process_kwargs
    result[field_meta.name] = cls.get_field_value(field_meta, field_build_parameters=field_build_parameters)
/var/virtualenv/lib/python3.10/site-packages/polyfactory/factories/base.py:600: in get_field_value
    return handle_complex_type(field_meta=field_meta, factory=cls)
/var/virtualenv/lib/python3.10/site-packages/polyfactory/value_generators/complex_types.py:72: in handle_complex_type
    return factory.get_field_value(field_meta)
/var/virtualenv/lib/python3.10/site-packages/polyfactory/factories/base.py:600: in get_field_value
    return handle_complex_type(field_meta=field_meta, factory=cls)
E   RecursionError: maximum recursion depth exceeded in comparison
!!! Recursion detected (same locals & position)
=============================================================================== short test summary info ===============================================================================
FAILED .../tests/test_ThingView.py::test_ThingView_does_right_thing[2] - RecursionError: maximum recursion depth exceeded in comparison
================================================================================== 1 failed in 1.34s ============================================================================

I've got some fairly complex models and haven't identified the root cause of this, but I'm also getting infinite recursion errors with pydantic factories. The models themselves definitely don't recurse though.

Python 3.10, pydantic 1.10.7, polyfactory 2.1.0

Stack trace if it's useful:

.../test_ThingView.py:24: in <listcomp>
    things = [thing_factory.build() for i in range(10)]
/var/virtualenv/lib/python3.10/site-packages/polyfactory/factories/pydantic_factory.py:166: in build
    processed_kwargs = cls.process_kwargs(**kwargs)
/var/virtualenv/lib/python3.10/site-packages/polyfactory/factories/base.py:681: in process_kwargs
    result[field_meta.name] = cls.get_field_value(field_meta, field_build_parameters=field_build_parameters)
/var/virtualenv/lib/python3.10/site-packages/polyfactory/factories/base.py:600: in get_field_value
    return handle_complex_type(field_meta=field_meta, factory=cls)
/var/virtualenv/lib/python3.10/site-packages/polyfactory/value_generators/complex_types.py:72: in handle_complex_type
    return factory.get_field_value(field_meta)
/var/virtualenv/lib/python3.10/site-packages/polyfactory/factories/base.py:600: in get_field_value
    return handle_complex_type(field_meta=field_meta, factory=cls)
E   RecursionError: maximum recursion depth exceeded in comparison
!!! Recursion detected (same locals & position)
=============================================================================== short test summary info ===============================================================================
FAILED .../tests/test_ThingView.py::test_ThingView_does_right_thing[2] - RecursionError: maximum recursion depth exceeded in comparison
================================================================================== 1 failed in 1.34s ============================================================================

Do you have an MCVE? Is it also related to nested discriminated unions?

Do you have an MCVE?

Not yet, models are a bit complex and I'll have to slowly remove things until I can identify source of the problem.