summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES8
-rw-r--r--examples/statemachine/statemachine.py14
2 files changed, 21 insertions, 1 deletions
diff --git a/CHANGES b/CHANGES
index e1fa06e..84d42ba 100644
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,14 @@
Change Log
==========
+Version 2.4.1 -
+----------------------
+- Updated statemachine example: refactored state transitions to use
+ overridden classmethods; added <statename>Mixin class to simplify
+ definition of application classes that "own" the state object and
+ delegate to it to model state-specific properties and behavior.
+
+
Version 2.4.0 - April, 2019
---------------------------
- Well, it looks like the API change that was introduced in 2.3.1 was more
diff --git a/examples/statemachine/statemachine.py b/examples/statemachine/statemachine.py
index c46e3d0..f4244a5 100644
--- a/examples/statemachine/statemachine.py
+++ b/examples/statemachine/statemachine.py
@@ -49,6 +49,9 @@ namedStateMachine = (pp.Keyword("statemachine") + ident("name") + ":"
def expand_state_definition(source, loc, tokens):
+ """
+ Parse action to convert statemachine to corresponding Python classes and methods
+ """
indent = " " * (pp.col(loc, source) - 1)
statedef = []
@@ -66,9 +69,11 @@ def expand_state_definition(source, loc, tokens):
"class %s(object):" % baseStateClass,
" def __str__(self):",
" return self.__class__.__name__",
+
" @classmethod",
" def states(cls):",
" return list(cls.__subclasses__())",
+
" def next_state(self):",
" return self._next_state_class()",
])
@@ -106,6 +111,10 @@ stateMachine.setParseAction(expand_state_definition)
def expand_named_state_definition(source, loc, tokens):
+ """
+ Parse action to convert statemachine with named transitions to corresponding Python
+ classes and methods
+ """
indent = " " * (pp.col(loc, source) - 1)
statedef = []
# build list of states and transitions
@@ -152,15 +161,18 @@ def expand_named_state_definition(source, loc, tokens):
"class %s(object):" % baseStateClass,
" def __str__(self):",
" return self.__class__.__name__",
+
" @classmethod",
" def states(cls):",
" return list(cls.__subclasses__())",
+
" @classmethod",
" def next_state(cls, name):",
" try:",
" return cls.tnmap[name]()",
" except KeyError:",
" raise InvalidTransitionException('%s does not support transition %r'% (cls.__name__, name))",
+
" def __bad_tn(name):",
" def _fn(cls):",
" raise InvalidTransitionException('%s does not support transition %r'% (cls.__name__, name))",
@@ -194,6 +206,7 @@ def expand_named_state_definition(source, loc, tokens):
)
])
+ # define <state>Mixin class for application classes that delegate to the state
statedef.extend([
"class {baseStateClass}Mixin:".format(baseStateClass=baseStateClass),
" def __init__(self):",
@@ -217,7 +230,6 @@ def expand_named_state_definition(source, loc, tokens):
" return '{0}: {1}'.format(self.__class__.__name__, self._state)"
])
-
return indent + ("\n" + indent).join(statedef) + "\n"
namedStateMachine.setParseAction(expand_named_state_definition)