vention-state-machine 0.4__py3-none-any.whl → 0.4.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
state_machine/core.py CHANGED
@@ -58,19 +58,12 @@ class StateMachine(HierarchicalGraphMachine):
58
58
  ) -> None:
59
59
  # Normalize state definitions
60
60
  if is_state_container(states):
61
- state_groups = [
62
- value
63
- for value in vars(states).values()
64
- if isinstance(value, StateGroup)
65
- ]
61
+ state_groups = [value for value in vars(states).values() if isinstance(value, StateGroup)]
66
62
  resolved_states = [group.to_state_list()[0] for group in state_groups]
67
63
  elif isinstance(states, list):
68
64
  resolved_states = states
69
65
  else:
70
- raise TypeError(
71
- f"`states` must be either a StateGroup container or a list of state dicts. "
72
- f"Got: {type(states).__name__}"
73
- )
66
+ raise TypeError(f"`states` must be either a StateGroup container or a list of state dicts. " f"Got: {type(states).__name__}")
74
67
 
75
68
  self._declared_states: list[dict[str, Any]] = resolved_states
76
69
 
@@ -95,9 +88,7 @@ class StateMachine(HierarchicalGraphMachine):
95
88
  self._timeouts: dict[str, asyncio.Task[Any]] = {}
96
89
  self._last_state: Optional[str] = None
97
90
  self._enable_recovery: bool = enable_last_state_recovery
98
- self._history: deque[dict[str, Any]] = deque(
99
- maxlen=history_size or self.DEFAULT_HISTORY_SIZE
100
- )
91
+ self._history: deque[dict[str, Any]] = deque(maxlen=history_size or self.DEFAULT_HISTORY_SIZE)
101
92
  self._current_start: Optional[datetime] = None
102
93
  self._guard_conditions: dict[str, List[Callable[[], bool]]] = {}
103
94
  self._state_change_callbacks: List[Callable[[str, str, str], None]] = []
@@ -110,9 +101,7 @@ class StateMachine(HierarchicalGraphMachine):
110
101
  BaseStates.FAULT.value,
111
102
  before="cancel_tasks",
112
103
  )
113
- self.add_transition(
114
- BaseTriggers.RESET.value, BaseStates.FAULT.value, BaseStates.READY.value
115
- )
104
+ self.add_transition(BaseTriggers.RESET.value, BaseStates.FAULT.value, BaseStates.READY.value)
116
105
  self._attach_after_hooks()
117
106
  self._add_guard_conditions_to_transitions()
118
107
 
@@ -137,9 +126,7 @@ class StateMachine(HierarchicalGraphMachine):
137
126
  except asyncio.CancelledError:
138
127
  pass
139
128
 
140
- def set_timeout(
141
- self, state_name: str, seconds: float, trigger_fn: Callable[[], str]
142
- ) -> None:
129
+ def set_timeout(self, state_name: str, seconds: float, trigger_fn: Callable[[], str]) -> None:
143
130
  """
144
131
  Schedule a timeout: if `state_name` remains active after `seconds`, fire `trigger_fn()`.
145
132
  """
@@ -191,9 +178,7 @@ class StateMachine(HierarchicalGraphMachine):
191
178
  """Get the last `n` history entries."""
192
179
  return list(self._history)[-n:] if n > 0 else []
193
180
 
194
- def add_transition_condition(
195
- self, trigger_name: str, condition_fn: Callable[[], bool]
196
- ) -> None:
181
+ def add_transition_condition(self, trigger_name: str, condition_fn: Callable[[], bool]) -> None:
197
182
  """
198
183
  Add a guard condition to a transition trigger.
199
184
  Multiple conditions can be added for the same trigger - ALL must pass for the transition to be allowed.
@@ -202,9 +187,7 @@ class StateMachine(HierarchicalGraphMachine):
202
187
  self._guard_conditions[trigger_name] = []
203
188
  self._guard_conditions[trigger_name].append(condition_fn)
204
189
 
205
- def add_state_change_callback(
206
- self, callback: Callable[[str, str, str], None]
207
- ) -> None:
190
+ def add_state_change_callback(self, callback: Callable[[str, str, str], None]) -> None:
208
191
  """
209
192
  Add a callback that fires on any state change.
210
193
 
@@ -38,14 +38,10 @@ class DecoratorManager:
38
38
  def _discover_state_callbacks(self, callback_fn: Any) -> None:
39
39
  """Discover on_enter_state and on_exit_state decorators."""
40
40
  if hasattr(callback_fn, "_on_enter_state"):
41
- self._decorator_bindings.append(
42
- (callback_fn._on_enter_state, "enter", callback_fn)
43
- )
41
+ self._decorator_bindings.append((callback_fn._on_enter_state, "enter", callback_fn))
44
42
 
45
43
  if hasattr(callback_fn, "_on_exit_state"):
46
- self._exit_decorator_bindings.append(
47
- (callback_fn._on_exit_state, "exit", callback_fn)
48
- )
44
+ self._exit_decorator_bindings.append((callback_fn._on_exit_state, "exit", callback_fn))
49
45
 
50
46
  def _discover_guard_conditions(self, callback_fn: Any) -> None:
51
47
  """Discover guard decorators."""
@@ -70,9 +66,7 @@ class DecoratorManager:
70
66
 
71
67
  def _bind_state_callbacks(self, instance: Any) -> None:
72
68
  """Bind state entry/exit callbacks."""
73
- for state_name, hook_type, callback_fn in (
74
- self._decorator_bindings + self._exit_decorator_bindings
75
- ):
69
+ for state_name, hook_type, callback_fn in self._decorator_bindings + self._exit_decorator_bindings:
76
70
  bound_fn = callback_fn.__get__(instance)
77
71
 
78
72
  if hook_type == "enter" and hasattr(callback_fn, "_timeout_config"):
@@ -54,9 +54,7 @@ def on_exit_state(
54
54
  return decorator
55
55
 
56
56
 
57
- def auto_timeout(
58
- seconds: float, trigger: Union[str, Callable[[], str]] = "to_fault"
59
- ) -> Callable[[CallableType], CallableType]:
57
+ def auto_timeout(seconds: float, trigger: Union[str, Callable[[], str]] = "to_fault") -> Callable[[CallableType], CallableType]:
60
58
  """
61
59
  Decorator that applies an auto-timeout configuration to a state entry handler.
62
60
  """
@@ -90,11 +88,7 @@ def guard(
90
88
  guard_fn._guard_conditions = {}
91
89
 
92
90
  for trigger in triggers:
93
- trigger_name = (
94
- getattr(trigger, "name", trigger)
95
- if hasattr(trigger, "name")
96
- else trigger
97
- )
91
+ trigger_name = getattr(trigger, "name", trigger) if hasattr(trigger, "name") else trigger
98
92
  if not isinstance(trigger_name, str):
99
93
  raise TypeError(f"Expected a Trigger or str, got {type(trigger)}")
100
94
 
state_machine/defs.py CHANGED
@@ -88,9 +88,7 @@ class Trigger:
88
88
  def __call__(self) -> str:
89
89
  return self.name
90
90
 
91
- def transition(
92
- self, source: Union[str, State], dest: Union[str, State]
93
- ) -> Dict[str, str]:
91
+ def transition(self, source: Union[str, State], dest: Union[str, State]) -> Dict[str, str]:
94
92
  """
95
93
  Build {"trigger": self.name, "source": <src>, "dest": <dst>}.
96
94
  `source` / `dest` may be raw strings or StateKey instances.
@@ -2,9 +2,7 @@ from typing import Protocol, Callable, Any
2
2
 
3
3
 
4
4
  class SupportsTimeout(Protocol):
5
- def set_timeout(
6
- self, state_name: str, seconds: float, trigger_fn: Callable[[], str]
7
- ) -> None: ...
5
+ def set_timeout(self, state_name: str, seconds: float, trigger_fn: Callable[[], str]) -> None: ...
8
6
 
9
7
 
10
8
  class SupportsStateCallbacks(Protocol):
@@ -12,15 +10,11 @@ class SupportsStateCallbacks(Protocol):
12
10
 
13
11
 
14
12
  class SupportsGuardConditions(Protocol):
15
- def add_transition_condition(
16
- self, trigger_name: str, condition_fn: Callable[[], bool]
17
- ) -> None: ...
13
+ def add_transition_condition(self, trigger_name: str, condition_fn: Callable[[], bool]) -> None: ...
18
14
 
19
15
 
20
16
  class SupportsStateChangeCallbacks(Protocol):
21
- def add_state_change_callback(
22
- self, callback: Callable[[str, str, str], None]
23
- ) -> None: ...
17
+ def add_state_change_callback(self, callback: Callable[[str, str, str], None]) -> None: ...
24
18
 
25
19
 
26
20
  class StateMachineProtocol(
state_machine/utils.py CHANGED
@@ -48,11 +48,8 @@ def is_state_container(state_source: object) -> bool:
48
48
  Return True if `obj` is an instance or class that contains StateGroup(s).
49
49
  """
50
50
  try:
51
- return any(
52
- isinstance(value, StateGroup) for value in vars(state_source).values()
53
- ) or any(
54
- isinstance(value, StateGroup)
55
- for value in vars(state_source.__class__).values()
51
+ return any(isinstance(value, StateGroup) for value in vars(state_source).values()) or any(
52
+ isinstance(value, StateGroup) for value in vars(state_source.__class__).values()
56
53
  )
57
54
  except TypeError:
58
55
  return False
@@ -116,10 +116,7 @@ def build_state_machine_rpc_bundle(
116
116
  if trigger_name not in allowed:
117
117
  raise ConnectError(
118
118
  code="failed_precondition",
119
- message=(
120
- f"Trigger '{trigger_name}' cannot run from '{current}'. "
121
- f"Allowed: {sorted(allowed)}"
122
- ),
119
+ message=(f"Trigger '{trigger_name}' cannot run from '{current}'. " f"Allowed: {sorted(allowed)}"),
123
120
  )
124
121
 
125
122
  # Fetch bound trigger method
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vention-state-machine
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: Declarative state machine framework for machine apps
5
5
  License: Proprietary
6
6
  Author: VentionCo
@@ -8,12 +8,28 @@ Requires-Python: >=3.10,<3.11
8
8
  Classifier: License :: Other/Proprietary License
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: Programming Language :: Python :: 3.10
11
- Requires-Dist: asyncio (>=3.4.3,<4.0.0)
12
- Requires-Dist: coverage (>=7.10.1,<8.0.0)
13
- Requires-Dist: graphviz (>=0.21,<0.22)
14
- Requires-Dist: transitions (>=0.9.3,<0.10.0)
15
- Requires-Dist: uvicorn (>=0.35.0,<0.36.0)
16
- Requires-Dist: vention-communication (>=0.2.2,<0.3.0)
11
+ Requires-Dist: annotated-doc (==0.0.4) ; python_version == "3.10"
12
+ Requires-Dist: annotated-types (==0.7.0) ; python_version == "3.10"
13
+ Requires-Dist: anyio (==4.11.0) ; python_version == "3.10"
14
+ Requires-Dist: asyncio (==3.4.3) ; python_version == "3.10"
15
+ Requires-Dist: click (==8.1.8) ; python_version == "3.10"
16
+ Requires-Dist: colorama (==0.4.6) ; python_version == "3.10" and platform_system == "Windows"
17
+ Requires-Dist: coverage (==7.10.7) ; python_version == "3.10"
18
+ Requires-Dist: exceptiongroup (==1.3.0) ; python_version == "3.10"
19
+ Requires-Dist: fastapi (==0.121.1) ; python_version == "3.10"
20
+ Requires-Dist: graphviz (==0.21) ; python_version == "3.10"
21
+ Requires-Dist: h11 (==0.16.0) ; python_version == "3.10"
22
+ Requires-Dist: idna (==3.11) ; python_version == "3.10"
23
+ Requires-Dist: pydantic (==2.12.3) ; python_version == "3.10"
24
+ Requires-Dist: pydantic-core (==2.41.4) ; python_version == "3.10"
25
+ Requires-Dist: six (==1.17.0) ; python_version == "3.10"
26
+ Requires-Dist: sniffio (==1.3.1) ; python_version == "3.10"
27
+ Requires-Dist: starlette (==0.48.0) ; python_version == "3.10"
28
+ Requires-Dist: transitions (==0.9.3) ; python_version == "3.10"
29
+ Requires-Dist: typing-extensions (==4.15.0) ; python_version == "3.10"
30
+ Requires-Dist: typing-inspection (==0.4.2) ; python_version == "3.10"
31
+ Requires-Dist: uvicorn (==0.35.0) ; python_version == "3.10"
32
+ Requires-Dist: vention-communication (==0.3.0) ; python_version == "3.10"
17
33
  Description-Content-Type: text/markdown
18
34
 
19
35
  # vention-state-machine
@@ -0,0 +1,12 @@
1
+ state_machine/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ state_machine/core.py,sha256=w0dmNx2MUCGSwVOs6Y9dGiHuRVNn7lWYskYtm1zpo4g,11007
3
+ state_machine/decorator_manager.py,sha256=rKyDKFMh-NmOrYntVwQNslSmW5Ac85BPzo0CXwe2Ixs,4336
4
+ state_machine/decorator_protocols.py,sha256=E6_xflTPxxTqDBa4Dj4p3OdPvR_EW0jA3PAjHTDlG8c,485
5
+ state_machine/decorators.py,sha256=mqlbbZ59d-eeRCmidbkFKGcjN4KPlF7l0Z6nEJwvt_Y,3598
6
+ state_machine/defs.py,sha256=RrM5SVgptfPZNu-AeRN56lk8QVRT1Uwot2xCx3SJpPo,2822
7
+ state_machine/machine_protocols.py,sha256=Q_rjlFTGrf3EvCndY4SWfurFNdJg4hB3qZkM0ISQxXI,784
8
+ state_machine/utils.py,sha256=1b54DZPv7s6hK0ud2KT4k1s1R1Li7wFUowKGTwMwxfw,2361
9
+ state_machine/vention_communication.py,sha256=Ggg4FvQzruHfpNJmPtDmdZM46w0JwH-BATDtsCS6T_I,5460
10
+ vention_state_machine-0.4.2.dist-info/METADATA,sha256=kb6qjgj-Ckjr8eBgn71n5AAqUuiUSvy3iY4vX68_A4k,12827
11
+ vention_state_machine-0.4.2.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
12
+ vention_state_machine-0.4.2.dist-info/RECORD,,
@@ -1,12 +0,0 @@
1
- state_machine/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- state_machine/core.py,sha256=lAiGGPtWCiYQPCh1iz3P26YFrz8VvveIGlL5k2AFvKs,11201
3
- state_machine/decorator_manager.py,sha256=uHhbtR1vS7idcn4kJsaNtJ1Z_7kiHf9YVa_cxkb-WNk,4420
4
- state_machine/decorator_protocols.py,sha256=E6_xflTPxxTqDBa4Dj4p3OdPvR_EW0jA3PAjHTDlG8c,485
5
- state_machine/decorators.py,sha256=V-KBJ6fSvINi7JHN_VmrQLTnOxGPy5iRV5QzXLKwWDw,3668
6
- state_machine/defs.py,sha256=eYtkTqRMm89ZHFKs3p7H3HyGNZbrOnoCzAJbSeMxSDg,2836
7
- state_machine/machine_protocols.py,sha256=Yxs4aw2-NJ1RluygbthsquVKn35-xMYae7PB7xlqQmE,826
8
- state_machine/utils.py,sha256=3eWL63_RAk_Jijh0ZIArBsUF3A7f0vQmwTjDRwRvpIs,2395
9
- state_machine/vention_communication.py,sha256=BZjHC1SsXFqLiSpX0ChCEGfhkEeitpXmLClZCQIgOrA,5530
10
- vention_state_machine-0.4.0.dist-info/METADATA,sha256=UlROQZDnqaO5j0AbfJJ2KofpSrrr_woWR8xPWbJY35c,11671
11
- vention_state_machine-0.4.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
12
- vention_state_machine-0.4.0.dist-info/RECORD,,