Source code for steplib.core.decorators

"""The ``@step`` decorator and related helpers.

The decorator stores ``StepInfo`` metadata on the decorated function. When
multiple decorators are stacked on the same function, each call appends a
new ``StepInfo`` entry to ``fn.__steplib_steps__``.
"""

from __future__ import annotations

from collections.abc import Callable
from typing import Any

from steplib.core.metadata import StepInfo
from steplib.core.params import Param

# Attribute name used to store step metadata on decorated functions.
_STEPLIB_ATTR = "__steplib_steps__"


[docs] def step( pattern: str, *, category: str, backend: str | None = None, description: str | None = None, parameters: list[Param] | None = None, example: str | None = None, tags: list[str] | None = None, version: str | None = None, deprecated: bool | str = False, i18n: dict[str, str] | None = None, requires: list[str] | None = None, ) -> Callable[[Callable[..., Any]], Callable[..., Any]]: """Attach ``StepInfo`` metadata to a step function. Can be stacked to register multiple patterns (e.g. for i18n or alternative backends) on the same implementation function. Args: pattern: The behave matching pattern (e.g. ``"I send a {method} request to {url}"``). category: Module/domain category (e.g. ``"api"``, ``"web"``). backend: Underlying technology (e.g. ``"httpx"``, ``"requests"``). description: Human-readable description; defaults to the function docstring. parameters: Typed parameter descriptors. example: Example usage in Gherkin. tags: Tags for grouping/filtering in the CLI. version: Semver of the step. deprecated: ``True``, a deprecation message, or ``False``. i18n: Translations of the pattern keyed by language code. requires: Context attributes the step needs (e.g. ``["steplib.api.client"]``). Returns: A decorator that records the metadata and returns the function unchanged. """ def decorator(fn: Callable[..., Any]) -> Callable[..., Any]: info = StepInfo( pattern=pattern, category=category, func=fn, backend=backend, description=description or fn.__doc__, parameters=parameters or [], example=example, tags=tags or [], version=version, deprecated=deprecated, i18n=i18n or {}, requires=requires or [], ) existing: list[StepInfo] = getattr(fn, _STEPLIB_ATTR, []) # Create a new list to avoid mutating a shared parent list. new_list = list(existing) new_list.append(info) setattr(fn, _STEPLIB_ATTR, new_list) return fn return decorator
[docs] def get_step_infos(fn: Callable[..., Any]) -> list[StepInfo]: """Return all ``StepInfo`` entries attached to a decorated function. Args: fn: A function decorated with ``@step``. Returns: A list of ``StepInfo`` objects (empty if the function is not a steplib step). """ return list(getattr(fn, _STEPLIB_ATTR, []))