Skip to content
Browse files

Merge branch 'master' of github.com:kmmbvnr/django-fsm

  • Loading branch information...
2 parents 58cc2dc + efa3975 commit 3e39e0d344bec1198b64ea8b0f05a32758c394da @kmmbvnr committed Aug 3, 2010
View
2 .gitignore
@@ -1,6 +1,8 @@
*.pyc
.coverage
+.cache
.ve
+reports
distribute-*.tar.gz
nosetests.xml
coverage.xml
View
19 django_fsm/db/fields/fsmfield.py
@@ -35,7 +35,7 @@ def _get_state_field(instance):
if found == 0:
raise TypeError("No FSMField found in model")
elif found > 1:
- raise TypeError("More than one FSMField found in model, please specify field name in transition decorator")
+ raise TypeError("More than one FSMField found in model")
return fields[0]
@staticmethod
@@ -50,15 +50,22 @@ def has_transition(self, instance):
"""
Lookup is any transition exists from current model state
"""
- return self.transitions.has_key(FSMMeta.current_state(instance))
+ return self.transitions.has_key(FSMMeta.current_state(instance)) or self.transitions.has_key('*')
def to_next_state(self, instance):
"""
Switch to next state
"""
field_name = FSMMeta._get_state_field(instance).name
curr_state = getattr(instance, field_name)
- setattr(instance, field_name, self.transitions[curr_state])
+
+ next_state = None
+ try:
+ next_state = self.transitions[curr_state]
+ except KeyError:
+ next_state = self.transitions['*']
+
+ setattr(instance, field_name, next_state)
def transition(source='*', target=None, save=False):
@@ -70,7 +77,11 @@ def inner_transition(func):
if not hasattr(func, '_django_fsm'):
setattr(func, '_django_fsm', FSMMeta())
- func._django_fsm.transitions[source] = target
+ if isinstance(source, (list, tuple)):
+ for state in source:
+ func._django_fsm.transitions[state] = target
+ else:
+ func._django_fsm.transitions[source] = target
@wraps(func)
def _change_state(instance, *args, **kwargs):
View
24 django_fsm/tests.py
@@ -21,6 +21,14 @@ def hide(self):
def remove(self):
raise Exception('No rights to delete %s' % self)
+ @transition(source=['published','hidden'], target='stolen')
+ def steal(self):
+ pass
+
+ @transition(source='*', target='moderated')
+ def moderate(self):
+ pass
+
class FSMFieldTest(TestCase):
def setUp(self):
@@ -43,6 +51,21 @@ def test_state_non_changed_after_fail(self):
self.assertRaises(Exception, self.model.remove)
self.assertEqual(self.model.state, 'new')
+ def test_mutiple_source_support_path_1_works(self):
+ self.model.publish()
+ self.model.steal()
+ self.assertEqual(self.model.state, 'stolen')
+
+ def test_mutiple_source_support_path_2_works(self):
+ self.model.publish()
+ self.model.hide()
+ self.model.steal()
+ self.assertEqual(self.model.state, 'stolen')
+
+ def test_star_shortcut_succeed(self):
+ self.model.moderate()
+ self.assertEqual(self.model.state, 'moderated')
+
class InvalidModel(models.Model):
state = FSMField(default='new')
@@ -76,6 +99,7 @@ def test_any_state_field_name_allowed(self):
class BlogPostStatus(models.Model):
name = models.CharField(max_length=3, unique=True)
+ objects = models.Manager()
@transition(source='new', target='published')
def publish(self):
View
0 tests/__init__.py
No changes.
View
7 tests/environment.pip
@@ -1,7 +0,0 @@
-nose
-coverage
-pylint
-http://code.djangoproject.com/svn/django/tags/releases/1.2
-git+git://github.com/cmheisel/nose-xcover.git#egg=nosexcover
-git+git://github.com/kmmbvnr/django-nose.git#egg=django-nose
-
View
31 tests/manage.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+SCRIPT_DIR=`dirname $0`
+ROOT_DIR=`cd $SCRIPT_DIR/.. && pwd`
+
+ENVSPEC=`stat -c %Y $ROOT_DIR/tests/requirements.pip`
+ENVTESTSPEC=`stat -c %Y $ROOT_DIR/tests/requirements_test.pip`
+ENVTIME=`test -r $ROOT_DIR/.ve/timestamp && stat -c %Y $ROOT_DIR/.ve/timestamp`
+set -e
+
+if [ -z "$PIP_DOWNLOAD_CACHE" ]; then
+ export PIP_DOWNLOAD_CACHE=$ROOT_DIR/.cache
+fi
+
+if [[ $ENVSPEC -gt $ENVTIME || $ENVTESTSPEC -gt $ENVTIME ]]; then
+ # Setup environment
+ rm -rf $ROOT_DIR/.ve
+ mkdir $ROOT_DIR/.ve
+ cd $ROOT_DIR/.ve
+ virtualenv --no-site-packages $ROOT_DIR/.ve
+ source $ROOT_DIR/.ve/bin/activate
+ pip install -r $ROOT_DIR/tests/requirements.pip
+ pip install -r $ROOT_DIR/tests/requirements_test.pip
+ touch $ROOT_DIR/.ve/timestamp
+else
+ source $ROOT_DIR/.ve/bin/activate
+fi
+
+cd $ROOT_DIR
+export PYTHONPATH=$ROOT_DIR
+python tests/test_runner.py $*
View
3 tests/requirements.pip
@@ -0,0 +1,3 @@
+django==1.2.1
+
+
View
4 tests/requirements_test.pip
@@ -0,0 +1,4 @@
+ipython
+ipdb
+git+git://github.com/kmmbvnr/django-hudson.git#egg=django-hudson
+
View
45 tests/run_tests.sh
@@ -1,45 +0,0 @@
-#!/bin/bash
-
-SCRIPT_DIR=`dirname $0`
-ROOT_DIR=`cd $SCRIPT_DIR/.. && pwd`
-
-ENVSPEC=`stat -c %Y $ROOT_DIR/tests/environment.pip`
-ENVTIME=`test -d $ROOT_DIR/.ve && stat -c %Y $ROOT_DIR/.ve`
-
-set -e
-
-cd $ROOT_DIR
-if [ $ENVSPEC -gt 0$ENVTIME ]; then
- # Setup environment
- virtualenv --no-site-packages $ROOT_DIR/.ve
- source $ROOT_DIR/.ve/bin/activate
- pip install -r $ROOT_DIR/tests/environment.pip
- touch $ROOT_DIR/.ve
-else
- source $ROOT_DIR/.ve/bin/activate
-fi
-
-# pylint
-pylint --rcfile=$ROOT_DIR/.pylintrc django_fsm > pylint.out || echo 'PyLint done'
-tail -n5 pylint.out
-
-# Run tests
-python <<EOF
-from django import conf
-from django.core import management
-
-__name__ = 'django_fsm.tests'
-class TestSettings(conf.UserSettingsHolder):
- INSTALLED_APPS=('django_fsm', 'django_nose')
- DATABASE_ENGINE='sqlite3'
- TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
- NOSE_ARGS = ['django_fsm',
- '--with-coverage',
- '--cover-package=django_fsm',
- '--with-xunit',
- '--with-xcoverage']
-
-conf.settings.configure(TestSettings(conf.global_settings))
-management.call_command('test', 'django_fsm')
-EOF
-
View
11 tests/test_runner.py
@@ -0,0 +1,11 @@
+PROJECT_APPS = ('django_fsm',)
+INSTALLED_APPS = ('django_hudson',) + PROJECT_APPS
+DATABASE_ENGINE = 'sqlite3'
+
+if __name__ == "__main__":
+ import sys, test_runner as settings
+ from django.core.management import execute_manager
+
+ if len(sys.argv) == 1:
+ sys.argv += ['test'] + list(PROJECT_APPS)
+ execute_manager(settings)

0 comments on commit 3e39e0d

Please sign in to comment.
Something went wrong with that request. Please try again.