pyfcstm.simulate.context

Read-only execution context for abstract function handlers.

This module provides the ReadOnlyExecutionContext class that gives abstract function handlers read-only access to the current execution state including the active state path and variable values.

The module contains the following main components:

Example:

>>> from pyfcstm.simulate import ReadOnlyExecutionContext
>>> def my_handler(ctx: ReadOnlyExecutionContext):
...     print(f"State: {ctx.get_full_state_path()}")
...     print(f"Counter: {ctx.get_var('counter')}")

ReadOnlyExecutionContext

class pyfcstm.simulate.context.ReadOnlyExecutionContext(state_path: Tuple[str, ...], vars: Mapping[str, int | float], action_name: str, action_stage: str, active_leaf: Tuple[str, ...] | None = None, call_stage: str | None = None, abstract_target: str | None = None, named_ref: str | None = None)[source]

Read-only execution context for abstract function handlers.

Provides immutable access to current state and variable values without allowing modifications. This context is passed to registered abstract handlers during execution. The existing state_path, action_name, and action_stage fields keep their public meaning, and the additional metadata fields expose the same callsite information in a fixture-friendly shape.

Parameters:
  • state_path (Tuple[str, ...]) – Current execution state path from root to leaf. For ancestor aspect actions this is the active descendant leaf.

  • vars (Mapping[str, Union[int, float]]) – Snapshot of current variable values (immutable mapping copy)

  • action_name (str) – Full path name of the resolved abstract action target.

  • action_stage (str) – Lifecycle stage at the current callsite ('enter', 'during', or 'exit').

  • active_leaf (Tuple[str, ...], optional) – Current active leaf state path. When omitted, it defaults to state_path.

  • call_stage (str, optional) – Explicit callsite lifecycle stage. When omitted, it defaults to action_stage.

  • abstract_target (str, optional) – Explicit resolved abstract target path. When omitted, it defaults to action_name.

  • named_ref (Optional[str], optional) – Full path of the named ref callsite, or None when the action was not invoked through a named reference.

Example:

>>> ctx = ReadOnlyExecutionContext(
...     state_path=('System', 'Active'),
...     vars={'counter': 10, 'temperature': 25.5},
...     action_name='System.Active.Monitor',
...     action_stage='during'
... )
>>> ctx.get_state_name()
'Active'
>>> ctx.get_var('counter')
10
>>> ctx.active_leaf
('System', 'Active')
>>> ctx.abstract_target
'System.Active.Monitor'
__post_init__() None[source]

Freeze and normalize the context snapshot.

Variable mappings are copied into a read-only proxy. Path-like metadata is normalized to tuples, and optional callsite aliases are derived from the existing four constructor fields when omitted. This preserves the original direct-construction API while exposing richer metadata to runtime-created handler contexts.

Returns:

None.

Return type:

None

Example:

>>> ctx = ReadOnlyExecutionContext(
...     state_path=('Root', 'A'),
...     vars={},
...     action_name='Root.A.Touch',
...     action_stage='during',
... )
>>> ctx.call_stage
'during'
>>> ctx.named_ref is None
True
get_full_state_path() str[source]

Get full state path as dot-separated string.

Returns:

Full state path

Return type:

str

Example:

>>> ctx.get_full_state_path()
'System.Active'
get_state_name() str[source]

Get current state name (last component of path).

Returns:

State name, or empty string if no state is active

Return type:

str

Example:

>>> ctx.get_state_name()
'Active'
get_var(name: str) int | float[source]

Get variable value by name.

Parameters:

name (str) – Variable name

Returns:

Variable value

Return type:

Union[int, float]

Raises:

KeyError – If variable does not exist

Example:

>>> ctx.get_var('counter')
10
has_var(name: str) bool[source]

Check if a variable exists.

Parameters:

name (str) – Variable name

Returns:

True if variable exists

Return type:

bool

Example:

>>> ctx.has_var('counter')
True
>>> ctx.has_var('nonexistent')
False