[Python-modules-commits] [python-transitions] 01/02: Import python-transitions_0.5.3.orig.tar.gz

Stein Magnus Jodal jodal at moszumanska.debian.org
Wed Jul 26 10:03:40 UTC 2017


This is an automated email from the git hooks/post-receive script.

jodal pushed a commit to branch master
in repository python-transitions.

commit 447d35cd623dc930b4d073cf9d045f025524918b
Author: Stein Magnus Jodal <jodal at debian.org>
Date:   Wed Jul 26 12:01:58 2017 +0200

    Import python-transitions_0.5.3.orig.tar.gz
---
 LICENSE                                   |  30 +
 MANIFEST.in                               |   1 +
 PKG-INFO                                  |  19 +
 setup.cfg                                 |   8 +
 setup.py                                  |  48 ++
 transitions.egg-info/PKG-INFO             |  19 +
 transitions.egg-info/SOURCES.txt          |  17 +
 transitions.egg-info/dependency_links.txt |   1 +
 transitions.egg-info/requires.txt         |   4 +
 transitions.egg-info/top_level.txt        |   1 +
 transitions/__init__.py                   |   9 +
 transitions/core.py                       | 909 ++++++++++++++++++++++++++++++
 transitions/extensions/__init__.py        |   6 +
 transitions/extensions/diagrams.py        | 428 ++++++++++++++
 transitions/extensions/factory.py         |  65 +++
 transitions/extensions/locking.py         | 145 +++++
 transitions/extensions/nesting.py         | 351 ++++++++++++
 transitions/version.py                    |   1 +
 18 files changed, 2062 insertions(+)

diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..656c73e
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+*******
+License
+*******
+
+The transitions package, including all examples, code snippets and attached 
+documentation is covered by the MIT license.
+
+::
+
+  The MIT License
+
+  Copyright (c) 2014 Tal Yarkoni
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+  THE SOFTWARE.
\ No newline at end of file
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..1aba38f
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1 @@
+include LICENSE
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..49ce14c
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,19 @@
+Metadata-Version: 1.1
+Name: transitions
+Version: 0.5.3
+Summary: A lightweight, object-oriented Python state machine implementation.
+Home-page: http://github.com/tyarkoni/transitions
+Author: Tal Yarkoni
+Author-email: tyarkoni at gmail.com
+License: MIT
+Download-URL: https://github.com/tyarkoni/transitions/archive/0.5.3.tar.gz
+Description: UNKNOWN
+Platform: UNKNOWN
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..8c9157d
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,8 @@
+[metadata]
+description-file = README.md
+
+[egg_info]
+tag_build = 
+tag_date = 0
+tag_svn_revision = 0
+
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..ee3c2a9
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,48 @@
+import sys
+from setuptools import setup, find_packages
+
+with open('transitions/version.py') as f:
+    exec(f.read())
+
+if len(set(('test', 'easy_install')).intersection(sys.argv)) > 0:
+    import setuptools
+
+tests_require = ['dill', 'pygraphviz']
+
+extra_setuptools_args = {}
+if 'setuptools' in sys.modules:
+    tests_require.append('nose')
+    extra_setuptools_args = dict(
+        test_suite='nose.collector',
+        extras_require=dict(
+            test='nose>=0.10.1')
+    )
+
+setup(
+    name="transitions",
+    version=__version__,
+    description="A lightweight, object-oriented Python state machine implementation.",
+    maintainer='Tal Yarkoni',
+    maintainer_email='tyarkoni at gmail.com',
+    url='http://github.com/tyarkoni/transitions',
+    packages=find_packages(exclude=['tests', 'test_*']),
+    package_data={'transitions': ['data/*'],
+                  'transitions.tests': ['data/*']
+                  },
+    include_package_data=True,
+    install_requires=['six'],
+    tests_require=tests_require,
+    license='MIT',
+    download_url='https://github.com/tyarkoni/transitions/archive/%s.tar.gz' % __version__,
+    classifiers=[
+        'License :: OSI Approved :: MIT License',
+        'Programming Language :: Python :: 2',
+        'Programming Language :: Python :: 2.7',
+        'Programming Language :: Python :: 3',
+        'Programming Language :: Python :: 3.3',
+        'Programming Language :: Python :: 3.4',
+        'Programming Language :: Python :: 3.5',
+        'Programming Language :: Python :: 3.6',
+    ],
+    **extra_setuptools_args
+)
diff --git a/transitions.egg-info/PKG-INFO b/transitions.egg-info/PKG-INFO
new file mode 100644
index 0000000..49ce14c
--- /dev/null
+++ b/transitions.egg-info/PKG-INFO
@@ -0,0 +1,19 @@
+Metadata-Version: 1.1
+Name: transitions
+Version: 0.5.3
+Summary: A lightweight, object-oriented Python state machine implementation.
+Home-page: http://github.com/tyarkoni/transitions
+Author: Tal Yarkoni
+Author-email: tyarkoni at gmail.com
+License: MIT
+Download-URL: https://github.com/tyarkoni/transitions/archive/0.5.3.tar.gz
+Description: UNKNOWN
+Platform: UNKNOWN
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
diff --git a/transitions.egg-info/SOURCES.txt b/transitions.egg-info/SOURCES.txt
new file mode 100644
index 0000000..ce8c14d
--- /dev/null
+++ b/transitions.egg-info/SOURCES.txt
@@ -0,0 +1,17 @@
+LICENSE
+MANIFEST.in
+setup.cfg
+setup.py
+transitions/__init__.py
+transitions/core.py
+transitions/version.py
+transitions.egg-info/PKG-INFO
+transitions.egg-info/SOURCES.txt
+transitions.egg-info/dependency_links.txt
+transitions.egg-info/requires.txt
+transitions.egg-info/top_level.txt
+transitions/extensions/__init__.py
+transitions/extensions/diagrams.py
+transitions/extensions/factory.py
+transitions/extensions/locking.py
+transitions/extensions/nesting.py
\ No newline at end of file
diff --git a/transitions.egg-info/dependency_links.txt b/transitions.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/transitions.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/transitions.egg-info/requires.txt b/transitions.egg-info/requires.txt
new file mode 100644
index 0000000..4cb53bf
--- /dev/null
+++ b/transitions.egg-info/requires.txt
@@ -0,0 +1,4 @@
+six
+
+[test]
+nose>=0.10.1
diff --git a/transitions.egg-info/top_level.txt b/transitions.egg-info/top_level.txt
new file mode 100644
index 0000000..9d8392e
--- /dev/null
+++ b/transitions.egg-info/top_level.txt
@@ -0,0 +1 @@
+transitions
diff --git a/transitions/__init__.py b/transitions/__init__.py
new file mode 100644
index 0000000..2610bbf
--- /dev/null
+++ b/transitions/__init__.py
@@ -0,0 +1,9 @@
+from __future__ import absolute_import
+from .version import __version__
+from .core import (State, Transition, Event, EventData, Machine, MachineError,
+                   logger)
+
+__copyright__ = "Copyright (c) 2017 Tal Yarkoni"
+__license__ = "MIT"
+__summary__ = "A lightweight, object-oriented finite state machine in Python"
+__uri__ = "https://github.com/tyarkoni/transitions"
diff --git a/transitions/core.py b/transitions/core.py
new file mode 100644
index 0000000..0778c27
--- /dev/null
+++ b/transitions/core.py
@@ -0,0 +1,909 @@
+try:
+    from builtins import object
+except ImportError:
+    # python2
+    pass
+import inspect
+import itertools
+import logging
+
+from collections import OrderedDict
+from collections import defaultdict
+from collections import deque
+from functools import partial
+from six import string_types
+
+import warnings
+warnings.simplefilter('default')
+
+logger = logging.getLogger(__name__)
+logger.addHandler(logging.NullHandler())
+
+
+def listify(obj):
+    if obj is None:
+        return []
+    else:
+        return obj if isinstance(obj, (list, tuple, type(None))) else [obj]
+
+
+def get_trigger(model, trigger_name, *args, **kwargs):
+    func = getattr(model, trigger_name, None)
+    if func:
+        return func(*args, **kwargs)
+    raise AttributeError("Model has no trigger named '%s'" % trigger_name)
+
+
+def prep_ordered_arg(desired_length, arg_name):
+    """Ensure arguments to add_ordered_transitions are the proper length and
+    replicate the given argument if only one given (apply same condition, callback
+    to all transitions)
+    """
+    arg_name = listify(arg_name) if arg_name else [None]
+    if len(arg_name) != desired_length and len(arg_name) != 1:
+        raise ValueError("Argument length must be either 1 or the same length as "
+                         "the number of transitions.")
+    if len(arg_name) == 1:
+        return arg_name * desired_length
+    return arg_name
+
+
+class State(object):
+
+    def __init__(self, name, on_enter=None, on_exit=None,
+                 ignore_invalid_triggers=False):
+        """
+        Args:
+            name (string): The name of the state
+            on_enter (string, list): Optional callable(s) to trigger when a
+                state is entered. Can be either a string providing the name of
+                a callable, or a list of strings.
+            on_exit (string, list): Optional callable(s) to trigger when a
+                state is exited. Can be either a string providing the name of a
+                callable, or a list of strings.
+            ignore_invalid_triggers (Boolean): Optional flag to indicate if
+                unhandled/invalid triggers should raise an exception
+
+        """
+        self.name = name
+        self.ignore_invalid_triggers = ignore_invalid_triggers
+        self.on_enter = listify(on_enter) if on_enter else []
+        self.on_exit = listify(on_exit) if on_exit else []
+
+    def enter(self, event_data):
+        """ Triggered when a state is entered. """
+        logger.debug("%sEntering state %s. Processing callbacks...", event_data.machine.id, self.name)
+        for oe in self.on_enter:
+            event_data.machine._callback(oe, event_data)
+        logger.info("%sEntered state %s", event_data.machine.id, self.name)
+
+    def exit(self, event_data):
+        """ Triggered when a state is exited. """
+        logger.debug("%sExiting state %s. Processing callbacks...", event_data.machine.id, self.name)
+        for oe in self.on_exit:
+            event_data.machine._callback(oe, event_data)
+        logger.info("%sExited state %s", event_data.machine.id, self.name)
+
+    def add_callback(self, trigger, func):
+        """ Add a new enter or exit callback.
+        Args:
+            trigger (string): The type of triggering event. Must be one of
+                'enter' or 'exit'.
+            func (string): The name of the callback function.
+        """
+        callback_list = getattr(self, 'on_' + trigger)
+        callback_list.append(func)
+
+    def __repr__(self):
+        return "<%s('%s')@%s>" % (type(self).__name__, self.name, id(self))
+
+
+class Condition(object):
+
+    def __init__(self, func, target=True):
+        """
+        Args:
+            func (string): Name of the condition-checking callable
+            target (bool): Indicates the target state--i.e., when True,
+                the condition-checking callback should return True to pass,
+                and when False, the callback should return False to pass.
+        Notes:
+            This class should not be initialized or called from outside a
+            Transition instance, and exists at module level (rather than
+            nesting under the transition class) only because of a bug in
+            dill that prevents serialization under Python 2.7.
+        """
+        self.func = func
+        self.target = target
+
+    def check(self, event_data):
+        """ Check whether the condition passes.
+        Args:
+            event_data (EventData): An EventData instance to pass to the
+            condition (if event sending is enabled) or to extract arguments
+            from (if event sending is disabled). Also contains the data
+            model attached to the current machine which is used to invoke
+            the condition.
+        """
+        predicate = getattr(event_data.model, self.func) if isinstance(self.func, string_types) else self.func
+
+        if event_data.machine.send_event:
+            return predicate(event_data) == self.target
+        else:
+            return predicate(
+                *event_data.args, **event_data.kwargs) == self.target
+
+    def __repr__(self):
+        return "<%s(%s)@%s>" % (type(self).__name__, self.func, id(self))
+
+
+class Transition(object):
+
+    def __init__(self, source, dest, conditions=None, unless=None, before=None,
+                 after=None, prepare=None):
+        """
+        Args:
+            source (string): The name of the source State.
+            dest (string): The name of the destination State.
+            conditions (string, list): Condition(s) that must pass in order for
+                the transition to take place. Either a string providing the
+                name of a callable, or a list of callables. For the transition
+                to occur, ALL callables must return True.
+            unless (string, list): Condition(s) that must return False in order
+                for the transition to occur. Behaves just like conditions arg
+                otherwise.
+            before (string or list): callbacks to trigger before the
+                transition.
+            after (string or list): callbacks to trigger after the transition.
+            prepare (string or list): callbacks to trigger before conditions are checked
+        """
+        self.source = source
+        self.dest = dest
+        self.prepare = [] if prepare is None else listify(prepare)
+        self.before = [] if before is None else listify(before)
+        self.after = [] if after is None else listify(after)
+
+        self.conditions = []
+        if conditions is not None:
+            for c in listify(conditions):
+                self.conditions.append(Condition(c))
+        if unless is not None:
+            for u in listify(unless):
+                self.conditions.append(Condition(u, target=False))
+
+    def execute(self, event_data):
+        """ Execute the transition.
+        Args:
+            event: An instance of class EventData.
+        Returns: boolean indicating whether or not the transition was
+            successfully executed (True if successful, False if not).
+        """
+        logger.debug("%sInitiating transition from state %s to state %s...",
+                     event_data.machine.id, self.source, self.dest)
+        machine = event_data.machine
+
+        for func in self.prepare:
+            machine._callback(func, event_data)
+            logger.debug("Executed callback '%s' before conditions." % func)
+
+        for c in self.conditions:
+            if not c.check(event_data):
+                logger.debug("%sTransition condition failed: %s() does not " +
+                             "return %s. Transition halted.", event_data.machine.id, c.func, c.target)
+                return False
+        for func in itertools.chain(machine.before_state_change, self.before):
+            machine._callback(func, event_data)
+            logger.debug("%sExecuted callback '%s' before transition.", event_data.machine.id, func)
+
+        self._change_state(event_data)
+
+        for func in itertools.chain(self.after, machine.after_state_change):
+            machine._callback(func, event_data)
+            logger.debug("%sExecuted callback '%s' after transition.", event_data.machine.id, func)
+        return True
+
+    def _change_state(self, event_data):
+        event_data.machine.get_state(self.source).exit(event_data)
+        event_data.machine.set_state(self.dest, event_data.model)
+        event_data.update(event_data.model)
+        event_data.machine.get_state(self.dest).enter(event_data)
+
+    def add_callback(self, trigger, func):
+        """ Add a new before, after, or prepare callback.
+        Args:
+            trigger (string): The type of triggering event. Must be one of
+                'before', 'after' or 'prepare'.
+            func (string): The name of the callback function.
+        """
+        callback_list = getattr(self, trigger)
+        callback_list.append(func)
+
+    def __repr__(self):
+        return "<%s('%s', '%s')@%s>" % (type(self).__name__,
+                                        self.source, self.dest, id(self))
+
+
+class EventData(object):
+
+    def __init__(self, state, event, machine, model, args, kwargs):
+        """
+        Args:
+            state (State): The State from which the Event was triggered.
+            event (Event): The triggering Event.
+            machine (Machine): The current Machine instance.
+            model (object): The model/object the machine is bound to.
+            args (list): Optional positional arguments from trigger method
+                to store internally for possible later use.
+            kwargs (dict): Optional keyword arguments from trigger method
+                to store internally for possible later use.
+        """
+        self.state = state
+        self.event = event
+        self.machine = machine
+        self.model = model
+        self.args = args
+        self.kwargs = kwargs
+        self.transition = None
+        self.error = None
+        self.result = False
+
+    def update(self, model):
+        """ Updates the current State to accurately reflect the Machine. """
+        self.state = self.machine.get_state(model.state)
+
+    def __repr__(self):
+        return "<%s('%s', %s)@%s>" % (type(self).__name__, self.state,
+                                      getattr(self, 'transition'), id(self))
+
+
+class Event(object):
+
+    def __init__(self, name, machine):
+        """
+        Args:
+            name (string): The name of the event, which is also the name of the
+                triggering callable (e.g., 'advance' implies an advance()
+                method).
+            machine (Machine): The current Machine instance.
+        """
+        self.name = name
+        self.machine = machine
+        self.transitions = defaultdict(list)
+
+    def add_transition(self, transition):
+        """ Add a transition to the list of potential transitions.
+        Args:
+            transition (Transition): The Transition instance to add to the
+                list.
+        """
+        self.transitions[transition.source].append(transition)
+
+    def trigger(self, model, *args, **kwargs):
+        f = partial(self._trigger, model, *args, **kwargs)
+        return self.machine._process(f)
+
+    def _trigger(self, model, *args, **kwargs):
+        """ Serially execute all transitions that match the current state,
+        halting as soon as one successfully completes.
+        Args:
+            args and kwargs: Optional positional or named arguments that will
+                be passed onto the EventData object, enabling arbitrary state
+                information to be passed on to downstream triggered functions.
+        Returns: boolean indicating whether or not a transition was
+            successfully executed (True if successful, False if not).
+        """
+        state = self.machine.get_state(model.state)
+        if state.name not in self.transitions:
+            msg = "%sCan't trigger event %s from state %s!" % (self.machine.id, self.name,
+                                                               state.name)
+            if state.ignore_invalid_triggers:
+                logger.warning(msg)
+                return False
+            else:
+                raise MachineError(msg)
+        event_data = EventData(state, self, self.machine, model, args=args, kwargs=kwargs)
+
+        for func in self.machine.prepare_event:
+            self.machine._callback(func, event_data)
+            logger.debug("Executed machine preparation callback '%s' before conditions." % func)
+
+        try:
+            for t in self.transitions[state.name]:
+                event_data.transition = t
+                if t.execute(event_data):
+                    event_data.result = True
+                    break
+        except Exception as e:
+            event_data.error = e
+            raise
+        finally:
+            for func in self.machine.finalize_event:
+                self.machine._callback(func, event_data)
+                logger.debug("Executed machine finalize callback '%s'." % func)
+        return event_data.result
+
+    def __repr__(self):
+        return "<%s('%s')@%s>" % (type(self).__name__, self.name, id(self))
+
+    def add_callback(self, trigger, func):
+        """ Add a new before or after callback to all available transitions.
+        Args:
+            trigger (string): The type of triggering event. Must be one of
+                'before', 'after' or 'prepare'.
+            func (string): The name of the callback function.
+        """
+        for t in itertools.chain(*self.transitions.values()):
+            t.add_callback(trigger, func)
+
+
+class Machine(object):
+
+    # Callback naming parameters
+    callbacks = ['before', 'after', 'prepare', 'on_enter', 'on_exit']
+    separator = '_'
+    wildcard_all = '*'
+    wildcard_same = '='
+
+    def __init__(self, model='self', states=None, initial='initial', transitions=None,
+                 send_event=False, auto_transitions=True,
+                 ordered_transitions=False, ignore_invalid_triggers=None,
+                 before_state_change=None, after_state_change=None, name=None,
+                 queued=False, add_self=True, prepare_event=None, finalize_event=None, **kwargs):
+        """
+        Args:
+            model (object): The object(s) whose states we want to manage. If 'self',
+                the current Machine instance will be used the model (i.e., all
+                triggering events will be attached to the Machine itself).
+            states (list): A list of valid states. Each element can be either a
+                string or a State instance. If string, a new generic State
+                instance will be created that has the same name as the string.
+            initial (string or State): The initial state of the Machine.
+            transitions (list): An optional list of transitions. Each element
+                is a dictionary of named arguments to be passed onto the
+                Transition initializer.
+            send_event (boolean): When True, any arguments passed to trigger
+                methods will be wrapped in an EventData object, allowing
+                indirect and encapsulated access to data. When False, all
+                positional and keyword arguments will be passed directly to all
+                callback methods.
+            auto_transitions (boolean): When True (default), every state will
+                automatically have an associated to_{state}() convenience
+                trigger in the base model.
+            ordered_transitions (boolean): Convenience argument that calls
+                add_ordered_transitions() at the end of initialization if set
+                to True.
+            ignore_invalid_triggers: when True, any calls to trigger methods
+                that are not valid for the present state (e.g., calling an
+                a_to_b() trigger when the current state is c) will be silently
+                ignored rather than raising an invalid transition exception.
+            before_state_change: A callable called on every change state before
+                the transition happened. It receives the very same args as normal
+                callbacks.
+            after_state_change: A callable called on every change state after
+                the transition happened. It receives the very same args as normal
+                callbacks.
+            name: If a name is set, it will be used as a prefix for logger output
+            queued (boolean): When True, processes transitions sequentially. A trigger
+                executed in a state callback function will be queued and executed later.
+                Due to the nature of the queued processing, all transitions will
+                _always_ return True since conditional checks cannot be conducted at queueing time.
+            add_self (boolean): If no model(s) provided, intialize state machine against self.
+            prepare_event: A callable called on for before possible transitions will be processed.
+                It receives the very same args as normal callbacks.
+            finalize_event: A callable called on for each triggered event after transitions have been processed.
+                This is also called when a transition raises an exception.
+
+            **kwargs additional arguments passed to next class in MRO. This can be ignored in most cases.
+        """
+
+        try:
+            super(Machine, self).__init__(**kwargs)
+        except TypeError as e:
+            raise ValueError('Passing arguments {0} caused an inheritance error: {1}'.format(kwargs.keys(), e))
+
+        # initialize protected attributes first
+        self._queued = queued
+        self._transition_queue = deque()
+        self._before_state_change = []
+        self._after_state_change = []
+        self._prepare_event = []
+        self._finalize_event = []
+        self._initial = None
+
+        self.states = OrderedDict()
+        self.events = {}
+        self.send_event = send_event
+        self.auto_transitions = auto_transitions
+        self.ignore_invalid_triggers = ignore_invalid_triggers
+        self.prepare_event = prepare_event
+        self.before_state_change = before_state_change
+        self.after_state_change = after_state_change
+        self.finalize_event = finalize_event
+        self.id = name + ": " if name is not None else ""
+
+        self.models = []
+
+        if model is None and add_self:
+            model = 'self'
+            warnings.warn("Starting from transitions version 0.6.0, passing model=None to the "
+                          "constructor will no longer add the machine instance as a model but add "
+                          "NO model at all. Consequently, add_self will be removed. To add the "
+                          "machine as a model (and also hide this warning) use the new default "
+                          "value model='self' instead.", PendingDeprecationWarning)
+
+        if add_self is not True:
+            warnings.warn("Starting from transitions version 0.6.0, passing model=None to the "
+                          "constructor will no longer add the machine instance as a model but add "
+                          "NO model at all. Consequently, add_self will be removed.",
+                          PendingDeprecationWarning)
+
+        if model and initial is None:
+            initial = 'initial'
+            warnings.warn("Starting from transitions version 0.6.0, passing initial=None to the constructor "
+                          "will no longer create and set the 'initial' state. If no initial"
+                          "state is provided but model is not None, an error will be raised.",
+                          PendingDeprecationWarning)
+
+        if states is not None:
+            self.add_states(states)
+
+        if initial is not None:
+            if isinstance(initial, State):
+                if initial.name not in self.states:
+                    self.add_state(initial)
+                else:
+                    assert self._has_state(initial)
+                self._initial = initial.name
+            else:
+                if initial not in self.states:
+                    self.add_state(initial)
+                self._initial = initial
+
+        if transitions is not None:
+            transitions = listify(transitions)
+            for t in transitions:
+                if isinstance(t, list):
+                    self.add_transition(*t)
+                else:
+                    self.add_transition(**t)
+
+        if ordered_transitions:
+            self.add_ordered_transitions()
+
+        if model:
+            self.add_model(model)
+
+    def add_model(self, model, initial=None):
+        """ Register a model with the state machine, initializing triggers and callbacks. """
+        models = listify(model)
+
+        if initial is None:
+            if self._initial is None:
+                raise ValueError("No initial state configured for machine, must specify when adding model.")
+            else:
+                initial = self._initial
+
+        for model in models:
+            model = self if model == 'self' else model
+            if model not in self.models:
+                if hasattr(model, 'trigger'):
+                    logger.warning("%sModel already contains an attribute 'trigger'. Skip method binding ",
+                                   self.id)
+                else:
+                    model.trigger = partial(get_trigger, model)
+
+                for trigger, _ in self.events.items():
+                    self._add_trigger_to_model(trigger, model)
+
+                for _, state in self.states.items():
+                    self._add_model_to_state(state, model)
+
+                self.set_state(initial, model=model)
+                self.models.append(model)
+
+    def remove_model(self, model):
+        """ Deregister a model with the state machine. The model will still contain all previously added triggers
+        and callbacks, but will not receive updates when states or transitions are added to the Machine. """
+        models = listify(model)
+
+        for model in models:
+            self.models.remove(model)
+
+    @staticmethod
+    def _create_transition(*args, **kwargs):
+        return Transition(*args, **kwargs)
+
+    @staticmethod
+    def _create_event(*args, **kwargs):
+        return Event(*args, **kwargs)
+
+    @staticmethod
+    def _create_state(*args, **kwargs):
+        return State(*args, **kwargs)
+
+    @property
+    def initial(self):
+        """ Return the initial state. """
+        return self._initial
+
+    @property
+    def has_queue(self):
+        """ Return boolean indicating if machine has queue or not """
+        return self._queued
+
+    @property
+    def model(self):
+        if len(self.models) == 1:
+            return self.models[0]
+        else:
+            return self.models
+
+    @property
+    def before_state_change(self):
+        return self._before_state_change
+
+    # this should make sure that _before_state_change is always a list
+    @before_state_change.setter
+    def before_state_change(self, value):
+        self._before_state_change = listify(value)
+
+    @property
+    def after_state_change(self):
+        return self._after_state_change
+
+    # this should make sure that _after_state_change is always a list
+    @after_state_change.setter
+    def after_state_change(self, value):
+        self._after_state_change = listify(value)
+
+    @property
+    def prepare_event(self):
+        return self._prepare_event
+
+    # this should make sure that prepare_event is always a list
+    @prepare_event.setter
+    def prepare_event(self, value):
+        self._prepare_event = listify(value)
+
+    @property
+    def finalize_event(self):
+        return self._finalize_event
+
+    # this should make sure that finalize_event is always a list
+    @finalize_event.setter
+    def finalize_event(self, value):
+        self._finalize_event = listify(value)
+
+    def is_state(self, state, model):
+        """ Check whether the current state matches the named state. """
+        return model.state == state
+
+    def get_state(self, state):
+        """ Return the State instance with the passed name. """
+        if state not in self.states:
+            raise ValueError("State '%s' is not a registered state." % state)
+        return self.states[state]
+
+    def set_state(self, state, model=None):
+        """ Set the current state. """
+        if isinstance(state, string_types):
+            state = self.get_state(state)
+        models = self.models if model is None else listify(model)
+        for m in models:
+            m.state = state.name
+
+    def add_state(self, *args, **kwargs):
+        """ Alias for add_states. """
+        self.add_states(*args, **kwargs)
+
+    def add_states(self, states, on_enter=None, on_exit=None,
+                   ignore_invalid_triggers=None):
+        """ Add new state(s).
+        Args:
+            state (list, string, dict, or State): a list, a State instance, the
+                name of a new state, or a dict with keywords to pass on to the
+                State initializer. If a list, each element can be of any of the
+                latter three types.
+            on_enter (string or list): callbacks to trigger when the state is
+                entered. Only valid if first argument is string.
+            on_exit (string or list): callbacks to trigger when the state is
+                exited. Only valid if first argument is string.
+            ignore_invalid_triggers: when True, any calls to trigger methods
+                that are not valid for the present state (e.g., calling an
+                a_to_b() trigger when the current state is c) will be silently
+                ignored rather than raising an invalid transition exception.
+                Note that this argument takes precedence over the same
+                argument defined at the Machine level, and is in turn
+                overridden by any ignore_invalid_triggers explicitly
+                passed in an individual state's initialization arguments.
+        """
+
+        ignore = ignore_invalid_triggers
+        if ignore is None:
+            ignore = self.ignore_invalid_triggers
+
+        states = listify(states)
+        for state in states:
+            if isinstance(state, string_types):
+                state = self._create_state(
+                    state, on_enter=on_enter, on_exit=on_exit,
+                    ignore_invalid_triggers=ignore)
+            elif isinstance(state, dict):
+                if 'ignore_invalid_triggers' not in state:
+                    state['ignore_invalid_triggers'] = ignore
+                state = self._create_state(**state)
+            self.states[state.name] = state
+            for model in self.models:
+                self._add_model_to_state(state, model)
+        # Add automatic transitions after all states have been created
+        if self.auto_transitions:
+            for s in self.states.keys():
+                self.add_transition('to_%s' % s, self.wildcard_all, s)
+
+    def _add_model_to_state(self, state, model):
+        setattr(model, 'is_%s' % state.name,
+                partial(self.is_state, state.name, model))
+        #  Add enter/exit callbacks if there are existing bound methods
+        enter_callback = 'on_enter_' + state.name
+        if hasattr(model, enter_callback) and \
+                inspect.ismethod(getattr(model, enter_callback)):
+            state.add_callback('enter', enter_callback)
+        exit_callback = 'on_exit_' + state.name
+        if hasattr(model, exit_callback) and \
+                inspect.ismethod(getattr(model, exit_callback)):
+            state.add_callback('exit', exit_callback)
+
+    def _add_trigger_to_model(self, trigger, model):
+        trig_func = partial(self.events[trigger].trigger, model)
+        setattr(model, trigger, trig_func)
+
+    def get_triggers(self, *args):
+        states = set(args)
+        return [t for (t, ev) in self.events.items() if any(state in ev.transitions for state in states)]
+
+    def add_transition(self, trigger, source, dest, conditions=None,
+                       unless=None, before=None, after=None, prepare=None, **kwargs):
+        """ Create a new Transition instance and add it to the internal list.
+        Args:
+            trigger (string): The name of the method that will trigger the
+                transition. This will be attached to the currently specified
+                model (e.g., passing trigger='advance' will create a new
+                advance() method in the model that triggers the transition.)
+            source(string): The name of the source state--i.e., the state we
+                are transitioning away from. This can be a single state, a
+                list of states or an asterisk for all states.
+            dest (string): The name of the destination State--i.e., the state
+                we are transitioning into. This can be a single state or an
+                equal sign to specify that the transition should be reflexive
+                so that the destination will be the same as the source for
+                every given source.
+            conditions (string or list): Condition(s) that must pass in order
+                for the transition to take place. Either a list providing the
+                name of a callable, or a list of callables. For the transition
+                to occur, ALL callables must return True.
+            unless (string, list): Condition(s) that must return False in order
+                for the transition to occur. Behaves just like conditions arg
+                otherwise.
+            before (string or list): Callables to call before the transition.
+            after (string or list): Callables to call after the transition.
+            prepare (string or list): Callables to call when the trigger is activated
+            **kwargs: Additional arguments which can be passed to the created transition.
+                This is useful if you plan to extend Machine.Transition and require more parameters.
+        """
+        if trigger not in self.events:
+            self.events[trigger] = self._create_event(trigger, self)
+            for model in self.models:
+                self._add_trigger_to_model(trigger, model)
+
+        if isinstance(source, string_types):
+            source = list(self.states.keys()) if source == self.wildcard_all else [source]
+        else:
+            source = [s.name if self._has_state(s) else s for s in listify(source)]
+
+        for s in source:
+            d = s if dest == self.wildcard_same else dest
+            if self._has_state(d):
+                d = d.name
+            t = self._create_transition(s, d, conditions, unless, before,
+                                        after, prepare, **kwargs)
+            self.events[trigger].add_transition(t)
+
+    def add_ordered_transitions(self, states=None, trigger='next_state',
+                                loop=True, loop_includes_initial=True,
+                                conditions=None, unless=None, before=None,
+                                after=None, prepare=None, **kwargs):
+        """ Add a set of transitions that move linearly from state to state.
+        Args:
+            states (list): A list of state names defining the order of the
+                transitions. E.g., ['A', 'B', 'C'] will generate transitions
+                for A --> B, B --> C, and C --> A (if loop is True). If states
+                is None, all states in the current instance will be used.
+            trigger (string): The name of the trigger method that advances to
+                the next state in the sequence.
+            loop (boolean): Whether or not to add a transition from the last
+                state to the first state.
+            loop_includes_initial (boolean): If no initial state was defined in
+                the machine, setting this to True will cause the _initial state
+                placeholder to be included in the added transitions.
+            conditions (string or list): Condition(s) that must pass in order
+                for the transition to take place. Either a list providing the
+                name of a callable, or a list of callables. For the transition
+                to occur, ALL callables must return True.
+            unless (string, list): Condition(s) that must return False in order
+                for the transition to occur. Behaves just like conditions arg
+                otherwise.
+            before (string or list): Callables to call before the transition.
+            after (string or list): Callables to call after the transition.
+            prepare (string or list): Callables to call when the trigger is activated
+            **kwargs: Additional arguments which can be passed to the created transition.
+                This is useful if you plan to extend Machine.Transition and require more parameters.
+        """
+        if states is None:
+            states = list(self.states.keys())  # need to listify for Python3
+        len_transitions = len(states)
... 1198 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-transitions.git



More information about the Python-modules-commits mailing list