Skip to content

Generators#

Generators are at the core of the generators submodule's business logic. They are responsible for generating expectations based on the values object and the given definition.

Each generator must adhere to the following protocol:

Python
class GeneratorProtocol(Protocol):
    """
    Generates expectation from a given object according to a definition.
    """

    definition: Any
    generator_factory: 'type[GeneratorFactoryProtocol]'

    def __init__(
        self,
        generator_factory: 'type[GeneratorFactoryProtocol]',
        definition: Any,  # noqa: ANN401
    ) -> None: ...

    @classmethod
    def matches(cls, definition: Any) -> bool:  # noqa: ANN401
        """
        Determines whether the provided definition can be handled by this generator.

        :param definition: the definition to be tested
        """

    def generate_expectation(self, object_: Any) -> Any:  # noqa: ANN401
        """
        Generates an expectation from the given object.

        :param object_: the object from which to generate an expectation
        """

Generator Factories#

When generating expectations, generators are created from definitions using factories. The factory maintains an ordered sequence of generator classes. When creating a generator for a specific definition, the factory iterates over the classes and uses the first one for which the matches method returns True.

The module provides a BuiltInGeneratorFactory that includes all out-of-the-box generators. Additionally, there is a blank factory called GeneratorFactory that does not have any generators registered.

To add a generator to the factory, use the register_generator class method with the following signature:

Python
1
2
3
4
5
6
def register_generator(
    generator: type[GeneratorProtocol],
    *,
    after: type[GeneratorProtocol] | None = None,
    before: type[GeneratorProtocol] | None = None,
) -> None:

The generator is registered at the earliest possible position. If after and before parameters are not set, it is added to the beginning of the list to be matched when creating a generator for a definition. The after and before parameters allow you to specify constraints on the generator's position.

When creating a subclass of a factory, it initially uses the same generators collection as its base class. However, once the first generator is registered, the collection from the base class is copied before adding new generators.