Ticket #16245: add_traceback_to_send_robust.v3.diff

File add_traceback_to_send_robust.v3.diff, 4.7 KB (added by Jim Dalton, 13 years ago)
  • django/dispatch/dispatcher.py

    diff --git a/django/dispatch/dispatcher.py b/django/dispatch/dispatcher.py
    index ed9da57..b2abd21 100644
    a b  
     1import sys
    12import weakref
    23import threading
    34
    class Signal(object):  
    173174            responses.append((receiver, response))
    174175        return responses
    175176
    176     def send_robust(self, sender, **named):
     177    def send_robust(self, sender, exc_info=False, **named):
    177178        """
    178179        Send signal from sender to all connected receivers catching errors.
    179180
    class Signal(object):  
    184185                registered with a connect if you actually want something to
    185186                occur).
    186187
     188            exc_info
     189                If an exception occurs in a receiver, return a triple (type,
     190                exception, traceback) as the response instead of just an exception
     191                instance.
     192
    187193            named
    188194                Named arguments which will be passed to receivers. These
    189195                arguments must be a subset of the argument names defined in
    class Signal(object):  
    194200
    195201        If any receiver raises an error (specifically any subclass of
    196202        Exception), the error instance is returned as the result for that
    197         receiver.
     203        receiver. If exc_info is True, a triple that includes the exception type,
     204        the exception instance, and a traceback (type, exception, traceback) will
     205        be returned instead of just the error instance.
    198206        """
    199207        responses = []
    200208        if not self.receivers:
    class Signal(object):  
    206214            try:
    207215                response = receiver(signal=self, sender=sender, **named)
    208216            except Exception, err:
    209                 responses.append((receiver, err))
     217                if exc_info:
     218                    responses.append((receiver, sys.exc_info()))
     219                else:
     220                    responses.append((receiver, err))
    210221            else:
    211222                responses.append((receiver, response))
    212223        return responses
  • docs/topics/signals.txt

    diff --git a/docs/topics/signals.txt b/docs/topics/signals.txt
    index df4b58b..9450749 100644
    a b Sending signals  
    231231There are two ways to send send signals in Django.
    232232
    233233.. method:: Signal.send(sender, **kwargs)
    234 .. method:: Signal.send_robust(sender, **kwargs)
     234.. method:: Signal.send_robust(sender, exc_info=True, **kwargs)
    235235
    236236To send a signal, call either :meth:`Signal.send` or :meth:`Signal.send_robust`.
    237237You must provide the ``sender`` argument, and may provide as many other keyword
    be notified of a signal in the face of an error.  
    260260``send_robust()`` catches all errors derived from Python's ``Exception`` class,
    261261and ensures all receivers are notified of the signal. If an error occurs, the
    262262error instance is returned in the tuple pair for the receiver that raised the error.
     263If ``exc_info`` is ``True``, a triple containing the error type, error instance and
     264traceback is returned instead of the error instance. This is identical to the value
     265returned by calling ``sys.exc_info()`` at the point of the exception and may be
     266useful for logging or debugging purposes.
     267
     268
     269.. versionchanged:: 1.4
     270   A triple containing the exception type, the exception instance and a full traceback
     271   can be returned as the response (instead of just a simple error instance) for a receiver that
     272   raises an exception by setting ``exc_info`` to ``True`` when calling
     273   ``send_robust()``.
    263274
    264275Disconnecting signals
    265276=====================
  • tests/regressiontests/dispatch/tests/test_dispatcher.py

    diff --git a/tests/regressiontests/dispatch/tests/test_dispatcher.py b/tests/regressiontests/dispatch/tests/test_dispatcher.py
    index a16d8e2..44c4cc0 100644
    a b  
    11import gc
    22import sys
     3from types import TracebackType
    34
    45from django.dispatch import Signal
    56from django.utils import unittest
    class DispatcherTests(unittest.TestCase):  
    9899        a_signal.connect(fails)
    99100        result = a_signal.send_robust(sender=self, val="test")
    100101        err = result[0][1]
     102        self.assertEqual(len(result[0]), 2)
    101103        self.assertTrue(isinstance(err, ValueError))
    102104        self.assertEqual(err.args, ('this',))
     105
     106        result = a_signal.send_robust(sender=self, exc_info=True, val="test")
     107        exc_info_triple = result[0][1]
     108        self.assertEqual(exc_info_triple[0], ValueError)
     109        self.assertTrue(isinstance(exc_info_triple[1], ValueError))
     110        self.assertTrue(isinstance(exc_info_triple[2], TracebackType))
    103111        a_signal.disconnect(fails)
    104112        self._testIsClean(a_signal)
    105113
Back to Top