diff options
| author | Jacob Kaplan-Moss <jacob@jacobian.org> | 2008-08-06 15:32:46 +0000 |
|---|---|---|
| committer | Jacob Kaplan-Moss <jacob@jacobian.org> | 2008-08-06 15:32:46 +0000 |
| commit | 34a3bd52255a2253696b74b2d76133aace839fd2 (patch) | |
| tree | 73bc39cc2e0a93925b1e8796b18224192e19e4a3 /tests | |
| parent | d06b474251c979c512a966a7fb41cd8a06487c14 (diff) | |
Major refactoring of django.dispatch with an eye towards speed. The net result is that signals are up to 90% faster.
Though some attempts and backwards-compatibility were made, speed trumped compatibility. Thus, as usual, check BackwardsIncompatibleChanges for the complete list of backwards-incompatible changes.
Thanks to Jeremy Dunck and Keith Busell for the bulk of the work; some ideas from Brian Herring's previous work (refs #4561) were incorporated.
Documentation is, sigh, still forthcoming.
Fixes #6814 and #3951 (with the new dispatch_uid argument to connect).
git-svn-id: http://code.djangoproject.com/svn/django/trunk@8223 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/modeltests/signals/models.py | 46 | ||||
| -rw-r--r-- | tests/regressiontests/dispatch/tests/__init__.py | 3 | ||||
| -rw-r--r-- | tests/regressiontests/dispatch/tests/test_dispatcher.py | 164 | ||||
| -rw-r--r-- | tests/regressiontests/dispatch/tests/test_robustapply.py | 34 |
4 files changed, 70 insertions, 177 deletions
diff --git a/tests/modeltests/signals/models.py b/tests/modeltests/signals/models.py index fc58d90a14..23d1f2d87d 100644 --- a/tests/modeltests/signals/models.py +++ b/tests/modeltests/signals/models.py @@ -3,7 +3,6 @@ Testing signals before/after saving and deleting. """ from django.db import models -from django.dispatch import dispatcher class Person(models.Model): first_name = models.CharField(max_length=20) @@ -12,19 +11,12 @@ class Person(models.Model): def __unicode__(self): return u"%s %s" % (self.first_name, self.last_name) - -def pre_save_nokwargs_test(sender, instance): - print 'pre_save_nokwargs signal' - -def post_save_nokwargs_test(sender, instance): - print 'post_save_nokwargs signal' - -def pre_save_test(sender, instance, **kwargs): +def pre_save_test(signal, sender, instance, **kwargs): print 'pre_save signal,', instance if kwargs.get('raw'): print 'Is raw' -def post_save_test(sender, instance, **kwargs): +def post_save_test(signal, sender, instance, **kwargs): print 'post_save signal,', instance if 'created' in kwargs: if kwargs['created']: @@ -34,44 +26,36 @@ def post_save_test(sender, instance, **kwargs): if kwargs.get('raw'): print 'Is raw' -def pre_delete_test(sender, instance, **kwargs): +def pre_delete_test(signal, sender, instance, **kwargs): print 'pre_delete signal,', instance print 'instance.id is not None: %s' % (instance.id != None) -def post_delete_test(sender, instance, **kwargs): +def post_delete_test(signal, sender, instance, **kwargs): print 'post_delete signal,', instance print 'instance.id is None: %s' % (instance.id == None) __test__ = {'API_TESTS':""" ->>> dispatcher.connect(pre_save_nokwargs_test, signal=models.signals.pre_save) ->>> dispatcher.connect(post_save_nokwargs_test, signal=models.signals.post_save) ->>> dispatcher.connect(pre_save_test, signal=models.signals.pre_save) ->>> dispatcher.connect(post_save_test, signal=models.signals.post_save) ->>> dispatcher.connect(pre_delete_test, signal=models.signals.pre_delete) ->>> dispatcher.connect(post_delete_test, signal=models.signals.post_delete) +>>> models.signals.pre_save.connect(pre_save_test) +>>> models.signals.post_save.connect(post_save_test) +>>> models.signals.pre_delete.connect(pre_delete_test) +>>> models.signals.post_delete.connect(post_delete_test) >>> p1 = Person(first_name='John', last_name='Smith') >>> p1.save() -pre_save_nokwargs signal pre_save signal, John Smith -post_save_nokwargs signal post_save signal, John Smith Is created >>> p1.first_name = 'Tom' >>> p1.save() -pre_save_nokwargs signal pre_save signal, Tom Smith -post_save_nokwargs signal post_save signal, Tom Smith Is updated # Calling an internal method purely so that we can trigger a "raw" save. >>> p1.save_base(raw=True) -pre_save_nokwargs signal pre_save signal, Tom Smith Is raw -post_save_nokwargs signal post_save signal, Tom Smith Is updated Is raw @@ -85,17 +69,13 @@ instance.id is None: False >>> p2 = Person(first_name='James', last_name='Jones') >>> p2.id = 99999 >>> p2.save() -pre_save_nokwargs signal pre_save signal, James Jones -post_save_nokwargs signal post_save signal, James Jones Is created >>> p2.id = 99998 >>> p2.save() -pre_save_nokwargs signal pre_save signal, James Jones -post_save_nokwargs signal post_save signal, James Jones Is created @@ -108,10 +88,8 @@ instance.id is None: False >>> Person.objects.all() [<Person: James Jones>] ->>> dispatcher.disconnect(pre_save_nokwargs_test, signal=models.signals.pre_save) ->>> dispatcher.disconnect(post_save_nokwargs_test, signal=models.signals.post_save) ->>> dispatcher.disconnect(post_delete_test, signal=models.signals.post_delete) ->>> dispatcher.disconnect(pre_delete_test, signal=models.signals.pre_delete) ->>> dispatcher.disconnect(post_save_test, signal=models.signals.post_save) ->>> dispatcher.disconnect(pre_save_test, signal=models.signals.pre_save) +>>> models.signals.post_delete.disconnect(post_delete_test) +>>> models.signals.pre_delete.disconnect(pre_delete_test) +>>> models.signals.post_save.disconnect(post_save_test) +>>> models.signals.pre_save.disconnect(pre_save_test) """} diff --git a/tests/regressiontests/dispatch/tests/__init__.py b/tests/regressiontests/dispatch/tests/__init__.py index 0fdefe48a7..150bb01dc0 100644 --- a/tests/regressiontests/dispatch/tests/__init__.py +++ b/tests/regressiontests/dispatch/tests/__init__.py @@ -2,6 +2,5 @@ Unit-tests for the dispatch project """ -from test_dispatcher import * -from test_robustapply import * from test_saferef import * +from test_dispatcher import * diff --git a/tests/regressiontests/dispatch/tests/test_dispatcher.py b/tests/regressiontests/dispatch/tests/test_dispatcher.py index f34173972d..baaae9cd95 100644 --- a/tests/regressiontests/dispatch/tests/test_dispatcher.py +++ b/tests/regressiontests/dispatch/tests/test_dispatcher.py @@ -1,5 +1,4 @@ -from django.dispatch.dispatcher import * -from django.dispatch import dispatcher, robust +from django.dispatch import Signal import unittest import copy import sys @@ -15,143 +14,94 @@ else: def garbage_collect(): gc.collect() -def x(a): - return a - -class Dummy(object): - pass +def receiver_1_arg(val, **kwargs): + return val class Callable(object): - def __call__(self, a): - return a + def __call__(self, val, **kwargs): + return val - def a(self, a): - return a + def a(self, val, **kwargs): + return val + +a_signal = Signal(providing_args=["val"]) class DispatcherTests(unittest.TestCase): """Test suite for dispatcher (barely started)""" - - def setUp(self): - # track the initial state, since it's possible that others have bleed receivers in - garbage_collect() - self.sendersBack = copy.copy(dispatcher.sendersBack) - self.connections = copy.copy(dispatcher.connections) - self.senders = copy.copy(dispatcher.senders) - - def _testIsClean(self): + + def _testIsClean(self, signal): """Assert that everything has been cleaned up automatically""" - self.assertEqual(dispatcher.sendersBack, self.sendersBack) - self.assertEqual(dispatcher.connections, self.connections) - self.assertEqual(dispatcher.senders, self.senders) + self.assertEqual(signal.receivers, []) + + # force cleanup just in case + signal.receivers = [] def testExact(self): - a = Dummy() - signal = 'this' - connect(x, signal, a) - expected = [(x,a)] - result = send('this',a, a=a) - self.assertEqual(result, expected) - disconnect(x, signal, a) - self.assertEqual(list(getAllReceivers(a,signal)), []) - self._testIsClean() - - def testAnonymousSend(self): - a = Dummy() - signal = 'this' - connect(x, signal) - expected = [(x,a)] - result = send(signal,None, a=a) - self.assertEqual(result, expected) - disconnect(x, signal) - self.assertEqual(list(getAllReceivers(None,signal)), []) - self._testIsClean() - - def testAnyRegistration(self): - a = Dummy() - signal = 'this' - connect(x, signal, Any) - expected = [(x,a)] - result = send('this',object(), a=a) - self.assertEqual(result, expected) - disconnect(x, signal, Any) - expected = [] - result = send('this',object(), a=a) + a_signal.connect(receiver_1_arg, sender=self) + expected = [(receiver_1_arg,"test")] + result = a_signal.send(sender=self, val="test") self.assertEqual(result, expected) - self.assertEqual(list(getAllReceivers(Any,signal)), []) - - self._testIsClean() - - def testAnyRegistration2(self): - a = Dummy() - signal = 'this' - connect(x, Any, a) - expected = [(x,a)] - result = send('this',a, a=a) + a_signal.disconnect(receiver_1_arg, sender=self) + self._testIsClean(a_signal) + + def testIgnoredSender(self): + a_signal.connect(receiver_1_arg) + expected = [(receiver_1_arg,"test")] + result = a_signal.send(sender=self, val="test") self.assertEqual(result, expected) - disconnect(x, Any, a) - self.assertEqual(list(getAllReceivers(a,Any)), []) - self._testIsClean() + a_signal.disconnect(receiver_1_arg) + self._testIsClean(a_signal) def testGarbageCollected(self): a = Callable() - b = Dummy() - signal = 'this' - connect(a.a, signal, b) - expected = [] - del a - garbage_collect() - result = send('this',b, a=b) - self.assertEqual(result, expected) - self.assertEqual(list(getAllReceivers(b,signal)), []) - self._testIsClean() - - def testGarbageCollectedObj(self): - class x: - def __call__(self, a): - return a - a = Callable() - b = Dummy() - signal = 'this' - connect(a, signal, b) + a_signal.connect(a.a, sender=self) expected = [] del a garbage_collect() - result = send('this',b, a=b) + result = a_signal.send(sender=self, val="test") self.assertEqual(result, expected) - self.assertEqual(list(getAllReceivers(b,signal)), []) - self._testIsClean() - + self._testIsClean(a_signal) def testMultipleRegistration(self): a = Callable() - b = Dummy() - signal = 'this' - connect(a, signal, b) - connect(a, signal, b) - connect(a, signal, b) - connect(a, signal, b) - connect(a, signal, b) - connect(a, signal, b) - result = send('this',b, a=b) + a_signal.connect(a) + a_signal.connect(a) + a_signal.connect(a) + a_signal.connect(a) + a_signal.connect(a) + a_signal.connect(a) + result = a_signal.send(sender=self, val="test") self.assertEqual(len(result), 1) - self.assertEqual(len(list(getAllReceivers(b,signal))), 1) + self.assertEqual(len(a_signal.receivers), 1) del a - del b del result garbage_collect() - self._testIsClean() + self._testIsClean(a_signal) + + def testUidRegistration(self): + def uid_based_receiver_1(**kwargs): + pass + + def uid_based_receiver_2(**kwargs): + pass + + a_signal.connect(uid_based_receiver_1, dispatch_uid = "uid") + a_signal.connect(uid_based_receiver_2, dispatch_uid = "uid") + self.assertEqual(len(a_signal.receivers), 1) + a_signal.disconnect(dispatch_uid = "uid") + self._testIsClean(a_signal) def testRobust(self): """Test the sendRobust function""" - def fails(): + def fails(val, **kwargs): raise ValueError('this') - a = object() - signal = 'this' - connect(fails, Any, a) - result = robust.sendRobust('this',a, a=a) + a_signal.connect(fails) + result = a_signal.send_robust(sender=self, val="test") err = result[0][1] self.assert_(isinstance(err, ValueError)) self.assertEqual(err.args, ('this',)) + a_signal.disconnect(fails) + self._testIsClean(a_signal) def getSuite(): return unittest.makeSuite(DispatcherTests,'test') diff --git a/tests/regressiontests/dispatch/tests/test_robustapply.py b/tests/regressiontests/dispatch/tests/test_robustapply.py deleted file mode 100644 index 499450eec4..0000000000 --- a/tests/regressiontests/dispatch/tests/test_robustapply.py +++ /dev/null @@ -1,34 +0,0 @@ -from django.dispatch.robustapply import * - -import unittest - -def noArgument(): - pass - -def oneArgument(blah): - pass - -def twoArgument(blah, other): - pass - -class TestCases(unittest.TestCase): - def test01(self): - robustApply(noArgument) - - def test02(self): - self.assertRaises(TypeError, robustApply, noArgument, "this") - - def test03(self): - self.assertRaises(TypeError, robustApply, oneArgument) - - def test04(self): - """Raise error on duplication of a particular argument""" - self.assertRaises(TypeError, robustApply, oneArgument, "this", blah = "that") - -def getSuite(): - return unittest.makeSuite(TestCases,'test') - - -if __name__ == "__main__": - unittest.main() - |
