Pydantic based mock data generation

Overview

PyPI - Python Version Coverage Maintainability Rating Reliability Rating Quality Gate Status

Pydantic-Factories

This library offers powerful mock data generation capabilities for pydantic based models. It can also be used with other libraries that use pydantic as a foundation, for example SQLModel, Beanie and ormar.

Features

  • supports both built-in and pydantic types
  • supports pydantic field constraints
  • supports complex field types
  • supports custom model fields

Why This Library?

  • 💯 powerful
  • 💯 extensible
  • 💯 simple
  • 💯 rigorously tested

Installation

Using your package manager of choice:

pip install pydantic-factories

OR

poetry add --dev pydantic-factories

OR

pipenv install --dev pydantic-factories

pydantic-factories has very few dependencies aside from pydantic - typing-extensions which is used for typing support in older versions of python, as well as faker and exrex, both of which are used for generating mock data.

Usage

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


result = PersonFactory.build()

That's it - with almost no work, we are able to create a mock data object fitting the Person class model definition.

This is possible because of the typing information available on the pydantic model and model-fields, which are used as a source of truth for data generation.

The factory parses the information stored in the pydantic model and generates a dictionary of kwargs that are passed to the Person class' init method.

Build Methods

The ModelFactory class exposes two build methods:

  • .build(**kwargs) - builds a single instance of the factory's model
  • .batch(size: int, **kwargs) - build a list of size n instances
result = PersonFactory.build()  # a single Person instance

result = PersonFactory.batch(size=5)  # list[Person, Person, Person, Person, Person]

Any kwargs you pass to .build, .batch or any of the persistence methods, will take precedence over whatever defaults are defined on the factory class itself.

Nested Models and Complex types

The automatic generation of mock data works for all types supported by pydantic, as well as nested classes that derive from BaseModel (including for 3rd party libraries) and complex types. Let's look at another example:

from datetime import date, datetime
from enum import Enum
from pydantic import BaseModel, UUID4
from typing import Any, Dict, List, Union

from pydantic_factories import ModelFactory


class Species(str, Enum):
    CAT = "Cat"
    DOG = "Dog"
    PIG = "Pig"
    MONKEY = "Monkey"


class Pet(BaseModel):
    name: str
    sound: str
    species: Species


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


class PersonFactory(ModelFactory):
    __model__ = Person


result = PersonFactory.build()

This example will also work out of the box although no factory was defined for the Pet class, that's not a problem - a factory will be dynamically generated for it on the fly.

The complex typing under the assets attribute is a bit more tricky, but the factory will generate a python object fitting this signature, therefore passing validation.

Please note: the one thing factories cannot handle is self referencing models, because this can lead to recursion errors. In this case you will need to handle the particular field by setting defaults for it.

Factory Configuration

Configuration of ModelFactory is done using class variables:

  • __model__: a required variable specifying the model for the factory. It accepts any class that extends _ pydantic's_ BaseModel including classes from other libraries. If this variable is not set, a ConfigurationException will be raised.

  • __faker__: an optional variable specifying a user configured instance of faker. If this variable is not set, the factory will default to using vanilla faker.

  • __sync_persistence__: an optional variable specifying the handler for synchronously persisting data. If this is variable is not set, the .create_sync and .create_batch_sync methods of the factory cannot be used. See: persistence methods

  • __async_persistence__: an optional variable specifying the handler for asynchronously persisting data. If this is variable is not set, the .create_async and .create_batch_async methods of the factory cannot be used. See: persistence methods

from faker import Faker
from pydantic_factories import ModelFactory

from app.models import Person
from .persistence import AsyncPersistenceHandler, SyncPersistenceHandler

Faker.seed(5)
my_faker = Faker("en-EN")


class PersonFactory(ModelFactory):
    __model__ = Person
    __faker__ = my_faker
    __sync_persistence__ = SyncPersistenceHandler
    __async_persistence__ = AsyncPersistenceHandler
    ...

Defining Factory Attributes

The factory api is designed to be as semantic and simple as possible, lets look at several examples that assume we have the following models:

from datetime import date, datetime
from enum import Enum
from pydantic import BaseModel, UUID4
from typing import Any, Dict, List, Union

from pydantic_factories import ModelFactory


class Species(str, Enum):
    CAT = "Cat"
    DOG = "Dog"


class Pet(BaseModel):
    name: str
    species: Species


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

One way of defining defaults is to use hardcoded values:

pet = Pet(name="Roxy", sound="woof woof", species=Species.DOG)


class PersonFactory(ModelFactory):
    __model__ = Person

    pets = [pet]

In this case when we call PersonFactory.build() the result will be randomly generated, except the pets list, which will be the hardcoded default we defined.

Use (field)

This though is often not desirable. We could instead, define a factory for Pet where we restrict the choices to a range we like. For example:

from enum import Enum
from pydantic_factories.fields import Use
from random import choice


class Species(str, Enum):
    CAT = "Cat"
    DOG = "Dog"


class PetFactory(ModelFactory):
    __model__ = Pet

    name = Use(choice, ["Ralph", "Roxy"])
    species = Use(choice, list(Species))


class PersonFactory(ModelFactory):
    __model__ = Person

    pets = Use(PetFactory.batch, size=2)

The signature for use is: cb: Callable, *args, **defaults, it can receive any sync callable. In the above example, we used the choice function from the standard library's random package, and the batch method of PetFactory.

You do not need to use the Use field, you can place callables (including classes) as values for a factory's attribute directly, and these will be invoked at build-time. Thus, you could for example re-write the above PetFactory like so:

class PetFactory(ModelFactory):
    __model__ = Pet

    name = lambda: choice(["Ralph", "Roxy"])
    species = lambda: choice(list(Species))

Use is merely a semantic abstraction that makes the factory cleaner and simpler to understand.

Ignore (field)

Ignore is another field exported by this library, and its used - as its name implies - to designate a given attribute as ignored:

from odmantic import EmbeddedModel, Model
from pydantic_factories.fields import Ignore

T = TypeVar("T", Model, EmbeddedModel)


class OdmanticModelFactory(ModelFactory[T]):
    id = Ignore()

The above example is basically the extension included in pydantic-factories for the library odmantic, which is a pydantic based mongo ODM.

For odmantic models, the id attribute should not be set by the factory, but rather handled by the odmantic logic itself. Thus the id field is marked as ignored.

When you ignore an attribute using Ignore, it will be completely ignored by the factory - that is, it will not be set as a kwarg passed to pydantic at all.

Require (field)

The Require field in turn specifies that a particular attribute is a required kwarg. That is, if a kwarg with a value for this particular attribute is not passed when calling factory.build(), a MissingBuildKwargError will be raised.

What is the use case for this? For example, lets say we have a document called Article which we store in some DB and is represented using a non-pydantic model, say, an elastic-dsl document. We then need to store in our pydantic object a reference to an id for this article. This value should not be some mock value, but must rather be an actual id passed to the factory. Thus, we can define this attribute as required:

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


class ArticleProxy(BaseModel):
    article_id: UUID
    ...


class ArticleProxyFactory(ModelFactory):
    __model__ = ArticleProxy

    article_id = Require()

If we call factory.build() without passing a value for article_id, an error will be raised.

Persistence

ModelFactory has four persistence methods:

  • .create_sync(**kwargs) - builds and persists a single instance of the factory's model synchronously
  • .create_batch_sync(size: int, **kwargs) - builds and persists a list of size n instances synchronously
  • .create_async(**kwargs) - builds and persists a single instance of the factory's model asynchronously
  • .create_batch_async(size: int, **kwargs) - builds and persists a list of size n instances asynchronously

To use these methods, you must first specify a sync and/or async persistence handlers for the factory:

T: ... # do stuff def save_many(self, data: List[T]) -> List[T]: ... # do stuff class AsyncPersistenceHandler(AsyncPersistenceProtocol[T]): async def save(self, data: T) -> T: ... # do stuff async def save_many(self, data: List[T]) -> List[T]: ... # do stuff ">
# persistence.py
from typing import TypeVar, List

from pydantic import BaseModel
from pydantic_factories import SyncPersistenceProtocol

T = TypeVar("T", bound=BaseModel)


class SyncPersistenceHandler(SyncPersistenceProtocol[T]):
    def save(self, data: T) -> T:
        ...  # do stuff

    def save_many(self, data: List[T]) -> List[T]:
        ...  # do stuff


class AsyncPersistenceHandler(AsyncPersistenceProtocol[T]):
    async def save(self, data: T) -> T:
        ...  # do stuff

    async def save_many(self, data: List[T]) -> List[T]:
        ...  # do stuff

You can then specify one or both of these handlers in your factory:

from pydantic_factories import ModelFactory

from app.models import Person
from .persistence import AsyncPersistenceHandler, SyncPersistenceHandler


class PersonFactory(ModelFactory):
    __model__ = Person
    __sync_persistence__ = SyncPersistenceHandler
    __async_persistence__ = AsyncPersistenceHandler

Or create your own base factory and reuse it in your various factories:

from pydantic_factories import ModelFactory

from app.models import Person
from .persistence import AsyncPersistenceHandler, SyncPersistenceHandler


class BaseModelFactory(ModelFactory):
    __sync_persistence__ = SyncPersistenceHandler
    __async_persistence__ = AsyncPersistenceHandler


class PersonFactory(BaseModelFactory):
    __model__ = Person

With the persistence handlers in place, you can now use all persistence methods. Please note - you do not need to define any or both persistence handlers. If you will only use sync or async persistence, you only need to define the respective handler to use these methods.

Extensions and Third Party Libraries

Any class that is derived from pydantic's BaseModel can be used as the __model__ of a factory. For most 3rd party libraries, e.g. SQLModel or Ormar, this library will work as is out of the box.

Currently, this library also includes extensions for two ODM libraries - odmatic and Beanie.

Odmatic

This extension includes a class called OdmanticModelFactory and it can be imported from pydantic_factory.extensions. This class is meant to be used with the Model and EmbeddedModel classes exported by the library, but it will also work with regular instances of pydantic's BaseModel.

Beanie

This extension includes a class called BeanieDocumentFactory as well as an BeaniePersistenceHandler. Both of these can be imported from pydantic_factory.extensions. The BeanieDocumentFactory is meant to be used with the Beanie Document class and it includes async persistence build in.

Contributing

This library is open to contributions - in fact we welcome it. Please see the contribution guide!

Comments
  • Feature: access already generated fields in custom generation

    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'
    
    
    enhancement 
    opened by blagasz 17
  • The flag allow_population_by_field_name is not recognized

    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

    enhancement help wanted good first issue 
    opened by islam-aymann 14
  • Use TypeVar's bound instead of constraint

    Use TypeVar's bound instead of constraint

    Using a factory in mypy strict requires a typed generic and providing the model itself as the generic type did not work because contrained TypeVar doesn't allow subclassing, as a bound TypeVar allows it.

    A file with this typing with its own mypy config was added to test the behaviour remains. Adding this showed that the DataclassProtocol was too narrow as a single field dataclass does not have __dataclass_params__ and __post_init__ attributes and it seems that marking them as Optional is not enough.

    EDIT BONUS: fix exclusion regex in pre-commit

    Fixes #21

    Notes

    EDIT This is fixed, was an issue with the exclusion regex. ~I added a test for this... I really tried hard to put the pydantic_factories/strict_typing_check.py file in the tests folder but i just couldn't figure out how to have it typed check in the mypy.ini. Something like [mypy-test.strict_typing_check] didn't seem to check the file at all.~

    ~If you have any suggestion where to put it? or how to make it work in the tests folder. Could also not package it... ?~

    opened by lindycoder 9
  • ModelFactory generic does not accept BaseModel subclasses

    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

    opened by lindycoder 8
  • Union types with __allow_none_optionals__ causing maximum recursion depth exceeded errors

    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
    
    bug 
    opened by hozn 7
  • Disable randomization option

    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.

    opened by thorin-schiffer 7
  • Implement auto registration hook

    Implement auto registration hook

    This PR Implement https://github.com/starlite-api/pydantic-factories/issues/115

    Here I use init_subclass class method to auto-register created model factories.

    opened by avihai-yosef 6
  • Register custom factories

    Register custom factories

    Enhancement - Having the ability to register custom factories. In our code base, we have common factories that are used a lot across the project. And we want one place to register these factories instead of assigning them manually as factory property.

    For example:

      class NestedModel(pydantic.BaseModel):
          # some fields
    
      class ParentModel(pydantic.BaseModel):
          nested: NestedModel
    
      class NestedModelFactory(ModelFactory):
           __model__ = NestedModel
           @classmethod
           def build(cls, ...):
                 # define my own logic of how to generate the model.
    
    
      parent_model_factory = create_factory(ParentModel)
      
      # I want parent_model_factory to use the NestedModelFactory when encountering NestedModel.
      
    

    Suggested usage:

    Option 1 - Overriding get_provider_map class method

    @classmethod
        def get_provider_map(cls):
            provider_map = cls.super()
            provider_map.update(AModel: CustomAModelFactory)
            return provider_map
    

    Option 2 - add a class method to register factories

    For example:

    @classmethod
        def register_factory(factory):
            pass
    

    Option 3 - creating a factory will automatically register it.

     class AModelFactory(ModelFactory):
         __ model__ =  AModel
         __auto_register__ = True
    
        @classemthod
        def build(cls):
            custom build implementation
    
    

    or

    create_factory(AModel, auto_register=True, a="const value")

    This can be implemented by customizing the metaclass of ModelFactory.

    opened by avihai-yosef 6
  • Allow partial attributes factory for child factories (randomly generating only missing fields for child models)

    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?

    bug 
    opened by phbernardes 6
  • Add support for `pytest-freezegun`

    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! :)

    opened by lyz-code 6
  • Fix OrmarModelFactory creation for relational field

    Fix OrmarModelFactory creation for relational field

    This PR fixes #27, where pydantic-factories is unable to create an instance of ormar.Model model if it contains a ormar.ForeignKey field to another model.

    As the issue describes, the previous hasattr(model_field.field_info, "choices") check was error prone, as for the ForeignKey field this attribute was set to False, which passed the check and resulted in an error when trying to check len() of a boolean.

    opened by mciszczon 6
  • unique values

    unique values

    It would be helpful to have a way to generate unique values for a model field, whenever a new instance is generated, for a process. i have model which assumes all the child objects will have unique integer ids, and every so often, two objects share the same random integer value, FactoryBoy uses a sequence pattern for this.

    opened by smcoll 4
  • Do deepcopy for ormar fields we mark as required

    Do deepcopy for ormar fields we mark as required

    Closes #128

    For some reason when setting model_field.required other attributes are resetted. So the best solution I was to able to come up is using deepcopy on model_field if we are going to set required to True. Everything else I tried failed on other stages damaging the initial model.

    opened by jtraub 1
  • How to get around reserved fields

    How to get around reserved fields

    I am getting the error:

    ModelFactory.should_set_field_value() got multiple values for argument 'field_name'

    because I guess field_name is reserved but it is also a field in my pydantic baseclass:

    class FooFactory(ModelFactory):
        __model__ = Foo
    
    class Foo(BaseModel):
        field_name: str
    
    ...
    
    FooFactory.build() # throws the above error
    

    Is there anyway to get around this?

    opened by maxisme 1
  • Model not seting default values after building a factory

    Model not seting default values after building a factory

    Creating a model after building a factory of the model rises a validation error of the default values not being defined.

    Example:

    class TestModel(ormar.Model):
        class Meta(ormar.ModelMeta):
            database = database
            metadata = meta
    
        id: UUID4 = ormar.UUID(primary_key=True, default=uuid4)
        text: str = ormar.Text()
        created_date: datetime.datetime = ormar.DateTime(default=datetime.datetime.now)
    
    
    class TestModelFactory(OrmarModelFactory):
        __model__ = TestModel
    
    
    def test_test_model():
        TestModelFactory.build()
        TestModel(text='qwerty')
    

    results in:

    >               raise validation_error
    E               pydantic.error_wrappers.ValidationError: 2 validation errors for TestModel
    E               id
    E                 field required (type=value_error.missing)
    E               created_date
    E                 field required (type=value_error.missing)
    

    Removing TestModelFactory.build() works as intended.

    The problem persists if the factory is called from one test and the instancing in the model in another one. Ex.

    def test_test_model_build():
        TestModelFactory.build()
    
    def test_test_model():
        TestModel(text='qwerty')
    
    bug 
    opened by eloi-martinez-qida 16
  • Constrained string regex + min/max length may produce invalid values

    Constrained string regex + min/max length may produce invalid values

    When a Field specified both max_length and regex that includes start and end of string tokens and a repeatable pattern can lead to generation of invalid string value that leads to ValidationError. See reproduction:

    from pydantic import BaseModel, Field
    from pydantic_factories import ModelFactory
    from pydantic_factories.value_generators.regex import RegexFactory
    
    PATTERN = r'^a+b$'
    GOOD_SEED = 0
    BAD_SEED = 5
    
    class A(BaseModel):
        a: str = Field(..., regex=pattern, min_length=2, max_length=10)
    
    class AF(ModelFactory[A]):
        __model__=A
    
    AF.seed_random(GOOD_SEED)
    print(AF.build()) # a='aaaaaaab'
    
    print(RegexFactory(seed=BAD_SEED)(pattern)) # aaaaaaaaaab
    AF.seed_random(BAD_SEED)
    print(AF.build()) # this breaks
    
    
    Traceback (most recent call last):
      File "[redacted]reproduce-bug.py", line 18, in <module>
        print(AF.build()) # This breaks
      File "[redacted]/factory.py", line 724, in build
        return cast("T", cls.__model__(**kwargs))  # pyright: ignore
      File "pydantic/main.py", line 342, in pydantic.main.BaseModel.__init__
    pydantic.error_wrappers.ValidationError: 1 validation error for A
    a
      string does not match regex "^a+b$" (type=value_error.str.regex; pattern=^a+b$)
    

    As far as I can tell, this is a result of this piece of code cutting off the end of string after calling RegexFactory. I was surprised that the test suite didn't catch this error earlier, but to my surprise the test case that is supposed to verify this behavior will not report any issues if the string produced by handle_constrained_string doesn't match the regex. Not sure if that was done on purpose, but adding assert match is not None leads to this test failing.

    I can't think of a quick solution to this issue, however I think having a note in the documentation regarding regex fields could be helpful.

    I am interested in working on a more structured solution to this issue, unless it's unlikely to be merged. :)

    opened by mishok13 4
  • `BeanieDocumentFactory` ignores all `PydanticObjectdIds`, even when they aren't the `_id`

    `BeanieDocumentFactory` ignores all `PydanticObjectdIds`, even when they aren't the `_id`

    in beanie_odm.py:

    class BeanieDocumentFactory(ModelFactory[Document]):
        ...
    
        def is_ignored_type(cls, value: Any) -> bool:
            return super().is_ignored_type(value=value) or value is PydanticObjectId
            # ^ here
    

    I'm sure this was done so that the factory can create a new object without an _id, but it doesn't allow a class to have a PydanticObjectId as a property.

    opened by gegnew 0
Releases(v1.17.0)
  • v1.17.0(Dec 4, 2022)

    What's Changed

    • Improve typing for internal number generator by @jtraub in https://github.com/starlite-api/pydantic-factories/pull/127
    • add auto registration hook by @avihai-yosef in https://github.com/starlite-api/pydantic-factories/pull/125
    • add support for GenericModel to is_pydantic_model checks.

    New Contributors

    • @avihai-yosef made their first contribution in https://github.com/starlite-api/pydantic-factories/pull/125

    Full Changelog: https://github.com/starlite-api/pydantic-factories/compare/v1.16.0...v1.17.0

    Source code(tar.gz)
    Source code(zip)
  • v1.16.0(Nov 24, 2022)

    What's Changed

    • Fix ranges support in conint by @jtraub in https://github.com/starlite-api/pydantic-factories/pull/114
    • Fixes deprecation warning for sre_parse on 3.11. by @peterschutt in https://github.com/starlite-api/pydantic-factories/pull/117
    • Add checks that given number range is valid by @jtraub in https://github.com/starlite-api/pydantic-factories/pull/119
    • Fix partial kwargs detection for deeply nested models by @jtraub in https://github.com/starlite-api/pydantic-factories/pull/123
    • Drop Python 3.7 support by @jtraub in https://github.com/starlite-api/pydantic-factories/pull/126

    Important

    • This version drops Python 3.7 support.

    Full Changelog: https://github.com/starlite-api/pydantic-factories/compare/v1.15.0...v1.16.0

    Source code(tar.gz)
    Source code(zip)
  • v1.15.0(Nov 7, 2022)

    What's Changed

    • Fix confrozenset by @jtraub in https://github.com/starlite-api/pydantic-factories/pull/109
    • Add NewType support by @jtraub in https://github.com/starlite-api/pydantic-factories/pull/112
    • Add unique_items support for conlist by @jtraub in https://github.com/starlite-api/pydantic-factories/pull/113

    Full Changelog: https://github.com/starlite-api/pydantic-factories/compare/v1.14.1...v1.15.0

    Source code(tar.gz)
    Source code(zip)
  • v1.14.1(Nov 4, 2022)

    What's Changed

    • Fix error when building Pydantic models with nested Dict field by @anthonyh209 in https://github.com/starlite-api/pydantic-factories/pull/107

    New Contributors

    • @anthonyh209 made their first contribution in https://github.com/starlite-api/pydantic-factories/pull/107

    Full Changelog: https://github.com/starlite-api/pydantic-factories/compare/v1.14.0...v1.14.1

    Source code(tar.gz)
    Source code(zip)
  • v1.14.0(Nov 4, 2022)

    What's Changed

    • Update BeanieExtension to support IDs by @gegnew in https://github.com/starlite-api/pydantic-factories/pull/103
    • Replace Xeger with local version by @Goldziher in https://github.com/starlite-api/pydantic-factories/pull/104

    New Contributors

    • @gegnew made their first contribution in https://github.com/starlite-api/pydantic-factories/pull/103

    Full Changelog: https://github.com/starlite-api/pydantic-factories/compare/v1.13.0...v1.14.0

    Source code(tar.gz)
    Source code(zip)
  • v1.13.0(Oct 26, 2022)

    What's Changed

    • Update CHANGELOG order by @ReznikovRoman in https://github.com/starlite-api/pydantic-factories/pull/91
    • Fix doc-string typo in ModelFactory.build by @EltonChou in https://github.com/starlite-api/pydantic-factories/pull/93
    • Add Konstantin Mikhailov as a maintainer by @jtraub in https://github.com/starlite-api/pydantic-factories/pull/95
    • Fix pydantic version not pinned to >= 1.10.0 by @Goldziher in https://github.com/starlite-api/pydantic-factories/pull/98
    • Fix factories not allowing to build when models have fields with similar keys to ModelFactory fields. by @Goldziher in https://github.com/starlite-api/pydantic-factories/pull/99

    New Contributors

    • @ReznikovRoman made their first contribution in https://github.com/starlite-api/pydantic-factories/pull/91
    • @jtraub made their first contribution in https://github.com/starlite-api/pydantic-factories/pull/95
    • @provinzkraut made their first contribution in https://github.com/starlite-api/pydantic-factories/pull/100

    Full Changelog: https://github.com/starlite-api/pydantic-factories/compare/v1.12.0...v1.13.0

    Source code(tar.gz)
    Source code(zip)
  • v1.12.0(Oct 17, 2022)

    What's Changed

    • Add TypeDict support by @Goldziher in https://github.com/starlite-api/pydantic-factories/pull/87

    Full Changelog: https://github.com/starlite-api/pydantic-factories/compare/v1.11.1...v1.12.0

    Source code(tar.gz)
    Source code(zip)
  • v1.11.1(Oct 16, 2022)

  • v1.11.0(Oct 16, 2022)

    What's Changed

    • Add Fixture field by @Goldziher in https://github.com/starlite-api/pydantic-factories/pull/86

    Full Changelog: https://github.com/starlite-api/pydantic-factories/compare/v1.10.0...v1.11.0

    Source code(tar.gz)
    Source code(zip)
  • v1.10.0(Oct 13, 2022)

    What's Changed

    • Add support for ConstrainedDate by @Goldziher in https://github.com/starlite-api/pydantic-factories/pull/83

    Full Changelog: https://github.com/starlite-api/pydantic-factories/compare/v1.9.0...v1.10.0

    Source code(tar.gz)
    Source code(zip)
  • v1.9.0(Oct 9, 2022)

    What's Changed

    • Expose 'get_faker' by @Goldziher in https://github.com/starlite-api/pydantic-factories/pull/81

    Full Changelog: https://github.com/starlite-api/pydantic-factories/compare/v1.8.2...v1.9.0

    Source code(tar.gz)
    Source code(zip)
  • v1.8.2(Oct 8, 2022)

    What's Changed

    • Removes top-level imports of pytest plugin. by @peterschutt in https://github.com/starlite-api/pydantic-factories/pull/78

    New Contributors

    • @peterschutt made their first contribution in https://github.com/starlite-api/pydantic-factories/pull/78

    Full Changelog: https://github.com/starlite-api/pydantic-factories/compare/v1.8.1...v1.8.2

    Source code(tar.gz)
    Source code(zip)
  • v1.8.1(Oct 7, 2022)

    What's Changed

    • Add support for discriminated unions by @Goldziher in https://github.com/Goldziher/pydantic-factories/pull/76

    Full Changelog: https://github.com/Goldziher/pydantic-factories/compare/v1.8.0...v1.8.1

    Source code(tar.gz)
    Source code(zip)
  • v1.8.0(Oct 7, 2022)

    What's Changed

    • Add register_fixture decorator by @EltonChou in https://github.com/Goldziher/pydantic-factories/pull/74

    New Contributors

    • @gigelu made their first contribution in https://github.com/Goldziher/pydantic-factories/pull/73
    • @EltonChou made their first contribution in https://github.com/Goldziher/pydantic-factories/pull/74

    Full Changelog: https://github.com/Goldziher/pydantic-factories/compare/v1.7.1...v1.8.0

    Source code(tar.gz)
    Source code(zip)
  • v1.7.1(Oct 1, 2022)

    What's Changed

    • Fix passing nested dicts with pydantic models as values by @Goldziher in https://github.com/Goldziher/pydantic-factories/pull/72
    • Official python 3.11 support

    Full Changelog: https://github.com/Goldziher/pydantic-factories/compare/v1.7.0...v1.7.1

    Source code(tar.gz)
    Source code(zip)
  • v1.7.0(Sep 28, 2022)

    What's Changed

    • add python 3.11 support by @Goldziher in https://github.com/Goldziher/pydantic-factories/pull/71

    Full Changelog: https://github.com/Goldziher/pydantic-factories/compare/v1.6.2...v1.7.0

    Source code(tar.gz)
    Source code(zip)
  • v1.6.2(Sep 15, 2022)

    What's Changed

    • Issue #68: UUID random-seed by @Goldziher in https://github.com/Goldziher/pydantic-factories/pull/69

    Full Changelog: https://github.com/Goldziher/pydantic-factories/compare/v1.6.1...v1.6.2

    Source code(tar.gz)
    Source code(zip)
  • v1.6.1(Aug 30, 2022)

  • v1.6.0(Aug 27, 2022)

  • v1.5.4(Aug 12, 2022)

    What's Changed

    • Fix decimal validation [Issue #57] by @Goldziher in https://github.com/Goldziher/pydantic-factories/pull/60
    • Fix error when building Pydantic models with Mapping fields [Issue #61] by @phbernardes in https://github.com/Goldziher/pydantic-factories/pull/62

    Full Changelog: https://github.com/Goldziher/pydantic-factories/compare/v1.5.2...v1.5.4

    Source code(tar.gz)
    Source code(zip)
  • v1.5.2(Aug 11, 2022)

    What's Changed

    • Fix error when building with a parameter that is a optional pydantic model [Issue #56] by @phbernardes in https://github.com/Goldziher/pydantic-factories/pull/58

    Full Changelog: https://github.com/Goldziher/pydantic-factories/compare/v1.5.1...v1.5.2

    Source code(tar.gz)
    Source code(zip)
  • v1.5.1(Aug 10, 2022)

    What's Changed

    • Fix error when building with a parameter that is a pydantic model [Issue #53] by @phbernardes in https://github.com/Goldziher/pydantic-factories/pull/54
    • Use TYPE_CHECKING blocks to optimize performance by @Goldziher in https://github.com/Goldziher/pydantic-factories/pull/55

    Full Changelog: https://github.com/Goldziher/pydantic-factories/compare/v1.5.0...v1.5.1

    Source code(tar.gz)
    Source code(zip)
  • v1.5.0(Aug 9, 2022)

    What's Changed

    • Handle partial attributes factory for child factories. by @phbernardes in https://github.com/Goldziher/pydantic-factories/pull/52

    New Contributors

    • @phbernardes made their first contribution in https://github.com/Goldziher/pydantic-factories/pull/52

    Full Changelog: https://github.com/Goldziher/pydantic-factories/compare/v1.4.1...v1.5.0

    Source code(tar.gz)
    Source code(zip)
  • v1.4.1(Jul 25, 2022)

    What's Changed

    • Fix sampling of Literal values

    New Contributors

    • @roeeyn made their first contribution in https://github.com/Goldziher/pydantic-factories/pull/48

    Full Changelog: https://github.com/Goldziher/pydantic-factories/compare/v1.4.0...v1.4.1

    Source code(tar.gz)
    Source code(zip)
  • v1.4.0(Jul 18, 2022)

  • v1.3.0(May 27, 2022)

    What's Changed

    • Feature/post generate by @blagasz in https://github.com/Goldziher/pydantic-factories/pull/42

    Full Changelog: https://github.com/Goldziher/pydantic-factories/compare/v1.2.9...v1.3.0

    Source code(tar.gz)
    Source code(zip)
  • v1.2.9(May 20, 2022)

    What's Changed

    • Update to use pydantic 1.9.1
    • Recognize the allow_population_by_field_name flag by @mrkovalchuk in https://github.com/Goldziher/pydantic-factories/pull/43

    New Contributors

    • @mrkovalchuk made their first contribution in https://github.com/Goldziher/pydantic-factories/pull/43

    Full Changelog: https://github.com/Goldziher/pydantic-factories/compare/v1.2.8...v1.2.9

    Source code(tar.gz)
    Source code(zip)
  • v1.2.8(May 3, 2022)

    • update random seed to affect exrex @blagasz

    What's Changed

    • Use default random instance by @blagasz in https://github.com/Goldziher/pydantic-factories/pull/40

    New Contributors

    • @blagasz made their first contribution in https://github.com/Goldziher/pydantic-factories/pull/40

    Full Changelog: https://github.com/Goldziher/pydantic-factories/compare/v1.2.7...v1.2.8

    Source code(tar.gz)
    Source code(zip)
  • v1.2.7(Mar 29, 2022)

  • v1.2.6(Mar 4, 2022)

Owner
Na'aman Hirschfeld
Full-stack developer with a passion for coding and open source
Na'aman Hirschfeld
Data Version Control or DVC is an open-source tool for data science and machine learning projects

Continuous Machine Learning project integration with DVC Data Version Control or DVC is an open-source tool for data science and machine learning proj

Azaria Gebremichael 2 Jul 29, 2021
Data from "Datamodels: Predicting Predictions with Training Data"

Data from "Datamodels: Predicting Predictions with Training Data" Here we provid

Madry Lab 51 Dec 9, 2022
Python-based implementations of algorithms for learning on imbalanced data.

ND DIAL: Imbalanced Algorithms Minimalist Python-based implementations of algorithms for imbalanced learning. Includes deep and representational learn

DIAL | Notre Dame 220 Dec 13, 2022
A project based example of Data pipelines, ML workflow management, API endpoints and Monitoring.

MLOps template with examples for Data pipelines, ML workflow management, API development and Monitoring.

Utsav 33 Dec 3, 2022
A framework for building (and incrementally growing) graph-based data structures used in hierarchical or DAG-structured clustering and nearest neighbor search

A framework for building (and incrementally growing) graph-based data structures used in hierarchical or DAG-structured clustering and nearest neighbor search

Nicholas Monath 31 Nov 3, 2022
Markov bot - A Writing bot based on Markov Chain for Data Structure Lab

基于马尔可夫链的写作机器人 前端 用html/css完成 Demo展示(已给出文本的相应展示) 用户提供相关的语料库后训练的成果 后端 要完成的几个接口 解析文

DysprosiumDy 9 May 5, 2022
A toolkit for making real world machine learning and data analysis applications in C++

dlib C++ library Dlib is a modern C++ toolkit containing machine learning algorithms and tools for creating complex software in C++ to solve real worl

Davis E. King 11.6k Jan 2, 2023
A library of extension and helper modules for Python's data analysis and machine learning libraries.

Mlxtend (machine learning extensions) is a Python library of useful tools for the day-to-day data science tasks. Sebastian Raschka 2014-2021 Links Doc

Sebastian Raschka 4.2k Dec 29, 2022
A machine learning toolkit dedicated to time-series data

tslearn The machine learning toolkit for time series analysis in Python Section Description Installation Installing the dependencies and tslearn Getti

null 2.3k Jan 5, 2023
Tool for producing high quality forecasts for time series data that has multiple seasonality with linear or non-linear growth.

Prophet: Automatic Forecasting Procedure Prophet is a procedure for forecasting time series data based on an additive model where non-linear trends ar

Facebook 15.4k Jan 7, 2023
A machine learning toolkit dedicated to time-series data

tslearn The machine learning toolkit for time series analysis in Python Section Description Installation Installing the dependencies and tslearn Getti

null 2.3k Dec 29, 2022
STUMPY is a powerful and scalable Python library for computing a Matrix Profile, which can be used for a variety of time series data mining tasks

STUMPY STUMPY is a powerful and scalable library that efficiently computes something called the matrix profile, which can be used for a variety of tim

TD Ameritrade 2.5k Jan 6, 2023
Automatically build ARIMA, SARIMAX, VAR, FB Prophet and XGBoost Models on Time Series data sets with a Single Line of Code. Now updated with Dask to handle millions of rows.

Auto_TS: Auto_TimeSeries Automatically build multiple Time Series models using a Single Line of Code. Now updated with Dask. Auto_timeseries is a comp

AutoViz and Auto_ViML 519 Jan 3, 2023
Visualize classified time series data with interactive Sankey plots in Google Earth Engine

sankee Visualize changes in classified time series data with interactive Sankey plots in Google Earth Engine Contents Description Installation Using P

Aaron Zuspan 76 Dec 15, 2022
Simple, light-weight config handling through python data classes with to/from JSON serialization/deserialization.

Simple but maybe too simple config management through python data classes. We use it for machine learning.

Eren Gölge 67 Nov 29, 2022
Apache Liminal is an end-to-end platform for data engineers & scientists, allowing them to build, train and deploy machine learning models in a robust and agile way

Apache Liminals goal is to operationalise the machine learning process, allowing data scientists to quickly transition from a successful experiment to an automated pipeline of model training, validation, deployment and inference in production. Liminal provides a Domain Specific Language to build ML workflows on top of Apache Airflow.

The Apache Software Foundation 121 Dec 28, 2022
Kats is a toolkit to analyze time series data, a lightweight, easy-to-use, and generalizable framework to perform time series analysis.

Kats, a kit to analyze time series data, a lightweight, easy-to-use, generalizable, and extendable framework to perform time series analysis, from understanding the key statistics and characteristics, detecting change points and anomalies, to forecasting future trends.

Facebook Research 4.1k Dec 29, 2022
Meerkat provides fast and flexible data structures for working with complex machine learning datasets.

Meerkat makes it easier for ML practitioners to interact with high-dimensional, multi-modal data. It provides simple abstractions for data inspection, model evaluation and model training supported by efficient and robust IO under the hood.

Robustness Gym 115 Dec 12, 2022
This machine-learning algorithm takes in data from the last 60 days and tries to predict tomorrow's price of any crypto you ask it.

Crypto-Currency-Predictor This machine-learning algorithm takes in data from the last 60 days and tries to predict tomorrow's price of any crypto you

Hazim Arafa 6 Dec 4, 2022