From e43c7dc8d93db637cfc0ab25f1ca00a397bc7c88 Mon Sep 17 00:00:00 2001 From: Fernando Macedo Date: Mon, 9 Sep 2024 10:38:28 -0300 Subject: [PATCH 1/3] fix: Extras [diagrams] to install pydot not working (#479) --- .github/workflows/python-package.yml | 2 +- .github/workflows/release.yml | 2 +- docs/contributing.md | 2 +- poetry.lock | 8 ++++---- pyproject.toml | 8 ++++---- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index ab98311f..bb611171 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -41,7 +41,7 @@ jobs: key: venv-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('**/poetry.lock') }} - name: Install dependencies if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true' - run: poetry install --no-interaction --no-root + run: poetry install --no-interaction --no-root --all-extras #---------------------------------------------- # run ruff #---------------------------------------------- diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 21e2ba0a..1cfd31c2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -41,7 +41,7 @@ jobs: key: venv-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('**/poetry.lock') }} - name: Install dependencies if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true' - run: poetry install --no-interaction --no-root + run: poetry install --no-interaction --no-root --all-extras - name: Test with pytest run: | source .venv/bin/activate diff --git a/docs/contributing.md b/docs/contributing.md index a0d4508c..ce4b4554 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -98,7 +98,7 @@ Ready to contribute? Here's how to set up `python-statemachine` for local develo 1. Run `poetry install` once to install all the dependencies and create a virtual environment:: - poetry install + poetry install --all-extras 1. Run `poetry shell` to enter the provided virtual diff --git a/poetry.lock b/poetry.lock index d8f27cdd..64c8725e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -855,7 +855,7 @@ files = [ name = "pydot" version = "2.0.0" description = "Python interface to Graphviz's Dot" -optional = false +optional = true python-versions = ">=3.7" files = [ {file = "pydot-2.0.0-py3-none-any.whl", hash = "sha256:408a47913ea7bd5d2d34b274144880c1310c4aee901f353cf21fe2e526a4ea28"}, @@ -888,7 +888,7 @@ windows-terminal = ["colorama (>=0.4.6)"] name = "pyparsing" version = "3.1.4" description = "pyparsing module - Classes and methods to define and execute parsing grammars" -optional = false +optional = true python-versions = ">=3.6.8" files = [ {file = "pyparsing-3.1.4-py3-none-any.whl", hash = "sha256:a6a7ee4235a3f944aa1fa2249307708f893fe5717dc603503c6c7969c070fb7c"}, @@ -1559,9 +1559,9 @@ docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] [extras] -diagrams = [] +diagrams = ["pydot"] [metadata] lock-version = "2.0" python-versions = ">=3.7" -content-hash = "5db0b36706ea17bdfbf6afc99254d49456b34a06228000fe7e03ab4ccf67dd67" +content-hash = "13f2f8f744cef83106ef7bf39cd95ff5ceae370d65f9ea71a9bcb3dd535f72e0" diff --git a/pyproject.toml b/pyproject.toml index 26afd2fa..7b239c6d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,14 +33,14 @@ classifiers = [ "Intended Audience :: Developers", ] -[tool.poetry.extras] -diagrams = ["pydot"] - [tool.poetry.dependencies] python = ">=3.7" +pydot = { version = ">=2.0.0", optional = true } + +[tool.poetry.extras] +diagrams = ["pydot"] [tool.poetry.group.dev.dependencies] -pydot = "^2.0.0" ruff = "^0.4.8" pre-commit = "*" mypy = "*" From e4a20927803da34409c5d90fbb8e75e16dce1dca Mon Sep 17 00:00:00 2001 From: Fernando Macedo Date: Wed, 11 Sep 2024 17:33:09 -0300 Subject: [PATCH 2/3] fix: Fix #480, engine was not assigned on the initial callback (#481) --- statemachine/engines/async_.py | 1 + statemachine/engines/sync.py | 1 + statemachine/statemachine.py | 9 +++---- tests/conftest.py | 4 ++-- tests/test_transitions.py | 4 ++-- tests/testcases/issue480.md | 43 ++++++++++++++++++++++++++++++++++ 6 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 tests/testcases/issue480.md diff --git a/statemachine/engines/async_.py b/statemachine/engines/async_.py index 84310836..b88cce71 100644 --- a/statemachine/engines/async_.py +++ b/statemachine/engines/async_.py @@ -15,6 +15,7 @@ class AsyncEngine: def __init__(self, sm: "StateMachine", rtc: bool = True): + sm._engine = self self.sm = proxy(sm) self._sentinel = object() if not rtc: diff --git a/statemachine/engines/sync.py b/statemachine/engines/sync.py index c89c7570..6a658e79 100644 --- a/statemachine/engines/sync.py +++ b/statemachine/engines/sync.py @@ -13,6 +13,7 @@ class SyncEngine: def __init__(self, sm: "StateMachine", rtc: bool = True): + sm._engine = self self.sm = proxy(sm) self._sentinel = object() self._rtc = rtc diff --git a/statemachine/statemachine.py b/statemachine/statemachine.py index a2e750aa..fb4e45a1 100644 --- a/statemachine/statemachine.py +++ b/statemachine/statemachine.py @@ -105,13 +105,14 @@ def __init__( ) self._put_nonblocking(trigger_data) - self._engine = self._get_engine(rtc) + self._engine: AsyncEngine | SyncEngine | None = None + self._select_engine(rtc) - def _get_engine(self, rtc: bool): + def _select_engine(self, rtc: bool): if self._callbacks_registry.has_async_callbacks: - return AsyncEngine(self, rtc=rtc) + AsyncEngine(self, rtc=rtc) else: - return SyncEngine(self, rtc=rtc) + SyncEngine(self, rtc=rtc) def activate_initial_state(self): result = self._engine.activate_initial_state() diff --git a/tests/conftest.py b/tests/conftest.py index a720a808..6ad318eb 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -135,8 +135,8 @@ class TrafficLightMachine(StateMachine): stop = yellow.to(red) go = red.to(green) - def _get_engine(self, rtc: bool): - return engine(self, rtc) + def _select_engine(self, rtc: bool): + engine(self, rtc) return TrafficLightMachine diff --git a/tests/test_transitions.py b/tests/test_transitions.py index c5bd7a81..3b6b52aa 100644 --- a/tests/test_transitions.py +++ b/tests/test_transitions.py @@ -252,8 +252,8 @@ class TestStateMachine(StateMachine): loop = initial.to.itself(internal=internal) - def _get_engine(self, rtc: bool): - return engine(self, rtc) + def _select_engine(self, rtc: bool): + engine(self, rtc) def on_exit_initial(self): calls.append("on_exit_initial") diff --git a/tests/testcases/issue480.md b/tests/testcases/issue480.md new file mode 100644 index 00000000..b86d37e6 --- /dev/null +++ b/tests/testcases/issue480.md @@ -0,0 +1,43 @@ + + +### Issue 480 + +A StateMachine that exercises the example given on issue +#[480](https://github.com/fgmacedo/python-statemachine/issues/480). + +Should be possible to trigger an event on the initial state activation handler. + +```py +>>> from statemachine import StateMachine, State +>>> +>>> class MyStateMachine(StateMachine): +... State_1 = State(initial=True) +... State_2 = State() +... Trans_1 = State_1.to(State_2) +... +... def __init__(self): +... super(MyStateMachine, self).__init__() +... +... def on_enter_State_1(self): +... print("Entering State_1 state") +... self.long_running_task() +... +... def on_exit_State_1(self): +... print("Exiting State_1 state") +... +... def on_enter_State_2(self): +... print("Entering State_2 state") +... +... def long_running_task(self): +... print("long running task process started") +... self.Trans_1() +... print("long running task process ended") +... +>>> sm = MyStateMachine() +Entering State_1 state +long running task process started +long running task process ended +Exiting State_1 state +Entering State_2 state + +``` From 97e457633ca3f0098b37b65ceacd3cf508ad7a16 Mon Sep 17 00:00:00 2001 From: Fernando Macedo Date: Wed, 11 Sep 2024 17:50:55 -0300 Subject: [PATCH 3/3] release: New 2.3.6 release doc --- docs/releases/2.3.6.md | 9 +++++++++ docs/releases/index.md | 1 + pyproject.toml | 2 +- statemachine/__init__.py | 2 +- 4 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 docs/releases/2.3.6.md diff --git a/docs/releases/2.3.6.md b/docs/releases/2.3.6.md new file mode 100644 index 00000000..6d37521f --- /dev/null +++ b/docs/releases/2.3.6.md @@ -0,0 +1,9 @@ +# StateMachine 2.3.6 + +*September 11, 2024* + + +## Bugfixes in 2.3.6 + +- Fixes [#474](https://github.com/fgmacedo/python-statemachine/issues/474) install with extra was not working to install `pydot`. +- Fixes [#480](https://github.com/fgmacedo/python-statemachine/issues/480) error when trying to trigger an event inside the initial callback. diff --git a/docs/releases/index.md b/docs/releases/index.md index f236ee22..7abc84d9 100644 --- a/docs/releases/index.md +++ b/docs/releases/index.md @@ -15,6 +15,7 @@ Below are release notes through StateMachine and its patch releases. ```{toctree} :maxdepth: 2 +2.3.6 2.3.5 2.3.4 2.3.3 diff --git a/pyproject.toml b/pyproject.toml index 7b239c6d..0f60d012 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "python-statemachine" -version = "2.3.5" +version = "2.3.6" description = "Python Finite State Machines made easy." authors = ["Fernando Macedo "] maintainers = [ diff --git a/statemachine/__init__.py b/statemachine/__init__.py index 8d1e4a10..75815537 100644 --- a/statemachine/__init__.py +++ b/statemachine/__init__.py @@ -3,6 +3,6 @@ __author__ = """Fernando Macedo""" __email__ = "fgmacedo@gmail.com" -__version__ = "2.3.5" +__version__ = "2.3.6" __all__ = ["StateMachine", "State"]