Repository navigation
Transition kinds: kind=external|local|internal across Python, YAML and SCXML #723
Description
Why
Transition types today are a boolean internal= whose meaning depends on the source state, and it does not line up with either UML or SCXML. One parameter with three values, consistent across Python, JSON/YAML and SCXML, and between UML and SCXML, removes that ambiguity. Decided by the maintainer during #696 (which only fixes B3/B4/B7 and stays as is).
Design
kind on transitions: external (default), local, internal.
kind |
UML | SCXML | Exit/entry |
|---|---|---|---|
external |
external | type="external" |
domain is the LCCA |
local |
local | type="internal" with a compound source and descendant targets |
domain is the source; the source is not exited |
internal |
internal | transition without target |
none; configuration unchanged |
to(None) is equivalent to kind="internal" (already the current behavior).
Strict validation (InvalidDefinition):
internal: target equal to the source or no target, on any kind of state.local: source must not be atomic; every target must be a proper descendant of the source.localtargeting the source itself is invalid (UML 2.5.1).- Passing both
kind=and the deprecatedinternal=on the same transition (Python or native document) is invalid, even when they agree.
local with a parallel source follows XState v5 (verified by running it): the parallel state is not exited; all its regions exit and re-enter their defaults. SCXML-family engines exit the parallel; the final configuration is the same.
Engine: get_transition_domain has three branches: internal (no exit/entry), local (domain is the source), external (domain is the LCCA). The special case for atomic sources goes away in 4.0 together with the alias.
SCXML reader resolves section 3.13 at parse time: no target becomes internal; type="internal" with a compound source and descendant targets becomes local; everything else becomes external.
Native format: kind as an enum in the JSON Schema, kept in sync with io/native.py.
Diagrams: internal drawn as an action inside the state; local and external as arrows.
Compatibility (3.x)
internal=True stays as a deprecated alias with DeprecationWarning, mapped to today's behavior:
- self-transition on an atomic state:
internal; - compound source to a descendant:
local; - self-transition on a compound or parallel state, and parallel source to a descendant:
external.
The warning names the kind that matches that specific transition, so migration is mechanical. enable_self_transition_entries (deprecated in #696) points to the same migration. Both are removed in 4.0.
Acceptance
- Validation tests for every invalid combination above.
- One machine written in Python, YAML and SCXML produces the same trace for each
kind. - Docs: transitions page with the UML/SCXML table; release notes; a "3.x to 4.0" upgrade page with the migration table.
- W3C SCXML and PSSM suites unchanged or improved.
Activity