From 25ef493b55c9411f7a1cac3205a03b7342d62b17 Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Sat, 13 Feb 2021 12:38:58 +0100 Subject: [PATCH] test proper subclassing for hierarchicalstatemachine (#510) --- Changelog.md | 1 + tests/test_nesting.py | 16 ++++++++++++++++ tests/test_nesting_legacy.py | 3 +++ transitions/extensions/nesting.py | 3 +++ 4 files changed, 23 insertions(+) diff --git a/Changelog.md b/Changelog.md index 6e4fee94..18b4e970 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,7 @@ - Bugfix #512: Use `model_attribute` consistently in `AsyncMachine` (thanks @thedrow) - Testing now treats most warnings as errors (thanks @thedrow) - As a consequence, `pygraphviz.Agraph` in `diagrams_pygraphviz` are now copied by `transitions` since `AGraph.copy` as of version `1.6` does not close temporary files appropriately +- `HierarchicalMachine` now checks whether `state_cls`, `event_cls` and `transition_cls` have been subclassed from nested base classes (e.g. `NestedState`) to prevent hard to debug inheritance errors ## 0.8.6 (December 2020) diff --git a/tests/test_nesting.py b/tests/test_nesting.py index edd641c7..75f07b06 100644 --- a/tests/test_nesting.py +++ b/tests/test_nesting.py @@ -570,6 +570,22 @@ def on_exit_C_1(self): model.to_C() self.assertTrue(model.is_C_1()) + def test_correct_subclassing(self): + from transitions.core import State + + class WrongStateClass(self.machine_cls): + state_cls = State + + class MyNestedState(NestedState): + pass + + class CorrectStateClass(self.machine_cls): + state_cls = MyNestedState + + with self.assertRaises(AssertionError): + m = WrongStateClass() + m = CorrectStateClass() + class TestSeparatorsBase(TestCase): diff --git a/tests/test_nesting_legacy.py b/tests/test_nesting_legacy.py index 797a4ecd..ab890386 100644 --- a/tests/test_nesting_legacy.py +++ b/tests/test_nesting_legacy.py @@ -100,6 +100,9 @@ def test_child_condition_persistence(self): def test_get_nested_transitions(self): pass # not supported by legacy machine + def test_correct_subclassing(self): + pass # not supported by legacy machine + class TestReuseLegacySeparatorDefault(TestReuseSeparatorBase): diff --git a/transitions/extensions/nesting.py b/transitions/extensions/nesting.py index 3b03c21b..d2bdb6db 100644 --- a/transitions/extensions/nesting.py +++ b/transitions/extensions/nesting.py @@ -334,6 +334,9 @@ class HierarchicalMachine(Machine): event_cls = NestedEvent def __init__(self, *args, **kwargs): + assert issubclass(self.state_cls, NestedState) + assert issubclass(self.event_cls, NestedEvent) + assert issubclass(self.transition_cls, NestedTransition) self._stack = [] self.scoped = self _super(HierarchicalMachine, self).__init__(*args, **kwargs)