python-statemachine 3.2.0__tar.gz → 3.2.1__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-3.2.1/.github/workflows/pages.yml +51 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/AGENTS.md +4 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/PKG-INFO +1 -1
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/actions.md +7 -4
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/behaviour.md +5 -1
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/events.md +77 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/guards.md +65 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/how-to/coming_from_transitions.md +26 -1
- python_statemachine-3.2.1/docs/io/security.md +217 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/3.2.0.md +108 -82
- python_statemachine-3.2.1/docs/releases/3.2.1.md +228 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/index.md +1 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/states.md +1 -1
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/pyproject.toml +1 -1
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/__init__.py +1 -1
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/contrib/diagram/extract.py +3 -3
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/dispatcher.py +5 -1
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/engines/async_.py +15 -3
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/engines/base.py +14 -3
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/exceptions.py +1 -1
- python_statemachine-3.2.1/statemachine/io/__init__.py +52 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/io/actions.py +120 -13
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/io/evaluators.py +37 -9
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/io/invoke.py +12 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/io/loader.py +17 -3
- python_statemachine-3.2.1/statemachine/io/scxml/__init__.py +15 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/io/scxml/processor.py +1 -1
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/io/scxml/reader.py +24 -9
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/io/system_variables.py +34 -19
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/orderedset.py +12 -3
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/spec_parser.py +69 -15
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/state.py +2 -2
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/test_loader.py +30 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/test_native_invoke.py +3 -1
- python_statemachine-3.2.1/tests/io/test_security.py +824 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_callbacks.py +96 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_conditions_algebra.py +30 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_scxml_units.py +62 -8
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_spec_parser.py +29 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_spec_parser_values.py +28 -1
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_state.py +15 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_statechart_compound.py +50 -0
- python_statemachine-3.2.1/tests/test_translation_names.py +121 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/uv.lock +1 -1
- python_statemachine-3.2.0/docs/io/security.md +0 -82
- python_statemachine-3.2.0/statemachine/io/__init__.py +0 -45
- python_statemachine-3.2.0/statemachine/io/scxml/__init__.py +0 -12
- python_statemachine-3.2.0/tests/io/test_security.py +0 -230
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/.git-blame-ignore-revs +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/.github/FUNDING.yml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/.github/ISSUE_TEMPLATE.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/.github/workflows/python-package.yml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/.github/workflows/release.yml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/.gitignore +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/.pre-commit-config.yaml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/.readthedocs.yaml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/CLAUDE.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/LICENSE +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/README.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/conftest.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/contributing.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/_static/custom_machine.css +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/api.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/async.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/authors.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/concepts.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/conf.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/contributing.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/diagram.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/error_handling.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/how-to/coming_from_state_pattern.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/images/_oc_machine_processing.svg +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/images/internal_transition_sc.png +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/images/lab_approval_machine_accepted.png +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/images/oc_machine_processing.svg +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/images/python-statemachine.png +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/images/readme_trafficlightmachine.png +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/images/test_state_machine_internal.png +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/images/traffic_light_machine.png +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/index.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/installation.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/integrations.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/invoke.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/io/formats.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/io/index.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/io/json_schema.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/listeners.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/models.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/processing_model.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/0.1.0.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/0.2.0.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/0.3.0.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/0.4.2.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/0.5.0.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/0.5.1.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/0.6.0.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/0.6.1.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/0.6.2.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/0.7.0.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/0.7.1.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/0.8.0.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/0.9.0.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/1.0.0.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/1.0.1.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/1.0.2.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/1.0.3.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/2.0.0.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/2.1.0.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/2.1.1.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/2.1.2.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/2.2.0.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/2.3.0.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/2.3.1.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/2.3.2.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/2.3.3.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/2.3.4.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/2.3.5.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/2.3.6.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/2.4.0.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/2.5.0.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/2.6.0.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/3.0.0.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/3.1.0.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/3.1.1.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/3.1.2.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/releases/upgrade_2x_to_3.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/statechart.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/timeout.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/transitions.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/tutorial.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/validations.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/weighted_transitions.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/callbacks.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/configuration.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/contrib/__init__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/contrib/diagram/__init__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/contrib/diagram/__main__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/contrib/diagram/formatter.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/contrib/diagram/model.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/contrib/diagram/renderers/__init__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/contrib/diagram/renderers/dot.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/contrib/diagram/renderers/mermaid.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/contrib/diagram/renderers/table.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/contrib/diagram/sphinx_ext.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/contrib/timeout.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/contrib/weighted.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/engines/__init__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/engines/sync.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/event.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/event_data.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/events.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/factory.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/graph.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/i18n.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/invoke.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/io/builder.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/io/class_factory.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/io/interpreter.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/io/json/__init__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/io/json/reader.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/io/model.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/io/native.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/io/ports.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/io/schemas/statechart.schema.json +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/io/validation.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/io/yaml/__init__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/io/yaml/reader.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/locale/en/LC_MESSAGES/statemachine.po +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/locale/hi_IN/LC_MESSAGES/statemachine.po +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/locale/pt_BR/LC_MESSAGES/statemachine.po +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/locale/zh_CN/LC_MESSAGES/statemachine.po +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/mixins.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/model.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/py.typed +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/registry.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/signature.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/statemachine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/states.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/transition.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/transition_list.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/transition_mixin.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/statemachine/utils.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/__init__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/conftest.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/django_project/app.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/django_project/core/__init__,.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/django_project/core/settings.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/django_project/core/wsgi.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/django_project/manage.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/django_project/workflow/__init__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/django_project/workflow/apps.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/django_project/workflow/models.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/django_project/workflow/statemachines.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/django_project/workflow/tests.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/README.rst +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/__init__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/ai_shell_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/air_conditioner_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/all_actions_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/async_guess_the_number_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/async_without_loop_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/enum_campaign_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/guess_the_number_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/lor_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/order_control_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/order_control_rich_model_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/persistent_model_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/recursive_event_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/reusing_transitions_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/sqlite_persistent_model_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/statechart_cleanup_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/statechart_compound_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/statechart_delayed_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/statechart_error_handling_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/statechart_eventless_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/statechart_history_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/statechart_in_condition_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/statechart_parallel_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/traffic_light_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/user_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/examples/weighted_idle_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/helpers.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/__init__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/format_parity/guarded_counter.json +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/format_parity/guarded_counter.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/format_parity/guarded_counter.yaml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/format_parity/invoke_child.json +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/format_parity/invoke_child.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/format_parity/invoke_child.yaml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/format_parity/native/order_pipeline.json +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/format_parity/native/order_pipeline.yaml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/format_parity/native/telemetry.json +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/format_parity/native/telemetry.yaml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/format_parity/system_event.json +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/format_parity/system_event.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/format_parity/system_event.yaml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/format_parity/w3c_test147_if.json +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/format_parity/w3c_test147_if.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/format_parity/w3c_test147_if.yaml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/format_parity/w3c_test155_foreach.json +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/format_parity/w3c_test155_foreach.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/format_parity/w3c_test155_foreach.yaml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/test_format_parity.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/test_guards_parity.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/test_interpreter.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/test_model.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/test_native.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/test_native_behavior.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/test_ports.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/test_readers.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/io/test_validation.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/__init__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/compound/__init__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/compound/middle_earth_journey.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/compound/middle_earth_journey_two_compounds.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/compound/middle_earth_journey_with_finals.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/compound/moria_expedition.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/compound/moria_expedition_with_escape.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/compound/quest_for_erebor.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/compound/shire_to_rivendell.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/donedata/__init__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/donedata/destroy_the_ring.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/donedata/destroy_the_ring_simple.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/donedata/nested_quest_donedata.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/donedata/quest_for_erebor_done_convention.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/donedata/quest_for_erebor_explicit_id.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/donedata/quest_for_erebor_multi_word.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/donedata/quest_for_erebor_with_event.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/error/__init__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/error/error_convention_event.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/error/error_convention_transition_list.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/error/error_in_action_sc.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/error/error_in_action_sm_with_flag.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/error/error_in_after_sc.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/error/error_in_error_handler_sc.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/error/error_in_guard_sc.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/error/error_in_guard_sm.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/error/error_in_on_enter_sc.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/eventless/__init__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/eventless/auto_advance.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/eventless/beacon_chain.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/eventless/beacon_chain_lighting.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/eventless/coordinated_advance.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/eventless/ring_corruption.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/eventless/ring_corruption_with_bear_ring.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/eventless/ring_corruption_with_tick.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/history/__init__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/history/deep_memory_of_moria.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/history/gollum_personality.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/history/gollum_personality_default_gollum.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/history/gollum_personality_with_default.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/history/shallow_moria.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/in_condition/__init__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/in_condition/combined_guard.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/in_condition/descendant_check.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/in_condition/eventless_in.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/in_condition/fellowship.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/in_condition/fellowship_coordination.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/in_condition/gate_of_moria.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/parallel/__init__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/parallel/session.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/parallel/session_with_done_state.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/parallel/two_towers.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/parallel/war_of_the_ring.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/parallel/war_with_exit.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/showcase_actions.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/showcase_compound.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/showcase_deep_history.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/showcase_guards.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/showcase_history.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/showcase_internal.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/showcase_parallel.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/showcase_parallel_compound.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/showcase_self_transition.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/showcase_simple.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/transition_from_any.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/tutorial_coffee_order.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/validators/__init__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/validators/multi_validator.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/validators/order_validation.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/validators/order_validation_no_error_events.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/validators/validator_fallthrough.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/validators/validator_with_cond.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/validators/validator_with_error_transition.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/workflow/__init__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/workflow/campaign_machine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/workflow/campaign_machine_with_validator.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/workflow/campaign_machine_with_values.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/machines/workflow/reverse_traffic_light.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/models.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scrape_images.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/__init__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/_harness.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/conftest.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/test_microwave.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/test_scxml_cases.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/LICENSE +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test144.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test145.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test147.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test148.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test149.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test150.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test151.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test152.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test153.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test155.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test156.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test158.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test159.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test172.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test173.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test174.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test175.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test176.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test179.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test183.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test185.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test186.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test187.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test189.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test190.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test191.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test192.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test194.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test198.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test199.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test200.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test205.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test207.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test208.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test210.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test215.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test216.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test216sub1.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test220.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test223.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test224.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test225.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test226.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test226sub1.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test228.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test229.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test232.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test233.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test234.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test235.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test236.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test237.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test239.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test239sub1.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test240.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test241.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test242.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test242sub1.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test243.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test244.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test245.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test247.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test252.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test253.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test276.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test276sub1.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test277.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test279.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test280.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test286.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test287.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test294.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test298.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test302.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test303.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test304.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test309.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test310.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test311.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test312.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test318.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test319.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test321.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test322.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test323.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test324.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test325.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test326.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test329.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test330.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test331.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test332.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test333.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test335.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test336.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test337.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test338.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test339.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test342.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test343.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test344.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test346.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test347.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test348.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test349.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test350.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test351.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test352.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test354.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test355.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test364.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test372.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test375.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test376.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test377.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test378.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test387.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test388.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test396.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test399.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test401.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test402.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test403a.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test403b.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test403c.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test404.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test405.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test406.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test407.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test409.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test411.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test412.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test413.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test416.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test417.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test419.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test421.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test422.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test423.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test487.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test488.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test495.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test496.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test500.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test501.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test503.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test504.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test505.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test506.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test521.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test525.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test527.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test528.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test529.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test530.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test533.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test550.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test551.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test552.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test552.txt +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test553.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test554.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test570.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test576.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test579.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/mandatory/test580.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test193.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test201.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test278.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test444.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test445.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test446.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test446.txt +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test448.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test449.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test451.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test452.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test453.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test456.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test457.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test459.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test460.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test509.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test510.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test518.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test519.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test520.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test522.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test531.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test532.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test534.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test557.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test557.txt +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test558.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test558.txt +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test560.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test561.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test562.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test567.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test569.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test577.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/scxml/w3c/optional/test578.scxml +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_actions.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_api_contract.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_async.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_async_futures.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_callbacks_isolation.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_class_listeners.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_configuration.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_contrib_diagram.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_contrib_timeout.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_copy.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_dispatcher.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_error_execution.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_events.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_examples.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_fellowship_quest.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_invoke.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_io.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_listener.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_mermaid_renderer.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_mixins.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_mock_compatibility.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_multiple_destinations.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_optional_pydot.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_profiling.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_registry.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_rtc.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_scxml_datamodel.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_signature.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_signature_positional_only.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_state_callbacks.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_statechart_delayed.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_statechart_donedata.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_statechart_error.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_statechart_eventless.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_statechart_history.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_statechart_in_condition.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_statechart_parallel.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_statemachine.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_statemachine_bounded_transitions.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_statemachine_compat.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_statemachine_inheritance.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_threading.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_transition_list.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_transition_table.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_transitions.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_validators.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/test_weighted_transitions.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/testcases/__init__.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/testcases/issue308.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/testcases/issue384_multiple_observers.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/testcases/issue449.md +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/testcases/test_issue434.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/testcases/test_issue480.py +0 -0
- {python_statemachine-3.2.0 → python_statemachine-3.2.1}/tests/testcases/test_issue509.py +0 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name: pages
|
|
2
|
+
|
|
3
|
+
# Publishes the static assets served at https://fgmacedo.github.io/python-statemachine/
|
|
4
|
+
# Currently: the native statechart JSON Schema, at the canonical URL used as its `$id`
|
|
5
|
+
# (statemachine/io/schemas/statechart.schema.json -> /schemas/statechart/v1.json).
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
branches: [develop]
|
|
10
|
+
paths:
|
|
11
|
+
- statemachine/io/schemas/statechart.schema.json
|
|
12
|
+
- .github/workflows/pages.yml
|
|
13
|
+
release:
|
|
14
|
+
types: [published]
|
|
15
|
+
workflow_dispatch:
|
|
16
|
+
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
pages: write
|
|
20
|
+
id-token: write
|
|
21
|
+
|
|
22
|
+
# Allow one concurrent deployment; don't cancel an in-progress publish.
|
|
23
|
+
concurrency:
|
|
24
|
+
group: pages
|
|
25
|
+
cancel-in-progress: false
|
|
26
|
+
|
|
27
|
+
jobs:
|
|
28
|
+
deploy:
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
environment:
|
|
31
|
+
name: github-pages
|
|
32
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v5
|
|
35
|
+
- name: Assemble site
|
|
36
|
+
run: |
|
|
37
|
+
mkdir -p _site/schemas/statechart
|
|
38
|
+
cp statemachine/io/schemas/statechart.schema.json _site/schemas/statechart/v1.json
|
|
39
|
+
cat > _site/index.html <<'HTML'
|
|
40
|
+
<!doctype html>
|
|
41
|
+
<meta charset="utf-8">
|
|
42
|
+
<title>python-statemachine</title>
|
|
43
|
+
<meta http-equiv="refresh" content="0; url=https://python-statemachine.readthedocs.io/">
|
|
44
|
+
<p>See the <a href="schemas/statechart/v1.json">statechart JSON Schema</a> or the
|
|
45
|
+
<a href="https://python-statemachine.readthedocs.io/">documentation</a>.</p>
|
|
46
|
+
HTML
|
|
47
|
+
- uses: actions/upload-pages-artifact@v3
|
|
48
|
+
with:
|
|
49
|
+
path: _site
|
|
50
|
+
- id: deployment
|
|
51
|
+
uses: actions/deploy-pages@v4
|
|
@@ -302,6 +302,10 @@ enforced, so when you add or change native vocabulary:
|
|
|
302
302
|
- Signed commits preferred (`git commit -s`)
|
|
303
303
|
- Use [Conventional Commits](https://www.conventionalcommits.org/) messages
|
|
304
304
|
(e.g., `feat:`, `fix:`, `refactor:`, `test:`, `docs:`, `chore:`, `perf:`)
|
|
305
|
+
- **NEVER bypass pre-commit hooks** (`--no-verify`, `-n`, or disabling hooks). The hooks
|
|
306
|
+
inspect every commit to keep regressions out; only the maintainer may decide to skip them.
|
|
307
|
+
If a hook modifies files (e.g. `generate-images` regenerating a diagram PNG), stage the
|
|
308
|
+
generated changes and commit again until the hooks pass — do not skip them.
|
|
305
309
|
|
|
306
310
|
## Security
|
|
307
311
|
|
|
@@ -145,10 +145,13 @@ levels of the hierarchy.
|
|
|
145
145
|
|
|
146
146
|
```{note}
|
|
147
147
|
The generic `on_exit_state()` and `on_enter_state()` callbacks also fire
|
|
148
|
-
once per state in the set,
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
state
|
|
148
|
+
once per state in the set, and the `state` parameter is bound to the
|
|
149
|
+
individual state being exited or entered, so you can tell each level of a
|
|
150
|
+
compound apart. On entry, `target` matches `state`; on exit, `source`
|
|
151
|
+
matches `state`. The opposite endpoint stays fixed at the transition's
|
|
152
|
+
`source` (on entry) or `target` (on exit). Prefer state-specific callbacks
|
|
153
|
+
(`on_exit_<state>`, `on_enter_<state>`) when you want to target one level
|
|
154
|
+
directly.
|
|
152
155
|
```
|
|
153
156
|
|
|
154
157
|
```{seealso}
|
|
@@ -28,7 +28,7 @@ SCXML-compliant behavior provides more predictable semantics.
|
|
|
28
28
|
```{warning}
|
|
29
29
|
This page describes runtime *semantics*. If you **load SCXML documents** via
|
|
30
30
|
`SCXMLProcessor`, note that SCXML is executable content: by default the
|
|
31
|
-
datamodel is evaluated with a restricted AST
|
|
31
|
+
datamodel is evaluated with a restricted AST allowlist and `<script>` is
|
|
32
32
|
rejected, so untrusted documents cannot execute arbitrary code. Pass
|
|
33
33
|
`trusted=True` only for SCXML you control. See the 3.2.0 release notes and
|
|
34
34
|
GHSA-v4jc-pm6r-3vj8.
|
|
@@ -158,6 +158,10 @@ When `True` (SCXML default), runtime exceptions in action callbacks
|
|
|
158
158
|
internal `error.execution` events. When `False` (legacy default), exceptions
|
|
159
159
|
propagate normally to the caller.
|
|
160
160
|
|
|
161
|
+
This flag only governs exceptions raised **inside** an action callback. An event
|
|
162
|
+
that doesn't match any enabled transition is a different case, controlled by
|
|
163
|
+
{ref}`allow_event_without_transition <behaviour>` instead.
|
|
164
|
+
|
|
161
165
|
```{note}
|
|
162
166
|
{ref}`Validators <validators>` are **not** affected by this flag — they
|
|
163
167
|
always propagate exceptions to the caller, regardless of the
|
|
@@ -131,6 +131,83 @@ delayed events, and cancellation.
|
|
|
131
131
|
```
|
|
132
132
|
|
|
133
133
|
|
|
134
|
+
(events-as-method-protocol)=
|
|
135
|
+
|
|
136
|
+
## Events as a method-call protocol
|
|
137
|
+
|
|
138
|
+
Because every event is a callable method, a state machine can act as a guard
|
|
139
|
+
for the **order** in which your object's methods may be called. Set
|
|
140
|
+
`allow_event_without_transition = False` so that any call that doesn't match an
|
|
141
|
+
enabled transition raises `TransitionNotAllowed` instead of being silently
|
|
142
|
+
ignored. The transitions then describe the legal
|
|
143
|
+
sequence, and the machine enforces it for you:
|
|
144
|
+
|
|
145
|
+
```py
|
|
146
|
+
>>> from statemachine import State, StateChart
|
|
147
|
+
|
|
148
|
+
>>> class Connection(StateChart):
|
|
149
|
+
... "A client whose methods can only be called in a valid order."
|
|
150
|
+
... allow_event_without_transition = False # reject any unexpected call
|
|
151
|
+
...
|
|
152
|
+
... disconnected = State(initial=True)
|
|
153
|
+
... connected = State()
|
|
154
|
+
... authenticated = State()
|
|
155
|
+
...
|
|
156
|
+
... connect = disconnected.to(connected)
|
|
157
|
+
... authenticate = connected.to(authenticated)
|
|
158
|
+
... disconnect = connected.to(disconnected) | authenticated.to(disconnected)
|
|
159
|
+
...
|
|
160
|
+
... def on_connect(self):
|
|
161
|
+
... print("socket opened")
|
|
162
|
+
...
|
|
163
|
+
... def on_authenticate(self):
|
|
164
|
+
... print("credentials accepted")
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Calling the methods in a valid order works:
|
|
169
|
+
|
|
170
|
+
```py
|
|
171
|
+
>>> conn = Connection()
|
|
172
|
+
>>> conn.connect()
|
|
173
|
+
socket opened
|
|
174
|
+
>>> conn.authenticate()
|
|
175
|
+
credentials accepted
|
|
176
|
+
>>> "authenticated" in conn.configuration_values
|
|
177
|
+
True
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
A call that isn't valid in the current state raises, so an out-of-order method
|
|
182
|
+
call fails loudly instead of doing nothing:
|
|
183
|
+
|
|
184
|
+
```py
|
|
185
|
+
>>> fresh = Connection()
|
|
186
|
+
|
|
187
|
+
>>> fresh.authenticate() # must connect first
|
|
188
|
+
Traceback (most recent call last):
|
|
189
|
+
...
|
|
190
|
+
statemachine.exceptions.TransitionNotAllowed: Can't Authenticate when in Disconnected.
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
The same protection applies to unknown event names sent dynamically:
|
|
195
|
+
|
|
196
|
+
```py
|
|
197
|
+
>>> fresh.send("teleport")
|
|
198
|
+
Traceback (most recent call last):
|
|
199
|
+
...
|
|
200
|
+
statemachine.exceptions.TransitionNotAllowed: Can't teleport when in Disconnected.
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
```{seealso}
|
|
205
|
+
{ref}`behaviour` explains `allow_event_without_transition` and the other
|
|
206
|
+
class-level flags that switch between this strict mode and the tolerant,
|
|
207
|
+
event-driven default.
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
|
|
134
211
|
(event-parameter)=
|
|
135
212
|
|
|
136
213
|
## The `event` parameter on transitions
|
|
@@ -132,6 +132,71 @@ example combining multiple transitions on the same event.
|
|
|
132
132
|
```
|
|
133
133
|
|
|
134
134
|
|
|
135
|
+
(callable conditions)=
|
|
136
|
+
|
|
137
|
+
### Callable conditions
|
|
138
|
+
|
|
139
|
+
Besides strings, `cond` and `unless` also accept callables directly, including
|
|
140
|
+
lambdas, allowing simple guards to be defined inline:
|
|
141
|
+
|
|
142
|
+
```py
|
|
143
|
+
>>> class Turnstile(StateChart):
|
|
144
|
+
... locked = State(initial=True)
|
|
145
|
+
... unlocked = State(final=True)
|
|
146
|
+
...
|
|
147
|
+
... coin = locked.to(unlocked, cond=lambda machine: machine.credits > 0)
|
|
148
|
+
...
|
|
149
|
+
... credits = 0
|
|
150
|
+
|
|
151
|
+
>>> sm = Turnstile()
|
|
152
|
+
>>> sm.send("coin")
|
|
153
|
+
>>> "locked" in sm.configuration_values
|
|
154
|
+
True
|
|
155
|
+
|
|
156
|
+
>>> sm.credits = 1
|
|
157
|
+
>>> sm.send("coin")
|
|
158
|
+
>>> "unlocked" in sm.configuration_values
|
|
159
|
+
True
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Like any callback, a callable condition receives its arguments via
|
|
164
|
+
{ref}`dependency injection <dependency-injection>`: declare only the
|
|
165
|
+
parameters you need, using the injectable names (`machine`, `event`,
|
|
166
|
+
`source`, `target`, `model`, ...) or the arguments passed when triggering
|
|
167
|
+
the event:
|
|
168
|
+
|
|
169
|
+
```py
|
|
170
|
+
>>> class Dispatcher(StateChart):
|
|
171
|
+
... idle = State(initial=True)
|
|
172
|
+
... dispatched = State(final=True)
|
|
173
|
+
...
|
|
174
|
+
... dispatch = idle.to(dispatched, cond=lambda priority=0: priority > 5)
|
|
175
|
+
|
|
176
|
+
>>> sm = Dispatcher()
|
|
177
|
+
>>> sm.send("dispatch", priority=1)
|
|
178
|
+
>>> "idle" in sm.configuration_values
|
|
179
|
+
True
|
|
180
|
+
|
|
181
|
+
>>> sm.send("dispatch", priority=9)
|
|
182
|
+
>>> "dispatched" in sm.configuration_values
|
|
183
|
+
True
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
```{warning}
|
|
188
|
+
Plain callables, like lambdas and functions defined outside the class body,
|
|
189
|
+
are called **unbound**, so `self` is not injected. A guard declared as
|
|
190
|
+
`cond=lambda self: ...` fails with a `TypeError` when evaluated. Use
|
|
191
|
+
`machine` instead of `self` to receive the state machine instance.
|
|
192
|
+
|
|
193
|
+
`self` is only available when the callable resolves to a bound method,
|
|
194
|
+
which happens when it is an attribute of the state machine class: either
|
|
195
|
+
referenced by name (`cond="my_condition"`) or defined in the class body
|
|
196
|
+
and passed by reference (`cond=my_condition`).
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
|
|
135
200
|
(condition expressions)=
|
|
136
201
|
|
|
137
202
|
### Condition expressions
|
{python_statemachine-3.2.0 → python_statemachine-3.2.1}/docs/how-to/coming_from_transitions.md
RENAMED
|
@@ -28,6 +28,7 @@ shown side by side where possible. For a quick overview, jump to the
|
|
|
28
28
|
| Error handling | Exceptions propagate | Optional {ref}`catch_errors_as_events <error-execution>` (`error.execution`) |
|
|
29
29
|
| Validations | None | {ref}`Structural + callback checks <validations>` at definition and creation time |
|
|
30
30
|
| SCXML compliance | [Not a goal](https://github.com/pytransitions/transitions/issues/446#issuecomment-646837282) | {ref}`W3C conformant <processing-model>` with automated test suite |
|
|
31
|
+
| Serialization / loading | `markup` dict round-trip (persist as JSON/YAML yourself; no SCXML) | [Secure `io.load()`](../io/index.md) from SCXML, JSON and YAML |
|
|
31
32
|
| Processing model | Immediate or queued | Always queued ({ref}`run-to-completion <rtc-model>`) |
|
|
32
33
|
|
|
33
34
|
|
|
@@ -178,7 +179,7 @@ python-statemachine also supports hierarchical features not available in *transi
|
|
|
178
179
|
See {ref}`compound-states` and {ref}`parallel-states` for the full reference.
|
|
179
180
|
|
|
180
181
|
|
|
181
|
-
### Creating machines from dicts
|
|
182
|
+
### Creating machines from dicts and documents
|
|
182
183
|
|
|
183
184
|
If you prefer the dict-based definition style familiar from *transitions*, you can
|
|
184
185
|
use {func}`~statemachine.io.create_machine_class_from_definition` to build a
|
|
@@ -218,6 +219,28 @@ The result is a regular `StateChart` subclass — all features (validations, dia
|
|
|
218
219
|
listeners, async) work exactly the same way. See
|
|
219
220
|
{func}`~statemachine.io.create_machine_class_from_definition` for the full API.
|
|
220
221
|
|
|
222
|
+
#### Loading from SCXML, JSON or YAML documents
|
|
223
|
+
|
|
224
|
+
*transitions* can serialize a built machine to a Python dict with `MarkupMachine`
|
|
225
|
+
(`machine.markup`) and rebuild it via `Machine(markup=...)`. That dict isn't tied to a file
|
|
226
|
+
format — you persist it as JSON/YAML yourself — and callbacks and conditions are method-name
|
|
227
|
+
strings resolved against the model by import at build time, so it isn't designed to load
|
|
228
|
+
untrusted definitions, has no published schema, and doesn't cover SCXML.
|
|
229
|
+
|
|
230
|
+
python-statemachine provides a first-class, secure loader, {func}`~statemachine.io.load`,
|
|
231
|
+
that reads SCXML, JSON and YAML *documents* straight into a `StateChart`:
|
|
232
|
+
|
|
233
|
+
```python
|
|
234
|
+
from statemachine.io import load
|
|
235
|
+
|
|
236
|
+
Machine = load("traffic_light.scxml") # or .json / .yaml; format detected from the extension
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Expressions in the document (guards, datamodel) are evaluated by a restricted allowlist —
|
|
240
|
+
never `eval` — so documents from untrusted sources are safe to load; the native JSON/YAML
|
|
241
|
+
format has a published JSON Schema (`validate=True`), and SCXML follows the W3C execution
|
|
242
|
+
model. See [](../io/index.md) for the full guide.
|
|
243
|
+
|
|
221
244
|
|
|
222
245
|
## Defining transitions
|
|
223
246
|
|
|
@@ -952,6 +975,8 @@ See {ref}`validations` for the full list.
|
|
|
952
975
|
| {ref}`Listener/observer pattern <listeners>` | No | **Yes** |
|
|
953
976
|
| {ref}`Definition-time validations <validations>` | No | **Yes** |
|
|
954
977
|
| {ref}`SCXML conformance <processing-model>` | No | **Yes** |
|
|
978
|
+
| [Load from SCXML/JSON/YAML documents](../io/index.md) | No | **Yes** |
|
|
979
|
+
| Serialize a built machine to a portable definition | Yes (`markup`) | Partial (load only) |
|
|
955
980
|
| {ref}`Diagrams <diagrams>` | Yes | Yes |
|
|
956
981
|
| {ref}`Django integration <machinemixin>` | Community | Built-in |
|
|
957
982
|
| {ref}`Model binding <models>` | Yes | Yes |
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# Security: secure by default
|
|
2
|
+
|
|
3
|
+
Loading a statechart compiles its guards, datamodel expressions and executable content into
|
|
4
|
+
callables. A statechart is an **executable document**, not inert data, so loading one is closer
|
|
5
|
+
to importing code than to parsing JSON. The IO layer is **secure by default** (`trusted=False`)
|
|
6
|
+
so that loading a semi-trusted document does not turn into code execution or file disclosure,
|
|
7
|
+
but it is worth being precise about what that guarantee does and does not cover.
|
|
8
|
+
|
|
9
|
+
## Intended use, and the limits of "safe"
|
|
10
|
+
|
|
11
|
+
The primary use case for declarative loading is your **own** dynamic definitions: statecharts
|
|
12
|
+
produced by your application, a no-code editor you ship, your own tooling, or configuration you
|
|
13
|
+
control. For those, `trusted=False` is a defense-in-depth backstop.
|
|
14
|
+
|
|
15
|
+
Loading a document authored by a genuine **adversary** is a stronger threat. `trusted=False`
|
|
16
|
+
removes the obvious code- and file-execution vectors described below, but a statechart is still
|
|
17
|
+
an executable document: the most reliable protection against a hostile document is to not run
|
|
18
|
+
it, or to run it under OS-level isolation (see [](#availability-is-not-sandboxed)). Treat
|
|
19
|
+
`trusted=False` as *hardening*, not as a sandbox, and do not rely on it as your only control
|
|
20
|
+
for documents from parties you do not trust.
|
|
21
|
+
|
|
22
|
+
## What the guarantee covers (and what it does not)
|
|
23
|
+
|
|
24
|
+
Loading a statechart produces a **runnable machine**, not the inert data `yaml.safe_load`
|
|
25
|
+
returns. So the `trusted` flag is best understood as a guarantee about **confidentiality and
|
|
26
|
+
integrity**, not about **availability**:
|
|
27
|
+
|
|
28
|
+
- **Loading is safe (confidentiality + integrity).** With the default `trusted=False`, loading
|
|
29
|
+
a document never runs arbitrary code and never reads arbitrary files. Expressions go through a
|
|
30
|
+
restricted evaluator (below), `<script>` is rejected, and external resource references
|
|
31
|
+
(`<data src>`, `<invoke src>`) are rejected. YAML is read with safe-load semantics and JSON
|
|
32
|
+
with the stdlib parser, so a document can never instantiate arbitrary Python objects.
|
|
33
|
+
- **Running is not sandboxed (availability).** Once you start a machine, the document's logic
|
|
34
|
+
executes. `trusted` does **not** bound how much CPU, memory or time that logic consumes. A
|
|
35
|
+
malicious document can still cause denial of service. See [](#availability-is-not-sandboxed).
|
|
36
|
+
|
|
37
|
+
## The two evaluation modes
|
|
38
|
+
|
|
39
|
+
`load(..., trusted=False)` (the default) uses a **restricted evaluator** built on an AST
|
|
40
|
+
allowlist. It allows the everyday building blocks of a guard or expression:
|
|
41
|
+
|
|
42
|
+
- comparisons (`==`, `!=`, `<`, `>=`, …) and boolean algebra (`and`, `or`, `not`);
|
|
43
|
+
- arithmetic, indexing (`items[0]`), and list/tuple/set/dict literals;
|
|
44
|
+
- reading attributes, **including property getters** (`order.is_ready`);
|
|
45
|
+
- the `In(state_id)` predicate for testing the active configuration.
|
|
46
|
+
|
|
47
|
+
It refuses anything that could escape the sandbox:
|
|
48
|
+
|
|
49
|
+
- function and method calls (the only exception is `In(...)`);
|
|
50
|
+
- builtins (`len`, `open`, `__import__`, …), lambdas and comprehensions;
|
|
51
|
+
- dunder or private attribute access (`x.__class__`, `x._secret`).
|
|
52
|
+
|
|
53
|
+
A rejected expression fails **at load time** with `InvalidDefinition`, not later at runtime:
|
|
54
|
+
|
|
55
|
+
```py
|
|
56
|
+
>>> from statemachine.io import load
|
|
57
|
+
>>> from statemachine.exceptions import InvalidDefinition
|
|
58
|
+
|
|
59
|
+
>>> doc = """
|
|
60
|
+
... states:
|
|
61
|
+
... s:
|
|
62
|
+
... initial: true
|
|
63
|
+
... transitions:
|
|
64
|
+
... - {event: go, target: s, cond: "escape_to_shell()"}
|
|
65
|
+
... """
|
|
66
|
+
>>> try:
|
|
67
|
+
... load(doc, format="yaml")
|
|
68
|
+
... except InvalidDefinition:
|
|
69
|
+
... print("rejected")
|
|
70
|
+
rejected
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
What the allowlist refuses is **call syntax** (`name()`, `obj.method()`), so an attacker's
|
|
75
|
+
expression cannot reach builtins, the one exception being `In(...)`:
|
|
76
|
+
|
|
77
|
+
- `cond: "order.is_ready"` — allowed (a plain attribute read, which runs the property getter).
|
|
78
|
+
- `cond: "order.is_ready()"` — rejected (call syntax).
|
|
79
|
+
|
|
80
|
+
Guards (`cond`/`unless`) have one extra affordance, matching class-defined guards: a bare name
|
|
81
|
+
that resolves to a model **method** is invoked by name, like a callback reference, receiving
|
|
82
|
+
the event's keyword arguments. That is still safe, it runs the integrator's own method named
|
|
83
|
+
in the document, not arbitrary code, so guard logic can be a property, an attribute or a
|
|
84
|
+
method without `trusted=True`.
|
|
85
|
+
|
|
86
|
+
## What `trusted=True` unlocks
|
|
87
|
+
|
|
88
|
+
`load(..., trusted=True)` evaluates expressions as full Python (`eval`) and enables the
|
|
89
|
+
`script` action (`exec`). Concretely, it adds exactly what the restricted mode withholds:
|
|
90
|
+
|
|
91
|
+
- method calls and builtins inside guards and expressions (`len(cart)`, `order.is_ready()`,
|
|
92
|
+
`_event.data.get("x")`);
|
|
93
|
+
- the `script` action, a block of Python statements that reads and writes the model.
|
|
94
|
+
|
|
95
|
+
Everything else, the `assign`, `raise`, `send`, `log`, `foreach`, `cancel` and `if` actions,
|
|
96
|
+
already works in both modes; `script` is the only action gated behind `trusted`. Errors in
|
|
97
|
+
trusted expressions surface at runtime (as `error.execution`) rather than at load time.
|
|
98
|
+
|
|
99
|
+
Use `trusted=True` **only** for documents you fully control.
|
|
100
|
+
|
|
101
|
+
## Write targets are confined to public attributes
|
|
102
|
+
|
|
103
|
+
Actions that write to the datamodel take the destination *name* from the document:
|
|
104
|
+
`<assign location>`, `<foreach item>`/`index`, `<data id>` and `<send>`/`<invoke>` `idlocation`.
|
|
105
|
+
In every case the name must be a plain, public model attribute. Private (`_`-prefixed), dunder
|
|
106
|
+
(`__class__`, `__init__`, …) and engine-protected names are rejected, and for a dotted
|
|
107
|
+
`<assign location="a.b.c">` the check applies to **every** segment, not just the last one. This
|
|
108
|
+
stops a document from traversing `__class__` to corrupt the shared model class (which would
|
|
109
|
+
break every machine in the process) or from overwriting engine internals. As a second layer,
|
|
110
|
+
a live engine-capability instance (the machine, the interpreter, a core `State`/`Transition`/
|
|
111
|
+
`Event`, or the `_event`/`_ioprocessors` system-variable views) is also rejected as a traversed
|
|
112
|
+
hop or write target, so even a value that somehow referenced one cannot be used to mutate state
|
|
113
|
+
shared across machines. A rejected write surfaces as `error.execution`, the same as any other
|
|
114
|
+
action failure.
|
|
115
|
+
|
|
116
|
+
## Arithmetic is magnitude-bounded
|
|
117
|
+
|
|
118
|
+
The restricted evaluator allows arithmetic, but `**` and `*` are capped so that a tiny
|
|
119
|
+
expression cannot exhaust CPU or memory: an exponentiation whose result would be enormous
|
|
120
|
+
(`9 ** 9 ** 9`, a ~370-million-digit number) and a sequence replication that would allocate a
|
|
121
|
+
huge object (`[0] * 20000000`) are both rejected before they run. Ordinary scalar arithmetic
|
|
122
|
+
(`x * 2`, `x ** 2`) is unaffected. Under `trusted=True` the full Python evaluator is used, so
|
|
123
|
+
these caps do not apply.
|
|
124
|
+
|
|
125
|
+
## External resource references (`src`)
|
|
126
|
+
|
|
127
|
+
`<data src="file:…">` and `<invoke src="…">` (and `srcexpr`) read a **local file** named by the
|
|
128
|
+
document. Because a malicious document could point them at any file on the host and then
|
|
129
|
+
exfiltrate the contents (via `<log>`, `<send>` or the datamodel), they are gated exactly like
|
|
130
|
+
`<script>`: rejected by default, allowed only with `trusted=True`.
|
|
131
|
+
|
|
132
|
+
```py
|
|
133
|
+
>>> from statemachine.io import load
|
|
134
|
+
>>> from statemachine.exceptions import InvalidDefinition
|
|
135
|
+
|
|
136
|
+
>>> doc = """
|
|
137
|
+
... <scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s">
|
|
138
|
+
... <datamodel><data id="x" src="file:///etc/passwd"/></datamodel>
|
|
139
|
+
... <state id="s"/>
|
|
140
|
+
... </scxml>
|
|
141
|
+
... """
|
|
142
|
+
>>> try:
|
|
143
|
+
... load(doc, format="scxml")
|
|
144
|
+
... except InvalidDefinition:
|
|
145
|
+
... print("rejected")
|
|
146
|
+
rejected
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
The file is never opened in the default mode: the rejection happens at load time, before any
|
|
151
|
+
`open()`. This also applies to a relative `src` (e.g. `src: child.yaml`), so loading a document
|
|
152
|
+
that includes a child from disk requires `trusted=True`.
|
|
153
|
+
|
|
154
|
+
## XML hardening
|
|
155
|
+
|
|
156
|
+
The SCXML parser refuses any `<!DOCTYPE>`/DTD. Internal entity definitions (which a DTD enables)
|
|
157
|
+
are the basis of *entity-expansion* denial-of-service bombs (billion laughs / quadratic blowup),
|
|
158
|
+
so they are rejected at parse time, independent of `trusted`:
|
|
159
|
+
|
|
160
|
+
```py
|
|
161
|
+
>>> bomb = """<?xml version="1.0"?>
|
|
162
|
+
... <!DOCTYPE scxml [<!ENTITY a "AAAAAAAAAA"><!ENTITY b "&a;&a;&a;&a;&a;">]>
|
|
163
|
+
... <scxml xmlns="http://www.w3.org/2005/07/scxml" initial="s"><state id="s"/></scxml>
|
|
164
|
+
... """
|
|
165
|
+
>>> try:
|
|
166
|
+
... load(bomb, format="scxml")
|
|
167
|
+
... except InvalidDefinition:
|
|
168
|
+
... print("rejected")
|
|
169
|
+
rejected
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Availability is not sandboxed
|
|
174
|
+
|
|
175
|
+
The guarantees above protect **confidentiality and integrity** of the host. They do **not** bound
|
|
176
|
+
the **resources** a running machine consumes. Even a document with no unsafe element can, once
|
|
177
|
+
started, exhaust CPU, memory or threads:
|
|
178
|
+
|
|
179
|
+
- **Eventless loops**: two states with eventless transitions between them (`a → b → a`) never
|
|
180
|
+
reach a stable configuration, so a macrostep never completes.
|
|
181
|
+
- **`<foreach>` over a huge collection**: iterating a very large iterable.
|
|
182
|
+
- **Recursive `<invoke>`**: a document that invokes itself (directly or in a cycle) spawns
|
|
183
|
+
unbounded child machines and threads.
|
|
184
|
+
- **Delayed-event accumulation**: scheduling many `<send delay="…">` events.
|
|
185
|
+
|
|
186
|
+
The state machine engine follows the SCXML run-to-completion model and intentionally does not
|
|
187
|
+
impose iteration, size or recursion limits. **If you load and run documents from untrusted
|
|
188
|
+
sources, run them under your own resource controls**: an execution timeout, and OS/process
|
|
189
|
+
limits on CPU, memory and threads (e.g. a subprocess with `resource` rlimits, a container, or a
|
|
190
|
+
watchdog that stops the machine).
|
|
191
|
+
|
|
192
|
+
## Background
|
|
193
|
+
|
|
194
|
+
This safe-by-default behaviour comes from the security advisory
|
|
195
|
+
[GHSA-v4jc-pm6r-3vj8](https://github.com/fgmacedo/python-statemachine/security/advisories/GHSA-v4jc-pm6r-3vj8)
|
|
196
|
+
(CVE-2026-47103).
|
|
197
|
+
Before it, SCXML datamodel expressions were evaluated with `eval`, which let a malicious
|
|
198
|
+
document run arbitrary code on load. The restricted evaluator removes that by default across
|
|
199
|
+
every format (SCXML, JSON and YAML).
|
|
200
|
+
|
|
201
|
+
A set of follow-up advisories hardened the restricted mode further and prompted the
|
|
202
|
+
confidentiality/integrity vs availability framing above:
|
|
203
|
+
|
|
204
|
+
- [GHSA-fj3w-533r-fvf6](https://github.com/fgmacedo/python-statemachine/security/advisories/GHSA-fj3w-533r-fvf6)
|
|
205
|
+
— `<data src="file:…">` and `<invoke src="…">` read local files during loading, regardless of
|
|
206
|
+
`trusted`. Loading now rejects external `src` references unless `trusted=True`, and refuses
|
|
207
|
+
`<!DOCTYPE>`/DTD to block XML entity-expansion bombs.
|
|
208
|
+
- [GHSA-v3qq-3xvg-m77g](https://github.com/fgmacedo/python-statemachine/security/advisories/GHSA-v3qq-3xvg-m77g)
|
|
209
|
+
/ [GHSA-4857-ggqc-p3jc](https://github.com/fgmacedo/python-statemachine/security/advisories/GHSA-4857-ggqc-p3jc)
|
|
210
|
+
— a document could write to a dunder/private/protected attribute (notably traversing
|
|
211
|
+
`__class__`) and corrupt the shared model class process-wide. Write targets are now confined
|
|
212
|
+
to public model attributes on every path segment.
|
|
213
|
+
- [GHSA-r8gj-366q-cgvj](https://github.com/fgmacedo/python-statemachine/security/advisories/GHSA-r8gj-366q-cgvj)
|
|
214
|
+
— `**`/`*` in the restricted evaluator had no magnitude bound, so a tiny expression could
|
|
215
|
+
exhaust CPU or memory. They are now magnitude-capped.
|
|
216
|
+
|
|
217
|
+
These were released together in 3.2.1.
|