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,
get_obj_by_attr,
)
fastapi_toolsets.fixtures.enum.Context
¶
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
¶
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")]
# load_fixtures_by_context(..., Context.BASE, Context.TESTING)
# → loads both User(admin) and User(tester) under the "users" name
```
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_all()
¶
Get all registered fixtures (all variants of all names).
get_by_context(*contexts)
¶
Get fixtures for specific contexts.
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. Both :class: |
()
|
Returns:
| Type | Description |
|---|---|
list[Fixture]
|
List of matching :class: |
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 |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If a fixture name already exists with overlapping contexts |
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: |
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_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., |
()
|
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.get_obj_by_attr(fixtures, attr_name, value)
¶
Get a SQLAlchemy model instance by matching an attribute value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fixtures
|
Callable[[], Sequence[ModelType]]
|
A fixture function registered via |
required |
attr_name
|
str
|
Name of the attribute to match against. |
required |
value
|
Any
|
Value to match. |
required |
Returns:
| Type | Description |
|---|---|
ModelType
|
The first model instance where the attribute matches the given value. |
Raises:
| Type | Description |
|---|---|
StopIteration
|
If no matching object is found in the fixture group. |