Bug: Pydantic ModelFactory coverage() function does not work with types including None
c-pletinckx opened this issue · 2 comments
Description
I have a simple pydantic model:
class SimpleModel(BaseModel):
a: int
b: float
c: str
d: Optional[bool]
I want to test a function that accepts an instance of this model as input. The actual function implementation is not important here:
def handle_input(input_instance: SimpleModel) -> None:
pass
In order to do so, I would like to use the coverage()
function of pydantic ModelFactory
as such:
def test_handle_input(self):
model_generator = SimpleModelFactory.coverage()
for model in model_generator:
handle_input(model)
This test, when called, returns a TypeError
exception at line for model in model_generator
.
However, it works very well with a pydantic model defined as follows:
class SimpleModel(BaseModel):
a: int
b: float
c: str
d: Union[bool, int]
I expected ModelFactory
to work for all cases where None
is a valid value (e.g. Optional[int]
, Union[NoneType, int, float]
, etc.) but it seems that, for now, either it is not a feature polyfactory wants to handle or there is a bug in the code base.
URL to code causing the issue
No response
MCVE
from typing import Optional
from polyfactory.factories.pydantic_factory import ModelFactory
from pydantic import BaseModel
class SimpleModel(BaseModel):
a: int
b: float
c: str
d: Optional[bool]
class SimpleModelFactory(ModelFactory[SimpleModel]):
__model__ = SimpleModel
for model in SimpleModelFactory.coverage():
print(model)
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
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
scratch.ipynb Cell 4 line 2
20 class SimpleModelFactory(ModelFactory[SimpleModel]):
21 __model__ = SimpleModel
---> 23 for model in SimpleModelFactory.coverage():
24 print(model)
File polyfactory/factories/base.py:928, in BaseFactory.coverage(cls, **kwargs)
919 @classmethod
920 def coverage(cls, **kwargs: Any) -> abc.Iterator[T]:
921 """Build a batch of the factory's Meta.model will full coverage of the sub-types of the model.
922
923 :param kwargs: Any kwargs. If field_meta names are set in kwargs, their values will be used.
(...)
926
927 """
--> 928 for data in cls.process_kwargs_coverage(**kwargs):
929 instance = cls.__model__(**data)
930 yield cast("T", instance)
File polyfactory/factories/base.py:886, in BaseFactory.process_kwargs_coverage(cls, **kwargs)
880 result[field_meta.name] = cls._handle_factory_field_coverage(
881 field_value=field_value,
882 field_build_parameters=field_build_parameters,
883 )
884 continue
--> 886 result[field_meta.name] = CoverageContainer(
887 cls.get_field_value_coverage(field_meta, field_build_parameters=field_build_parameters),
888 )
890 for resolved in resolve_kwargs_coverage(result):
891 for field_name, post_generator in generate_post.items():
File polyfactory/utils/model_coverage.py:45, in CoverageContainer.__init__(self, instances)
43 def __init__(self, instances: Iterable[T]) -> None:
44 self._pos = 0
---> 45 self._instances = list(instances)
46 if not self._instances:
47 msg = "CoverageContainer must have at least one instance"
File polyfactory/factories/base.py:721, in BaseFactory.get_field_value_coverage(cls, field_meta, field_build_parameters)
718 elif is_any(unwrapped_annotation) or isinstance(unwrapped_annotation, TypeVar):
719 yield create_random_string(cls.__random__, min_length=1, max_length=10)
--> 721 elif provider := cls.get_provider_map().get(unwrapped_annotation):
722 yield CoverageContainerCallable(provider)
724 elif callable(unwrapped_annotation):
725 # if value is a callable we can try to naively call it.
726 # this will work for callables that do not require any parameters passed
TypeError: unhashable type: 'list'
Release Version
- Python 3.10.12
- polyfactory 2.12.0
- pydantic 1.10.13
- faker 20.1.0
- typing-extensions 4.8.0
Platform
- Linux
- Mac
- Windows
- Other (Please specify in the description above)
Note
While we are open for sponsoring on GitHub Sponsors and
OpenCollective, we also utilize Polar.sh to engage in pledge-based sponsorship.
Check out all issues funded or available for funding on our Polar.sh Litestar dashboard
- If you would like to see an issue prioritized, make a pledge towards it!
- We receive the pledge once the issue is completed & verified
- This, along with engagement in the community, helps us know which features are a priority to our users.
@c-pletinckx, this was fixed in #440 but it just hasn't been released yet. I'll do a release today or tomorrow.
@c-pletinckx so sorry for the delay in the release! v2.13.0 has been released which includes the fix for this.