orca-runtime-python 0.1.25__py3-none-any.whl → 0.1.26__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.
@@ -33,7 +33,7 @@ from .persistence import PersistenceAdapter, AsyncPersistenceAdapter, FilePersis
33
33
 
34
34
  from .logging import LogSink, FileSink, ConsoleSink, MultiSink
35
35
 
36
- __version__ = "0.1.25"
36
+ __version__ = "0.1.26"
37
37
 
38
38
  __all__ = [
39
39
  # Types
@@ -390,10 +390,10 @@ class OrcaMachine:
390
390
  from_state=str(self._state),
391
391
  )
392
392
 
393
- # Find matching transition
394
- transition = self._find_transition(evt)
393
+ # Find matching transitions (may be multiple with different guards)
394
+ candidates = self._find_transitions(evt)
395
395
 
396
- if not transition:
396
+ if not candidates:
397
397
  # No transition found - event unhandled
398
398
  return TransitionResult(
399
399
  taken=False,
@@ -401,16 +401,28 @@ class OrcaMachine:
401
401
  error=f"No transition for event {event_key} from {self._state.leaf()}"
402
402
  )
403
403
 
404
- # Evaluate guard if present
405
- if transition.guard:
406
- guard_passed = await self._evaluate_guard(transition.guard)
407
- if not guard_passed:
408
- return TransitionResult(
409
- taken=False,
410
- from_state=str(self._state),
411
- guard_failed=True,
412
- error=f"Guard '{transition.guard}' failed"
413
- )
404
+ # Try each candidate in order; first whose guard passes wins
405
+ transition = None
406
+ last_guard_name = None
407
+ for candidate in candidates:
408
+ if candidate.guard:
409
+ guard_passed = await self._evaluate_guard(candidate.guard)
410
+ if guard_passed:
411
+ transition = candidate
412
+ break
413
+ last_guard_name = candidate.guard
414
+ else:
415
+ # No guard — unconditional match
416
+ transition = candidate
417
+ break
418
+
419
+ if transition is None:
420
+ return TransitionResult(
421
+ taken=False,
422
+ from_state=str(self._state),
423
+ guard_failed=True,
424
+ error=f"Guard '{last_guard_name}' failed"
425
+ )
414
426
 
415
427
  # Execute the transition
416
428
  old_state = StateValue(self._state.value)
@@ -532,16 +544,20 @@ class OrcaMachine:
532
544
  # Default fallback
533
545
  return EventType.STATE_CHANGED
534
546
 
535
- def _find_transition(self, event: Event) -> Transition | None:
536
- """Find a transition matching the current state and event."""
547
+ def _find_transitions(self, event: Event) -> list[Transition]:
548
+ """Find all transitions matching the current state and event."""
537
549
  event_key = event.event_name or event.type.value
550
+ result: list[Transition] = []
538
551
 
539
552
  # Check all active leaf states (important for parallel states)
540
553
  for current in self._state.leaves():
541
554
  # Try direct match on current leaf state
542
555
  for t in self.definition.transitions:
543
556
  if t.source == current and t.event == event_key:
544
- return t
557
+ result.append(t)
558
+
559
+ if result:
560
+ return result
545
561
 
546
562
  # For compound states, also check parent's transitions
547
563
  # Transitions on parent fire from any child
@@ -549,10 +565,12 @@ class OrcaMachine:
549
565
  while parent:
550
566
  for t in self.definition.transitions:
551
567
  if t.source == parent and t.event == event_key:
552
- return t
568
+ result.append(t)
569
+ if result:
570
+ return result
553
571
  parent = self._get_parent_state(parent)
554
572
 
555
- return None
573
+ return result
556
574
 
557
575
  def _get_parent_state(self, state_name: str) -> str | None:
558
576
  """Get parent state name if state is nested (searches parallel regions too)."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: orca-runtime-python
3
- Version: 0.1.25
3
+ Version: 0.1.26
4
4
  Summary: Python async runtime for Orca state machines
5
5
  License: Apache-2.0
6
6
  Project-URL: Homepage, https://github.com/orca-lang/orca-lang
@@ -1,12 +1,12 @@
1
- orca_runtime_python/__init__.py,sha256=72lz085_ZdaZnEizGbB0DATdV_frmMz3hqdfb_ZwrBk,1290
1
+ orca_runtime_python/__init__.py,sha256=kqs4D7foxyJmKPXy0STXG-zWTmWsg1xlkaPss1oQOg8,1290
2
2
  orca_runtime_python/bus.py,sha256=kCdMwm3O97wlX5hr3_aK-YkhABO7Z0M-eaYPYJAIa9g,7171
3
3
  orca_runtime_python/effects.py,sha256=eAkm2JdHSH5wUm8ZQjBf7ncgMI1iw7xq9bKi5X1AJEM,5649
4
4
  orca_runtime_python/logging.py,sha256=Bnw_PCGlMQaDbti3UNMudhj0RcOckF_7YYt_5yWatGY,4360
5
- orca_runtime_python/machine.py,sha256=V_Z4kA7cG_ImYLE4Ys8aIqXuMRnaMsTPbqhRz0LYeyA,36057
5
+ orca_runtime_python/machine.py,sha256=cSX9bIGvr-A9-H8mGrQId8a_P69fUoOBkDdeHrg0fhA,36662
6
6
  orca_runtime_python/parser.py,sha256=SC6YYQstJ9Jn2kuPuBsOPXsnn1m0ZDJ0dSS6AyUbW0M,33250
7
7
  orca_runtime_python/persistence.py,sha256=rjrgXDhfs3IA-c_xkQcFC4lCBlzmQtLL5lNWGu2kWu4,3330
8
8
  orca_runtime_python/types.py,sha256=Pzso9IfR_yPWGluqydj5dFbM3mS1rJ3x3czCW6XP5zc,7275
9
- orca_runtime_python-0.1.25.dist-info/METADATA,sha256=AVau6uaBfSgtPdfaJTmKukbiHwnJDc8sdFp9E63b4JE,7165
10
- orca_runtime_python-0.1.25.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
11
- orca_runtime_python-0.1.25.dist-info/top_level.txt,sha256=r7KIKsP_6Io6KiMqlBoNEc4IwzaE7O3VTG-PSEu0wVY,20
12
- orca_runtime_python-0.1.25.dist-info/RECORD,,
9
+ orca_runtime_python-0.1.26.dist-info/METADATA,sha256=rJU1sEp5wvK1q_RcHYUk3A7mQ-9nXWtIfw2aDy3kE_I,7165
10
+ orca_runtime_python-0.1.26.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
11
+ orca_runtime_python-0.1.26.dist-info/top_level.txt,sha256=r7KIKsP_6Io6KiMqlBoNEc4IwzaE7O3VTG-PSEu0wVY,20
12
+ orca_runtime_python-0.1.26.dist-info/RECORD,,