Giter Club home page Giter Club logo

polyfactory's People

Contributors

adhtruong avatar allcontributors[bot] avatar alwavshumilin avatar anthonyh209 avatar butch78 avatar daanrademaker avatar dependabot[bot] avatar eltonchou avatar goldziher avatar gsakkis avatar guacs avatar jacobcoffee avatar jtraub avatar lindycoder avatar lyz-code avatar mciszczon avatar mdczaplicki avatar nguyent avatar peterschutt avatar phbernardes avatar provinzkraut avatar reznikovroman avatar sam-or avatar simske avatar sobolevn avatar sondrelg avatar tcrasset avatar thorin-schiffer avatar timdumol avatar wer153 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

polyfactory's Issues

Import Test Dependancies

Hello :)

I just wanted to try, but i get a missing import module.

    from pydantic_factories.value_generators.constrained_number import (
  File "/.../pypoetry/virtualenvs/8L729wLl-py3.8/lib/python3.8/site-packages/pydantic_factories/value_generators/constrained_number.py", line 7, in <module>
    from tests.utils import passes_pydantic_multiple_validator

I not sure if this is missing or a wrong import but it seem this file/folder/module is not part of your package.

I just install pydantic_factories with poetry add pydantic_factories

Anyway, thanks for your work it's seem promising

Error when building with a parameter that is a pydantic model

Hello!

New in version 1.5.0 this previously working code seems to be broken

from pydantic import BaseModel
from pydantic_factories import ModelFactory


class MySubClass(BaseModel):
    sub_value:str


class MyClass(BaseModel):
    sub_obj: MySubClass


class MyClassFactory(ModelFactory[MyClass]):
    __model__ = MyClass


MyClassFactory.build(sub_obj=MySubClass(sub_value="wat"))

Produces the following error

.../.venv/bin/python .../reproduce.py 
Traceback (most recent call last):
  File ".../reproduce.py", line 17, in <module>
    MyClassFactory.build(sub_obj=MySubClass(sub_value="wat"))
  File ".../.venv/lib/python3.9/site-packages/pydantic_factories/factory.py", line 555, in build
    if cls.should_set_field_value(field_name, model_field, **kwargs):
  File ".../.venv/lib/python3.9/site-packages/pydantic_factories/factory.py", line 523, in should_set_field_value
    not is_field_in_kwargs or cls._is_pydantic_with_partial_fields(field_name, model_field, **kwargs)
  File ".../.venv/lib/python3.9/site-packages/pydantic_factories/factory.py", line 503, in _is_pydantic_with_partial_fields
    return any(
  File ".../.venv/lib/python3.9/site-packages/pydantic_factories/factory.py", line 504, in <genexpr>
    cls._is_kwargs_missing_pydantic_fields(pydantic_model, pydantic_model_kwargs)
  File ".../.venv/lib/python3.9/site-packages/pydantic_factories/factory.py", line 483, in _is_kwargs_missing_pydantic_fields
    kwargs_field_names = set(pydantic_model_kwargs.keys())
AttributeError: 'tuple' object has no attribute 'keys'

Bug: passing a dict of object to the factory is ignored

Hello!

When setting a .build() override for a dict where the value is a Pydantic model, it seems to be ignored.
pydantic-factories version 1.6.2

Following code repoduces: note that i made a simple dict to show that it doesn't work with classes only

from pydantic import BaseModel
from pydantic_factories import ModelFactory, Use


class MyMappedClass(BaseModel):
    val: str


class MyClass(BaseModel):
    my_mapping_obj: dict[str, MyMappedClass]
    my_mapping_str: dict[str, str]


class MyClassFactory(ModelFactory[MyClass]):
    __model__ = MyClass


obj = MyClassFactory.build(
    my_mapping_obj={"foo": MyMappedClass(val="bar")},
    my_mapping_str={"foo": "bar"},
)

print(obj.json(indent=2))

Output is

{
  "my_mapping_obj": {
    "xNLsYhvhemQDptZfpDWz": {
      "val": "DzMmWPdDALDUROEsduqT"
    }
  },
  "my_mapping_str": {
    "foo": "bar"
  }
}

expected output is

{
  "my_mapping_obj": {
    "foo": {             <---
      "val": "bar"       <---
    }
  },
  "my_mapping_str": {
    "foo": "bar"
  }
}

Thank you!

ModelFactory.seed_random does not produce deterministic UUIDs

When using ModelFactory.seed_random, UUID fields do not generate deterministic values.

from pydantic import BaseModel
from pydantic_factories import ModelFactory
from uuid import UUID


class UUIDModel(BaseModel):
    id: UUID
    string: str


class UUIDModelFactory(ModelFactory):
    __model__ = UUIDModel


UUIDModelFactory.seed_random(5)
rmodel1 = UUIDModelFactory.build()

UUIDModelFactory.seed_random(5)
rmodel2 = UUIDModelFactory.build()

# This assertion passes, as expected
assert rmodel1.string == rmodel2.string

# This assertion unexpectedly fails
assert rmodel1.id == rmodel2.id

build function ignores passed arguments for certain types

What happened
Since version 1.5, the factory.build function ignores passed arguments for certain types. For instance, this was verified for a pydantic model which had a field of type Mapping[str, NestedModel]. On the other hand, a field of type Mapping[str, str] is still accepted and taken into account during the build call.

What did you expect to happen
Expected that the build function respects the passed arguments as version 1.4.1

How can we reproduce it

class NestedSchema(BaseModel):
    v: str
    z: int


class UpperSchema(BaseModel):
    a: int
    b: Mapping[str, str]
    nested: Mapping[str, NestedSchema]


class NestedSchemaFactory(ModelFactory):
    __model__ = NestedSchema


class UpperSchemaFactory(ModelFactory):
    __model__ = UpperSchema


def test_factory_not_ok():
    nested = NestedSchema(v="hello", z=0)
    some_dict = {"test": "fine"}
    upper = UpperSchemaFactory.build(b=some_dict, nested={"nested": nested})
    
    assert upper.b["test"] == "fine"   # this is ok
    
    # all assertions below fail
    assert "nested" in upper.nested
    random_new_key = [k for k in upper.nested][0]
    assert upper.nested[random_new_key].v == nested.v
    assert upper.b[random_new_key].z == nested.z

Anything else we need to know
A nested schema without being nested in another dict (as shown in the example) works as intended

Affected versions
all 1.5 versions

How to use factory fixtures in other factories?

Hey thanks for adding the register_fixtures decorator. One issue I've got with this is that I can't reference a factory fixture in other factories. We have something like this:

class BarFactory(ModelFactory):
    __model__ = Bar
    
    baz = 42


class FooFactory(ModelFactory):
    __model__ = Foo

    bar = Use(BarFactory.build)

We use BarFactory in some tests by itself, so if we register the fixture, that works great. But I'm having trouble figuring out how to use the bar_factory fixture inside of the FooFactory. We can't do this:

@register_fixture
class BarFactory(ModelFactory):
    __model__ = Bar
    
    baz = 42


@register_fixture
class FooFactory(ModelFactory):
    __model__ = Foo

    bar = Use(BarFactory.build)

... because BarFactory is now a FixtureFunction and we get an AttributeError: 'function' object has no attribute 'build'. We can't do bar = Use(bar_factory.build) since bar_factory is a fixture that isn't available to the field. If we could access fixtures within the Factory definition, then we could do other things like use the pytest request fixture to allow for parameterization. Actually, I suppose if we just had access to the pytest request fixture, we could get any other fixture we needed and we could parametrize, too.

Do you have any thoughts on how we can make the pytest request fixture (or other fixtures) available in the Factory definition?

Automatically generated factories don't inherit the overridden get_provider_map

Issue

I'm trying to generate some deeply nested models, and somewhere in the tree are fields defined as Optional[Exception]. Pydantic Factories doesn't have a handler for Exception. I'm not sure if that's intentional, but it creates a problem for me. I tried to override get_provider_map, but this didn't help because the field is in a nested model.

When a factory dynamically generates a new ModelFactory, the generated factory doesn't use the parent's overridden class methods. This makes it difficult or impossible to influence how those models are generated and resolve any errors in the process.

I was able to work around the issue by also overriding create_factory, so that generated factories will inherit from their parent in the hierarchy. If this is the preferred solution, then it would be great to have that documented. Otherwise, it would be good to have an option to enable that inheritance or otherwise pass on the top level get_provider_map.

Also, is it intentional that there's no provider for Exception?

Anyway, thank you this library is great and it's going to make my tests much more maintainable.

Workaround

class RootFactory(ModelFactory):
    __model__ = RootModel

    @classmethod
    def get_provider_map(cls) -> Dict[Any, Callable]:
        provider_map = super().get_provider_map()
        provider_map.update({Exception: Exception})
        return provider_map

    @classmethod
    def create_factory(cls, model, base=None, **kwargs):
        return super().create_factory(model, cls, **kwargs)

How to access faker to generate realistic value

Hello, thanks for this useful project! ๐Ÿ‘

As for the title of my question, in factory_boy we can access faker like this:

class RandomUserFactory(factory.Factory):
    class Meta:
        model = models.User

    first_name = factory.Faker('first_name')
    last_name = factory.Faker('last_name')

The goal is to generate realistic values, as for example first names, that will be handled by faker.
How to access faker, in a similar way it is possible in factory_boy?

I was able with

class PersonFactory(ModelFactory[Person]):
    __model__ = Person
    
    name = ModelFactory._get_faker().first_name

But being _get_faker() private I was wondering why and if there is a public method to this.

Random seed is not propagated to the exrex package

Hi! I'm using Field to define JSON Schema. The regex randomisation is working, but it would be more useful if the seed would work as well.

Minimal working example:

from pydantic import BaseModel, Field
from pydantic_factories import ModelFactory

class MyModel(BaseModel):
    id: int
    special_id: str = Field(
        title='study',
        description='the study id for the data',
        regex=r'study-[1-9]{3}\.[1-9]{3}'
    )

class MyModelFactory(ModelFactory):
    __model__ = MyModel

ModelFactory.seed_random(1651)

print(MyModelFactory.build())

# id=4 special_id='study-281.776'
# id=4 special_id='study-297.351'
# id=4 special_id='study-249.654'
# ...

Bug: pytest plugin causing runtime error

Looks like introduced in #74

app_1    |   File "/app/./app/main.py", line 14, in <module>
app_1    |     from starlite import Provide, Starlite
app_1    |   File "/usr/local/lib/python3.10/site-packages/starlite/__init__.py", line 1, in <module>
app_1    |     from starlite.app import Starlite
app_1    |   File "/usr/local/lib/python3.10/site-packages/starlite/app.py", line 11, in <module>
app_1    |     from starlite.asgi import (
app_1    |   File "/usr/local/lib/python3.10/site-packages/starlite/asgi.py", line 33, in <module>
app_1    |     from starlite.utils import AsyncCallable
app_1    |   File "/usr/local/lib/python3.10/site-packages/starlite/utils/__init__.py", line 8, in <module>
app_1    |     from .model import convert_dataclass_to_model, create_parsed_model_field
app_1    |   File "/usr/local/lib/python3.10/site-packages/starlite/utils/model.py", line 5, in <module>
app_1    |     from pydantic_factories.utils import create_model_from_dataclass
app_1    |   File "/usr/local/lib/python3.10/site-packages/pydantic_factories/__init__.py", line 11, in <module>
app_1    |     from .plugins import register_fixture
app_1    |   File "/usr/local/lib/python3.10/site-packages/pydantic_factories/plugins/__init__.py", line 1, in <module>
app_1    |     from .pytest_plugin import register_fixture
app_1    |   File "/usr/local/lib/python3.10/site-packages/pydantic_factories/plugins/pytest_plugin.py", line 6, in <module>
app_1    |     import pytest
app_1    | ModuleNotFoundError: No module named 'pytest'

handle `Optional` fields according to a setting

Hello, thanks for making this library. Been looking forward to seeing something like this.

i noticed that in #5 it was decided to include None as a possible value for Optional fields. i can certainly see the use case for that. In my case, i'm using pydantic-factories to dynamically generate example data for FastAPI OpenAPI docs and would rather have these fields include values by default, and certainly don't want non-deterministic behavior.

Seems to me that a class variable could be set to support three possible behaviors: 1) always include, 2) sometimes include, 3) never include. We could leave the default behavior as sometimes include. That would satisfy my requirement for being able to reliably generate values for Optional fields dynamically.

That said, there is really a matrix of two cases: whether an Optional field should be included, and whether its value could be None. i noticed that you have a should_set_field_value classmethod for the former case, and then the second case seems to be handled inside get_field_value as a function of the result of the is_optional and a random boolean value.

Because the code for the library is so well modularized, i was able to get something working for my needs, so maybe class variables won't be deemed as necessary.

class SchemaFactory(ModelFactory):
    """ Factory which always creates a value for an Optional field.
    """
    __model__ = model

    @classmethod
    def create_factory(cls, model: Type[BaseModel]) -> "ModelFactory":
        # NOTE: i needed this because the create_factory method was no using my custom base factory class for child objects
        # If something like the following works, it would make subclassing easier for similar uses
        return cast(
            cls,
            type(
                f"{model.__name__}Factory",
                (cls,),
                {
                    "__model__": model,
                    "__faker__": cls._get_faker(),
                },
            ),
        )

    @classmethod
    def should_set_field_value(cls, field_name: str, **kwargs) -> bool:
        """ Always set a field value """
        return True

    @classmethod
    def get_field_value(cls, model_field: ModelField) -> Any:
        """Returns a field value on the sub-class if existing, otherwise returns a mock value"""
        if model_field.field_info.const:
            return model_field.get_default()
        # NOTE: skipping the `is_optional` check.
        # if is_optional(model_field=model_field) and not create_random_boolean():
        #     return None
        outer_type = model_field.outer_type_
        if isinstance(outer_type, EnumMeta):
            return cls.handle_enum(outer_type)
        if is_pydantic_model(outer_type) or is_dataclass(outer_type):
            return cls.create_factory(model=outer_type).build()
        if cls.is_constrained_field(outer_type):
            return cls.handle_constrained_field(model_field=model_field)
        if model_field.sub_fields:
            return handle_complex_type(model_field=model_field, model_factory=cls)
        # this is a workaround for the following issue: https://github.com/samuelcolvin/pydantic/issues/3415
        field_type = model_field.type_ if model_field.type_ is not Any else outer_type
        if cls.is_ignored_type(field_type):
            return None
        return cls.get_mock_value(field_type=field_type)

Two things which would have made this implementation simpler are:

  1. not explicitly naming ModelFactory inside the create_factory class method (so it wouldn't have to be overridden to affect behavior for child objects)
  2. having a dedicated class method for the is_optional/create_random_boolean bit, so the get_field_value method didn't have to be overridden.

Allow building a pydantic class without validation

When using pydantic factories, we encountered a use case where we we sometimes want to create pydantic models without validating them

this can be achieved in pydantic by using the construct method

we were thinking about adding this functionality to pydantic factories as well,
probably by adding a new class bool variable

    @classmethod
    def build(cls, **kwargs) -> T:
        """builds an instance of the factory's Meta.model"""
        for field_name, model_field in cls.get_model_fields(cls._get_model()):
            if model_field.alias:
                field_name = model_field.alias
            if cls.should_set_field_value(field_name, **kwargs):
                if hasattr(cls, field_name):
                    kwargs[field_name] = cls.handle_factory_field(field_name=field_name)
                else:
                    kwargs[field_name] = cls.get_field_value(model_field=model_field)
        if cls.__validate_pydantic_model__:
            return cls.__model__(**kwargs)
        return cls.__model__.construct(**kwargs)

Happy to open a PR if OK by you?

Bad handling of constrained decimal

Hi,
Given the following Pydantic model and factory:

from pydantic import BaseModel, condecimal
from pydantic_factories import ModelFactory

class MyModel(BaseModel):
    qty: condecimal(max_digits=8, decimal_places=5, gt=0, le=Decimal('999.99999'))

class MyFactory(ModelFactory[MyModel]):
    __model__ = MyModel

If we run

for _ in range(10000):
    MyFactory.build()

The following error would be raised:

ValidationError: 1 validation error for MyModel
qty
  ensure that there are no more than 3 digits before the decimal point (type=value_error.decimal.whole_digits; whole_digits=3)

The issue comes from the fact that pydantic_factories.constraints.constrained_decimal_handler.handle_decimal_length would return an invalid value.
For example:
handle_decimal_length(generated_decimal=Decimal('999.9'), max_digits=8, decimal_places=5)
would return Decimal('9990') instead of Decimal('999.90000')

Make it easier to extend the supported attribute types

As a user, I want to easily extend the available mappers of the pydantic model attribute types, for example, if there is a class that has an attribute type not supported by pydantic-factories and involves third-party libraries like this case, the extension of the mappers should be done on the user side.

Right now to do this the user has to subclass ModelFactory, override the method and extend the base value. This has the downsides that:

  • As the returned value of get_provider_map is generated on the return statement, to override the method the user has to copy and paste the whole dictionary potentially being outdated on future pydantic-factories releases.
  • It's not documented how to do this.
  • It's not easy for the user to do all this.

What I'm proposing is that ModelFactory has an internal attribute settable by the user where she can define the additional mappers, for example to give support to FakeDateTime the user's code would be:

from freezegun.api import FakeDatetime

class CustomModelFactory(ModelFactory):
    additional_mappers = { FakeDateTime: cls._get_faker().date_time_between }

We'll have to tweak get_provider_map so that it merges the default mapper dictionary with the user's

Allow access to sub-factory fields from build method.

It would be great to be able to customize the field of a sub-factory (or sub-sub-factory, etc.) right from the parent's build method. For example:

class Bar(BaseModel):
    x: int

class Foo(BaseModel):
    a: int
    bar: Bar

class FooFactory(ModelFactory):
    __model__ = Foo

test_foo = FooFactory.build(bar__x=42)

print(f'{test_foo!r}')  # prints Foo(a=9817, bar=Bar(x=42))

A real example of code that I have to write is something like this:

def test_the_lambda_handler(item_of_interest_fixture):
    test_event = SqsModelFactory.build((Records=[
        SqsRecordsFactory.build(
            body=WebhookEventFactory.build(
                details=WebhookEventDetailsFactory.build(resource_id=item_of_interest_fixture.id)
            ).json()
        )
    ]))

I'd love to be able to do something like this:

def test_the_lambda_handler(item_of_interest_fixture):
    test_event = SqsModelFactory.build(
        Records = SqsRecordsFactory.batch(size=1, body__details__resource_id=item_of_interest_fixture.id)
    )

Everything else can be either the default values or whatever I've customized in the various sub-factories and the test has the value I'm interested in.

Literal support

When specifying my model, using a Literal, I run into an error in the generation.

class MyModel(BaseModel):
    mykey: Literal['attribute']

Pydantic model error output

E           pydantic.error_wrappers.ValidationError: 1 validation error for MyModel
E           mykey
E             none is not an allowed value (type=type_error.none.not_allowed)

Guessing it's currently returning None rather than "attribute".

I might be mis-using pydantic here. Are you able to confirm whether this is a bug or user error @Goldziher? ๐Ÿ™‚ Happy to help resolve this if it's a bug.

Implement an init

What?

Similar to other factory boy extensions, I'd expect to be able to simply construct the object and not have to call .build, like the basic usage example from the factory boy docs

Behavior I want

from pydantic import BaseModel
from pydantic_factories import ModelFactory


class Person(BaseModel):
    id: int
    name: str
    phone_number: str


class PersonFactory(ModelFactory):
    __model__ = Person


# rn I have to do PersonFactory.build()
print(PersonFactory())
#> id=6744 name='wqIOcAeNxRziXJlQEBqr' phone_number='lEJcvhasvbUJWRPvHMez'

Why do I care?

It'd be nice if I could change this in my packages that serialize using Pydantic and not change every downstream test to use .build

Mypy error cannot subclass "ModelFactory" (has type "Any")

Hi, when using the ModelFactory I get the next mypy error:

Class cannot subclass "ModelFactory" (has type "Any")  [misc]

For example with the code in the readme:

from datetime import date, datetime
from typing import List, Union

from pydantic import BaseModel, UUID4

from pydantic_factories import ModelFactory


class Person(BaseModel):
    id: UUID4
    name: str
    hobbies: List[str]
    age: Union[float, int]
    birthday: Union[datetime, date]


class PersonFactory(ModelFactory):
    __model__ = Person

I think this might be related with this pydantic issue.

Do you have any idea on how to solve it?

Union types with __allow_none_optionals__ causing maximum recursion depth exceeded errors

When I have

  1. A model defined where some fields are Union of types and None and
  2. __allow_none_optionals__= True

I'm getting an error: RecursionError: maximum recursion depth exceeded while getting the repr of an object

# snip
File "/Users/hans/workspace/example/.venv/lib/python3.10/site-packages/pydantic_factories/value_generators/complex_types.py", line 94, in handle_complex_type
  return model_factory.get_field_value(model_field=model_field)
File "/Users/hans/workspace/example/.venv/lib/python3.10/site-packages/pydantic_factories/factory.py", line 431, in get_field_value
  return handle_complex_type(model_field=model_field, model_factory=cls)
File "/Users/hans/workspace/example/.venv/lib/python3.10/site-packages/pydantic_factories/value_generators/complex_types.py", line 94, in handle_complex_type
  return model_factory.get_field_value(model_field=model_field)
File "/Users/hans/workspace/example/.venv/lib/python3.10/site-packages/pydantic_factories/factory.py", line 431, in get_field_value
  return handle_complex_type(model_field=model_field, model_factory=cls)
File "/Users/hans/workspace/example/.venv/lib/python3.10/site-packages/pydantic_factories/value_generators/complex_types.py", line 88, in handle_complex_type
  if is_union(model_field=model_field) and model_field.sub_fields:
File "/Users/hans/workspace/example/.venv/lib/python3.10/site-packages/pydantic_factories/utils.py", line 74, in is_union
  return repr(model_field.outer_type_).split("[")[0] == "typing.Union"
RecursionError: maximum recursion depth exceeded while getting the repr of an object`

Here's a simple (python 3.10) reproduce script:

import uuid

from pydantic import BaseModel
from pydantic_factories import ModelFactory


class Location(BaseModel):
    id: uuid.UUID | str | None
    name: str | None


class LocationFactory(ModelFactory):
    __model__ = Location
    __allow_none_optionals__ = False


if __name__ == "__main__":
    LocationFactory.build()

Version info:

โฏ pip freeze | grep pydantic
pydantic==1.9.0
pydantic-factories==1.2.6

โฏ python --version
Python 3.10.2

Enhancement: Auto-register factories as pytest fixtures

It would be super handy to have some method that would easily create a fixture out of a factory. For example:

class SomeLongNamedModel(BaseModel):
    id: UUID


@register_fixture   # Or some better name?
class SomeLongNamedModelFactory(ModelFactory):
    """Factory to create SomeLongNameModel instances
    
    Use this factory to generate SomeLongNameModels filled with random data
    """
    __model__ = SomeLongNamedModel

And then

$ pytest --fixtures

# other output...
some_long_named_model_factory
    Factory to create SomeLongNameModel instances
    
    Use this factory to generate SomeLongNameModels filled with random data

This is following the model of pytest-factoryboy which automatically converts the PascalCase class names to be the snake_case equivalent for the fixtures.

SQLModel integration

Hi,

I have the problem integrating your tool with my models to keep correct constraints keys etc.
Please give me some examples or tips.

Specifying ModelFactory for nested model

Hello!

Given the following models:

class B(BaseModel):
    c: str

class A(BaseModel):
    b: B

I want to generate instances of type A, while keeping c deterministic.

I tried to do the following:

class BFactory(ModelFactory):
    __model__ = B  
    c = "deterministic-value"
     
class AFactory(ModelFactory):
    __model__ = A

When I call AFactory.build(), c is randomly generated, so it's not using BFactory.

Is there any way to make AFactory use BFactory without having to set it explicitly as b = BFactory.build() in AFactory?

Mypy error `Skipping analyzing "pydantic_factories": found module but no type hints or library stubs [import]`

When importing the ModelFactory mypy returns the error:

Skipping analyzing "pydantic_factories": found module but no type hints or library stubs  [import]

When using the code:

from pydantic_factories import ModelFactory # error raised here

This can be patched by adding the next lines to mypy.ini:

[mypy-pydantic_factories.*]
ignore_missing_imports = True

But it would be better if pydantic-factories provided the information. Mypy gives some hints on how to make your library compatible with mypy.

Allow specifying that an Optional field should have a value when building the Factory

In all cases except a few, the feature to alternate between None and a value for Optional fields is very useful. However, in some cases I need there to always be a value. Now, one could import Faker and create a random value manually; however, something like the following would be super helpful:

MyModelFactory.build(x="some value", optional_y=Require())

In fact, I tried this on the offchance that it would work, but alas no!

If you have any thoughts on this feature, I could take a stab at implementing, but some guidance on how you would do it would be grand. Cheers!

It seems that Literals are not sampled at random

I have something similar to:

class MyModel(BaseModel):
    my_key: Literal["value1", "value2"]

And if I have a factory:

instance_1 = factories.MyModel.build()
instance_2 = factories.MyModel.build()

I get in both cases "value1" for my_key even if I try generate more instances.

Ability to extend __allow_none_optionals__ to nested models

Amazing library, thank you!
For the case when the data model is complex, there is a need to cover all non-trivial cases.
Looks like in pydantic_factories/factory.py:369 the check for is_optional and not create_random_boolean can be placed to a separate method like it's done with other checks. -> Old version

So if I have:

class B(BaseModel):
   ...

class A(BaseModel):
    b: Optional[B] = None

class AFactory(ModelFactory):
    __allow_none_optionals__ = False
    __model__ = A

__allow_none_optionals__=False behavior won't be applied to B, which is correct, but an option to enforce the "never none if optional" would very nice.

Currently, I work around it in tests with:

@pytest.fixture
def patch_pydantic_factories(monkeypatch):
    from pydantic_factories import ModelFactory
    monkeypatch.setattr(ModelFactory, "__allow_none_optionals__", False)

Feature: access already generated fields in custom generation

It would be a nice feature to have access to the already generated field values in a customised generator scenario, e.g.

from typing import Any
from pydantic_factories import ModelFactory

class CustomFactory(ModelFactory[Any]):
    """Tweak the ModelFactory to add our custom mocks."""

    @classmethod
    def get_mock_value(cls, field_type: Any, previous_fields: dict[str, Any]) -> Any:
        """Add our custom mock value."""
        if str(field_type) == "my_dependant_field" and previous_fields["my_relying_on"] == 'special_value':
            return cls._get_faker().date_time_between()

        return super().get_mock_value(field_type)

I could even imagine some decorator or annotation based solution to the same problem, e.g.

class MyFactory(ModelFactory):
  __model__ = MyModel

  @depends('field_relying_on')
  def dependant_field_name(self, current_value: Any, other_value: Any):
    return 'special_value_generated_based_on_context'

Allow setting the key value of a container type

When we have this:

class Foo(BaseModel):
    name: str


class Foos(BaseModel):
    __root__: dict(str, Foo)

and this:

class FooFactory(ModelFactory):
    __model__ = Foo


class FoosFactory(ModelFactory):
    __model__ = Foos

There is no way (that I can tell) to customize the key value of the root model. I'd like to be able to do this

test_foos = FoosFactory.build(root_key='asdf_qewr_1234_wow', foo=FooFactory.build(name='omg'))  # root_key isn't a thing, but just pretend
print(test_foos.json(indent=2))

"""
this would output
{
  'asdf_qwer_1234_wow': {
      'name': 'omg'
  }
}
"""

Or maybe this:

class Foos_factory(ModelFactory):
    __model__ = Foos

    root_key = f'FOO#{ModelFactory._get_faker().uuid4()}'

I don't know if root_key is the right value here, but it would be very useful to have something to hook into to customize this value.

Typing: DataclassProtocol.__dataclass_fields__ should be ClassVar

https://github.com/starlite-api/pydantic-factories/blob/d5ebb7a2071ed393926dbdd2f7f7e47fd2a026a6/pydantic_factories/protocols.py#L10-L11

Defined here:

    # Remember all of the fields on our class (including bases).  This
    # also marks this class as being a dataclass.
    setattr(cls, _FIELDS, fields)

Where _FIELDS is:

# The name of an attribute on the class where we store the Field
# objects.  Also used to check if a class is a Data Class.
_FIELDS = '__dataclass_fields__'

I ran into this when trying to use the types in Starlite:

/home/peter/PycharmProjects/starlite/starlite/types/partial.py
  /home/peter/PycharmProjects/starlite/starlite/types/partial.py:137:49 - error: Protocol class "DataclassProtocol" does not define "__dataclass_fields__" as a ClassVar (reportGeneralTypeIssues)

Randomly return `None` in `Optional` fields

Hi @Goldziher first of all, thank you, thank you and thank you. I've been close to create something like this several times. You're a life saver :)

In most of my pydantic models I have some property of type Optional[...]. It would be awesome if pydantic-factories was able to understand them and randomly return None on some of the objects.

I dealt with this problem in the past, and created faker-optional a faker provider just for that, maybe it's interesting for this use case.

Thanks!

`Use` only works for aliases

If the original pydantic model's field is aliased then only the aliased name could be overridden even if th allow_population_by_field_name config is set to true in the original model.

It would be nice to support the original field names override.

Add support for `pytest-freezegun`

Hi @Goldziher, I'm having issues using pydantic_factories with pytest_freezegun, the problem is that pytest_factories is not able to find the factory function for the datetime attributes

tests/unit/test_source.py:16: in test_cant_merge_if_url_is_not_equal
    original = SourceFactory.build()
../../.venvs/airss/lib/python3.9/site-packages/pydantic_factories/factory.py:495: in build
    kwargs[field_name] = cls.get_field_value(model_field=model_field)
../../.venvs/airss/lib/python3.9/site-packages/pydantic_factories/factory.py:438: in get_field_value
    return cls.get_mock_value(field_type=field_type)
../../.venvs/airss/lib/python3.9/site-packages/pydantic_factories/factory.py:339: in get_mock_value
    raise ParameterError(
E   pydantic_factories.exceptions.ParameterError: Unsupported type: <class 'datetime.datetime'>
E
E   Either extend the providers map or add a factory function for this model field

Adding a pdb trace on line 339 I get the next result:

(Pdb) cls.get_provider_map().get(field_type)
(Pdb) cls.get_provider_map().get(datetime)
<bound method Provider.date_time_between of <faker.providers.date_time.en_US.Provider object at 0x7f004133b580>>
(Pdb) type(field_type)
<class 'type'>
(Pdb) field_type
<class 'datetime.datetime'>
(Pdb) datetime
<class 'freezegun.api.FakeDatetime'>

If you feel it's a corner case and you don't want to support pytest-freezegun, can you point me in the direction on how to extend the providers map locally?

Thanks! :)

TypingType[BaseModel] not supported

Hello,

TL;DR:
I think pydantic-factory can't handle this line:

 Message: Union[str, TypingType[BaseModel]]

I'm trying to build a factory for this model:

class SnsModel(BaseModel):
    Records: List[SnsRecordModel]

class SnsModelFactory(ModelFactory[SnsModel]):
    __model__ = SnsModel

sns_event = SnsModelFactory.build()

I get the error:

Unsupported type: typing.Type[pydantic.main.BaseModel]

By digging the entire hierarchy of nested models I found it comes from this:

class SnsNotificationModel(BaseModel):
    Subject: Optional[str]
    TopicArn: str
    UnsubscribeUrl: HttpUrl
    Type: Literal["Notification"]
    MessageAttributes: Optional[Dict[str, SnsMsgAttributeModel]]
    Message: Union[str, TypingType[BaseModel]]  # <- Trouble HERE
    MessageId: str
    SigningCertUrl: HttpUrl
    Signature: str
    Timestamp: datetime
    SignatureVersion: str

So I've tried to recreate the entire hierarchy of nested factories (entire reproducible example) based on the hierarchy of nested models (sns events having as payload s3 events) from here and here:

from aws_lambda_powertools.utilities.parser.models import SnsNotificationModel, SnsModel, SnsRecordModel
from aws_lambda_powertools.utilities.parser.models.s3 import S3Model, S3RecordModel, S3Message, S3Object, S3Bucket

from pydantic_factories import ModelFactory

# S3 MODELS
# ------------
class S3ObjectFactory(ModelFactory[S3Object]):
    __model__ = S3Object

    key = 'aaabbb'


class S3BucketFactory(ModelFactory[S3Bucket]):
    __model__ = S3Bucket

    key = 'aaabbb'


class S3MessageFactory(ModelFactory[S3Message]):
    __model__ = S3Message

    object = S3ObjectFactory
    bucket = S3BucketFactory


class S3RecordModelFactory(ModelFactory[S3RecordModel]):
    __model__ = S3RecordModel

    s3 = S3MessageFactory


s3_records = S3RecordModelFactory.batch(size=5)


class S3ModelFactory(ModelFactory[S3Model]):
    __model__ = S3Model

    Records = s3_records


# SNS MODELS
class SnsNotificationModelFactory(ModelFactory[SnsNotificationModel]):
    __model__ = SnsNotificationModel

    Message = S3ModelFactory


class SnsRecordModelFactory(ModelFactory[SnsRecordModel]):
    __model__ = SnsRecordModel

    Sns = SnsNotificationModelFactory


sns_records = SnsRecordModelFactory.batch(size=4)


class SnsModelFactory(ModelFactory[SnsModel]):
    __model__ = SnsModel

    Records = sns_records


sns_event = SnsModelFactory.build()

And this time I get the error:

2 validation errors for SnsNotificationModel
Message
  str type expected (type=type_error.str)
Message
  subclass of BaseModel expected (type=type_error.subclass; expected_class=BaseModel)

Somehow it's not happy that the field Message is an S3ModelFactory

class SnsNotificationModelFactory(ModelFactory[SnsNotificationModel]):
    __model__ = SnsNotificationModel

    Message = S3ModelFactory

but that is odd because the S3ModelFactory is a factory for the S3Model that is a direct subclass of BaseModel.

Disable randomization option

While randomizing the input is a good idea, big test suits want to remain determined, so the reason of failure can be investigated properly.
In multiple places in the codebase random.choice is used, so if a field belongs to a composite type like Union, random results can be expected even if faker seed is set.

What would be very cool, is a global option or similar where randomization can be disabled completely and only determined results are delivered.

Shortcut function

This is mostly a question: would you consider adding shortcut functions to the library @Goldziher?

Background

I run into this pattern a lot. I have a mock like this:

mock = mocker.patch.object(my_object, 'my_method', AsyncMock(return_value=...))

and realize I can use pydantic-factories to provide the return data (yay ๐ŸŽ‰ )

My issue is that the declaration needed to create a one-off model here is a little bit much for the scenarios where I just want valid data (I'm not testing inputs, I'm testing unrelated behavior, and just need valid filler). To make this work, I currently have to do this:

class MyMockModel(ModelFactory):
    __model__ = MyModel

mock_data = MyMockModel().build().dict()
mock = mocker.patch.object(my_object, 'my_method', AsyncMock(return_value=mock_data))

Suggestion

Could it make sense to provide a shortcut function for these cases, where we simply do something like this?

mock_data = default_factory(MyModel).build().dict()
mock = mocker.patch.object(my_object, 'my_method', AsyncMock(return_value=mock_data))

Haven't thought about the naming or implementation - wanted to hear your thoughts first ๐Ÿ™‚ Happy to help implement this if it seems reasonable.

Constrained decimal handler cannot generate values between 0 and 1

Hi, there seems to be a bug when generating decimal values between 0 and 1.

With this example:

from decimal import Decimal

from pydantic import BaseModel, Field
from pydantic_factories import ModelFactory


class FractionExample(BaseModel):
    fraction: Decimal = Field(ge=0, le=1, decimal_places=2, max_digits=3)


class FractionExampleFactory(ModelFactory):
    __model__ = FractionExample


# This raises the error:
FractionExampleFactory.build()

I get following error

Traceback (most recent call last):
  File ".../site-packages/pydantic_factories/factory.py", line 370, in handle_constrained_field
    return handle_constrained_decimal(field=cast("ConstrainedDecimal", outer_type))
  File ".../site-packages/pydantic_factories/constraints/constrained_decimal_handler.py", line 75, in handle_constrained_decimal
    validate_max_digits(max_digits=max_digits, minimum=cast("Decimal", minimum), decimal_places=decimal_places)
  File ".../site-packages/pydantic_factories/constraints/constrained_decimal_handler.py", line 24, in validate_max_digits
    assert max_digits >= len(str(abs(minimum))), "minimum is greater than max_digits"
AssertionError: minimum is greater than max_digits

I'd expect that the factory would create fractions like 0.00, 0.12 and 1.00.

Versions:

  • Python: 3.10.5
  • pydantic: 1.9.1
  • pydantic-factories: 1.5.1

create_sync do not check contraints like primary key

HI.

I use sqlmodel-model which combine pydantic and sqlalchemy in one.

Your fantastic library helped me a LOT for unit tests and I really want to tell you THANK YOU.

However, when I implement the persistence handler protocol, somehow, it does save items with an id of None (since the id is an Optional field, otherwise we would not be able to create a new instance).

I saw that from this issue, you added the None random value for Optional fields, but there are some fields that are declared as Optional but are not really optional when dealing with persistence (like primary key attribute).

So I wonder how to handle this case :

class Hero(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str
    secret_name: str
    age: Optional[int] = None

`OrmarModelFactory.get_field_value` TypeError("object of type 'bool' has no len()")

Hi @Goldziher!

First of all, thanks for this superb library, I just started integrating it into my project and it seems very promising. I stumbled upon a problem, though, and I think it might be a problem with the library itself.

The OrmarModelFactory overrides the get_field_value method to handle choices field. However, in my model I have a ormar.ForeignKey field:

user: Optional[Union[User, Dict]] = ormar.ForeignKey(User)

When trying to create an instance of this model using pydantic_factories, the aforementioned method raises an error:

    @classmethod
    def get_field_value(cls, model_field: ModelField) -> Any:
        """
        We need to handle here both choices and the fact that ormar sets values to be optional
        """
        model_field.required = True
>       if hasattr(model_field.field_info, "choices") and len(model_field.field_info.choices) > 0:  # type: ignore
E       TypeError: object of type 'bool' has no len()

The problem is that this model_field actually does have the choices attribute in the field_info dict, but it is set to False. The hasattr(model_field.field_info, "choices") check does not accommodate for that and returns true, and then len(False) obviously fails.

I am not sure if I am thinking correctly, but if so, then simply replacing hasattr(model_field.field_info, "choices") with:

getattr(model_field.field_info, "choices", False)

will resolve the issue (it did it for me).

If I am not missing anything and my solution is right, I can make a PR tomorrow as well :) It's just a 1 line change anyway.

Thanks!

Discussion: handle recursion?

Currently this library does not handle self-referencing models and models with cyclical references. For example:

from pydantic import BaseModel

class A(BaseModel):
    bs: List["B"]

class B(BaseModel):
    a: A

In the above there are two models with cyclical dependencies - A that has a list of B and B that has A. If we simply resolve the forward ref and then generate values for one of these, we will hit a recursion exception. While my original thinking was that we should not handle this case and instead let users customize factories to handle it manually - this creates problems downstream, see: litestar-org/litestar#196. I would like to discuss how to resolve this.

Infinite recursion error with discriminated unions

I tried to create a factory for a model that makes use of a discriminated union and it ends up in an infinite recursion.

python: 3.7
pydantic_factories version: 1.7.1

Below is a minimal example using the pydantic example at https://pydantic-docs.helpmanual.io/usage/types/#nested-discriminated-unions
as a starting point

from typing import Literal, Union

from typing_extensions import Annotated

from pydantic import BaseModel, Field, ValidationError

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

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

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

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

Pet = Annotated[Union[Cat, Dog], Field(discriminator='pet_type')]

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

from pydantic_factories import ModelFactory

class MyModelFactory(ModelFactory):
    __model__ = Model

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

Error when building with a parameter that is a optional pydantic model

Hello again!

Sorry to be the bearer of bad news!

We found another problem with the new partial factories when giving a None for an optional attribute.

pydantic-factories==1.5.1

from typing import Optional

from pydantic import BaseModel
from pydantic_factories import ModelFactory


class MySubClass(BaseModel):
    sub_value:str


class MyClass(BaseModel):
    sub_obj: Optional[MySubClass]


class MyClassFactory(ModelFactory[MyClass]):
    __model__ = MyClass


MyClassFactory.build(sub_obj=None)

Will Produce the following

.../.venv/bin/python .../scratch/pydantic_factories_check/reproduce_with_none.py 
Traceback (most recent call last):
  File ".../reproduce_with_none.py", line 19, in <module>
    MyClassFactory.build(sub_obj=None)
  File ".../.venv/lib/python3.9/site-packages/pydantic_factories/factory.py", line 556, in build
    if cls.should_set_field_value(field_name, model_field, **kwargs):
  File ".../.venv/lib/python3.9/site-packages/pydantic_factories/factory.py", line 524, in should_set_field_value
    not is_field_in_kwargs or cls._is_pydantic_with_partial_fields(field_name, model_field, **kwargs)
  File ".../.venv/lib/python3.9/site-packages/pydantic_factories/factory.py", line 502, in _is_pydantic_with_partial_fields
    return cls._is_kwargs_missing_pydantic_fields(pydantic_model, list_of_pydantic_models_kwargs)
  File ".../.venv/lib/python3.9/site-packages/pydantic_factories/factory.py", line 486, in _is_kwargs_missing_pydantic_fields
    kwargs_field_names = set(pydantic_model_kwargs.keys())
AttributeError: 'NoneType' object has no attribute 'keys'

`ParameterError` raised on complex model for already supported types

I'm starting to use the library in clinv, when using the VPCFactory defined as:

from clinv.model import aws

class VPCFactory(ModelFactory):  # type: ignore
    """Define the factory for the model VPC."""

    __model__ = aws.VPC

And running VPCFactory.build() I get the error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/lyz/.venvs/clinv/lib/python3.9/site-packages/pydantic_factories/factory.py", line 363, in build
    kwargs[field_name] = cls.get_field_value(field_name=field_name, model_field=model_field)
  File "/home/lyz/.venvs/clinv/lib/python3.9/site-packages/pydantic_factories/factory.py", line 333, in get_field_value
    return handle_complex_type(model_field=model_field, model_factory=cls)
  File "/home/lyz/.venvs/clinv/lib/python3.9/site-packages/pydantic_factories/value_generators/complex_types.py", line 90, in handle_complex_type
    return handle_container_type(
  File "/home/lyz/.venvs/clinv/lib/python3.9/site-packages/pydantic_factories/value_generators/complex_types.py", line 69, in handle_container_type
    value = handle_complex_type(model_field=choice(model_field.sub_fields), model_factory=model_factory)
  File "/home/lyz/.venvs/clinv/lib/python3.9/site-packages/pydantic_factories/value_generators/complex_types.py", line 109, in handle_complex_type
    raise ParameterError(
pydantic_factories.exceptions.ParameterError: Unsupported type: <enum 'Environment'>

Either extend the providers map or add a factory function for this model field

When the property environment is not None.

The interesting snippets of the model definition are:

src/model/aws.py

VPC inherits from AWSEntity in the same file that uses the Environment Enum from another file.

from .entity import Entity, Environment

class AWSEntity(Entity):
    environment: Optional[List[Environment]] = Field(default_factory=list)

class VPCID(ConstrainedStr):
    """Define the resource id format."""

    regex = re.compile("^vpc-.*$")

class VPC(AWSEntity):
    id_: VPCID
    cidr: IPvAnyNetwork
    region: str

src/model/entity.py

from enum import Enum

class Environment(str, Enum):
    STAGING = "Staging"
    PRODUCTION = "Production"
    TESTING = "Testing"

class Entity(BaseModel):
   ...

After some debugging, it looks like the handle_complex_type function is not able to handle the <enum 'Environment'>. But I have no idea why, as a simple test works:

import re
from enum import Enum

from model import Server
from pydantic import BaseModel, ConstrainedStr
from pydantic_factories import ModelFactory


class ServerID(ConstrainedStr):
    """Define the resource id format."""

    regex = re.compile("^server-.*$")


class Environment(str, Enum):
    """Set the possible logical environments."""

    STAGING = "Staging"
    PRODUCTION = "Production"
    TESTING = "Testing"


class Server(BaseModel):
    id_: ServerID
    name: str
    environment: Environment


class ServerFactory(ModelFactory):
    __model__ = Server

ServerFactory.build()

ModelFactory generic does not accept BaseModel subclasses

Hi!

Thank you for this tool, it's a great idea!

Versions

Python: 3.9.9
Libraries:

  • pydantic-factories==1.1.0
  • mypy==0.930

Issue

While trying to use it with mypy in strict mode

[tool.mypy]
strict=true

I would get

error: Missing type parameters for generic type "ModelFactory"

If trying to specify the type with class PersonFactory(ModelFactory[Person]), i would get

error: Value of type variable "T" of "ModelFactory" cannot be "Person"

Reproduce

I've put up a reproduction repo here: https://github.com/lindycoder/pydantic-factories-mypy-issue

Solution

(Disclaimer : still new to mypy)

I think the TypeVar might be misdefined, as per https://mypy.readthedocs.io/en/stable/generics.html#type-variables-with-upper-bounds

Maybe it should be

T = TypeVar("T", bound=Union[BaseModel, DataclassProtocol])

I will try open a PR for this

Allow partial attributes factory for child factories (randomly generating only missing fields for child models)

Given the following Pydantic models and Factory:

from pydantic_factories import ModelFactory
from pydantic import BaseModel


class Pet(BaseModel):
    name: str
    age: int


class Person(BaseModel):
    name: str
    pets: list[Pet]
    age: int


class PersonFactory(ModelFactory[Person]):
    __model__ = Person

When trying to build:

data = {
    'name': 'John',
    'pets': [
        {'name': 'dog'},
        {'name': 'cat'},
    ],
}

PersonFactory.build(**data)

Then the following exception is raised:

ValidationError: 2 validation errors for Person
pets -> 0 -> age
  field required (type=value_error.missing)
pets -> 1 -> age
  field required (type=value_error.missing)

We see that the age is missing in the data, so the factory is not able to construct the model.

If we add the age to the data:

data = {
    'name': 'John',
    'pets': [
        {'name': 'dog', 'age': 3},
        {'name': 'cat', 'age': 4},
    ],
}

PersonFactory.build(**data)

The factory will construct the model instance:

Person(name='John', pets=[Pet(name='dog', age=3), Pet(name='cat', age=4)], age=5978)

Note: only the age of the Pets (child model) is necessary, ModelFactory handles to randomly fill the age of Person.

It would be great to have the same behaviour of Factory Boy. If we pass only part of the attributes of a child model, then the factory will generate the missing attributes for us.

Can we work on this feature?

Enhancement: Support `stricturl`

Hi, is it true? I got an error:

E   pydantic_factories.exceptions.ParameterError: Unsupported type: <class 'xxx.xxx.models.UrlValue'>
E   
E   Either extend the providers map or add a factory function for this model field

The flag allow_population_by_field_name is not recognized

I have two models User, Review and their ModelFactorys.

from pydantic import BaseModel, Field

from pydantic_factories import ModelFactory


class User(BaseModel):
    login: str


class Review(BaseModel):
    body: str
    author: User = Field(alias="user")

    class Config:
        allow_population_by_field_name = True


class UserFactory(ModelFactory):
    __model__ = User


class ReviewFactory(ModelFactory):
    __model__ = Review


if __name__ == '__main__':
    author: User = UserFactory.build(login="me")

    review: Review = ReviewFactory.build(author=author)
    assert id(author) != id(review.author)
    assert review.author.login != author.login

    review: Review = ReviewFactory.build(user=author)
    assert id(author) != id(review.author)  # ๐Ÿ™„ why?
    assert review.author.login == author.login

*note: all assertion are successful

Review model has the allow_population_by_field_name flag set to True which means
Review model should be able to accept both author and user attributes to
populate the User model, however it's not recognized on building the instance and
new instance gets created.

I also noticed that new object was created on supplying a valid User instance to the ReviewFactory!!
see the why line

Bug: can't construct models with fields named like `ModelFactory`s classmethods

Hello, I stumbled upon this recently:

class C(BaseModel):
    batch: int

class CFactory(ModelFactory):
    __model__ = C

CFactory.build() # TypeError: ModelFactory.batch() missing 1 required positional argument: 'size'

โ€“ looks like it fails due to CFactory.build detecting and incorrectly recognizing CFactory.batch as a factory field instead of its own classmethod. Similar issue occurs with e.g. build or get_model_fields.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.