Skip to content

Commit

Permalink
Allow setting a workflow state by its name (Closes #6).
Browse files Browse the repository at this point in the history
Also ensures that when ``name in TheWorkflow.states`` is ``True``,
``TheWorkflow.states[name]`` doesn't raise ``KeyError``.
  • Loading branch information
rbarrois committed Jan 28, 2014
1 parent 7257a21 commit d2dd10a
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 5 deletions.
15 changes: 15 additions & 0 deletions doc/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,21 @@ to a plain attribute:
from typos in the code (:exc:`AttributeError` would be raised), whereas
raw strings provide no such guarantee.

- Easily setting the current value::

>>> obj.state = MyWorkflow.states.ready
>>> obj.state.is_ready
True

>>> # Setting from a state name is also possible
>>> obj.state = 'ready'
>>> obj.state.is_ready
True

.. note:: Setting the state without going through transitions defeats the goal of
xworkflows; this feature should only be used for faster testing or when
saving/restoring objects from external storage.


Using transitions
-----------------
Expand Down
47 changes: 47 additions & 0 deletions tests/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,53 @@ def test_representation(self):
self.assertEqual(hash(self.foo.name), hash(self.sf))


class WorkflowEnabledTestCase(unittest.TestCase):
def setUp(self):
super(WorkflowEnabledTestCase, self).setUp()

class MyWorkflow(base.Workflow):
states = (
('foo', "Foo"),
('bar', "Bar"),
('baz', "Baz"),
)
transitions = (
('foobar', 'foo', 'bar'),
('gobaz', ('foo', 'bar'), 'baz'),
('bazbar', 'baz', 'bar'),
)
initial_state = 'foo'

class MyWorkflowEnabled(base.WorkflowEnabled):
state = MyWorkflow()

self.foo = MyWorkflow.states.foo
self.bar = MyWorkflow.states.bar
self.wf = MyWorkflow
self.wfe = MyWorkflowEnabled

def test_access_state(self):
obj = self.wfe()
self.assertEqual(self.foo, obj.state)
self.assertTrue(obj.state.is_foo)
self.assertFalse(obj.state.is_bar)

obj.state = self.bar

self.assertEqual(self.bar, obj.state)
self.assertTrue(obj.state.is_bar)
self.assertFalse(obj.state.is_foo)

def test_compare_state_text(self):
obj = self.wfe()

obj.state = 'bar'

self.assertEqual(self.bar, obj.state)
self.assertTrue(obj.state.is_bar)
self.assertFalse(obj.state.is_foo)


class ImplementationPropertyTestCase(unittest.TestCase):

def setUp(self):
Expand Down
15 changes: 10 additions & 5 deletions xworkflows/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,11 @@ def __getattr__(self, name):
def __len__(self):
return len(self._states)

def __getitem__(self, name):
return self._states[name]
def __getitem__(self, name_or_state):
if isinstance(name_or_state, State):
return self._states[name_or_state.name]
else:
return self._states[name_or_state]

def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self._states)
Expand Down Expand Up @@ -883,7 +886,7 @@ def __init__(self, state, workflow):
def __eq__(self, other):
if isinstance(other, self.__class__):
return self.state == other.state
if isinstance(other, State):
elif isinstance(other, State):
return self.state == other
elif is_string(other):
return self.state.name == other
Expand Down Expand Up @@ -941,10 +944,12 @@ def __get__(self, instance, owner):

def __set__(self, instance, value):
"""Set the current state of the 'instance' object."""
if not value in self.workflow.states:
try:
state = self.workflow.states[value]
except KeyError:
raise ValueError("Value %s is not a valid state for workflow %s." %
(value, self.workflow))
instance.__dict__[self.field_name] = value
instance.__dict__[self.field_name] = state

def __str__(self):
return 'StateProperty(%s, %s)' % (self.workflow, self.field_name)
Expand Down

0 comments on commit d2dd10a

Please sign in to comment.