mirror of
https://github.com/django/django.git
synced 2025-10-31 09:41:08 +00:00
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
This commit is contained in:
@@ -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 *
|
||||
|
||||
@@ -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)
|
||||
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)
|
||||
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)
|
||||
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, 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)
|
||||
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)
|
||||
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)
|
||||
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()
|
||||
|
||||
def testGarbageCollectedObj(self):
|
||||
class x:
|
||||
def __call__(self, a):
|
||||
return a
|
||||
a = Callable()
|
||||
b = Dummy()
|
||||
signal = 'this'
|
||||
connect(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()
|
||||
|
||||
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')
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user