Ticket #16245: add_traceback_to_send_robust.v2.diff
File add_traceback_to_send_robust.v2.diff, 4.5 KB (added by , 13 years ago) |
---|
-
docs/topics/signals.txt
231 231 There are two ways to send send signals in Django. 232 232 233 233 .. method:: Signal.send(sender, **kwargs) 234 .. method:: Signal.send_robust(sender, **kwargs)234 .. method:: Signal.send_robust(sender, append_traceback=True, **kwargs) 235 235 236 236 To send a signal, call either :meth:`Signal.send` or :meth:`Signal.send_robust`. 237 237 You must provide the ``sender`` argument, and may provide as many other keyword … … 260 260 ``send_robust()`` catches all errors derived from Python's ``Exception`` class, 261 261 and ensures all receivers are notified of the signal. If an error occurs, the 262 262 error instance is returned in the tuple pair for the receiver that raised the error. 263 If ``append_traceback`` is True, a ``traceback`` object with the call stack at the 264 point where the exception occurred will also be added to the tuple. In that case, 265 the tuple response would look like ``(receiver, error, traceback)``. 263 266 267 268 .. versionchanged:: 1.4 269 A ``traceback`` object can be appended to the tuple response for a receiver that 270 raises an exception by setting ``append_traceback`` to ``True`` when calling 271 ``send_robust()``. 272 264 273 Disconnecting signals 265 274 ===================== 266 275 -
django/dispatch/dispatcher.py
1 import sys 1 2 import weakref 2 3 import threading 3 4 … … 173 174 responses.append((receiver, response)) 174 175 return responses 175 176 176 def send_robust(self, sender, **named):177 def send_robust(self, sender, append_traceback=False, **named): 177 178 """ 178 179 Send signal from sender to all connected receivers catching errors. 179 180 … … 184 185 registered with a connect if you actually want something to 185 186 occur). 186 187 188 append_traceback 189 If an exception occurs in a receiver, append a traceback object 190 to the tuple result for that receiver. 191 187 192 named 188 193 Named arguments which will be passed to receivers. These 189 194 arguments must be a subset of the argument names defined in … … 194 199 195 200 If any receiver raises an error (specifically any subclass of 196 201 Exception), the error instance is returned as the result for that 197 receiver. 202 receiver. If append_traceback is True, a traceback object will 203 also be included in the result, i.e. (receiver, error, traceback). 198 204 """ 199 205 responses = [] 200 206 if not self.receivers: … … 206 212 try: 207 213 response = receiver(signal=self, sender=sender, **named) 208 214 except Exception, err: 209 responses.append((receiver, err)) 215 if append_traceback: 216 # Wrap traceback in try...finally to prevent circular reference 217 # See warning at http://docs.python.org/library/sys.html#sys.exc_info 218 try: 219 traceback = sys.exc_info()[2] 220 responses.append((receiver, err, traceback)) 221 finally: 222 del traceback 223 else: 224 responses.append((receiver, err)) 210 225 else: 211 226 responses.append((receiver, response)) 212 227 return responses -
tests/regressiontests/dispatch/tests/test_dispatcher.py
1 1 import gc 2 2 import sys 3 from types import TracebackType 3 4 4 5 from django.dispatch import Signal 5 6 from django.utils import unittest … … 98 99 a_signal.connect(fails) 99 100 result = a_signal.send_robust(sender=self, val="test") 100 101 err = result[0][1] 102 self.assertEqual(len(result[0]), 2) 101 103 self.assertTrue(isinstance(err, ValueError)) 102 104 self.assertEqual(err.args, ('this',)) 105 106 result = a_signal.send_robust(sender=self, append_traceback=True, val="test") 107 traceback = result[0][2] 108 self.assertTrue(isinstance(traceback, TracebackType)) 103 109 a_signal.disconnect(fails) 104 110 self._testIsClean(a_signal) 105 111