Skip to content

# `fixtures`

Here's the reference for the fixture registry, enums, and loading utilities.

You can import them directly from `fastapi_toolsets.fixtures`:

    from fastapi_toolsets.fixtures import (
        Context,
        LoadStrategy,
        Fixture,
        FixtureRegistry,
        load_fixtures,
        load_fixtures_by_context,
    )

## `fastapi_toolsets.fixtures.enum.Context`

Bases: `str`, `Enum`

Predefined fixture contexts.

### `BASE = 'base'` `class-attribute` `instance-attribute`

Base fixtures loaded in all environments.

### `DEVELOPMENT = 'development'` `class-attribute` `instance-attribute`

Development fixtures.

### `PRODUCTION = 'production'` `class-attribute` `instance-attribute`

Production-only fixtures.

### `TESTING = 'testing'` `class-attribute` `instance-attribute`

Test fixtures.

## `fastapi_toolsets.fixtures.enum.LoadStrategy`

Bases: `str`, `Enum`

Strategy for loading fixtures into the database.

### `INSERT = 'insert'` `class-attribute` `instance-attribute`

Insert new records. Fails if record already exists.

### `MERGE = 'merge'` `class-attribute` `instance-attribute`

Insert or update based on primary key (SQLAlchemy merge).

### `SKIP_EXISTING = 'skip_existing'` `class-attribute` `instance-attribute`

Insert only if record doesn't exist (based on primary key).

## `fastapi_toolsets.fixtures.registry.Fixture` `dataclass`

A fixture definition with metadata.

## `fastapi_toolsets.fixtures.registry.FixtureRegistry`

Registry for managing fixtures with dependencies.

Example

    from fastapi_toolsets.fixtures import FixtureRegistry, Context

    fixtures = FixtureRegistry()

    @fixtures.register
    def roles():
        return [
            Role(id=1, name="admin"),
            Role(id=2, name="user"),
        ]

    @fixtures.register(depends_on=["roles"])
    def users():
        return [
            User(id=1, username="admin", role_id=1),
        ]

    @fixtures.register(depends_on=["users"], contexts=[Context.TESTING])
    def test_data():
        return [
            Post(id=1, title="Test", user_id=1),
        ]

Fixtures with the same name may be registered for different contexts. When multiple contexts are loaded together, their instances are merged:

    ```python
    @fixtures.register(contexts=[Context.BASE])
    def users():
        return [User(id=1, username="admin")]

    @fixtures.register(contexts=[Context.TESTING])
    def users():
        return [User(id=2, username="tester")]
    ```

### `field(name, attr_name, value, *, field='id')`

Get a single field value from a fixture object matched by an attribute.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`name` | `str` | Fixture name to look up. | required
`attr_name` | `str` | Name of the attribute to match against. | required
`value` | `Any` | Value to match. | required
`field` | `str` | Attribute name to return from the matched object (default: `"id"`). | `'id'`

Returns:

Type | Description
--- | ---
`Any` | The value of `field` on the first matching model instance.

Raises:

Type | Description
--- | ---
`KeyError` | If no fixture named name is registered.
`StopIteration` | If no matching object is found.

### `get(name)`

Get a fixture by name.

Raises:

Type | Description
--- | ---
`KeyError` | If no fixture with name is registered.
`ValueError` | If the fixture has multiple context variants — use :meth:`get_variants` in that case.

### `get_all()`

Get all registered fixtures (all variants of all names).

### `get_by_context(*contexts)`

Get fixtures for specific contexts.

### `get_dependencies(name)`

Get the union of `depends_on` across all variants of name.

Raises:

Type | Description
--- | ---
`KeyError` | If no fixture named name is registered.

### `get_load_variants(name, *contexts)`

Return variants for name filtered by contexts.

Raises:

Type | Description
--- | ---
`KeyError` | If no fixture with name is registered.

### `get_variants(name, *contexts)`

Return all registered variants for name, optionally filtered by context.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`name` | `str` | Fixture name. | required
`*contexts` | `str | Enum` | If given, only return variants whose context set intersects with these values (:class:`Context.BASE` variants are always included). Both :class:`Context` enum values and plain strings are accepted. | `()`

Returns:

Type | Description
--- | ---
`list[Fixture]` | List of matching :class:`Fixture` objects (may be empty when a
`list[Fixture]` | context filter is applied and nothing matches).

Raises:

Type | Description
--- | ---
`KeyError` | If no fixture with name is registered.

### `include_registry(registry)`

Include another `FixtureRegistry` in the same current `FixtureRegistry`.

Fixtures with the same name are allowed as long as their context sets do not overlap. Conflicting contexts raise :class:`ValueError`.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`registry` | `FixtureRegistry` | The `FixtureRegistry` to include | required

Raises:

Type | Description
--- | ---
`ValueError` | If a fixture name already exists with overlapping contexts

Example

    registry = FixtureRegistry()
    dev_registry = FixtureRegistry()

    @dev_registry.register
    def dev_data():
        return [...]

    registry.include_registry(registry=dev_registry)

### `obj(name, attr_name, value)`

Get a model instance from a registered fixture by attribute value.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`name` | `str` | Fixture name to look up. | required
`attr_name` | `str` | Name of the attribute to match against. | required
`value` | `Any` | Value to match. | required

Returns:

Type | Description
--- | ---
`DeclarativeBase` | The first model instance where the attribute matches the given value.

Raises:

Type | Description
--- | ---
`KeyError` | If no fixture named name is registered.
`StopIteration` | If no matching object is found.

### `register(func=None, *, name=None, depends_on=None, contexts=None)`

Register a fixture function.

Can be used as a decorator with or without arguments.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`func` | `Callable[[], Sequence[DeclarativeBase]] | None` | Fixture function returning list of model instances | `None`
`name` | `str | None` | Fixture name (defaults to function name) | `None`
`depends_on` | `list[str] | None` | List of fixture names this depends on | `None`
`contexts` | `list[str | Enum] | None` | List of contexts this fixture belongs to. Both :class:`Context` enum values and plain strings are accepted. | `None`

Example

```python @fixtures.register def roles(): return [Role(id=1, name="admin")]

@fixtures.register(depends_on=["roles"], contexts=[Context.TESTING]) def test_users(): return [User(id=1, username="test", role_id=1)]

### `resolve_context_dependencies(*contexts)`

Resolve all fixtures for contexts with dependencies.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`*contexts` | `str | Enum` | Contexts to load | `()`

Returns:

Type | Description
--- | ---
`list[str]` | List of fixture names in load order

### `resolve_dependencies(*names)`

Resolve fixture dependencies in topological order.

When a fixture name has multiple context variants, the union of all variants' `depends_on` lists is used.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`*names` | `str` | Fixture names to resolve | `()`

Returns:

Type | Description
--- | ---
`list[str]` | List of fixture names in load order (dependencies first)

Raises:

Type | Description
--- | ---
`KeyError` | If a fixture is not found
`ValueError` | If circular dependency detected

## `fastapi_toolsets.fixtures.utils.load_fixtures(session, registry, *names, strategy=LoadStrategy.MERGE)` `async`

Load specific fixtures by name with dependencies.

All context variants of each requested fixture are loaded and merged.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`session` | `AsyncSession` | Database session | required
`registry` | `FixtureRegistry` | Fixture registry | required
`*names` | `str` | Fixture names to load (dependencies auto-resolved) | `()`
`strategy` | `LoadStrategy` | How to handle existing records | `MERGE`

Returns:

Type | Description
--- | ---
`dict[str, list[DeclarativeBase]]` | Dict mapping fixture names to loaded instances

## `fastapi_toolsets.fixtures.utils.load_fixtures_by_context(session, registry, *contexts, strategy=LoadStrategy.MERGE)` `async`

Load all fixtures for specific contexts.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`session` | `AsyncSession` | Database session | required
`registry` | `FixtureRegistry` | Fixture registry | required
`*contexts` | `str | Enum` | Contexts to load (e.g., `Context.TESTING`, or plain strings for custom contexts) | `()`
`strategy` | `LoadStrategy` | How to handle existing records | `MERGE`

Returns:

Type | Description
--- | ---
`dict[str, list[DeclarativeBase]]` | Dict mapping fixture names to loaded instances