Skip to content

Commit f60429d

Browse files
committed
refactor: replace deep: bool with type: HistoryType on HistoryState
Replace the boolean `deep` parameter with a `HistoryType(str, Enum)` that mirrors the SCXML spec (`type="deep"` / `type="shallow"`). The `(str, Enum)` hybrid allows passing either `"deep"` or `HistoryType.DEEP`. V3 hasn't been released yet, so no backward-compatibility shims are needed.
1 parent 0385d88 commit f60429d

16 files changed

Lines changed: 58 additions & 26 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ True
239239

240240
```
241241

242-
Use `HistoryState(deep=True)` for deep history that remembers the exact leaf
242+
Use `HistoryState(type="deep")` for deep history that remembers the exact leaf
243243
state across nested compounds.
244244

245245

docs/releases/3.0.0.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ Events in one region don't affect others. See {ref}`statecharts` for full detail
159159

160160
The **History pseudo-state** records the configuration of a compound state when it
161161
is exited. Re-entering via the history state restores the previously active child.
162-
Supports both shallow (`HistoryState()`) and deep (`HistoryState(deep=True)`) history:
162+
Supports both shallow (`HistoryState()`) and deep (`HistoryState(type="deep")`) history:
163163

164164
```py
165165
>>> from statemachine import HistoryState, State, StateChart

docs/statecharts.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ By default, `HistoryState()` uses **shallow** history: it remembers only the dir
462462
child of the compound. If the remembered child is itself a compound, it re-enters
463463
from its initial state.
464464

465-
Use `HistoryState(deep=True)` for **deep** history, which remembers the exact leaf
465+
Use `HistoryState(type="deep")` for **deep** history, which remembers the exact leaf
466466
state and restores the full hierarchy:
467467

468468
```py
@@ -475,7 +475,7 @@ state and restores the full hierarchy:
475475
... chamber = State()
476476
... explore = entrance.to(chamber)
477477
... assert isinstance(halls, State)
478-
... h = HistoryState(deep=True)
478+
... h = HistoryState(type="deep")
479479
... bridge = State(final=True)
480480
... flee = halls.to(bridge)
481481
... outside = State()

docs/states.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ True
284284

285285
```
286286

287-
Use `HistoryState(deep=True)` for deep history that remembers the exact leaf state
287+
Use `HistoryState(type="deep")` for deep history that remembers the exact leaf state
288288
in nested compounds.
289289

290290
```{seealso}

statemachine/__init__.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from .event import Event
22
from .state import HistoryState
3+
from .state import HistoryType
34
from .state import State
45
from .statemachine import StateChart
56
from .statemachine import StateMachine
@@ -9,4 +10,12 @@
910
__email__ = "fgmacedo@gmail.com"
1011
__version__ = "3.0.0"
1112

12-
__all__ = ["StateChart", "StateMachine", "State", "HistoryState", "Event", "TModel"]
13+
__all__ = [
14+
"StateChart",
15+
"StateMachine",
16+
"State",
17+
"HistoryState",
18+
"HistoryType",
19+
"Event",
20+
"TModel",
21+
]

statemachine/contrib/diagram.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ def _state_id(state):
132132
return state.id
133133

134134
def _history_node(self, state):
135-
label = "H*" if state.deep else "H"
135+
label = "H*" if state.type.is_deep else "H"
136136
return pydot.Node(
137137
self._state_id(state),
138138
label=label,

statemachine/engines/base.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ def _prepare_exit_states(
474474
for info in ordered_states:
475475
state = info.state
476476
for history in state.history:
477-
if history.deep:
477+
if history.type.is_deep:
478478
history_value = [s for s in self.sm.configuration if s.is_descendant(state)] # noqa: E501
479479
else: # shallow history
480480
history_value = [s for s in self.sm.configuration if s.parent == state]
@@ -767,12 +767,12 @@ def add_descendant_states_to_enter( # noqa: C901
767767
self._log_id,
768768
state.parent,
769769
state,
770-
"deep" if state.deep else "shallow",
770+
state.type.value,
771771
[s.id for s in self.sm.history_values[state.id]],
772772
)
773773
for history_state in self.sm.history_values[state.id]:
774774
info_to_add = StateTransition(transition=info.transition, state=history_state)
775-
if state.deep:
775+
if state.type.is_deep:
776776
states_to_enter.add(info_to_add)
777777
else:
778778
self.add_descendant_states_to_enter(

statemachine/io/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class StateKwargs(BaseStateKwargs, total=False):
5656
class HistoryKwargs(TypedDict, total=False):
5757
name: str
5858
value: Any
59-
deep: bool
59+
type: str
6060

6161

6262
class HistoryDefinition(HistoryKwargs, total=False):

statemachine/io/scxml/parser.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import re
22
import xml.etree.ElementTree as ET
33
from typing import List
4+
from typing import Literal
45
from typing import Set
6+
from typing import cast
57
from urllib.parse import urlparse
68

79
from .schema import Action
@@ -141,9 +143,10 @@ def parse_history(state_elem: ET.Element) -> HistoryState:
141143
if not state_id:
142144
raise ValueError("History must have an 'id' attribute")
143145

146+
history_type = cast("Literal['shallow', 'deep']", state_elem.get("type", "shallow"))
144147
state = HistoryState(
145148
id=state_id,
146-
deep=state_elem.get("type") == "deep",
149+
type=history_type,
147150
)
148151
for trans_elem in state_elem.findall("transition"):
149152
transition = parse_transition(trans_elem)

statemachine/io/scxml/processor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ def _process_history(self, history: Dict[str, HistoryState]) -> Dict[str, Histor
153153
for state_id, state in history.items():
154154
state_dict = HistoryDefinition()
155155

156-
state_dict["deep"] = state.deep
156+
state_dict["type"] = state.type
157157

158158
# Process transitions
159159
if state.transitions:

0 commit comments

Comments
 (0)