Skip to content

Commit 1e7f40d

Browse files
committed
chore: Drop support for Python3.7 and 3.8 due to the lack of support for TypedDict and | operator
1 parent 05a326c commit 1e7f40d

File tree

5 files changed

+148
-278
lines changed

5 files changed

+148
-278
lines changed

.github/ISSUE_TEMPLATE.md

+2
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@ Tell us what happened, what went wrong, and what you expected to happen.
1313
Paste the command(s) you ran and the output.
1414
If there was a crash, please include the traceback here.
1515
```
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.

.github/workflows/python-package.yml

+1-5
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
strategy:
1616
fail-fast: false
1717
matrix:
18-
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
18+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
1919

2020
steps:
2121
- uses: actions/checkout@v4
@@ -33,10 +33,6 @@ jobs:
3333
cache-suffix: "python${{ matrix.python-version }}"
3434
- name: Install the project
3535
run: uv sync --all-extras --dev
36-
- name: Install old pydot for 3.7 only
37-
if: matrix.python-version == 3.7
38-
run: |
39-
uv pip install pydot==2.0.0
4036
#----------------------------------------------
4137
# run ruff
4238
#----------------------------------------------

pyproject.toml

+10-12
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,11 @@ classifiers = [
1717
"Programming Language :: Python :: 3.11",
1818
"Programming Language :: Python :: 3.12",
1919
"Programming Language :: Python :: 3.13",
20-
"Programming Language :: Python :: 3.7",
21-
"Programming Language :: Python :: 3.8",
2220
"Programming Language :: Python :: 3.9",
2321
"Topic :: Home Automation",
2422
"Topic :: Software Development :: Libraries",
2523
]
26-
requires-python = ">=3.7"
24+
requires-python = ">=3.9"
2725

2826
[project.urls]
2927
homepage = "https://github.com/fgmacedo/python-statemachine"
@@ -45,15 +43,15 @@ dev = [
4543
"pydot",
4644
"pydot",
4745
"django >=5.0.8; python_version >='3.10'",
48-
"pytest-django >=4.8.0; python_version >'3.8'",
49-
"Sphinx; python_version >'3.8'",
50-
"sphinx-gallery; python_version >'3.8'",
51-
"myst-parser; python_version >'3.8'",
52-
"pillow; python_version >'3.8'",
53-
"sphinx-autobuild; python_version >'3.8'",
54-
"furo >=2024.5.6; python_version >'3.8'",
55-
"sphinx-copybutton >=0.5.2; python_version >'3.8'",
56-
"pdbr>=0.8.9; python_version >='3.8'",
46+
"pytest-django >=4.8.0",
47+
"Sphinx",
48+
"sphinx-gallery",
49+
"myst-parser",
50+
"pillow",
51+
"sphinx-autobuild",
52+
"furo >=2024.5.6",
53+
"sphinx-copybutton >=0.5.2",
54+
"pdbr>=0.8.9",
5755
]
5856

5957
[build-system]

statemachine/io/__init__.py

+43-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,50 @@
1+
from typing import Any
2+
from typing import Callable
13
from typing import Dict
4+
from typing import List
5+
from typing import Mapping
6+
from typing import TypedDict
7+
from typing import cast
28

39
from ..factory import StateMachineMetaclass
410
from ..state import State
511
from ..statemachine import StateMachine
612
from ..transition_list import TransitionList
713

14+
CallbacksType = str | Callable | List[str] | List[Callable]
815

9-
def create_machine_class_from_definition(name: str, **definition) -> StateMachine: # noqa: C901
16+
17+
class TransitionDict(TypedDict, total=False):
18+
target: str
19+
event: str
20+
internal: bool
21+
validators: bool
22+
cond: CallbacksType
23+
unless: CallbacksType
24+
on: CallbacksType
25+
before: CallbacksType
26+
after: CallbacksType
27+
28+
29+
class StateDict(TypedDict, total=False):
30+
name: str
31+
value: Any
32+
initial: bool
33+
final: bool
34+
enter: CallbacksType
35+
exit: CallbacksType
36+
37+
38+
class StateWithTransitionsDict(StateDict, total=False):
39+
on: Dict[str, List[TransitionDict]]
40+
41+
42+
StateOptions = StateDict | StateWithTransitionsDict
43+
44+
45+
def create_machine_class_from_definition(
46+
name: str, states: Mapping[str, StateOptions], **definition
47+
) -> StateMachine: # noqa: C901
1048
"""
1149
Creates a StateMachine class from a dictionary definition, using the StateMachineMetaclass.
1250
@@ -27,10 +65,10 @@ def create_machine_class_from_definition(name: str, **definition) -> StateMachin
2765
states_instances: Dict[str, State] = {}
2866
events_definitions: Dict[str, dict] = {}
2967

30-
for state_id, state_kwargs in definition.pop("states").items():
31-
on_events = state_kwargs.pop("on", {})
32-
if on_events:
33-
events_definitions[state_id] = on_events
68+
for state_id, state_kwargs in states.items():
69+
transition_definitions = cast(StateWithTransitionsDict, state_kwargs).pop("on", {})
70+
if transition_definitions:
71+
events_definitions[state_id] = transition_definitions
3472

3573
states_instances[state_id] = State(**state_kwargs)
3674

0 commit comments

Comments
 (0)