Spaces:
Sleeping
Sleeping
| """Immutable step context β the single object that flows through every step.""" | |
| from __future__ import annotations | |
| import dataclasses | |
| from dataclasses import dataclass, field | |
| from types import MappingProxyType | |
| from typing import Any, Self | |
| class StepContext: | |
| """Frozen context object passed from step to step. | |
| The pipeline engine only requires ``sample`` and ``metadata``. All | |
| domain-specific fields are added by subclassing β the engine never reads | |
| anything beyond these two fields. | |
| Consuming applications subclass ``StepContext`` to add named fields for | |
| concepts shared across their pipelines. Integration-specific data goes | |
| in ``metadata`` to prevent field accumulation on the subclass. | |
| Steps never mutate the incoming context β they call ``.replace()`` to | |
| produce a new one. | |
| """ | |
| sample: Any = None | |
| metadata: MappingProxyType = field(default_factory=lambda: MappingProxyType({})) | |
| def __post_init__(self) -> None: | |
| # Coerce plain dict β MappingProxyType so mutation is a hard runtime error | |
| if not isinstance(self.metadata, MappingProxyType): | |
| object.__setattr__(self, "metadata", MappingProxyType(self.metadata)) | |
| def replace(self, **changes: Any) -> Self: | |
| """Return a new context with the given fields replaced.""" | |
| return dataclasses.replace(self, **changes) | |