Ticket #16245: add_traceback_to_send_robust.diff

File add_traceback_to_send_robust.diff, 3.9 KB (added by Jim Dalton, 13 years ago)
  • docs/topics/signals.txt

     
    248248            pizza_done.send(sender=self, toppings=toppings, size=size)
    249249            ...
    250250
    251 Both ``send()`` and ``send_robust()`` return a list of tuple pairs
    252 ``[(receiver, response), ... ]``, representing the list of called receiver
    253 functions and their response values.
     251``send()`` returns a list of tuple pairs ``[(receiver, response), ... ]``,
     252representing the list of called receiver functions and their response values.
    254253
    255254``send()`` differs from ``send_robust()`` in how exceptions raised by receiver
    256255functions are handled. ``send()`` does *not* catch any exceptions raised by
    257 receivers; it simply allows errors to propagate. Thus not all receivers may
    258 be notified of a signal in the face of an error.
     256receivers; it simply allows errors to propagate. Thus not all receivers may be
     257notified of a signal in the face of an error.
    259258
    260 ``send_robust()`` catches all errors derived from Python's ``Exception`` class,
    261 and ensures all receivers are notified of the signal. If an error occurs, the
    262 error instance is returned in the tuple pair for the receiver that raised the error.
     259``send_robust()``, on the other hand, catches all errors derived from Python's
     260``Exception`` class, and ensures all receivers are notified of the signal.
    263261
     262For receivers that run without raising an exception, ``send_robust()`` appends a
     263tuple pair ``(receiver, response)`` to the returned list, just like ``send()``. If
     264an error occurs, however, a three tuple ``(receiver, error, traceback)`` is appended
     265to the list instead. This tuple contains the receiver that had an error, the
     266``Exception`` instance raised by that receiver, and a ``traceback`` object with the
     267call stack at the point where the exception occurred.
     268
     269.. versionchanged:: 1.4
     270   A ``traceback`` object was added to the tuple that is appended to the returned
     271   list in ``send_robust()`` when an exception is raised by a receiver function.
     272
    264273Disconnecting signals
    265274=====================
    266275
  • django/dispatch/dispatcher.py

     
    11import weakref
    22import threading
     3import sys
    34
    45from django.dispatch import saferef
    56
     
    206207            try:
    207208                response = receiver(signal=self, sender=sender, **named)
    208209            except Exception, err:
    209                 responses.append((receiver, err))
     210                # Wrap traceback in try...finally to prevent circular reference
     211                # See warning at http://docs.python.org/library/sys.html#sys.exc_info
     212                try:
     213                    traceback = sys.exc_info()[2]
     214                    responses.append((receiver, err, traceback))
     215                finally:
     216                    del traceback
    210217            else:
    211218                responses.append((receiver, response))
    212219        return responses
  • tests/regressiontests/dispatch/tests/test_dispatcher.py

     
    11import gc
    22import sys
     3from types import TracebackType
    34
    45from django.dispatch import Signal
    56from django.utils import unittest
     
    9899        a_signal.connect(fails)
    99100        result = a_signal.send_robust(sender=self, val="test")
    100101        err = result[0][1]
     102        traceback = result[0][2]
    101103        self.assertTrue(isinstance(err, ValueError))
     104        self.assertTrue(isinstance(traceback, TracebackType))
    102105        self.assertEqual(err.args, ('this',))
    103106        a_signal.disconnect(fails)
    104107        self._testIsClean(a_signal)
Back to Top