python-statemachine 2.6.0__tar.gz → 3.0.0__tar.gz
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.
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/.github/ISSUE_TEMPLATE.md +2 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/.github/workflows/python-package.yml +2 -2
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/.github/workflows/release.yml +1 -1
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/.pre-commit-config.yaml +7 -1
- python_statemachine-3.0.0/AGENTS.md +243 -0
- python_statemachine-3.0.0/PKG-INFO +414 -0
- python_statemachine-3.0.0/README.md +386 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/conftest.py +4 -2
- python_statemachine-3.0.0/docs/actions.md +642 -0
- python_statemachine-3.0.0/docs/api.md +161 -0
- python_statemachine-3.0.0/docs/async.md +201 -0
- python_statemachine-3.0.0/docs/behaviour.md +186 -0
- python_statemachine-3.0.0/docs/concepts.md +152 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/conf.py +2 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/contributing.md +130 -0
- python_statemachine-3.0.0/docs/diagram.md +142 -0
- python_statemachine-3.0.0/docs/error_handling.md +246 -0
- python_statemachine-3.0.0/docs/events.md +373 -0
- python_statemachine-3.0.0/docs/guards.md +396 -0
- python_statemachine-3.0.0/docs/how-to/coming_from_state_pattern.md +396 -0
- python_statemachine-3.0.0/docs/how-to/coming_from_transitions.md +963 -0
- python_statemachine-3.0.0/docs/images/internal_transition_sc.png +0 -0
- python_statemachine-3.0.0/docs/images/order_control_machine_initial.png +0 -0
- python_statemachine-3.0.0/docs/images/order_control_machine_initial_300dpi.png +0 -0
- python_statemachine-3.0.0/docs/images/order_control_machine_processing.png +0 -0
- python_statemachine-3.0.0/docs/images/readme_orderworkflow.png +0 -0
- python_statemachine-3.0.0/docs/images/readme_trafficlightmachine.png +0 -0
- python_statemachine-3.0.0/docs/images/test_state_machine_internal.png +0 -0
- python_statemachine-3.0.0/docs/images/transition_compound_cancel.png +0 -0
- python_statemachine-3.0.0/docs/images/transition_from_any.png +0 -0
- python_statemachine-3.0.0/docs/images/tutorial_coffeeorder.png +0 -0
- python_statemachine-3.0.0/docs/index.md +90 -0
- python_statemachine-3.0.0/docs/integrations.md +171 -0
- python_statemachine-3.0.0/docs/invoke.md +487 -0
- python_statemachine-3.0.0/docs/listeners.md +277 -0
- python_statemachine-3.0.0/docs/models.md +70 -0
- python_statemachine-3.0.0/docs/processing_model.md +317 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/2.0.0.md +4 -1
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/2.2.0.md +14 -14
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/2.3.0.md +13 -15
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/2.4.0.md +19 -21
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/2.5.0.md +35 -56
- python_statemachine-3.0.0/docs/releases/3.0.0.md +667 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/index.md +18 -6
- python_statemachine-3.0.0/docs/releases/upgrade_2x_to_3.md +477 -0
- python_statemachine-3.0.0/docs/statechart.md +286 -0
- python_statemachine-3.0.0/docs/states.md +230 -0
- python_statemachine-3.0.0/docs/timeout.md +92 -0
- python_statemachine-3.0.0/docs/transitions.md +386 -0
- python_statemachine-3.0.0/docs/tutorial.md +736 -0
- python_statemachine-3.0.0/docs/validations.md +280 -0
- python_statemachine-3.0.0/docs/weighted_transitions.md +234 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/pyproject.toml +26 -11
- python_statemachine-3.0.0/statemachine/__init__.py +21 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/callbacks.py +131 -38
- python_statemachine-3.0.0/statemachine/contrib/diagram.py +370 -0
- python_statemachine-3.0.0/statemachine/contrib/timeout.py +68 -0
- python_statemachine-3.0.0/statemachine/contrib/weighted.py +193 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/dispatcher.py +2 -2
- python_statemachine-3.0.0/statemachine/engines/async_.py +533 -0
- python_statemachine-3.0.0/statemachine/engines/base.py +943 -0
- python_statemachine-3.0.0/statemachine/engines/sync.py +208 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/event.py +90 -21
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/event_data.py +26 -11
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/events.py +12 -3
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/exceptions.py +8 -4
- python_statemachine-3.0.0/statemachine/factory.py +359 -0
- python_statemachine-3.0.0/statemachine/graph.py +62 -0
- python_statemachine-3.0.0/statemachine/invoke.py +603 -0
- python_statemachine-3.0.0/statemachine/io/__init__.py +225 -0
- python_statemachine-3.0.0/statemachine/io/scxml/actions.py +649 -0
- python_statemachine-3.0.0/statemachine/io/scxml/invoke.py +233 -0
- python_statemachine-3.0.0/statemachine/io/scxml/parser.py +473 -0
- python_statemachine-3.0.0/statemachine/io/scxml/processor.py +263 -0
- python_statemachine-3.0.0/statemachine/io/scxml/schema.py +175 -0
- python_statemachine-3.0.0/statemachine/locale/en/LC_MESSAGES/statemachine.po +133 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/locale/hi_IN/LC_MESSAGES/statemachine.po +51 -26
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/locale/pt_BR/LC_MESSAGES/statemachine.po +51 -26
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/locale/zh_CN/LC_MESSAGES/statemachine.po +47 -26
- python_statemachine-3.0.0/statemachine/orderedset.py +118 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/registry.py +4 -10
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/signature.py +3 -1
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/spec_parser.py +50 -9
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/state.py +227 -26
- python_statemachine-3.0.0/statemachine/statemachine.py +547 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/states.py +22 -19
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/transition.py +46 -8
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/transition_list.py +7 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/transition_mixin.py +6 -2
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/utils.py +2 -1
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/conftest.py +144 -22
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/django_project/workflow/statemachines.py +4 -2
- python_statemachine-3.0.0/tests/examples/__init__.py +0 -0
- python_statemachine-3.0.0/tests/examples/ai_shell_machine.py +568 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/examples/air_conditioner_machine.py +3 -3
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/examples/all_actions_machine.py +5 -4
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/examples/async_guess_the_number_machine.py +9 -7
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/examples/async_without_loop_machine.py +4 -4
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/examples/enum_campaign_machine.py +13 -15
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/examples/guess_the_number_machine.py +4 -3
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/examples/lor_machine.py +11 -10
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/examples/order_control_machine.py +5 -3
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/examples/order_control_rich_model_machine.py +7 -4
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/examples/persistent_model_machine.py +6 -6
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/examples/recursive_event_machine.py +3 -2
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/examples/reusing_transitions_machine.py +3 -3
- python_statemachine-3.0.0/tests/examples/statechart_cleanup_machine.py +111 -0
- python_statemachine-3.0.0/tests/examples/statechart_compound_machine.py +97 -0
- python_statemachine-3.0.0/tests/examples/statechart_delayed_machine.py +189 -0
- python_statemachine-3.0.0/tests/examples/statechart_error_handling_machine.py +104 -0
- python_statemachine-3.0.0/tests/examples/statechart_eventless_machine.py +99 -0
- python_statemachine-3.0.0/tests/examples/statechart_history_machine.py +125 -0
- python_statemachine-3.0.0/tests/examples/statechart_in_condition_machine.py +115 -0
- python_statemachine-3.0.0/tests/examples/statechart_parallel_machine.py +97 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/examples/traffic_light_machine.py +4 -4
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/examples/user_machine.py +5 -4
- python_statemachine-3.0.0/tests/examples/weighted_idle_machine.py +41 -0
- python_statemachine-3.0.0/tests/scxml/__init__.py +0 -0
- python_statemachine-3.0.0/tests/scxml/conftest.py +74 -0
- python_statemachine-3.0.0/tests/scxml/test_microwave.py +130 -0
- python_statemachine-3.0.0/tests/scxml/test_scxml_cases.py +101 -0
- python_statemachine-3.0.0/tests/scxml/w3c/LICENSE +11 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test144.scxml +33 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test145.scxml +31 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test147.scxml +36 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test148.scxml +36 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test149.scxml +32 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test150.scxml +46 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test151.scxml +46 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test152.scxml +52 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test153.scxml +45 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test155.scxml +31 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test156.scxml +34 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test158.scxml +31 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test159.scxml +26 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test172.scxml +25 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test173.scxml +26 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test174.scxml +26 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test175.scxml +34 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test176.scxml +36 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test179.scxml +24 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test183.scxml +26 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test185.scxml +27 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test186.scxml +39 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test187.scxml +40 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test189.scxml +29 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test190.scxml +45 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test191.scxml +40 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test192.scxml +57 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test194.scxml +26 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test198.scxml +26 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test199.scxml +23 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test200.scxml +23 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test205.scxml +36 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test207.scxml +63 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test208.scxml +26 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test210.scxml +28 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test215.scxml +41 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test216.scxml +33 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test216sub1.scxml +8 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test220.scxml +33 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test223.scxml +40 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test224.scxml +43 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test225.scxml +49 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test226.scxml +50 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test226sub1.scxml +18 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test228.scxml +44 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test229.scxml +54 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test232.scxml +51 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test233.scxml +46 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test234.scxml +77 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test235.scxml +34 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test236.scxml +51 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test237.scxml +52 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test239.scxml +42 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test239sub1.scxml +7 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test240.scxml +77 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test241.scxml +109 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test242.scxml +64 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test242sub1.scxml +7 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test243.scxml +46 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test244.scxml +49 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test245.scxml +46 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test247.scxml +32 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test252.scxml +58 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test253.scxml +80 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test276.scxml +27 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test276sub1.scxml +24 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test277.scxml +39 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test279.scxml +32 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test280.scxml +40 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test286.scxml +30 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test287.scxml +30 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test294.scxml +39 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test298.scxml +34 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test302.scxml +25 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test303.scxml +31 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test304.scxml +24 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test309.scxml +24 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test310.scxml +28 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test311.scxml +27 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test312.scxml +30 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test318.scxml +38 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test319.scxml +30 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test321.scxml +25 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test322.scxml +47 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test323.scxml +25 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test324.scxml +32 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test325.scxml +27 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test326.scxml +46 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test329.scxml +63 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test330.scxml +38 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test331.scxml +70 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test332.scxml +40 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test333.scxml +25 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test335.scxml +25 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test336.scxml +36 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test337.scxml +25 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test338.scxml +49 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test339.scxml +26 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test342.scxml +36 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test343.scxml +36 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test344.scxml +32 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test346.scxml +67 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test347.scxml +53 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test348.scxml +28 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test349.scxml +41 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test350.scxml +34 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test351.scxml +59 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test352.scxml +39 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test354.scxml +63 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test355.scxml +25 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test364.scxml +81 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test372.scxml +36 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test375.scxml +36 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test376.scxml +33 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test377.scxml +41 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test378.scxml +36 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test387.scxml +61 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test388.scxml +76 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test396.scxml +27 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test399.scxml +77 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test401.scxml +27 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test402.scxml +51 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test403a.scxml +48 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test403b.scxml +43 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test403c.scxml +54 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test404.scxml +71 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test405.scxml +78 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test406.scxml +76 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test407.scxml +31 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test409.scxml +45 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test411.scxml +44 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test412.scxml +66 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test413.scxml +59 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test416.scxml +33 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test417.scxml +43 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test419.scxml +27 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test421.scxml +35 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test422.scxml +86 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test423.scxml +36 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test487.scxml +27 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test488.scxml +34 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test495.scxml +35 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test496.scxml +28 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test500.scxml +27 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test501.scxml +31 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test503.scxml +48 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test504.scxml +81 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test505.scxml +58 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test506.scxml +64 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test521.scxml +34 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test525.scxml +31 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test527.scxml +29 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test528.scxml +34 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test529.scxml +27 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test530.scxml +39 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test533.scxml +74 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test550.scxml +26 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test551.scxml +28 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test552.scxml +24 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test552.txt +1 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test553.scxml +34 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test554.scxml +36 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test570.scxml +48 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test576.scxml +45 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test579.scxml +63 -0
- python_statemachine-3.0.0/tests/scxml/w3c/mandatory/test580.scxml +46 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test193.scxml +30 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test201.scxml +25 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test278.scxml +32 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test444.scxml +23 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test445.scxml +22 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test446.scxml +28 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test446.txt +1 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test448.scxml +39 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test449.scxml +19 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test451.scxml +22 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test452.scxml +39 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test453.scxml +28 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test456.scxml +26 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test457.scxml +63 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test459.scxml +46 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test460.scxml +31 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test509.scxml +26 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test510.scxml +31 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test518.scxml +27 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test519.scxml +27 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test520.scxml +31 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test522.scxml +29 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test531.scxml +28 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test532.scxml +28 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test534.scxml +26 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test557.scxml +34 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test557.txt +4 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test558.scxml +33 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test558.txt +3 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test560.scxml +25 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test561.scxml +31 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test562.scxml +28 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test567.scxml +39 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test569.scxml +21 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test577.scxml +26 -0
- python_statemachine-3.0.0/tests/scxml/w3c/optional/test578.scxml +25 -0
- python_statemachine-3.0.0/tests/test_async.py +557 -0
- python_statemachine-3.0.0/tests/test_async_futures.py +341 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_callbacks.py +43 -5
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_callbacks_isolation.py +5 -3
- python_statemachine-3.0.0/tests/test_class_listeners.py +477 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_conditions_algebra.py +10 -7
- python_statemachine-3.0.0/tests/test_contrib_diagram.py +377 -0
- python_statemachine-3.0.0/tests/test_contrib_timeout.py +139 -0
- python_statemachine-3.0.0/tests/test_copy.py +190 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_dispatcher.py +4 -2
- python_statemachine-3.0.0/tests/test_error_execution.py +1132 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_events.py +43 -21
- python_statemachine-3.0.0/tests/test_fellowship_quest.py +452 -0
- python_statemachine-3.0.0/tests/test_invoke.py +1072 -0
- python_statemachine-3.0.0/tests/test_io.py +46 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_listener.py +2 -27
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_mixins.py +1 -1
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_mock_compatibility.py +2 -2
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_multiple_destinations.py +22 -10
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_profiling.py +5 -2
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_registry.py +1 -4
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_rtc.py +46 -92
- python_statemachine-3.0.0/tests/test_scxml_units.py +1040 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_spec_parser.py +61 -60
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_state.py +31 -2
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_state_callbacks.py +2 -2
- python_statemachine-3.0.0/tests/test_statechart_compound.py +341 -0
- python_statemachine-3.0.0/tests/test_statechart_delayed.py +100 -0
- python_statemachine-3.0.0/tests/test_statechart_donedata.py +198 -0
- python_statemachine-3.0.0/tests/test_statechart_error.py +83 -0
- python_statemachine-3.0.0/tests/test_statechart_eventless.py +174 -0
- python_statemachine-3.0.0/tests/test_statechart_history.py +224 -0
- python_statemachine-3.0.0/tests/test_statechart_in_condition.py +162 -0
- python_statemachine-3.0.0/tests/test_statechart_parallel.py +275 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_statemachine.py +329 -85
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_statemachine_bounded_transitions.py +2 -2
- python_statemachine-3.0.0/tests/test_statemachine_compat.py +374 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_statemachine_inheritance.py +3 -3
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_threading.py +37 -55
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_transition_list.py +42 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_transitions.py +110 -40
- python_statemachine-3.0.0/tests/test_validators.py +277 -0
- python_statemachine-3.0.0/tests/test_weighted_transitions.py +458 -0
- python_statemachine-3.0.0/tests/testcases/__init__.py +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/testcases/issue308.md +16 -10
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/testcases/issue384_multiple_observers.md +5 -5
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/testcases/issue449.md +6 -6
- python_statemachine-3.0.0/tests/testcases/test_issue434.py +75 -0
- python_statemachine-3.0.0/tests/testcases/test_issue480.py +56 -0
- python_statemachine-3.0.0/tests/testcases/test_issue509.py +63 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/uv.lock +225 -561
- python_statemachine-2.6.0/AGENTS.md +0 -114
- python_statemachine-2.6.0/PKG-INFO +0 -433
- python_statemachine-2.6.0/README.md +0 -403
- python_statemachine-2.6.0/docs/actions.md +0 -463
- python_statemachine-2.6.0/docs/api.md +0 -81
- python_statemachine-2.6.0/docs/async.md +0 -186
- python_statemachine-2.6.0/docs/diagram.md +0 -154
- python_statemachine-2.6.0/docs/guards.md +0 -277
- python_statemachine-2.6.0/docs/images/order_control_machine_initial.png +0 -0
- python_statemachine-2.6.0/docs/images/order_control_machine_initial_300dpi.png +0 -0
- python_statemachine-2.6.0/docs/images/order_control_machine_processing.png +0 -0
- python_statemachine-2.6.0/docs/images/readme_trafficlightmachine.png +0 -0
- python_statemachine-2.6.0/docs/images/test_state_machine_internal.png +0 -0
- python_statemachine-2.6.0/docs/index.md +0 -33
- python_statemachine-2.6.0/docs/integrations.md +0 -90
- python_statemachine-2.6.0/docs/listeners.md +0 -105
- python_statemachine-2.6.0/docs/mixins.md +0 -93
- python_statemachine-2.6.0/docs/models.md +0 -27
- python_statemachine-2.6.0/docs/processing_model.md +0 -138
- python_statemachine-2.6.0/docs/readme.md +0 -2
- python_statemachine-2.6.0/docs/states.md +0 -166
- python_statemachine-2.6.0/docs/transitions.md +0 -378
- python_statemachine-2.6.0/statemachine/__init__.py +0 -9
- python_statemachine-2.6.0/statemachine/contrib/diagram.py +0 -242
- python_statemachine-2.6.0/statemachine/engines/async_.py +0 -158
- python_statemachine-2.6.0/statemachine/engines/base.py +0 -40
- python_statemachine-2.6.0/statemachine/engines/sync.py +0 -158
- python_statemachine-2.6.0/statemachine/factory.py +0 -261
- python_statemachine-2.6.0/statemachine/graph.py +0 -20
- python_statemachine-2.6.0/statemachine/locale/en/LC_MESSAGES/statemachine.po +0 -107
- python_statemachine-2.6.0/statemachine/statemachine.py +0 -334
- python_statemachine-2.6.0/tests/test_async.py +0 -279
- python_statemachine-2.6.0/tests/test_contrib_diagram.py +0 -90
- python_statemachine-2.6.0/tests/test_copy.py +0 -232
- python_statemachine-2.6.0/tests/testcases/issue434.md +0 -87
- python_statemachine-2.6.0/tests/testcases/issue480.md +0 -43
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/.git-blame-ignore-revs +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/.github/FUNDING.yml +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/.gitignore +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/.readthedocs.yaml +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/CLAUDE.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/LICENSE +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/contributing.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/_static/custom_machine.css +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/authors.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/images/_oc_machine_processing.svg +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/images/lab_approval_machine_accepted.png +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/images/oc_machine_processing.svg +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/images/python-statemachine.png +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/images/traffic_light_machine.png +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/installation.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/0.1.0.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/0.2.0.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/0.3.0.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/0.4.2.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/0.5.0.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/0.5.1.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/0.6.0.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/0.6.1.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/0.6.2.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/0.7.0.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/0.7.1.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/0.8.0.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/0.9.0.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/1.0.0.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/1.0.1.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/1.0.2.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/1.0.3.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/2.1.0.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/2.1.1.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/2.1.2.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/2.3.1.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/2.3.2.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/2.3.3.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/2.3.4.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/2.3.5.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/2.3.6.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/docs/releases/2.6.0.md +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/contrib/__init__.py +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/engines/__init__.py +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/i18n.py +0 -0
- {python_statemachine-2.6.0/tests → python_statemachine-3.0.0/statemachine/io/scxml}/__init__.py +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/mixins.py +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/model.py +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/statemachine/py.typed +0 -0
- {python_statemachine-2.6.0/tests/django_project/workflow → python_statemachine-3.0.0/tests}/__init__.py +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/django_project/app.py +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/django_project/core/__init__,.py +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/django_project/core/settings.py +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/django_project/core/wsgi.py +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/django_project/manage.py +0 -0
- {python_statemachine-2.6.0/tests/examples → python_statemachine-3.0.0/tests/django_project/workflow}/__init__.py +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/django_project/workflow/apps.py +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/django_project/workflow/models.py +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/django_project/workflow/tests.py +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/examples/README.rst +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/helpers.py +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/models.py +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/scrape_images.py +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_actions.py +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_examples.py +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_signature.py +0 -0
- {python_statemachine-2.6.0 → python_statemachine-3.0.0}/tests/test_signature_positional_only.py +0 -0
|
@@ -13,3 +13,5 @@ Tell us what happened, what went wrong, and what you expected to happen.
|
|
|
13
13
|
Paste the command(s) you ran and the output.
|
|
14
14
|
If there was a crash, please include the traceback here.
|
|
15
15
|
```
|
|
16
|
+
|
|
17
|
+
If you're reporting a bug, consider providing a complete example that can be used directly in the automated tests. We allways write tests to reproduce the issue in order to avoid future regressions.
|
{python_statemachine-2.6.0 → python_statemachine-3.0.0}/.github/workflows/python-package.yml
RENAMED
|
@@ -15,7 +15,7 @@ jobs:
|
|
|
15
15
|
strategy:
|
|
16
16
|
fail-fast: false
|
|
17
17
|
matrix:
|
|
18
|
-
python-version: ["3.
|
|
18
|
+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
19
19
|
|
|
20
20
|
steps:
|
|
21
21
|
- uses: actions/checkout@v4
|
|
@@ -46,7 +46,7 @@ jobs:
|
|
|
46
46
|
#----------------------------------------------
|
|
47
47
|
- name: Test with pytest
|
|
48
48
|
run: |
|
|
49
|
-
uv run pytest --cov-report=xml:coverage.xml
|
|
49
|
+
uv run pytest -n auto --cov --cov-report=xml:coverage.xml
|
|
50
50
|
uv run coverage xml
|
|
51
51
|
#----------------------------------------------
|
|
52
52
|
# upload coverage
|
|
@@ -25,9 +25,15 @@ repos:
|
|
|
25
25
|
types: [python]
|
|
26
26
|
language: system
|
|
27
27
|
pass_filenames: false
|
|
28
|
+
- id: pyright
|
|
29
|
+
name: Pyright
|
|
30
|
+
entry: uv run pyright statemachine/
|
|
31
|
+
types: [python]
|
|
32
|
+
language: system
|
|
33
|
+
pass_filenames: false
|
|
28
34
|
- id: pytest
|
|
29
35
|
name: Pytest
|
|
30
|
-
entry: uv run pytest
|
|
36
|
+
entry: uv run pytest -n auto --cov-fail-under=100
|
|
31
37
|
types: [python]
|
|
32
38
|
language: system
|
|
33
39
|
pass_filenames: false
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
# python-statemachine
|
|
2
|
+
|
|
3
|
+
Python Finite State Machines made easy.
|
|
4
|
+
|
|
5
|
+
## Project overview
|
|
6
|
+
|
|
7
|
+
A library for building finite state machines in Python, with support for sync and async engines,
|
|
8
|
+
Django integration, diagram generation, and a flexible callback/listener system.
|
|
9
|
+
|
|
10
|
+
- **Source code:** `statemachine/`
|
|
11
|
+
- **Tests:** `tests/`
|
|
12
|
+
- **Documentation:** `docs/` (Sphinx + MyST Markdown, hosted on ReadTheDocs)
|
|
13
|
+
|
|
14
|
+
## Architecture
|
|
15
|
+
|
|
16
|
+
- `statemachine.py` — Core `StateMachine` and `StateChart` classes
|
|
17
|
+
- `factory.py` — `StateMachineMetaclass` handles class construction, state/transition validation
|
|
18
|
+
- `state.py` / `event.py` — Descriptor-based `State` and `Event` definitions
|
|
19
|
+
- `transition.py` / `transition_list.py` — Transition logic and composition (`|` operator)
|
|
20
|
+
- `callbacks.py` — Priority-based callback registry (`CallbackPriority`, `CallbackGroup`)
|
|
21
|
+
- `dispatcher.py` — Listener/observer pattern, `callable_method` wraps callables with signature adaptation
|
|
22
|
+
- `signature.py` — `SignatureAdapter` for dependency injection into callbacks
|
|
23
|
+
- `engines/base.py` — Shared engine logic (microstep, transition selection, error handling)
|
|
24
|
+
- `engines/sync.py`, `engines/async_.py` — Sync and async processing loops
|
|
25
|
+
- `registry.py` — Global state machine registry (used by `MachineMixin`)
|
|
26
|
+
- `mixins.py` — `MachineMixin` for domain model integration (e.g., Django models)
|
|
27
|
+
- `spec_parser.py` — Boolean expression parser for condition guards
|
|
28
|
+
- `contrib/diagram.py` — Diagram generation via pydot/Graphviz
|
|
29
|
+
|
|
30
|
+
## Processing model
|
|
31
|
+
|
|
32
|
+
The engine follows the SCXML run-to-completion (RTC) model with two processing levels:
|
|
33
|
+
|
|
34
|
+
- **Microstep**: atomic execution of one transition set (before → exit → on → enter → after).
|
|
35
|
+
- **Macrostep**: complete processing cycle for one external event; repeats microsteps until
|
|
36
|
+
the machine reaches a **stable configuration** (no eventless transitions enabled, internal
|
|
37
|
+
queue empty).
|
|
38
|
+
|
|
39
|
+
### Event queues
|
|
40
|
+
|
|
41
|
+
- `send()` → **external queue** (processed after current macrostep ends).
|
|
42
|
+
- `raise_()` → **internal queue** (processed within the current macrostep, before external events).
|
|
43
|
+
|
|
44
|
+
### Error handling (`catch_errors_as_events`)
|
|
45
|
+
|
|
46
|
+
- `StateChart` has `catch_errors_as_events=True` by default; `StateMachine` has `False`.
|
|
47
|
+
- Errors are caught at the **block level** (per onentry/onexit/transition `on` block), not per
|
|
48
|
+
microstep. This means `after` callbacks still run even when an action raises — making
|
|
49
|
+
`after_<event>()` a natural **finalize** hook (runs on both success and failure paths).
|
|
50
|
+
- `error.execution` is dispatched as an internal event; define transitions for it to handle
|
|
51
|
+
errors within the statechart.
|
|
52
|
+
- Error during `error.execution` handling → ignored to prevent infinite loops.
|
|
53
|
+
|
|
54
|
+
#### `on_error` asymmetry: transition `on` vs onentry/onexit
|
|
55
|
+
|
|
56
|
+
Transition `on` content uses `on_error` **only for non-`error.execution` events**. During
|
|
57
|
+
`error.execution` processing, `on_error` is disabled for transition `on` content — errors
|
|
58
|
+
propagate to `microstep()` where `_send_error_execution` ignores them. This prevents infinite
|
|
59
|
+
loops in self-transition error handlers (e.g., `error_execution = s1.to(s1, on="handler")`
|
|
60
|
+
where `handler` raises). `onentry`/`onexit` blocks always use `on_error` regardless of the
|
|
61
|
+
current event.
|
|
62
|
+
|
|
63
|
+
### Eventless transitions
|
|
64
|
+
|
|
65
|
+
- Bare transition statements (not assigned to a variable) are **eventless** — they fire
|
|
66
|
+
automatically when their guard condition is met.
|
|
67
|
+
- Assigned transitions (e.g., `go = s1.to(s2)`) create **named events**.
|
|
68
|
+
- `error_` prefix naming convention: `error_X` auto-registers both `error_X` and `error.X`
|
|
69
|
+
event names (explicit `id=` takes precedence).
|
|
70
|
+
|
|
71
|
+
### Callback conventions
|
|
72
|
+
|
|
73
|
+
- Generic callbacks (always available): `prepare_event()`, `before_transition()`,
|
|
74
|
+
`on_transition()`, `on_exit_state()`, `on_enter_state()`, `after_transition()`.
|
|
75
|
+
- Event-specific: `before_<event>()`, `on_<event>()`, `after_<event>()`.
|
|
76
|
+
- State-specific: `on_enter_<state>()`, `on_exit_<state>()`.
|
|
77
|
+
- `on_error_execution()` works via naming convention but **only** when a transition for
|
|
78
|
+
`error.execution` is declared — it is NOT a generic callback.
|
|
79
|
+
|
|
80
|
+
### Invoke (`<invoke>`)
|
|
81
|
+
|
|
82
|
+
- `invoke.py` — `InvokeManager` on the engine manages the lifecycle: `mark_for_invoke()`,
|
|
83
|
+
`cancel_for_state()`, `spawn_pending_sync/async()`, `send_to_child()`.
|
|
84
|
+
- `_cleanup_terminated()` only removes invocations that are both terminated **and** cancelled.
|
|
85
|
+
A terminated-but-not-cancelled invocation means the handler's `run()` returned but the owning
|
|
86
|
+
state is still active — it must stay in `_active` so `send_to_child()` can still route events.
|
|
87
|
+
- **Child machine constructor blocks** in the processing loop. Use a listener pattern (e.g.,
|
|
88
|
+
`_ChildRefSetter`) to capture the child reference during the first `on_enter_state`, before
|
|
89
|
+
the loop spins.
|
|
90
|
+
- `#_<invokeid>` send target: routed via `_send_to_invoke()` in `io/scxml/actions.py` →
|
|
91
|
+
`InvokeManager.send_to_child()` → handler's `on_event()`.
|
|
92
|
+
- **Tests with blocking threads**: use `threading.Event.wait(timeout=)` instead of
|
|
93
|
+
`time.sleep()` for interruptible waits — avoids thread leak errors in teardown.
|
|
94
|
+
|
|
95
|
+
## Environment setup
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
uv sync --all-extras --dev
|
|
99
|
+
pre-commit install
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Running tests
|
|
103
|
+
|
|
104
|
+
Always use `uv` to run commands. Also, use a timeout to avoid being stuck in the case of a leaked thread or infinite loop:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# Run all tests (parallel)
|
|
108
|
+
timeout 120 uv run pytest -n 4
|
|
109
|
+
|
|
110
|
+
# Run a specific test file
|
|
111
|
+
uv run pytest tests/test_signature.py
|
|
112
|
+
|
|
113
|
+
# Run a specific test
|
|
114
|
+
uv run pytest tests/test_signature.py::TestSignatureAdapter::test_wrap_fn_single_positional_parameter
|
|
115
|
+
|
|
116
|
+
# Skip slow tests
|
|
117
|
+
uv run pytest -m "not slow"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
When trying to run all tests, prefer to use xdist (`-n`) as some SCXML tests uses timeout of 30s to verify fallback mechanism.
|
|
121
|
+
Don't specify the directory `tests/`, because this will exclude doctests from both source modules (`--doctest-modules`) and markdown docs
|
|
122
|
+
(`--doctest-glob=*.md`) (enabled by default):
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
timeout 120 uv run pytest -n 4
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Testes normally run under 60s (~40s on average), so take a closer look if they take longer, it can be a regression.
|
|
129
|
+
|
|
130
|
+
When analyzing warnings or extensive output, run the tests **once** saving the output to a file
|
|
131
|
+
(`> /tmp/pytest-output.txt 2>&1`), then analyze the file — instead of running the suite
|
|
132
|
+
repeatedly with different greps.
|
|
133
|
+
|
|
134
|
+
Coverage is enabled by default (`--cov` is in `pyproject.toml`'s `addopts`). To generate a
|
|
135
|
+
coverage report to a file, pass `--cov-report` **in addition to** `--cov`:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
# JSON report (machine-readable, includes missing_lines per file)
|
|
139
|
+
timeout 120 uv run pytest -n auto --cov=statemachine --cov-report=json:cov.json
|
|
140
|
+
|
|
141
|
+
# Terminal report with missing lines
|
|
142
|
+
timeout 120 uv run pytest -n auto --cov=statemachine --cov-report=term-missing
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Note: `--cov=statemachine` is required to activate coverage collection; `--cov-report`
|
|
146
|
+
alone only changes the output format.
|
|
147
|
+
|
|
148
|
+
### Testing both sync and async engines
|
|
149
|
+
|
|
150
|
+
Use the `sm_runner` fixture (from `tests/conftest.py`) when you need to test the same
|
|
151
|
+
statechart on both sync and async engines. It is parametrized with `["sync", "async"]`
|
|
152
|
+
and provides `start()` / `send()` helpers that handle engine selection automatically:
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
async def test_something(self, sm_runner):
|
|
156
|
+
sm = await sm_runner.start(MyStateChart)
|
|
157
|
+
await sm_runner.send(sm, "some_event")
|
|
158
|
+
assert "expected_state" in sm.configuration_values
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Do **not** manually add async no-op listeners or duplicate test classes — prefer `sm_runner`.
|
|
162
|
+
|
|
163
|
+
## Linting and formatting
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# Lint
|
|
167
|
+
uv run ruff check .
|
|
168
|
+
|
|
169
|
+
# Auto-fix lint issues
|
|
170
|
+
uv run ruff check --fix .
|
|
171
|
+
|
|
172
|
+
# Format
|
|
173
|
+
uv run ruff format .
|
|
174
|
+
|
|
175
|
+
# Type check
|
|
176
|
+
uv run mypy statemachine/ tests/
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Code style
|
|
180
|
+
|
|
181
|
+
- **Formatter/Linter:** ruff (line length 99, target Python 3.9)
|
|
182
|
+
- **Rules:** pycodestyle, pyflakes, isort, pyupgrade, flake8-comprehensions, flake8-bugbear, flake8-pytest-style
|
|
183
|
+
- **Imports:** single-line, sorted by isort. **Always prefer top-level imports** — only use
|
|
184
|
+
lazy (in-function) imports when strictly necessary to break circular dependencies
|
|
185
|
+
- **Docstrings:** Google convention
|
|
186
|
+
- **Naming:** PascalCase for classes, snake_case for functions/methods, UPPER_SNAKE_CASE for constants
|
|
187
|
+
- **Type hints:** used throughout; `TYPE_CHECKING` for circular imports
|
|
188
|
+
- Pre-commit hooks enforce ruff + mypy + pytest
|
|
189
|
+
|
|
190
|
+
## Design principles
|
|
191
|
+
|
|
192
|
+
- **Use GRASP/SOLID patterns to guide decisions.** When refactoring or designing, explicitly
|
|
193
|
+
apply patterns like Information Expert, Single Responsibility, and Law of Demeter to decide
|
|
194
|
+
where logic belongs — don't just pick a convenient location.
|
|
195
|
+
- **Information Expert (GRASP):** Place logic in the module/class that already has the
|
|
196
|
+
knowledge it needs. If a method computes a result, it should signal or return it rather
|
|
197
|
+
than forcing another method to recompute the same thing.
|
|
198
|
+
- **Law of Demeter:** Methods should depend only on the data they need, not on the
|
|
199
|
+
objects that contain it. Pass the specific value (e.g., a `Future`) rather than the
|
|
200
|
+
parent object (e.g., `TriggerData`) — this reduces coupling and removes the need for
|
|
201
|
+
null-checks on intermediate accessors.
|
|
202
|
+
- **Single Responsibility:** Each module, class, and function should have one clear reason
|
|
203
|
+
to change. Functions and types belong in the module that owns their domain (e.g.,
|
|
204
|
+
event-name helpers belong in `event.py`, not in `factory.py`).
|
|
205
|
+
- **Interface Segregation:** Depend on narrow interfaces. If a helper only needs one field
|
|
206
|
+
from a dataclass, accept that field directly.
|
|
207
|
+
- **Decouple infrastructure from domain:** Modules like `signature.py` and `dispatcher.py` are
|
|
208
|
+
general-purpose (signature adaptation, listener/observer pattern) and intentionally not coupled
|
|
209
|
+
to the state machine domain. Prefer this separation even for modules that are only used
|
|
210
|
+
internally — it keeps responsibilities clear and the code easier to reason about.
|
|
211
|
+
- **Favor small, focused modules:** When adding new functionality, consider whether it can live in
|
|
212
|
+
its own module with a well-defined boundary, rather than growing an existing one.
|
|
213
|
+
|
|
214
|
+
## Building documentation
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
# Build HTML docs
|
|
218
|
+
uv run sphinx-build docs docs/_build/html
|
|
219
|
+
|
|
220
|
+
# Live reload for development
|
|
221
|
+
uv run sphinx-autobuild docs docs/_build/html --re-ignore "auto_examples/.*"
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Documentation code examples
|
|
225
|
+
|
|
226
|
+
All code examples in `docs/*.md` **must** be testable doctests (using ```` ```py ```` with
|
|
227
|
+
`>>>` prompts), not plain ```` ```python ```` blocks. The test suite collects them via
|
|
228
|
+
`--doctest-glob=*.md`. If an example cannot be expressed as a doctest (e.g., it requires
|
|
229
|
+
real concurrency), write it as a unit test in `tests/` and reference it from the docs instead.
|
|
230
|
+
|
|
231
|
+
## Git workflow
|
|
232
|
+
|
|
233
|
+
- Main branch: `develop`
|
|
234
|
+
- PRs target `develop`
|
|
235
|
+
- Releases are tagged as `v*.*.*`
|
|
236
|
+
- Signed commits preferred (`git commit -s`)
|
|
237
|
+
- Use [Conventional Commits](https://www.conventionalcommits.org/) messages
|
|
238
|
+
(e.g., `feat:`, `fix:`, `refactor:`, `test:`, `docs:`, `chore:`, `perf:`)
|
|
239
|
+
|
|
240
|
+
## Security
|
|
241
|
+
|
|
242
|
+
- Do not commit secrets, credentials, or `.env` files
|
|
243
|
+
- Validate at system boundaries; trust internal code
|