Skip to content

Commit

Permalink
Allow setdefault in actions too
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexandreDecan committed Aug 23, 2018
1 parent e896b4b commit 9778993
Show file tree
Hide file tree
Showing 4 changed files with 10 additions and 16 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Unreleased
- (Added) Some documentation about running multiple statecharts.
- (Added) An ``unbind`` method for an ``Interpreter``.
- (Added) A ``remove`` method on ``EventQueue`` and a corresponding ``cancel`` method on ``Interpreter``.
- (Added) A ``setdefault`` function that can be used in the preamble of a statechart to assign default values to variables.
- (Added) A ``setdefault`` function that can be used in the preamble and actions of a statechart to assign default values to variables.
- (Changed) Meta-Event *step started* has a ``time`` attribute.
- (Changed) The current event queue can be consulted as a list using ``interpreter._event_queue``.
- (Fixed) Hook-errors reported by ``sismic-bdd`` CLI are a little bit more verbose (`#81 <https://github.com/AlexandreDecan/sismic/issues/81>`__).
Expand Down
4 changes: 2 additions & 2 deletions docs/code.rst
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ While the initial context provided to the interpreter defined the value of ``x``
contained in the preamble overrode its value. If you want to make use of the initial context to
somehow *parametrize* the execution of the statechart while still providing *default* values for
these parameters, you should either check the existence of the variables before setting their values
or rely on the ``setdefault`` function that is exposed by the Python code evaluator when the preamble
of a statechart is executed.
or rely on the ``setdefault`` function that is exposed by the Python code evaluator when a piece of
code is executed (not only in the preamble).

This function can be used to define (and return) a variable, very similarly to the
``setdefault`` method of a dictionary. Using this function, we can easily rewrite the preamble
Expand Down
11 changes: 4 additions & 7 deletions sismic/code/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ class PythonEvaluator(Evaluator):
- A *notify(name: str, **kwargs) -> None* function that takes an event name and additional keyword parameters and
raises a meta-event with it. Meta-events are only sent to bound property statecharts.
- If the code is related to a transition, the *event: Event* that fires the transition is exposed.
- A *default(name:str, value: Any) -> Any* function that defines and returns variable *name* in
the global scope if it is not yet defined.
- On guard or contract evaluation:
- If the code is related to a transition, the *event: Event* that fires the transition is exposed.
- On guard or contract (except preconditions) evaluation:
Expand All @@ -92,9 +94,6 @@ class PythonEvaluator(Evaluator):
was sent during the current step.
- A *received(name: str) -> bool* function that takes an event name and return True if an event with the
same name is currently processed in this step.
- On preamble execution:
- A *default(name:str, value: Any) -> Any* function that defines and returns variable *name* in
the global scope if it is not yet defined.
If an exception occurred while executing or evaluating a piece of code, it is propagated by the
evaluator.
Expand Down Expand Up @@ -240,6 +239,7 @@ def _execute_code(self, code: Optional[str], *, additional_context: Mapping=None
'send': _create_send_function(sent_events),
'notify': _create_notify_function(sent_events),
'time': self._interpreter.time,
'setdefault': self._setdefault,
}
exposed_context.update(additional_context if additional_context is not None else {})

Expand All @@ -257,10 +257,7 @@ def execute_statechart(self, statechart: Statechart):
:param statechart: statechart to consider
"""
if statechart.preamble:
additional_context = {
'setdefault': self._setdefault
}
events = self._execute_code(statechart.preamble, additional_context=additional_context)
events = self._execute_code(statechart.preamble)
if len(events) > 0:
raise CodeEvaluationError('Events cannot be raised by statechart preamble')

Expand Down
9 changes: 3 additions & 6 deletions tests/test_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,11 @@ def test_condition_on_event(self, evaluator):
assert evaluator._evaluate_code('event.data[\'a\'] == 1', additional_context={'event': Event('test', a=1)})
assert evaluator._evaluate_code('event.name == \'test\'', additional_context={'event': Event('test')})

def test_setdefault(self, evaluator, mocker):
statechart = mocker.MagicMock()
statechart.preamble = 'setdefault("x", 2)'
evaluator.execute_statechart(statechart)
def test_setdefault(self, evaluator):
evaluator._execute_code('setdefault("x", 2)')
assert evaluator.context['x'] == 1

statechart.preamble = 'b = setdefault("a", 0)'
evaluator.execute_statechart(statechart)
evaluator._execute_code('b = setdefault("a", 0)')
assert evaluator.context['a'] == 0
assert evaluator.context['b'] == 0

Expand Down

0 comments on commit 9778993

Please sign in to comment.