* Bug #610: Decorate models appropriately when `HierarchicalMachine` is passed to `add_state` (thanks @e0lithic) * Bug #647: Let `may_<trigger>` check all parallel states in processing order (thanks @spearsear) * Bug: `HSM.is_state` works with parallel states now * Experimental features: + Add `model_override` to Machine constructor to determine the mode of operation. With `model_override=Fale` (default), `transitions` will not override already defined methods on a model just as it did before. For workflows relying on typing, `model_override=True` will override methods already defined on the model and only those (!). This allows to control which convenience methods shall be assigned to the model and keeps the statically 'assumed' model in sync with its runtime counterpart. Since defining each and every method manually is rather tiresome, `transitions.experimental.utils.generate_base_model` features a way to convert a machine configuration into a `BaseClass` with all convenience functions and callbacks. + Add `transitions.experimental.utils.{add_transitions, event, with_model_definitions, transition}` to define trigger methods in a class model for more convenient type checking. `add_transitions` can be used as a function decorator and is stackable. `event` returns a placeholder object for attribute assigment. `add_transitions` and `event` have the same signature and support transition definition like machine constructors. The function `transition` can used for better typing and returns a dictionary that can be passed to the utility functions but also to a machine constructor. `add_transitions` and `event` require a machine decorated with `with_model_definitions`. Decorating a machine `with_model_definitions` implies `model_override=True`. * Feature: Add `may_trigger` to models to check whether transitions can OBS-URL: https://build.opensuse.org/package/show/devel:languages:python/python-transitions?expand=0&rev=24
257 lines
10 KiB
Diff
257 lines
10 KiB
Diff
From: Alexandre Detiste <alexandre.detiste@gmail.com>
|
|
Date: Sun, 14 Apr 2024 14:28:03 +0200
|
|
Subject: [PATCH] remove Python 2 crumbs
|
|
|
|
---
|
|
tests/test_nesting.py | 7 +------
|
|
transitions/core.py | 23 +++-----------------
|
|
transitions/extensions/diagrams_base.py | 4 +---
|
|
transitions/extensions/factory.py | 2 +-
|
|
transitions/extensions/markup.py | 19 ++++-------------
|
|
transitions/extensions/nesting.py | 28 +++++++------------------
|
|
6 files changed, 18 insertions(+), 65 deletions(-)
|
|
|
|
diff -Nru transitions-0.9.2.orig/tests/test_nesting.py transitions-0.9.2/tests/test_nesting.py
|
|
--- transitions-0.9.2.orig/tests/test_nesting.py 2024-08-06 15:30:55.000000000 +0200
|
|
+++ transitions-0.9.2/tests/test_nesting.py 2025-04-03 15:37:00.639048015 +0200
|
|
@@ -1,10 +1,5 @@
|
|
# -*- coding: utf-8 -*-
|
|
|
|
-try:
|
|
- from builtins import object
|
|
-except ImportError:
|
|
- pass
|
|
-
|
|
import sys
|
|
import tempfile
|
|
from os.path import getsize
|
|
@@ -37,7 +32,7 @@
|
|
default_separator = NestedState.separator
|
|
|
|
|
|
-class Dummy(object):
|
|
+class Dummy:
|
|
pass
|
|
|
|
|
|
diff -Nru transitions-0.9.2.orig/transitions/core.py transitions-0.9.2/transitions/core.py
|
|
--- transitions-0.9.2.orig/transitions/core.py 2024-08-06 15:30:55.000000000 +0200
|
|
+++ transitions-0.9.2/transitions/core.py 2025-04-03 15:37:00.639277420 +0200
|
|
@@ -6,23 +6,7 @@
|
|
and transition concepts.
|
|
"""
|
|
|
|
-
|
|
-try:
|
|
- from builtins import object
|
|
-except ImportError: # pragma: no cover
|
|
- # python2
|
|
- pass
|
|
-
|
|
-try:
|
|
- # Enums are supported for Python 3.4+ and Python 2.7 with enum34 package installed
|
|
- from enum import Enum, EnumMeta
|
|
-except ImportError: # pragma: no cover
|
|
- # If enum is not available, create dummy classes for type checks
|
|
- class Enum: # type:ignore
|
|
- """This is just an Enum stub for Python 2 and Python 3.3 and before without Enum support."""
|
|
-
|
|
- class EnumMeta: # type:ignore
|
|
- """This is just an EnumMeta stub for Python 2 and Python 3.3 and before without Enum support."""
|
|
+from enum import Enum, EnumMeta
|
|
|
|
import inspect
|
|
import itertools
|
|
@@ -31,7 +15,6 @@
|
|
|
|
from collections import OrderedDict, defaultdict, deque
|
|
from functools import partial
|
|
-from six import string_types
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
_LOGGER.addHandler(logging.NullHandler())
|
|
@@ -838,7 +821,7 @@
|
|
states = listify(states)
|
|
|
|
for state in states:
|
|
- if isinstance(state, (string_types, Enum)):
|
|
+ if isinstance(state, (str, Enum)):
|
|
state = self._create_state(
|
|
state, on_enter=on_enter, on_exit=on_exit,
|
|
ignore_invalid_triggers=ignore, **kwargs)
|
|
@@ -1204,7 +1187,7 @@
|
|
Returns:
|
|
callable function resolved from string or func
|
|
"""
|
|
- if isinstance(func, string_types):
|
|
+ if isinstance(func, str):
|
|
try:
|
|
func = getattr(event_data.model, func)
|
|
if not callable(func): # if a property or some other not callable attribute was passed
|
|
diff -Nru transitions-0.9.2.orig/transitions/extensions/diagrams_base.py transitions-0.9.2/transitions/extensions/diagrams_base.py
|
|
--- transitions-0.9.2.orig/transitions/extensions/diagrams_base.py 2024-08-06 15:30:55.000000000 +0200
|
|
+++ transitions-0.9.2/transitions/extensions/diagrams_base.py 2025-04-03 15:37:00.639470446 +0200
|
|
@@ -8,14 +8,12 @@
|
|
import copy
|
|
import abc
|
|
import logging
|
|
-import six
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
_LOGGER.addHandler(logging.NullHandler())
|
|
|
|
|
|
-@six.add_metaclass(abc.ABCMeta)
|
|
-class BaseGraph(object):
|
|
+class BaseGraph(metaclass=abc.ABCMeta):
|
|
"""Provides the common foundation for graphs generated either with pygraphviz or graphviz. This abstract class
|
|
should not be instantiated directly. Use .(py)graphviz.(Nested)Graph instead.
|
|
Attributes:
|
|
diff -Nru transitions-0.9.2.orig/transitions/extensions/factory.py transitions-0.9.2/transitions/extensions/factory.py
|
|
--- transitions-0.9.2.orig/transitions/extensions/factory.py 2024-08-06 15:30:55.000000000 +0200
|
|
+++ transitions-0.9.2/transitions/extensions/factory.py 2025-04-03 15:37:00.639536752 +0200
|
|
@@ -34,7 +34,7 @@
|
|
"""A mock of NestedAsyncTransition for Python 3.6 and earlier."""
|
|
|
|
|
|
-class MachineFactory(object):
|
|
+class MachineFactory:
|
|
"""Convenience factory for machine class retrieval."""
|
|
|
|
# get one of the predefined classes which fulfill the criteria
|
|
diff -Nru transitions-0.9.2.orig/transitions/extensions/markup.py transitions-0.9.2/transitions/extensions/markup.py
|
|
--- transitions-0.9.2.orig/transitions/extensions/markup.py 2024-08-06 15:30:55.000000000 +0200
|
|
+++ transitions-0.9.2/transitions/extensions/markup.py 2025-04-03 15:37:51.412268665 +0200
|
|
@@ -7,24 +7,13 @@
|
|
also be used to store and transfer machines.
|
|
"""
|
|
|
|
+from enum import Enum, EnumMeta
|
|
from functools import partial
|
|
import importlib
|
|
import itertools
|
|
import numbers
|
|
|
|
-from six import string_types, iteritems
|
|
-
|
|
-try:
|
|
- # Enums are supported for Python 3.4+ and Python 2.7 with enum34 package installed
|
|
- from enum import Enum, EnumMeta
|
|
-except ImportError: # pragma: no cover
|
|
- # If enum is not available, create dummy classes for type checks
|
|
- # typing must be prevented redefinition issues with mypy
|
|
- class Enum: # type:ignore
|
|
- """This is just an Enum stub for Python 2 and Python 3.3 and before without Enum support."""
|
|
-
|
|
- class EnumMeta: # type:ignore
|
|
- """This is just an EnumMeta stub for Python 2 and Python 3.3 and before without Enum support."""
|
|
+from six import iteritems
|
|
|
|
from ..core import Machine
|
|
from .nesting import HierarchicalMachine
|
|
@@ -236,7 +225,7 @@
|
|
|
|
def rep(func, format_references=None):
|
|
"""Return a string representation for `func`."""
|
|
- if isinstance(func, string_types):
|
|
+ if isinstance(func, str):
|
|
return func
|
|
if isinstance(func, numbers.Number):
|
|
return str(func)
|
|
@@ -249,7 +238,7 @@
|
|
val = getattr(obj, key, False)
|
|
if not val:
|
|
continue
|
|
- if isinstance(val, string_types):
|
|
+ if isinstance(val, str):
|
|
definition[key] = val
|
|
elif val is True:
|
|
definition[key] = True
|
|
diff -Nru transitions-0.9.2.orig/transitions/extensions/nesting.py transitions-0.9.2/transitions/extensions/nesting.py
|
|
--- transitions-0.9.2.orig/transitions/extensions/nesting.py 2024-08-06 15:30:55.000000000 +0200
|
|
+++ transitions-0.9.2/transitions/extensions/nesting.py 2025-04-03 15:37:00.639796826 +0200
|
|
@@ -9,23 +9,11 @@
|
|
|
|
from collections import OrderedDict
|
|
import copy
|
|
+from enum import Enum, EnumMeta
|
|
from functools import partial, reduce
|
|
import inspect
|
|
import logging
|
|
|
|
-try:
|
|
- # Enums are supported for Python 3.4+ and Python 2.7 with enum34 package installed
|
|
- from enum import Enum, EnumMeta
|
|
-except ImportError: # pragma: no cover
|
|
- # If enum is not available, create dummy classes for type checks
|
|
- class Enum: # type: ignore
|
|
- """This is just an Enum stub for Python 2 and Python 3.3 and before without Enum support."""
|
|
-
|
|
- class EnumMeta: # type: ignore
|
|
- """This is just an EnumMeta stub for Python 2 and Python 3.3 and before without Enum support."""
|
|
-
|
|
-from six import string_types
|
|
-
|
|
from ..core import State, Machine, Transition, Event, listify, MachineError, EventData
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
@@ -414,7 +402,7 @@
|
|
)
|
|
|
|
def __call__(self, to_scope=None):
|
|
- if isinstance(to_scope, string_types):
|
|
+ if isinstance(to_scope, str):
|
|
state_name = to_scope.split(self.state_cls.separator)[0]
|
|
state = self.states[state_name]
|
|
to_scope = (state, state.states, state.events, self.prefix_path + [state_name])
|
|
@@ -448,7 +436,7 @@
|
|
if hasattr(initial_name, 'name'):
|
|
initial_name = initial_name.name
|
|
# initial states set by add_model or machine might contain initial states themselves.
|
|
- if isinstance(initial_name, string_types):
|
|
+ if isinstance(initial_name, str):
|
|
initial_states = self._resolve_initial(models, initial_name.split(self.state_cls.separator))
|
|
# when initial is set to a (parallel) state, we accept it as it is
|
|
else:
|
|
@@ -513,7 +501,7 @@
|
|
state = {'name': state, 'children': state.value}
|
|
elif isinstance(state.value, dict):
|
|
state = dict(name=state, **state.value)
|
|
- if isinstance(state, string_types):
|
|
+ if isinstance(state, str):
|
|
self._add_string_state(state, on_enter, on_exit, ignore, remap, **kwargs)
|
|
elif isinstance(state, Enum):
|
|
self._add_enum_state(state, on_enter, on_exit, ignore, remap, **kwargs)
|
|
@@ -640,7 +628,7 @@
|
|
"""
|
|
if isinstance(state, Enum):
|
|
state = self._get_enum_path(state)
|
|
- elif isinstance(state, string_types):
|
|
+ elif isinstance(state, str):
|
|
state = state.split(self.state_cls.separator)
|
|
if not hint:
|
|
state = copy.copy(state)
|
|
@@ -692,11 +680,11 @@
|
|
"""
|
|
with self():
|
|
source_path = [] if source == "*" \
|
|
- else source.split(self.state_cls.separator) if isinstance(source, string_types) \
|
|
+ else source.split(self.state_cls.separator) if isinstance(source, str) \
|
|
else self._get_enum_path(source) if isinstance(source, Enum) \
|
|
else self._get_state_path(source)
|
|
dest_path = [] if dest == "*" \
|
|
- else dest.split(self.state_cls.separator) if isinstance(dest, string_types) \
|
|
+ else dest.split(self.state_cls.separator) if isinstance(dest, str) \
|
|
else self._get_enum_path(dest) if isinstance(dest, Enum) \
|
|
else self._get_state_path(dest)
|
|
matches = self.get_nested_transitions(trigger, source_path, dest_path)
|
|
@@ -1166,7 +1154,7 @@
|
|
self._init_state(substate)
|
|
|
|
def _recursive_initial(self, value):
|
|
- if isinstance(value, string_types):
|
|
+ if isinstance(value, str):
|
|
path = value.split(self.state_cls.separator, 1)
|
|
if len(path) > 1:
|
|
state_name, suffix = path
|