Source code for behave_kit.fixtures.registry
"""`@fixture` — register tag-based fixtures with scope and dependencies.
A fixture is a callable ``(context) -> FixtureResult`` where
``FixtureResult`` is either:
- ``None`` — the function performed setup directly, no teardown needed.
- ``(setup_fn, teardown_fn)`` — two callables, both receiving ``context``.
``setup_fn`` is called immediately; ``teardown_fn`` is deferred until
the scope ends.
Fixture names match Behave tags: a scenario tagged ``@database``
triggers the fixture named ``"database"``.
"""
from __future__ import annotations
from collections.abc import Callable
from behave_kit._core.registry import Registry
from behave_kit._core.types import Context, Scope
FixtureSetup = Callable[[Context], None]
FixtureTeardown = Callable[[Context], None]
FixtureResult = tuple[FixtureSetup, FixtureTeardown] | None
FixtureFactory = Callable[[Context], FixtureResult]
_registry: Registry[FixtureFactory] = Registry()
def _normalize_requires(requires: str | list[str] | None) -> list[str]:
if requires is None:
return []
if isinstance(requires, str):
return [requires]
return list(requires)
[docs]
def fixture(
name: str,
scope: Scope = Scope.SCENARIO,
requires: str | list[str] | None = None,
) -> Callable[[FixtureFactory], FixtureFactory]:
"""Register ``func`` as the fixture named ``name``.
:param name: Fixture name (matches a Behave tag).
:param scope: Lifetime of the fixture (scenario or feature).
:param requires: Other fixture names this one depends on.
Accepts a single string or a list of strings.
"""
def decorator(func: FixtureFactory) -> FixtureFactory:
"""Register ``func`` as the fixture named ``name``."""
_registry.register(name, func, scope=scope, requires=_normalize_requires(requires))
return func
return decorator
[docs]
def get_fixture(name: str) -> FixtureFactory:
"""Return the fixture factory registered under ``name``."""
return _registry.get(name)
[docs]
def fixture_names(scope: Scope | None = None) -> list[str]:
"""Return registered fixture names, optionally filtered by ``scope``."""
return _registry.names(scope)
[docs]
def fixture_scope(name: str) -> Scope:
"""Return the scope of the fixture registered under ``name``."""
return _registry.scope_of(name)
[docs]
def resolve_fixture_order(name: str) -> list[str]:
"""Return the dependency chain for ``name`` in setup order."""
return _registry.resolve_dependencies(name)