Skip to content

Commit

Permalink
PEP 8
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexandreDecan committed Jan 29, 2016
1 parent 7e31457 commit c145252
Show file tree
Hide file tree
Showing 12 changed files with 83 additions and 52 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
Changelog
=========

Unreleased
----------

- (Added) An ``io.text.export_to_tree`` that returns a textual representation of the states.
- (Changed) ``Statechart.rename_to`` does not anymore raise ``KeyError`` but ``exceptions.StatechartError``.


0.17.1 (2016-01-25)
-------------------

Expand Down
5 changes: 3 additions & 2 deletions sismic/code/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ class PythonEvaluator(Evaluator):
if this state is currently active, ie. it is in the active configuration of the ``Interpreter`` instance
that makes use of this evaluator.
- On code execution:
- A *send(name, **kwargs)* function that takes an event name and additional keyword parameters and fires an internal event with.
- A *send(name, **kwargs)* function that takes an event name and additional keyword parameters and fires
an internal event with.
- If the code is related to a transition, the *event* that fires the transition is exposed.
- On code evaluation:
- If the code is related to a transition, the *event* that fires the transition is exposed.
Expand Down Expand Up @@ -79,7 +80,7 @@ def __get_memory(self, obj):
:param obj: *StateMixin* or *Transition*
:return: an instance of *FrozenContext*
"""
return self._memory.get(id(obj), None)
return self._memory.get(id(obj), {})

def __send(self, name: str, **kwargs):
"""
Expand Down
34 changes: 20 additions & 14 deletions sismic/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def __init__(self, statechart: model.Statechart, evaluator_klass=None,
self._bound = [] # List of bound event callbacks

# Evaluator
self._evaluator = evaluator_klass(self, initial_context) if evaluator_klass else PythonEvaluator(self, initial_context)
self._evaluator = (evaluator_klass if evaluator_klass else PythonEvaluator)(self, initial_context)
self._evaluator.execute_statechart(statechart)

# Initial step and stabilization
Expand Down Expand Up @@ -264,9 +264,11 @@ def _sort_transitions(self, transitions: list) -> list:

# Their LCA must be an orthogonal state!
if not isinstance(lca_state, model.OrthogonalState):
raise NonDeterminismError('Non-determinist choice between transitions {t1} and {t2}'
'\nConfiguration is {c}\nEvent is {e}\nTransitions are:{t}\n'
.format(c=self.configuration, e=t1.event, t=transitions, t1=t1, t2=t2))
raise NonDeterminismError(
'Non-determinist choice between transitions {t1} and {t2}'
'\nConfiguration is {c}\nEvent is {e}\nTransitions are:{t}\n'
.format(c=self.configuration, e=t1.event, t=transitions, t1=t1, t2=t2)
)

# Check (2)
# This check must be done wrt. to LCA, as the combination of from_states could
Expand All @@ -280,10 +282,12 @@ def _sort_transitions(self, transitions: list) -> list:
# Target must be a descendant (or self) of this state
if (transition.target and
(transition.target not in
[last_before_lca] + self._statechart.descendants_for(last_before_lca))):
raise ConflictingTransitionsError('Conflicting transitions: {t1} and {t2}'
'\nConfiguration is {c}\nEvent is {e}\nTransitions are:{t}\n'
.format(c=self.configuration, e=t1.event, t=transitions, t1=t1, t2=t2))
[last_before_lca] + self._statechart.descendants_for(last_before_lca))):
raise ConflictingTransitionsError(
'Conflicting transitions: {t1} and {t2}'
'\nConfiguration is {c}\nEvent is {e}\nTransitions are:{t}\n'
.format(c=self.configuration, e=t1.event, t=transitions, t1=t1, t2=t2)
)

# Define an arbitrary order based on the depth and the name of source states.
transitions = sorted(transitions, key=lambda t: (-self._statechart.depth_for(t.source), t.source))
Expand Down Expand Up @@ -355,7 +359,7 @@ def _compute_stabilization_step(self) -> model.MicroStep:
"""
# Check if we are in a set of "stable" states
leaves_names = self._statechart.leaf_for(list(self._configuration))
leaves = list(map(lambda s: self._statechart.state_for(s), leaves_names))
leaves = map(self._statechart.state_for, leaves_names)
leaves = sorted(leaves, key=lambda s: (-self._statechart.depth_for(s.name), s.name))

# Final states?
Expand All @@ -381,8 +385,8 @@ def _execute_step(self, step: model.MicroStep):
:param step: *MicroStep* instance
"""
entered_states = list(map(lambda s: self._statechart.state_for(s), step.entered_states))
exited_states = list(map(lambda s: self._statechart.state_for(s), step.exited_states))
entered_states = list(map(self._statechart.state_for, step.entered_states))
exited_states = list(map(self._statechart.state_for, step.exited_states))

# Exit states
for state in exited_states:
Expand Down Expand Up @@ -492,17 +496,19 @@ def run_in_background(interpreter: Interpreter, delay: float=0.05, callback=None
import time
import threading

def _task(interpreter, delay):
def _task():
starttime = time.time()
while not interpreter.final:
interpreter.time = time.time() - starttime
steps = interpreter.execute()
if callback:
callback(steps)
time.sleep(delay)
thread = threading.Thread(target=_task, args=(interpreter, delay))
thread = threading.Thread(target=_task)

def stop_thread():
interpreter._configuration = []

def stop_thread(): interpreter._configuration = []
thread.stop = stop_thread

thread.start()
Expand Down
2 changes: 1 addition & 1 deletion sismic/io/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .yaml import import_from_yaml, export_to_yaml
from . import text

__all__ = ['import_from_yaml', 'export_to_yaml', 'text']
__all__ = ['import_from_yaml', 'export_to_yaml']
15 changes: 8 additions & 7 deletions sismic/io/datadict.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,17 +86,17 @@ def _import_state_from_dict(state_d: dict) -> StateMixin:
:return: a specialized instance of State
"""
name = state_d.get('name')
type = state_d.get('type', None)
stype = state_d.get('type', None)
on_entry = state_d.get('on entry', None)
on_exit = state_d.get('on exit', None)

if type == 'final':
if stype == 'final':
state = FinalState(name, on_entry=on_entry, on_exit=on_exit)
elif type == 'shallow history':
elif stype == 'shallow history':
state = ShallowHistoryState(name, on_entry=on_entry, on_exit=on_exit, memory=state_d.get('memory', None))
elif type == 'deep history':
elif stype == 'deep history':
state = DeepHistoryState(name, on_entry=on_entry, on_exit=on_exit, memory=state_d.get('memory', None))
elif type is None:
elif stype is None:
substates = state_d.get('states', None)
parallel_substates = state_d.get('parallel states', None)

Expand All @@ -109,7 +109,7 @@ def _import_state_from_dict(state_d: dict) -> StateMixin:
else:
state = BasicState(name, on_entry=on_entry, on_exit=on_exit)
else:
raise StatechartError('Unknown type {} for state {}'.format(type, name))
raise StatechartError('Unknown type {} for state {}'.format(stype, name))

# Preconditions, postconditions and invariants
for condition in state_d.get('contract', []):
Expand All @@ -127,7 +127,8 @@ def export_to_dict(statechart: Statechart, ordered=True) -> dict:
Export given StateChart instance to a dict.
:param statechart: a StateChart instance
:return: a dict that can be used in *_import_from_dict``
:param ordered: set to True to use an ordereddict instead of a dict
:return: a dict that can be used in *_import_from_dict*
"""
d = OrderedDict() if ordered else {}
d['name'] = statechart.name
Expand Down
2 changes: 1 addition & 1 deletion sismic/io/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def export_to_tree(statechart: Statechart, spaces: int=3) -> str:
def to_tree(state: str):
children = sorted(statechart.children_for(state))

trees = map(lambda child: to_tree(child), children)
trees = map(to_tree, children)
flat_trees = itertools.chain.from_iterable(trees)
children_repr = map(lambda x: spaces * ' ' + x, flat_trees)
return [state] + list(children_repr)
Expand Down
3 changes: 2 additions & 1 deletion sismic/model/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .elements import ContractMixin, StateMixin, ActionStateMixin, TransitionStateMixin, CompositeStateMixin, HistoryStateMixin
from .elements import ContractMixin, StateMixin, ActionStateMixin, \
TransitionStateMixin, CompositeStateMixin, HistoryStateMixin
from .elements import BasicState, CompoundState, OrthogonalState, ShallowHistoryState, DeepHistoryState, FinalState
from .elements import Transition
from .statechart import Statechart
Expand Down
4 changes: 3 additions & 1 deletion sismic/model/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ def __hash__(self):

def __repr__(self):
if self.data:
return '{}({}, {})'.format(self.__class__.__name__, self.name, ', '.join('{}={}'.format(k, v) for k,v in self.data.items()))
return '{}({}, {})'.format(self.__class__.__name__,
self.name,
', '.join('{}={}'.format(k, v) for k, v in self.data.items()))
else:
return '{}({})'.format(self.__class__.__name__, self.name)

Expand Down
49 changes: 27 additions & 22 deletions sismic/model/statechart.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def preamble(self):
"""
return self._preamble

########## STATES ##########
# ######### STATES ##########

@property
def states(self):
Expand All @@ -64,7 +64,7 @@ def add_state(self, state: StateMixin, parent):
if not parent:
# Check root state
if self.root:
raise StatechartError('Root is already defined, {} should declare an existing parent state'.format(state))
raise StatechartError('Root already defined, {} should declare an existing parent state'.format(state))
else:
parent_state = self.state_for(parent)

Expand Down Expand Up @@ -109,11 +109,11 @@ def remove_state(self, name: str):
self.remove_transition(transition)

# Remove compoundstate's initial and historystate's memory
for other_name, other_state in self._states.items():
if isinstance(other_state, CompoundState):
other_state.initial = None
elif isinstance(other_state, HistoryStateMixin):
other_state.memory = None
for o_state in self._states.values():
if isinstance(o_state, CompoundState):
o_state.initial = None
elif isinstance(o_state, HistoryStateMixin):
o_state.memory = None

# Remove state
self._states.pop(name)
Expand All @@ -133,7 +133,9 @@ def rename_state(self, old_name: str, new_name: str):
return
if new_name in self._states:
raise StatechartError('State {} already exists!'.format(new_name))
state = self._states[old_name]

# Check state exists
state = self.state_for(old_name)

# Change transitions
for transition in self.transitions:
Expand All @@ -160,15 +162,17 @@ def rename_state(self, old_name: str, new_name: str):
if self._parent[other_state.name] == old_name:
self._parent[other_state.name] = new_name

# Renaming
# Adapt structures
parent_name = self._parent[old_name]
self._children[parent_name].remove(old_name)
self._children[parent_name].append(new_name)

self._states[new_name] = self._states.pop(old_name)
self._parent[new_name] = self._parent.pop(old_name)
self._children[new_name] = self._children.pop(old_name)

self._children[parent_name].remove(old_name)
self._children[parent_name].append(new_name)
# Rename state!
state._name = new_name

def move_state(self, name: str, new_parent: str):
"""
Expand All @@ -183,7 +187,7 @@ def move_state(self, name: str, new_parent: str):
"""
# Check that both states exist
state = self.state_for(name)
new_parent_state = self.state_for(new_parent)
self.state_for(new_parent)

# Check that parent is not a descendant (or self) of given state
if new_parent in [name] + self.descendants_for(name):
Expand Down Expand Up @@ -253,7 +257,7 @@ def ancestors_for(self, name: str) -> list:
Return an ordered list of ancestors for the given state.
Ancestors are ordered by decreasing depth.
:param state: name of the state
:param name: name of the state
:return: state's ancestors
:raise StatechartError: if state does not exist
"""
Expand Down Expand Up @@ -344,7 +348,7 @@ def leaf_for(self, names: list) -> list:
leaves.append(state)
return leaves

########## TRANSITIONS ##########
# ######### TRANSITIONS ##########

@property
def transitions(self):
Expand All @@ -361,7 +365,7 @@ def add_transition(self, transition: Transition):
:raise StatechartError:
"""
# Check that source state is known
if not transition.source in self._states:
if transition.source not in self._states:
raise StatechartError('Unknown source state for {}'.format(transition))

from_state = self.state_for(transition.source)
Expand Down Expand Up @@ -391,8 +395,7 @@ def rotate_transition(self, transition: Transition, **kwargs):
"""
Rotate given transition.
You MUST specify either *new_source* (a valid state name) or *new_target* (a valid state name or None)
or both.
You MUST specify *new_source* (a valid state name) or *new_target* (a valid state name or None) or both.
:param transition: a *Transition* instance
:param new_source: a state name
Expand Down Expand Up @@ -468,7 +471,7 @@ def transitions_with(self, event: str) -> list:
transitions.append(transition)
return transitions

########## EVENTS ##########
# ######### EVENTS ##########

def events_for(self, name_or_names=None) -> list:
"""
Expand All @@ -495,7 +498,7 @@ def events_for(self, name_or_names=None) -> list:
names.add(transition.event)
return sorted(names)

########## TOOLS ##########
# ######### TOOLS ##########

def _validate_compoundstate_initial(self):
"""
Expand All @@ -506,9 +509,9 @@ def _validate_compoundstate_initial(self):
"""
for name, state in self._states.items():
if isinstance(state, CompoundState) and state.initial:
if not state.initial in self._states:
if state.initial not in self._states:
raise StatechartError('Initial state {} of {} does not exist'.format(state.initial, state))
if not state.initial in self.children_for(name):
if state.initial not in self.children_for(name):
raise StatechartError('Initial state {} of {} must be a child state'.format(state.initial, state))
return True

Expand All @@ -526,7 +529,9 @@ def _validate_historystate_memory(self):
if state.memory not in self._states:
raise StatechartError('Initial memory {} of {} does not exist'.format(state.memory, state))
if state.memory not in self.children_for(self.parent_for(name)):
raise StatechartError('Initial memory {} of {} must be a child of its parent'.format(state.memory, state))
raise StatechartError(
'Initial memory {} of {} must be a parent\'s child'.format(state.memory, state)
)
return True

def validate(self):
Expand Down
3 changes: 2 additions & 1 deletion sismic/model/steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ def __init__(self, event: Event = None, transition: Transition = None,
self.exited_states = exited_states if exited_states else []

def __repr__(self):
return 'MicroStep({}, {}, >{}, <{})'.format(self.event, self.transition, self.entered_states, self.exited_states)
return 'MicroStep({}, {}, >{}, <{})'.format(self.event, self.transition,
self.entered_states, self.exited_states)

def __eq__(self, other):
return (isinstance(other, MicroStep) and
Expand Down
2 changes: 1 addition & 1 deletion sismic/stories.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def random_stories_generator(items, length: int=None, number: int=None):
number = number if number else -1
while number != 0:
story = Story()
for i in range(length):
for _ in range(length):
story.append(random.choice(items)) # Not random.sample, replacements needed
yield story
number -= 1
Expand Down
9 changes: 8 additions & 1 deletion tests/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ def setUp(self):
self.sc = io.import_from_yaml(open('tests/yaml/internal.yaml'))

def test_rename_unexisting_state(self):
with self.assertRaises(KeyError):
with self.assertRaises(exceptions.StatechartError):
self.sc.rename_state('unknown', 's3')
self.sc.validate()

Expand Down Expand Up @@ -366,6 +366,13 @@ def test_rename_old_disappears(self):
self.sc.parent_for('s1')
self.sc.validate()

def test_rename_change_state_name(self):
self.sc = io.import_from_yaml(open('tests/yaml/composite.yaml'))

state = self.sc.state_for('s1')
self.sc.rename_state('s1', 'new s1')
self.assertEqual(state.name, 'new s1')

def test_rename_new_appears(self):
self.sc = io.import_from_yaml(open('tests/yaml/composite.yaml'))
self.sc.rename_state('s1', 'new s1')
Expand Down

0 comments on commit c145252

Please sign in to comment.