pyfcstm.model.plantuml
PlantUML generation configuration and options.
This module provides configuration classes for controlling PlantUML diagram generation
from state machine models. The main class PlantUMLOptions allows fine-grained
control over what elements are displayed in the generated diagrams.
The configuration system uses a hierarchical fallback mechanism:
User-specified values (non-None)
Parent configuration values (e.g., show_lifecycle_actions)
detail_level preset values
Final fallback defaults
The main public components are:
DetailLevelLiteral- Literal type for preset detail levelsPlantUMLOptions- Configuration class for PlantUML generationformat_state_name()- Format state names according to configurationformat_event_name()- Format event names according to configuration
Example:
>>> from pyfcstm.model.plantuml import PlantUMLOptions
>>> options = PlantUMLOptions(
... detail_level='normal',
... show_lifecycle_actions=True,
... )
>>> config = options.to_config()
>>> config.show_enter_actions # True (inherited from show_lifecycle_actions)
__all__
- pyfcstm.model.plantuml.__all__ = ['DetailLevelLiteral', 'PlantUMLOptionsInput', 'PlantUMLOptions', 'format_state_name', 'format_event_name', 'escape_plantuml_table_cell', 'should_show_action', 'format_action_text', 'collect_event_transitions', 'assign_event_colors']
Built-in mutable sequence.
If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.
DetailLevelLiteral
- pyfcstm.model.plantuml.DetailLevelLiteral
alias of
Literal[‘minimal’, ‘normal’, ‘full’]
PlantUMLOptionsInput
- pyfcstm.model.plantuml.PlantUMLOptionsInput
alias of
PlantUMLOptions|Literal[‘minimal’, ‘normal’, ‘full’] |None
PlantUMLOptions
- class pyfcstm.model.plantuml.PlantUMLOptions(detail_level: Literal['minimal', 'normal', 'full'] = 'normal', show_variable_definitions: bool | None = None, variable_display_mode: Literal['note', 'legend', 'hide'] = 'legend', variable_legend_position: Literal['top left', 'top center', 'top right', 'bottom left', 'bottom center', 'bottom right', 'left', 'right', 'center'] = 'top left', state_name_format: Tuple[Literal['name', 'extra_name', 'path'], ...] = ('extra_name',), show_pseudo_state_style: bool | None = None, collapse_empty_states: bool = False, show_lifecycle_actions: bool | None = None, show_enter_actions: bool | None = None, show_during_actions: bool | None = None, show_exit_actions: bool | None = None, show_aspect_actions: bool | None = None, show_abstract_actions: bool | None = None, show_concrete_actions: bool | None = None, abstract_action_marker: Literal['text', 'symbol', 'none'] = 'text', max_action_lines: int | None = None, show_transition_guards: bool | None = None, show_transition_effects: bool | None = None, transition_effect_mode: Literal['note', 'inline', 'hide'] = 'note', show_events: bool | None = None, event_name_format: Tuple[Literal['name', 'extra_name', 'path', 'relpath'], ...] = ('extra_name', 'relpath'), event_visualization_mode: Literal['none', 'color', 'legend', 'both', 'dependency_view'] = 'none', event_legend_position: Literal['top left', 'top center', 'top right', 'bottom left', 'bottom center', 'bottom right', 'left', 'right', 'center'] = 'right', max_depth: int | None = None, collapsed_state_marker: str = '...', use_skinparam: bool = True, use_stereotypes: bool = True, custom_colors: dict | None = None)[source]
Configuration options for PlantUML diagram generation.
This class provides fine-grained control over what elements are displayed in generated PlantUML diagrams. It supports two usage modes:
Quick mode: Use
detail_levelpresets ('minimal','normal','full')Fine-grained mode: Configure individual options explicitly
Configuration Inheritance
The configuration system uses a hierarchical fallback mechanism:
User-specified values (non-None parameters)
Parent configuration values (e.g.,
show_lifecycle_actionscontrols child options)detail_levelpreset valuesFinal fallback defaults
Inheritance relationships:
show_enter_actions,show_during_actions,show_exit_actions,show_aspect_actionsinherit fromshow_lifecycle_actionsshow_abstract_actions,show_concrete_actionsinherit fromshow_lifecycle_actionsshow_transition_guards,show_transition_effectsare independently configurable
Detail Level Presets
minimal: Clean diagrams focusing on structure
Shows: variable definitions (legend), transition guards, transition effects, events
Hides: lifecycle actions, pseudo state styling
normal (default): Balanced view for typical use cases
Shows: variable definitions (legend), transition guards, transition effects, events, pseudo state styling
Hides: lifecycle actions
full: Complete information for detailed analysis
Shows: everything including variable definitions (legend) and lifecycle actions
Parameters
- detail_levelDetailLevelLiteral, default=’normal’
Preset detail level. One of
'minimal','normal', or'full'.Example:
>>> PlantUMLOptions(detail_level='minimal') # Clean structure view >>> PlantUMLOptions(detail_level='full') # Show all details
- show_variable_definitionsOptional[bool], default=None
Whether to display variable definitions in the diagram.
True: Show variable definitions as note or legendFalse: Hide variable definitionsNone: Usedetail_levelpreset (True for all levels)
Example:
>>> # Show variables in a note block >>> PlantUMLOptions(show_variable_definitions=True, variable_display_mode='note') >>> # Output: note as DefinitionNote >>> # defines { >>> # def int counter = 0; >>> # } >>> # end note
- variable_display_modeLiteral[‘note’, ‘legend’, ‘hide’], default=’legend’
How to display variable definitions when
show_variable_definitions=True.'note': Display as a floating note block'legend': Display as a legend table (more compact)'hide': Don’t display (same asshow_variable_definitions=False)
Example:
>>> # Legend format (compact table) >>> PlantUMLOptions(show_variable_definitions=True, variable_display_mode='legend') >>> # Output: legend top left >>> # |= Variable |= Type |= Initial Value | >>> # | counter | int | 0 | >>> # endlegend
- variable_legend_positionLiteral[‘top left’, ‘top center’, ‘top right’, ‘bottom left’, ‘bottom center’, ‘bottom right’, ‘left’, ‘right’, ‘center’], default=’top left’
Position of the variable legend when
variable_display_mode='legend'.'top left': Legend at top-left corner (default)'top center': Legend at top-center'top right': Legend at top-right corner'bottom left': Legend at bottom-left corner'bottom center': Legend at bottom-center'bottom right': Legend at bottom-right corner'left': Legend on the left side'right': Legend on the right side'center': Legend in the center
Example:
>>> # Place legend at top-left (default) >>> PlantUMLOptions(variable_display_mode='legend', variable_legend_position='top left') >>> # Output: legend top left >>> # |= Variable |= Type |= Initial Value | >>> # endlegend >>> # Place legend at bottom-right >>> PlantUMLOptions(variable_display_mode='legend', variable_legend_position='bottom right') >>> # Output: legend bottom right >>> # |= Variable |= Type |= Initial Value | >>> # endlegend
- state_name_formatTuple[Literal[‘name’, ‘extra_name’, ‘path’], …], default=(‘extra_name’,)
Tuple of display elements for state names. Elements are combined with the first as the main display and others in parentheses.
'name': State identifier (e.g.,'Running')'extra_name': Localized/display name (e.g.,'运行中')'path': Full hierarchical path (e.g.,'System.Module.Running')
Example:
>>> # Show only extra_name (default) >>> PlantUMLOptions(state_name_format=('extra_name',)) >>> # Output: state "运行中" as running >>> # Show extra_name with name in parentheses >>> PlantUMLOptions(state_name_format=('extra_name', 'name')) >>> # Output: state "运行中 (Running)" as running >>> # Show name with full path >>> PlantUMLOptions(state_name_format=('name', 'path')) >>> # Output: state "Running (System.Module.Running)" as system__module__running
- show_pseudo_state_styleOptional[bool], default=None
Whether to apply visual styling to pseudo states (dotted border).
True: Pseudo states shown with#line.dottedstyleFalse: Pseudo states shown without special stylingNone: Usedetail_levelpreset (False for minimal, True for normal/full)
Example:
>>> PlantUMLOptions(show_pseudo_state_style=True) >>> # Output: state "PseudoState" as pseudo_state <<pseudo>> #line.dotted
- collapse_empty_statesbool, default=False
Whether to hide action text for states with no lifecycle actions.
True: Empty states don’t show action text (cleaner diagrams)False: All states show their structure
Example:
>>> # With collapse_empty_states=True, empty states are more compact >>> PlantUMLOptions(collapse_empty_states=True) >>> # State with no actions: state "EmptyState" as empty_state >>> # (no "EmptyState :" line)
- show_lifecycle_actionsOptional[bool], default=None
Master switch for all lifecycle actions (enter/during/exit/aspect).
True: Show all lifecycle actions (unless overridden by specific options)False: Hide all lifecycle actionsNone: Usedetail_levelpreset (False for minimal/normal, True for full)
This option controls the default for
show_enter_actions,show_during_actions,show_exit_actions,show_aspect_actions,show_abstract_actions, andshow_concrete_actions.Example:
>>> # Show all lifecycle actions >>> PlantUMLOptions(show_lifecycle_actions=True) >>> # Output: state "Active" as active >>> # active : enter {\n counter = 0;\n}\nduring {\n counter++;\n}
- show_enter_actionsOptional[bool], default=None
Whether to show enter actions. Inherits from
show_lifecycle_actionsif None.Example:
>>> # Show only enter actions, hide others >>> PlantUMLOptions(show_lifecycle_actions=False, show_enter_actions=True)
- show_during_actionsOptional[bool], default=None
Whether to show during actions. Inherits from
show_lifecycle_actionsif None.- show_exit_actionsOptional[bool], default=None
Whether to show exit actions. Inherits from
show_lifecycle_actionsif None.- show_aspect_actionsOptional[bool], default=None
Whether to show aspect actions (
>> during before/after). Inherits fromshow_lifecycle_actionsif None.Example:
>>> # Show aspect actions for cross-cutting concerns >>> PlantUMLOptions(show_lifecycle_actions=True, show_aspect_actions=True) >>> # Output: state : >> during before abstract GlobalMonitor;
- show_abstract_actionsOptional[bool], default=None
Whether to show abstract actions (actions without implementation). Inherits from
show_lifecycle_actionsif None.Example:
>>> # Show only abstract actions (API surface) >>> PlantUMLOptions(show_lifecycle_actions=True, ... show_abstract_actions=True, ... show_concrete_actions=False) >>> # Output: state : enter abstract InitHardware;
- show_concrete_actionsOptional[bool], default=None
Whether to show concrete actions (actions with implementation). Inherits from
show_lifecycle_actionsif None.Example:
>>> # Show only concrete actions (implementation details) >>> PlantUMLOptions(show_lifecycle_actions=True, ... show_abstract_actions=False, ... show_concrete_actions=True) >>> # Output: state : enter {\n counter = 0;\n}
- abstract_action_markerLiteral[‘text’, ‘symbol’, ‘none’], default=’text’
How to mark abstract actions when displayed.
'text': Useabstractkeyword (e.g.,enter abstract Init)'symbol': Use guillemet markers (e.g.,enter «abstract» Init)'none': No marker (e.g.,enter Init)
Example:
>>> PlantUMLOptions(show_lifecycle_actions=True, abstract_action_marker='symbol') >>> # Output: state : enter «abstract» InitHardware;
- max_action_linesOptional[int], default=None
Maximum number of lines to display per action. Lines beyond this limit are truncated with
...ellipsis.None: No limit (show all lines)> 0: Limit to specified number of lines
Example:
>>> # Limit actions to 3 lines for compact diagrams >>> PlantUMLOptions(show_lifecycle_actions=True, max_action_lines=3) >>> # Output: state : enter {\n a = 1;\n b = 2;\n...
- show_transition_guardsOptional[bool], default=None
Whether to show guard conditions on transitions.
True: Show guard conditions (e.g.,StateA -> StateB : [counter > 10])False: Hide guard conditionsNone: Usedetail_levelpreset (True for all levels)
Example:
>>> PlantUMLOptions(show_transition_guards=True) >>> # Output: idle --> active : [temperature > 25]
- show_transition_effectsOptional[bool], default=None
Whether to show transition effects (operations executed during transition).
True: Show effects according totransition_effect_modeFalse: Hide effectsNone: Usedetail_levelpreset (True for all levels)
Example:
>>> PlantUMLOptions(show_transition_effects=True, transition_effect_mode='inline') >>> # Output: idle --> active : Start / counter = 0
- transition_effect_modeLiteral[‘note’, ‘inline’, ‘hide’], default=’note’
How to display transition effects when
show_transition_effects=True.'note': Display as note on link (detailed, multi-line)'inline': Display inline with/separator (compact, single-line)'hide': Don’t display (same asshow_transition_effects=False)
Example:
>>> # Note format (detailed) >>> PlantUMLOptions(show_transition_effects=True, transition_effect_mode='note') >>> # Output: idle --> active : Start >>> # note on link >>> # effect { >>> # counter = 0; >>> # } >>> # end note >>> # Inline format (compact) >>> PlantUMLOptions(show_transition_effects=True, transition_effect_mode='inline') >>> # Output: idle --> active : Start / counter = 0
- show_eventsOptional[bool], default=None
Whether to show event names on transitions.
True: Show event namesFalse: Hide event names (show only guards/effects)None: Usedetail_levelpreset (True for all levels)
- event_name_formatTuple[Literal[‘name’, ‘extra_name’, ‘path’, ‘relpath’], …], default=(‘extra_name’, ‘relpath’)
Tuple of display elements for event names.
'name': Event identifier (e.g.,'Start')'extra_name': Localized/display name (e.g.,'启动')'path': Absolute path (e.g.,'/System.Start')'relpath': Relative path from transition source (e.g.,'State.Start')
Example:
>>> # Show extra_name with relative path >>> PlantUMLOptions(event_name_format=('extra_name', 'relpath')) >>> # Output: idle --> active : 启动 (State.Start) >>> # Show only name >>> PlantUMLOptions(event_name_format=('name',)) >>> # Output: idle --> active : Start
- event_visualization_modeLiteral[‘none’, ‘color’, ‘legend’, ‘both’, ‘dependency_view’], default=’none’
How to visualize events in the diagram.
'none': No special visualization'color': Apply colors to transitions by event (colorblind-friendly palette)'legend': Show event legend with transition counts'both': Apply colors and show legend'dependency_view': Reserved for future use
Example:
>>> # Color-code transitions by event >>> PlantUMLOptions(event_visualization_mode='color') >>> # Output: idle --> active : Start #4E79A7 >>> # Show event legend >>> PlantUMLOptions(event_visualization_mode='legend') >>> # Output: legend right >>> # Event Scoping >>> # * Start: 3 transitions >>> # endlegend
- event_legend_positionLiteral[‘top left’, ‘top center’, ‘top right’, ‘bottom left’, ‘bottom center’, ‘bottom right’, ‘left’, ‘right’, ‘center’], default=’right’
Position of the event legend when
event_visualization_modeis'legend'or'both'.'top left': Legend at top-left corner'top center': Legend at top-center'top right': Legend at top-right corner'bottom left': Legend at bottom-left corner'bottom center': Legend at bottom-center'bottom right': Legend at bottom-right corner'left': Legend on the left side'right': Legend on the right side (default)'center': Legend in the center
Example:
>>> # Place event legend on the right (default) >>> PlantUMLOptions(event_visualization_mode='legend', event_legend_position='right') >>> # Place event legend at bottom-right >>> PlantUMLOptions(event_visualization_mode='legend', event_legend_position='bottom right')
- max_depthOptional[int], default=None
Maximum depth to expand in state hierarchy. States beyond this depth are collapsed and shown with
collapsed_state_marker.None: Expand all levels (no limit)0: Show only root state> 0: Expand to specified depth
Example:
>>> # Show only 2 levels deep >>> PlantUMLOptions(max_depth=2, collapsed_state_marker='[...]') >>> # Output: state "Level1" as level1 { >>> # state "Level2" as level1__level2 { >>> # state "[...]" as level1__level2___collapsed_ >>> # } >>> # }
- collapsed_state_markerstr, default=’…’
Text marker to display for collapsed states when
max_depthis exceeded.Example:
>>> PlantUMLOptions(max_depth=1, collapsed_state_marker='[more states...]') >>> # Output: state "[more states...]" as parent___collapsed_
- use_skinparambool, default=True
Whether to include skinparam styling block for pseudo and composite states.
True: Include skinparam block with predefined colorsFalse: No skinparam block (use PlantUML defaults)
Example:
>>> PlantUMLOptions(use_skinparam=True) >>> # Output: skinparam state { >>> # BackgroundColor<<pseudo>> LightGray >>> # BackgroundColor<<composite>> LightBlue >>> # BorderColor<<pseudo>> Gray >>> # FontStyle<<pseudo>> italic >>> # }
- use_stereotypesbool, default=True
Whether to add stereotype markers (
<<pseudo>>,<<composite>>) to states.True: Add stereotypes for pseudo and composite statesFalse: No stereotypes
Example:
>>> PlantUMLOptions(use_stereotypes=True) >>> # Output: state "Parent" as parent <<composite>> { >>> # state "Child" as parent__child >>> # }
- custom_colorsOptional[Dict[str, str]], default=None
Custom color mapping for events. Keys are event paths (e.g.,
'Root.Start'), values are hex color codes (e.g.,'#FF0000').Only used when
event_visualization_modeis'color'or'both'.Example:
>>> PlantUMLOptions( ... event_visualization_mode='color', ... custom_colors={'Root.Start': '#FF0000', 'Root.Stop': '#00FF00'} ... ) >>> # Output: idle --> active : Start #FF0000 >>> # active --> idle : Stop #00FF00
Examples
Quick mode with presets:
>>> # Minimal diagram for presentations >>> options = PlantUMLOptions(detail_level='minimal') >>> sm.to_plantuml(options) >>> # Full details for documentation >>> options = PlantUMLOptions(detail_level='full') >>> sm.to_plantuml(options)
Fine-grained control:
>>> # Show only abstract actions (API surface) >>> options = PlantUMLOptions( ... show_lifecycle_actions=True, ... show_abstract_actions=True, ... show_concrete_actions=False, ... abstract_action_marker='symbol' ... ) >>> # Compact diagram with depth limit >>> options = PlantUMLOptions( ... max_depth=2, ... collapsed_state_marker='[...]', ... collapse_empty_states=True ... ) >>> # Event-focused view with colors >>> options = PlantUMLOptions( ... event_visualization_mode='both', ... event_name_format=('extra_name', 'name'), ... custom_colors={'Root.Start': '#00FF00'} ... )
Combining options:
>>> # Custom configuration inheriting from 'normal' >>> options = PlantUMLOptions( ... detail_level='normal', ... show_lifecycle_actions=True, # Override preset ... show_enter_actions=True, # Show only enter actions ... show_during_actions=False, ... show_exit_actions=False, ... max_action_lines=5 # Limit verbosity ... )
See Also
format_state_name : Format state names according to configuration format_event_name : Format event names according to configuration
- __post_init__()[source]
Validate configuration after initialization.
- Raises:
ValueError – If name format tuples are empty
- classmethod from_value(value: PlantUMLOptions | Literal['minimal', 'normal', 'full'] | None) PlantUMLOptions[source]
Normalize user-provided PlantUML option input to a
PlantUMLOptionsinstance.- Parameters:
value (PlantUMLOptionsInput) – Input configuration value. Accepts an existing options object, detail-level string, or
None.- Returns:
Normalized PlantUML options object
- Return type:
- Raises:
TypeError – If
valueis not supported
- to_config() PlantUMLOptions[source]
Export resolved configuration with all Optional fields resolved.
This method resolves all Optional[bool] fields according to the inheritance hierarchy and detail_level presets, returning a new PlantUMLOptions instance where all fields have definite values (no None).
Resolution priority (highest to lowest):
User-specified values (non-None)
Parent configuration values (e.g., show_lifecycle_actions)
detail_level preset values
Final fallback defaults
- Returns:
New PlantUMLOptions with all Optional fields resolved
- Return type:
Example:
>>> options = PlantUMLOptions( ... detail_level='normal', ... show_lifecycle_actions=True, ... show_enter_actions=None, ... ) >>> config = options.to_config() >>> config.show_lifecycle_actions # True >>> config.show_enter_actions # True (inherited) >>> config.show_during_actions # True (inherited)
format_state_name
- pyfcstm.model.plantuml.format_state_name(state: State, name_format: Tuple[Literal['name', 'extra_name', 'path'], ...]) str[source]
Format state name according to the specified format tuple.
- Parameters:
- Returns:
Formatted state name
- Return type:
str
Example:
>>> format_state_name(state, ('extra_name', 'name')) '系统运行中 (Running)'
format_event_name
- pyfcstm.model.plantuml.format_event_name(event: Event, name_format: Tuple[Literal['name', 'extra_name', 'path', 'relpath'], ...], trans_node: object | None = None) str[source]
Format event name according to the specified format tuple.
- Parameters:
- Returns:
Formatted event name
- Return type:
str
Example:
>>> format_event_name(event, ('extra_name', 'name')) '启动模块 (Start)' >>> format_event_name(event, ('extra_name', 'relpath'), trans_node) '启动模块 (State.Start)'
escape_plantuml_table_cell
- pyfcstm.model.plantuml.escape_plantuml_table_cell(text: str) str[source]
Escape special characters in PlantUML table cells.
PlantUML uses pipe (|) as table cell delimiter, so any pipe characters in cell content must be escaped to prevent breaking the table structure.
- Parameters:
text (str) – Text to escape
- Returns:
Escaped text safe for use in PlantUML table cells
- Return type:
str
Example:
>>> escape_plantuml_table_cell("2 | 5") '2 \| 5' >>> escape_plantuml_table_cell("normal text") 'normal text'
should_show_action
- pyfcstm.model.plantuml.should_show_action(action: OnStage | OnAspect, config: PlantUMLOptions) bool[source]
Determine if an action should be shown based on abstract/concrete filtering.
- Parameters:
action (Union[OnStage, OnAspect]) – Action object (OnStage or OnAspect) to check
config (PlantUMLOptions) – PlantUML configuration options
- Returns:
True if the action should be shown, False otherwise
- Return type:
bool
Example:
>>> # For an abstract action >>> should_show_action(action, config) True
format_action_text
- pyfcstm.model.plantuml.format_action_text(action: OnStage | OnAspect, config: PlantUMLOptions) str[source]
Format action text with abstract marker and line limit.
- Parameters:
action (Union[OnStage, OnAspect]) – Action object (OnStage or OnAspect) to format
config (PlantUMLOptions) – PlantUML configuration options
- Returns:
Formatted action text
- Return type:
str
Example:
>>> format_action_text(action, config) 'enter abstract InitHardware'
collect_event_transitions
- pyfcstm.model.plantuml.collect_event_transitions(state_machine: StateMachine) Dict[str, List[Tuple[State, Transition]]][source]
Collect all events and their associated transitions from a state machine.
- Parameters:
state_machine (StateMachine) – The state machine to analyze
- Returns:
Dictionary mapping event paths to list of (state, transition) tuples
- Return type:
Dict[str, List[Tuple[State, Transition]]]
Example:
>>> event_map = collect_event_transitions(sm) >>> event_map['System.ErrorEvent'] [(state1, trans1), (state2, trans2)]
assign_event_colors
- pyfcstm.model.plantuml.assign_event_colors(event_map: Dict[str, List], custom_colors: dict | None = None) Dict[str, str][source]
Assign colors to events for visualization.
Only assigns colors to events that appear 2 or more times. Events that appear only once will not be assigned a color (use default transition color).
- Parameters:
event_map (Dict[str, List]) – Dictionary mapping event paths to transitions
custom_colors (Optional[dict]) – Optional custom color mapping
- Returns:
Dictionary mapping event paths to color codes
- Return type:
Dict[str, str]
Example:
>>> colors = assign_event_colors(event_map) >>> colors['System.ErrorEvent'] # Only if ErrorEvent appears >= 2 times '#FF6B6B'