# Declaring Factories

Defining factories is done using a declarative syntax. That is - users declare factory classes, which are subclasses of base factories.

Declaring a factory for a dataclass

    from dataclasses import dataclass

    from polyfactory.factories import DataclassFactory

    @dataclass
    class Person:
        name: str
        age: float
        height: float
        weight: float

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

    def test_is_person() -> None:
        person_instance = PersonFactory.build()
        assert isinstance(person_instance, Person)
        assert isinstance(person_instance.name, str)
        assert isinstance(person_instance.age, float)
        assert isinstance(person_instance.height, float)
        assert isinstance(person_instance.weight, float)

You can also specify the model type by only specifying the factory generic type parameter.

    @dataclass
    class Person:
        name: str
        age: float
        height: float
        weight: float

    class PersonFactory(DataclassFactory[Person]):
        ...

Note

The syntax with the `__model__` class attribute omitting is only available since version 2.13.0.

The same applies to the other factories exported by this library, for example:

Declaring a factory for a typed-dict

    from typing import TypedDict

    from polyfactory.factories import TypedDictFactory

    class Person(TypedDict):
        name: str
        age: float
        height: float
        weight: float

    class PersonFactory(TypedDictFactory[Person]): ...

    def test_is_person() -> None:
        person_instance = PersonFactory.build()
        assert isinstance(person_instance, dict)
        assert isinstance(person_instance.get("name"), str)
        assert isinstance(person_instance.get("age"), float)
        assert isinstance(person_instance.get("height"), float)
        assert isinstance(person_instance.get("weight"), float)

Or for pydantic models:

Declaring a factory for a pydantic model

    from pydantic import BaseModel

    from polyfactory.factories.pydantic_factory import ModelFactory

    class Person(BaseModel):
        name: str
        age: float
        height: float
        weight: float

    class PersonFactory(ModelFactory[Person]): ...

    def test_is_person() -> None:
        person_instance = PersonFactory.build()
        assert isinstance(person_instance, Person)
        assert isinstance(person_instance.name, str)
        assert isinstance(person_instance.age, float)
        assert isinstance(person_instance.height, float)
        assert isinstance(person_instance.weight, float)

Note

You can also define factories for any 3rd party implementation of dataclasses, as long as it fulfills the stdlib dataclasses interface. For example, this is using the pydantic `@dataclass` decorator:

Declaring a factory for a pydantic dataclass

    from pydantic.dataclasses import dataclass

    from polyfactory.factories import DataclassFactory

    @dataclass
    class Person:
        name: str
        age: float
        height: float
        weight: float

    class PersonFactory(DataclassFactory[Person]): ...

    def test_is_person() -> None:
        person_instance = PersonFactory.build()
        assert isinstance(person_instance, Person)
        assert isinstance(person_instance.name, str)
        assert isinstance(person_instance.age, float)
        assert isinstance(person_instance.height, float)
        assert isinstance(person_instance.weight, float)

Or for attrs models:

Declaring a factory for a attrs model

    from datetime import date, datetime
    from typing import Any, Dict, List, Union
    from uuid import UUID

    import attrs

    from polyfactory.factories.attrs_factory import AttrsFactory

    @attrs.define
    class Person:
        id: UUID
        name: str
        hobbies: List[str]
        age: Union[float, int]
        # an aliased variable
        birthday: Union[datetime, date] = attrs.field(alias="date_of_birth")
        # a "private" variable
        _assets: List[Dict[str, Dict[str, Any]]]

    class PersonFactory(AttrsFactory[Person]): ...

    def test_person_factory() -> None:
        person = PersonFactory.build()

        assert isinstance(person, Person)

Note

Validators are not currently supported - neither the built in validators that come with attrs nor custom validators.

## Imperative Factory Creation

Although the definition of factories is primarily meant to be done declaratively, factories expose the `create_factory` method. This method is used internally inside factories to dynamically create factories for models. For example, below the `PersonFactory` will dynamically create a `PetFactory`:

Dynamic factory generation

    from dataclasses import dataclass
    from datetime import date, datetime
    from enum import Enum
    from typing import Any, Dict, List, Union
    from uuid import UUID

    from polyfactory.factories import DataclassFactory

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

    @dataclass
    class Pet:
        name: str
        species: Species
        sound: str

    @dataclass
    class Person:
        id: UUID
        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(DataclassFactory[Person]): ...

    def test_dynamic_factory_generation() -> None:
        person_instance = PersonFactory.build()
        assert len(person_instance.pets) > 0
        assert isinstance(person_instance.pets[0], Pet)

You can also use this method to create factories imperatively:

Imperative factory creation

    from dataclasses import dataclass
    from enum import Enum

    from polyfactory.factories import DataclassFactory

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

    @dataclass
    class Pet:
        name: str
        species: Species
        sound: str

    def test_imperative_factory_creation() -> None:
        pet_factory = DataclassFactory.create_factory(model=Pet)
        pet_instance = pet_factory.build()
        assert isinstance(pet_instance, Pet)

Eventually you can use this method on an existing concrete factory to create a sub factory overriding some parent configuration:

Imperative sub factory creation

    from dataclasses import dataclass
    from enum import Enum

    from polyfactory.factories import DataclassFactory

    class Species(str, Enum):
        CAT = "Cat"
        DOG = "Dog"
        RABBIT = "Rabbit"
        MOUSE = "Mouse"

    @dataclass
    class Pet:
        name: str
        species: Species
        sound: str

    def test_imperative_sub_factory_creation() -> None:
        pet_factory = DataclassFactory.create_factory(model=Pet)
        cat_factory = pet_factory.create_factory(species=Species.CAT)
        cat_instance = cat_factory.build()

        assert isinstance(cat_instance, Pet)
        assert cat_instance.species == Species.CAT

In this case you don’t need to specify the model argument to the `create_factory` method. The one from the parent factory will be used.