pyfcstm.model.model
Hierarchical state machine model and DSL conversion utilities.
This module provides the core model objects used to represent hierarchical state machines, along with conversion helpers that map between the internal model and the DSL/AST representation. The primary capabilities include:
Defining states, transitions, events, and variable definitions.
Representing entry, during, exit, and aspect-oriented actions.
Parsing a DSL AST into a structured
StateMachine.Exporting models to AST nodes and PlantUML diagrams.
The main public components are:
Operation- Operation assignments used in actions and transitions.Event- Event definitions scoped to a state path.Transition- Transition definitions with optional guards and effects.OnStage- Entry/during/exit actions for a state.OnAspect- Aspect-oriented during actions.State- Hierarchical state container with actions and transitions.VarDefine- Typed variable definitions.StateMachine- Root container for the full state machine.parse_dsl_node_to_state_machine()- DSL AST parsing utility.
Note
The parsing utilities validate state and variable references. Syntax errors are raised when invalid references or structural inconsistencies are found.
Example:
>>> from pyfcstm.dsl import node as dsl_nodes
>>> from pyfcstm.model.model import parse_dsl_node_to_state_machine
>>> program = dsl_nodes.StateMachineDSLProgram(
... definitions=[],
... root_state=dsl_nodes.StateDefinition("root")
... )
>>> sm = parse_dsl_node_to_state_machine(program)
>>> sm.root_state.name
'root'
__all__
- pyfcstm.model.model.__all__ = ['OperationStatement', 'Operation', 'IfBlockBranch', 'IfBlock', 'Event', 'Transition', 'OnStage', 'OnAspect', 'State', 'VarDefine', 'StateMachine', 'parse_dsl_node_to_state_machine']
Built-in mutable sequence.
If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.
OperationStatement
Operation
- class pyfcstm.model.model.Operation(var_name: str, expr: Expr)[source]
Represents an operation that assigns a value to a variable.
An operation consists of a variable name and an expression that will be assigned to the variable when the operation is executed.
- Parameters:
var_name (str) – The name of the variable to assign to
expr (Expr) – The expression to evaluate and assign to the variable
Example:
>>> op = Operation(var_name="counter", expr=some_expr) >>> op.var_name 'counter'
- to_ast_node() OperationAssignment[source]
Convert this operation to an AST node.
- Returns:
An operation assignment AST node
- Return type:
dsl_nodes.OperationAssignment
IfBlockBranch
- class pyfcstm.model.model.IfBlockBranch(condition: Expr | None, statements: List[OperationStatement])[source]
Represents a single branch inside a model-layer
ifblock.- Parameters:
condition (Optional[Expr]) – Branch condition, or
Nonefor the finalelsebranchstatements (List[OperationStatement]) – Statements executed when the branch is selected
- to_ast_node() OperationIfBranch[source]
Convert this branch back to a DSL AST node.
- Returns:
Operation-if branch AST node
- Return type:
dsl_nodes.OperationIfBranch
IfBlock
- class pyfcstm.model.model.IfBlock(branches: List[IfBlockBranch])[source]
Represents an
if / else if / elsestatement in a model operation block.- Parameters:
branches (List[IfBlockBranch]) – Ordered branch list
- to_ast_node() OperationIf[source]
Convert this if-block back to a DSL AST node.
- Returns:
Operation-if AST node
- Return type:
dsl_nodes.OperationIf
Event
- class pyfcstm.model.model.Event(name: str, state_path: Tuple[str, ...], extra_name: str | None = None)[source]
Represents an event that can trigger state transitions.
An event has a name and is associated with a specific state path in the state machine hierarchy.
- Parameters:
name (str) – The name of the event
state_path (Tuple[str, ...]) – The path to the state that owns this event
extra_name (Optional[str]) – Optional extra name for display purposes
Example:
>>> event = Event(name="button_pressed", state_path=("root", "idle")) >>> event.path ('root', 'idle', 'button_pressed')
- property path: Tuple[str, ...]
Get the full path of the event including the state path and event name.
- Returns:
The full path to the event
- Return type:
Tuple[str, …]
- property path_name: str
Get the canonical dot-separated path string for this event.
The returned string serves as the stable identifier used by the runtime for event indexing and transition matching. This format matches the fully-qualified event paths used in the DSL.
Event paths follow the state hierarchy where the event is defined. For example, a local event
Godefined in stateSystem.Activewould have the pathSystem.Active.Go.- Returns:
Dot-separated event path matching the DSL structure
- Return type:
str
Example:
>>> event = Event(name="Start", state_path=("System", "Idle")) >>> event.path_name 'System.Idle.Start'
Note
This property is used internally by
SimulationRuntimewhen building the event dictionary for transition matching. The returned string must be stable and unique within the state machine.
- to_ast_node() EventDefinition[source]
Convert this event to an AST node.
- Returns:
An event definition AST node
- Return type:
dsl_nodes.EventDefinition
Transition
- class pyfcstm.model.model.Transition(from_state: str | _StateSingletonMark, to_state: str | _StateSingletonMark, event: Event | None, guard: Expr | None, effects: List[OperationStatement], parent_ref: ReferenceType | None = None)[source]
Represents a transition between states in a state machine.
A transition defines how the state machine moves from one state to another, potentially triggered by an event, guarded by a condition, and with effects that execute when the transition occurs.
- Parameters:
from_state (Union[str, dsl_nodes._StateSingletonMark]) – The source state name or special state marker
to_state (Union[str, dsl_nodes._StateSingletonMark]) – The target state name or special state marker
event (Optional[Event]) – The event that triggers this transition, if any
guard (Optional[Expr]) – The condition that must be true for the transition to occur, if any
effects (List[OperationStatement]) – Operation statements to execute when the transition occurs
parent_ref (Optional[weakref.ReferenceType]) – Weak reference to the parent state
Example:
>>> transition = Transition( ... from_state="idle", ... to_state="active", ... event=None, ... guard=None, ... effects=[] ... )
- property parent: State | None
Get the parent state of this transition.
- Returns:
The parent state or None if no parent is set
- Return type:
Optional[‘State’]
- property parent: State | None
Get the parent state of this transition.
- Returns:
The parent state or None if no parent is set
- Return type:
Optional[‘State’]
- to_ast_node() TransitionDefinition[source]
Convert this transition to an AST node.
- Returns:
A transition definition AST node
- Return type:
dsl_nodes.TransitionDefinition
OnStage
- class pyfcstm.model.model.OnStage(stage: str, aspect: str | None, name: str | None, doc: str | None, operations: List[OperationStatement], is_abstract: bool, state_path: Tuple[str | None, ...], ref: OnStage | OnAspect | None = None, ref_state_path: Tuple[str, ...] | None = None, parent_ref: ReferenceType | None = None)[source]
Represents an action that occurs during a specific stage of a state’s lifecycle.
OnStage can represent enter, during, or exit actions, and can be either concrete operations or abstract function declarations.
- Parameters:
stage (str) – The lifecycle stage (‘enter’, ‘during’, or ‘exit’)
aspect (Optional[str]) – For ‘during’ actions in composite states, specifies if the action occurs ‘before’ or ‘after’ substates
name (Optional[str]) – For abstract functions, the name of the function
doc (Optional[str]) – For abstract functions, the documentation string
operations (List[OperationStatement]) – For concrete actions, the list of operation statements to execute
is_abstract (bool) – Whether this is an abstract function declaration
state_path (Tuple[Optional[str], ...]) – The path to the state that owns this action
ref (Union['OnStage', 'OnAspect', None]) – Reference to another OnStage or OnAspect for function references
ref_state_path (Optional[Tuple[str, ...]]) – The path to the referenced state for function references
parent_ref (Optional[weakref.ReferenceType]) – Weak reference to the parent state
Example:
>>> on_enter = OnStage( ... stage="enter", ... aspect=None, ... name="init_counter", ... doc=None, ... operations=[], ... is_abstract=False, ... state_path=("root", "init_counter") ... )
- property func_name: str
Get the readable dot-separated path string for this action.
The returned string represents the action’s location in the state hierarchy, making it easy to identify which state owns the action in log messages and diagnostic output.
Unnamed actions (where the name component is
None) are rendered with<unnamed>in the terminal position.- Returns:
Dot-separated action path with state hierarchy
- Return type:
str
Example:
>>> # Named enter action >>> action.func_name 'System.Active.Initialize' >>> # Unnamed during action >>> action.func_name 'System.Active.<unnamed>'
- property is_aspect: bool
Check if this is an aspect-oriented action.
- Returns:
False for OnStage instances (always)
- Return type:
bool
- property is_ref: bool
Check if this action is a reference to another function.
- Returns:
True if this is a reference, False otherwise
- Return type:
bool
- property parent: State | None
Get the parent state of this action.
- Returns:
The parent state or None if no parent is set
- Return type:
Optional[‘State’]
- property parent: State | None
Get the parent state of this action.
- Returns:
The parent state or None if no parent is set
- Return type:
Optional[‘State’]
- to_ast_node() EnterStatement | DuringStatement | ExitStatement[source]
Convert this OnStage to an appropriate AST node based on the stage.
- Returns:
An enter, during, or exit statement AST node
- Return type:
Union[dsl_nodes.EnterStatement, dsl_nodes.DuringStatement, dsl_nodes.ExitStatement]
- Raises:
ValueError – If the stage is not one of ‘enter’, ‘during’, or ‘exit’
OnAspect
- class pyfcstm.model.model.OnAspect(stage: str, aspect: str | None, name: str | None, doc: str | None, operations: List[OperationStatement], is_abstract: bool, state_path: Tuple[str | None, ...], ref: OnStage | OnAspect | None = None, ref_state_path: Tuple[str, ...] | None = None, parent_ref: ReferenceType | None = None)[source]
Represents an aspect-oriented action that occurs during a specific stage of a state’s lifecycle.
OnAspect is specifically used for aspect-oriented programming features in the state machine, allowing actions to be defined that apply across multiple states.
- Parameters:
stage (str) – The lifecycle stage (currently only supports ‘during’)
aspect (Optional[str]) – Specifies if the action occurs ‘before’ or ‘after’ substates
name (Optional[str]) – For abstract functions, the name of the function
doc (Optional[str]) – For abstract functions, the documentation string
operations (List[OperationStatement]) – For concrete actions, the list of operation statements to execute
is_abstract (bool) – Whether this is an abstract function declaration
state_path (Tuple[Optional[str], ...]) – The path to the state that owns this action
ref (Union['OnStage', 'OnAspect', None]) – Reference to another OnStage or OnAspect for function references
ref_state_path (Optional[Tuple[str, ...]]) – The path to the referenced state for function references
parent_ref (Optional[weakref.ReferenceType]) – Weak reference to the parent state
Example:
>>> aspect = OnAspect( ... stage="during", ... aspect="before", ... name="log_entry", ... doc=None, ... operations=[], ... is_abstract=True, ... state_path=("root", "log_entry") ... )
- property func_name: str
Get the readable dot-separated path string for this action.
The returned string represents the action’s location in the state hierarchy, making it easy to identify which state owns the action in log messages and diagnostic output.
Unnamed actions (where the name component is
None) are rendered with<unnamed>in the terminal position.- Returns:
Dot-separated action path with state hierarchy
- Return type:
str
Example:
>>> # Named aspect action >>> action.func_name 'System.PreProcess' >>> # Unnamed aspect action >>> action.func_name 'System.<unnamed>'
- property is_aspect: bool
Check if this is an aspect-oriented action.
- Returns:
True for OnAspect instances (always)
- Return type:
bool
- property is_ref: bool
Check if this action is a reference to another function.
- Returns:
True if this is a reference, False otherwise
- Return type:
bool
- property parent: State | None
Get the parent state of this aspect action.
- Returns:
The parent state or None if no parent is set
- Return type:
Optional[‘State’]
- property parent: State | None
Get the parent state of this aspect action.
- Returns:
The parent state or None if no parent is set
- Return type:
Optional[‘State’]
- to_ast_node() DuringAspectStatement[source]
Convert this OnAspect to an appropriate AST node based on the stage.
- Returns:
A during aspect statement AST node
- Return type:
Union[dsl_nodes.DuringAspectStatement]
- Raises:
ValueError – If the stage is not ‘during’
State
- class pyfcstm.model.model.State(name: str, path: Tuple[str, ...], substates: Dict[str, State], events: Dict[str, Event] | None = None, transitions: List[Transition] | None = None, named_functions: Dict[str, OnStage | OnAspect] | None = None, on_enters: List[OnStage] | None = None, on_durings: List[OnStage] | None = None, on_exits: List[OnStage] | None = None, on_during_aspects: List[OnAspect] | None = None, parent_ref: ReferenceType | None = None, substate_name_to_id: Dict[str, int] | None = None, extra_name: str | None = None, is_pseudo: bool = False)[source]
Represents a state in a hierarchical state machine.
A state can contain substates, transitions between those substates, and actions that execute on enter, during, or exit of the state.
- Parameters:
name (str) – The name of the state
path (Tuple[str, ...]) – The full path to this state in the hierarchy
substates (Dict[str, 'State']) – Dictionary mapping substate names to State objects
events (Dict[str, Event]) – Dictionary mapping event names to Event objects
transitions (List[Transition]) – List of transitions between substates
named_functions (Dict[str, Union[OnStage, OnAspect]]) – Dictionary mapping function names to their implementations
on_enters (List[OnStage]) – List of actions to execute when entering the state
on_durings (List[OnStage]) – List of actions to execute while in the state
on_exits (List[OnStage]) – List of actions to execute when exiting the state
on_during_aspects (List[OnAspect]) – List of aspect-oriented actions for the during stage
parent_ref (Optional[weakref.ReferenceType]) – Weak reference to the parent state
substate_name_to_id (Dict[str, int]) – Dictionary mapping substate names to numeric IDs
extra_name (Optional[str]) – Optional extra name for display purposes
is_pseudo (bool) – Whether this is a pseudo state
Example:
>>> state = State( ... name="idle", ... path=("root", "idle"), ... substates={} ... ) >>> state.is_leaf_state True
- __post_init__() None[source]
Initialize default values for optional fields after instance creation.
- property abstract_on_during_aspects: List[OnAspect]
Get all abstract during aspect actions.
- Returns:
List of abstract during aspect actions
- Return type:
List[OnAspect]
- property abstract_on_durings: List[OnStage]
Get all abstract during actions.
- Returns:
List of abstract during actions
- Return type:
List[OnStage]
- property abstract_on_enters: List[OnStage]
Get all abstract enter actions.
- Returns:
List of abstract enter actions
- Return type:
List[OnStage]
- property abstract_on_exits: List[OnStage]
Get all abstract exit actions.
- Returns:
List of abstract exit actions
- Return type:
List[OnStage]
- property init_transitions: List[Transition]
Get all transitions that start from the initial state (INIT_STATE).
- Returns:
List of transitions from INIT_STATE
- Return type:
List[Transition]
- property is_leaf_state: bool
Check if this state is a leaf state (has no substates).
- Returns:
True if this is a leaf state, False otherwise
- Return type:
bool
- property is_root_state: bool
Check if this state is the root state (has no parent).
- Returns:
True if this is the root state, False otherwise
- Return type:
bool
- property is_stoppable: bool
Check if this state is stoppable (is a leaf state and not pseudo).
- Returns:
True if this state is stoppable, False otherwise
- Return type:
bool
- iter_on_during_after_aspect_recursively(is_abstract: bool | None = None, with_ids: bool = False) Iterator[Tuple[int, State, OnAspect | OnStage] | Tuple[State, OnAspect | OnStage]][source]
Recursively iterate through ‘after’ aspect during actions from this state to the root state.
This method traverses the state hierarchy from this state to the root state, yielding all ‘after’ aspect during actions along the way.
- Parameters:
is_abstract (Optional[bool]) – If provided, filter to only abstract (True) or non-abstract (False) actions
with_ids (bool) – Whether to include numeric IDs with the actions
- Yield:
Tuples of (state, action) or (id, state, action) if with_ids is True
- Return type:
Iterator[Union[Tuple[int, ‘State’, Union[OnAspect, OnStage]], Tuple[‘State’, Union[OnAspect, OnStage]]]]
- iter_on_during_aspect_recursively(is_abstract: bool | None = None, with_ids: bool = False) Iterator[Tuple[int, State, OnAspect | OnStage] | Tuple[State, OnAspect | OnStage]][source]
Recursively iterate through all during actions in the proper execution order.
This method yields actions in the following order:
‘Before’ aspect actions from root state to this state
Regular during actions for this state
‘After’ aspect actions from this state to root state
- Parameters:
is_abstract (Optional[bool]) – If provided, filter to only abstract (True) or non-abstract (False) actions
with_ids (bool) – Whether to include numeric IDs with the actions
- Yield:
Tuples of (state, action) or (id, state, action) if with_ids is True
- Return type:
Iterator[Union[Tuple[int, ‘State’, Union[OnAspect, OnStage]], Tuple[‘State’, Union[OnAspect, OnStage]]]]
- iter_on_during_before_aspect_recursively(is_abstract: bool | None = None, with_ids: bool = False) Iterator[Tuple[int, State, OnAspect | OnStage] | Tuple[State, OnAspect | OnStage]][source]
Recursively iterate through ‘before’ aspect during actions from parent states to this state.
This method traverses the state hierarchy from the root state to this state, yielding all ‘before’ aspect during actions along the way.
- Parameters:
is_abstract (Optional[bool]) – If provided, filter to only abstract (True) or non-abstract (False) actions
with_ids (bool) – Whether to include numeric IDs with the actions
- Yield:
Tuples of (state, action) or (id, state, action) if with_ids is True
- Return type:
Iterator[Union[Tuple[int, ‘State’, Union[OnAspect, OnStage]], Tuple[‘State’, Union[OnAspect, OnStage]]]]
- list_on_during_aspect_recursively(is_abstract: bool | None = None, with_ids: bool = False) List[Tuple[int, State, OnAspect | OnStage] | Tuple[State, OnAspect | OnStage]][source]
Get a list of all during actions in the proper execution order.
This is a convenience method that collects the results of iter_on_during_aspect_recursively.
- Parameters:
is_abstract (Optional[bool]) – If provided, filter to only abstract (True) or non-abstract (False) actions
with_ids (bool) – Whether to include numeric IDs with the actions
- Returns:
List of during actions in execution order
- Return type:
List[Union[Tuple[int, ‘State’, Union[OnAspect, OnStage]], Tuple[‘State’, Union[OnAspect, OnStage]]]]
- list_on_during_aspects(is_abstract: bool | None = None, aspect: str | None = None, with_ids: bool = False) List[Tuple[int, OnAspect] | OnAspect][source]
Get a list of during aspect actions, optionally filtered by abstract status, aspect, and with IDs.
- Parameters:
is_abstract (Optional[bool]) – If provided, filter to only abstract (True) or non-abstract (False) actions
aspect (Optional[str]) – If provided, filter to only actions with the given aspect (‘before’ or ‘after’)
with_ids (bool) – Whether to include numeric IDs with the actions
- Returns:
List of during aspect actions, optionally with IDs
- Return type:
- list_on_durings(is_abstract: bool | None = None, aspect: str | None = None, with_ids: bool = False) List[Tuple[int, OnStage] | OnStage][source]
Get a list of during actions, optionally filtered by abstract status, aspect, and with IDs.
- Parameters:
is_abstract (Optional[bool]) – If provided, filter to only abstract (True) or non-abstract (False) actions
aspect (Optional[str]) – If provided, filter to only actions with the given aspect (‘before’ or ‘after’)
with_ids (bool) – Whether to include numeric IDs with the actions
- Returns:
List of during actions, optionally with IDs
- Return type:
- list_on_enters(is_abstract: bool | None = None, with_ids: bool = False) List[Tuple[int, OnStage] | OnStage][source]
Get a list of enter actions, optionally filtered by abstract status and with IDs.
- list_on_exits(is_abstract: bool | None = None, with_ids: bool = False) List[Tuple[int, OnStage] | OnStage][source]
Get a list of exit actions, optionally filtered by abstract status and with IDs.
- property non_abstract_on_during_aspects: List[OnAspect]
Get all non-abstract during aspect actions.
- Returns:
List of non-abstract during aspect actions
- Return type:
List[OnAspect]
- property non_abstract_on_durings: List[OnStage]
Get all non-abstract during actions.
- Returns:
List of non-abstract during actions
- Return type:
List[OnStage]
- property non_abstract_on_enters: List[OnStage]
Get all non-abstract enter actions.
- Returns:
List of non-abstract enter actions
- Return type:
List[OnStage]
- property non_abstract_on_exits: List[OnStage]
Get all non-abstract exit actions.
- Returns:
List of non-abstract exit actions
- Return type:
List[OnStage]
- property parent: State | None
Get the parent state of this state.
- Returns:
The parent state or None if this is the root state
- Return type:
Optional[‘State’]
- property parent: State | None
Get the parent state of this state.
- Returns:
The parent state or None if this is the root state
- Return type:
Optional[‘State’]
- resolve_event(event_ref: str, *, collect_into: DiagnosticSink | None = None) Event | None[source]
Resolve an event reference string to an existing Event object in the state hierarchy.
This method supports three types of event references:
Relative events (e.g.,
"xxx.yyy.zzz"): Resolved relative to the current state’s path. If the current state isXXX.YYY, the event resolves toXXX.YYY.xxx.yyy.zzz.Parent-relative events (e.g.,
".xxx.yyy.zzz"): Each leading dot represents moving up one level in the state hierarchy. If the current state isXXX.YYY.ZZZ, then.xxxresolves toXXX.YYY.xxx(up one level), and..xxxresolves toXXX.xxx(up two levels).Absolute events (e.g.,
"/xxx.yyy"): Resolved relative to the root state. If the root state isRoot, the event resolves toRoot.xxx.yyy.
- Parameters:
event_ref (str) – The event reference string to resolve
collect_into (pyfcstm.diagnostics.DiagnosticSink, optional) –
Optional structured-diagnostic sink. Behavior depends on which sink mode the caller picked:
None(the default) — raiseModelValueErrororModelLookupErrorimmediately on failure. Both multi-inheritValueError/LookupErrorfor backwards compatibility with existingexcept ValueError:/except LookupError:callers.DiagnosticSink(collect=True)— record the failure as apyfcstm.utils.validate.ModelDiagnosticon the sink and returnNoneinstead of raising. Lets callers accumulate multiple diagnostics across many invocations in a single pass (IDE / agent loop usage).DiagnosticSink(collect=False)(strict sink) — also raise, but route the diagnostic through the sink first so any previously accumulated entries (e.g. warnings) are carried into the raise. The raise still uses the typedModelValueError/ModelLookupErrorsubclass, preserving the legacy catch surface.
- Returns:
The resolved Event object from the state hierarchy, or
Nonewhencollect_intois acollect=Truesink and resolution failed.- Return type:
Optional[Event]
- Raises:
pyfcstm.utils.validate.ModelValueError – If the event reference is syntactically invalid (empty, malformed, exceeds root). Multi-inherits
ValueError. Raised whencollect_intoisNoneor a strict sink.pyfcstm.utils.validate.ModelLookupError – If the event reference parses but the targeted state or event does not exist. Multi-inherits
LookupError. Raised whencollect_intoisNoneor a strict sink.
Example:
>>> # Assuming current state path is ("Root", "System", "Active") >>> # and an event "critical" exists in state "Root.System.Active.error" >>> state.resolve_event("error.critical") Event(name="critical", state_path=("Root", "System", "Active", "error")) >>> state.resolve_event(".error.critical") Event(name="critical", state_path=("Root", "System", "error")) >>> state.resolve_event("/global.shutdown") Event(name="shutdown", state_path=("Root", "global"))
- to_ast_node() StateDefinition[source]
Convert this state to an AST node.
- Returns:
A state definition AST node
- Return type:
dsl_nodes.StateDefinition
- to_plantuml(options: PlantUMLOptions | Literal['minimal', 'normal', 'full'] | None = None, current_depth: int = 0, event_colors: Dict[str, str] | None = None) str[source]
Convert this state to PlantUML notation.
- Parameters:
options (PlantUMLOptionsInput) – Configuration input for PlantUML generation
current_depth (int) – Current depth in the state hierarchy (for max_depth support)
event_colors (Optional[Dict[str, str]]) – Optional mapping of event paths to color codes
- Returns:
PlantUML representation of the state
- Return type:
str
- to_transition_ast_node(transition: Transition) TransitionDefinition[source]
Convert a transition to an AST node in the context of this state.
- Parameters:
transition (Transition) – The transition to convert
- Returns:
A transition definition AST node
- Return type:
dsl_nodes.TransitionDefinition
- classmethod transition_to_ast_node(self: State | None, transition: Transition) TransitionDefinition[source]
Convert a transition to an AST node, considering the context of its parent state.
- Parameters:
self (Optional['State']) – The parent state, or None
transition (Transition) – The transition to convert
- Returns:
A transition definition AST node
- Return type:
dsl_nodes.TransitionDefinition
- property transitions_entering_children: List[Transition]
Get all transitions that start from the initial state (INIT_STATE).
These are the transitions that define the initial substate when entering this state.
- Returns:
List of transitions from INIT_STATE
- Return type:
List[Transition]
- property transitions_entering_children_simplified: List[Transition | None]
Get a simplified list of transitions entering child states.
If there’s a default transition (no event or guard), only include that one. Otherwise include all transitions and add None at the end.
- Returns:
List of transitions, possibly with None at the end
- Return type:
List[Optional[Transition]]
- property transitions_from: List[Transition]
Get all transitions that start from this state.
For non-root states, these are transitions in the parent state where this state is the source. For the root state, a synthetic transition to EXIT_STATE is returned.
- Returns:
List of transitions from this state
- Return type:
List[Transition]
- property transitions_to: List[Transition]
Get all transitions that end at this state.
For non-root states, these are transitions in the parent state where this state is the target. For the root state, a synthetic transition from INIT_STATE is returned.
- Returns:
List of transitions to this state
- Return type:
List[Transition]
VarDefine
- class pyfcstm.model.model.VarDefine(name: str, type: str, init: Expr)[source]
Represents a variable definition in a state machine.
- Parameters:
name (str) – The name of the variable
type (str) – The type of the variable
init (Expr) – The initial value expression
Example:
>>> var_def = VarDefine(name="counter", type="int", init=some_expr) >>> var_def.name 'counter'
- name_ast_node() Name[source]
Convert the variable name to an AST node.
- Returns:
A name AST node
- Return type:
dsl_nodes.Name
- to_ast_node() DefAssignment[source]
Convert this variable definition to an AST node.
- Returns:
A definition assignment AST node
- Return type:
dsl_nodes.DefAssignment
StateMachine
- class pyfcstm.model.model.StateMachine(defines: Dict[str, VarDefine], root_state: State)[source]
Represents a complete state machine with variable definitions and a root state.
- Parameters:
Example:
>>> sm = StateMachine(defines={}, root_state=some_state) >>> list(sm.walk_states()) # Get all states in the machine [...]
- resolve_event(event_path: str, *, collect_into: DiagnosticSink | None = None) Event | None[source]
Resolve a full event path to an existing Event object in the state machine.
This method requires a complete event path in the format
State1.State2.State3.event_name, where the path must include all states from the root to the event location. UnlikeState.resolve_event(), this method does not support relative, parent-relative, or absolute path notations (no leading dots or slashes).- Parameters:
event_path (str) – The complete event path (e.g.,
"Root.System.Active.error")collect_into (pyfcstm.diagnostics.DiagnosticSink, optional) –
Optional structured-diagnostic sink. Behavior depends on the sink mode (see
State.resolve_event()for the full matrix):None— raiseModelValueError/ModelLookupErrorimmediately.DiagnosticSink(collect=True)— accumulate on the sink and returnNone.DiagnosticSink(collect=False)(strict) — also raise the typed subclass, but route through the sink first so any previously accumulated entries are preserved into the raise.
- Returns:
The resolved Event object, or
Nonewhencollect_intois acollect=Truesink and resolution failed.- Return type:
Optional[Event]
- Raises:
pyfcstm.utils.validate.ModelValueError – If the event path is invalid or empty (multi-inherits
ValueError). Raised whencollect_intoisNoneor strict.pyfcstm.utils.validate.ModelLookupError – If any state in the path or the event does not exist (multi-inherits
LookupError). Raised whencollect_intoisNoneor strict.
Example:
>>> # Assuming a state machine with Root -> System -> Active -> error event >>> sm = StateMachine(defines={}, root_state=root_state) >>> event = sm.resolve_event("Root.System.Active.error") >>> event.name 'error'
- to_ast_node() StateMachineDSLProgram[source]
Convert this state machine to an AST node.
- Returns:
A state machine DSL program AST node
- Return type:
dsl_nodes.StateMachineDSLProgram
- to_plantuml(options: PlantUMLOptions | Literal['minimal', 'normal', 'full'] | None = None) str[source]
Convert this state machine to PlantUML notation.
- Parameters:
options (PlantUMLOptionsInput) – Configuration input for PlantUML generation
- Returns:
PlantUML representation of the state machine
- Return type:
str
parse_dsl_node_to_state_machine
- pyfcstm.model.model.parse_dsl_node_to_state_machine(dnode: StateMachineDSLProgram, path: str | None = None, *, collect: bool = False) StateMachine | Tuple[StateMachine | None, List[ModelDiagnostic]][source]
Parse a state machine DSL program AST node into a StateMachine object.
This function validates the state machine structure and builds a complete StateMachine object with all states, transitions, events, and variable definitions.
The implementation routes every semantic error through a
pyfcstm.diagnostics.DiagnosticSink. In the default strict mode (collect=False), the first error raisespyfcstm.utils.validate.ModelValidationErrorcarrying apyfcstm.utils.validate.ModelDiagnosticlist. In collect mode (collect=True), all detected errors are accumulated and returned alongside the partially-built model (which may beNoneif construction could not progress past a fatal point).The
ModelValidationErrorexception multi-inherits fromSyntaxError, so callers usingexcept SyntaxError:continue to work after this refactor.- Parameters:
dnode (dsl_nodes.StateMachineDSLProgram) – The state machine DSL program AST node to parse
path (Optional[str]) – Optional path contract reserved for import-aware assembly. When provided, the value defines the current DSL location for import resolution. When omitted, the current working directory is used. Existing directories are treated as import base directories directly, while file paths use their parent directory as the import base.
collect (bool) – When
True, return(model_or_None, diagnostics)instead of raising on the first error. Defaults toFalse.
- Returns:
The parsed state machine, or a
(model, diagnostics)tuple whencollect=True.- Return type:
Union[StateMachine, Tuple[Optional[StateMachine], List[ModelDiagnostic]]]
- Raises:
pyfcstm.utils.validate.ModelValidationError – When
collect=Falseand the DSL contains a semantic error. Multi-inherits fromSyntaxErrorfor backwards compatibility.
Example:
>>> # Assuming you have a parsed DSL node >>> state_machine = parse_dsl_node_to_state_machine( ... dsl_program_node, ... path="root.fcstm", ... ) >>> state_machine.root_state.name 'root'