Fixed #16245 -- Included traceback in send_robust()'s response

Exceptions from the (receiver, exception) tuples returned by
``send_robust()`` now have always their traceback attached as their
``__traceback__`` argument.
This commit is contained in:
Unai Zalakain 2013-10-30 12:11:04 +01:00 committed by Tim Graham
parent 79e9da3d1e
commit ebb0279f4a
4 changed files with 15 additions and 2 deletions

View File

@ -220,7 +220,8 @@ class Signal(object):
If any receiver raises an error (specifically any subclass of
Exception), the error instance is returned as the result for that
receiver.
receiver. The traceback is always attached to the error at
``__traceback__``.
"""
responses = []
if not self.receivers or self.sender_receivers_cache.get(sender) is NO_RECEIVERS:
@ -232,6 +233,8 @@ class Signal(object):
try:
response = receiver(signal=self, sender=sender, **named)
except Exception as err:
if not hasattr(err, '__traceback__'):
err.__traceback__ = sys.exc_info()[2]
responses.append((receiver, err))
else:
responses.append((receiver, response))

View File

@ -153,7 +153,9 @@ Models
Signals
^^^^^^^
* ...
* Exceptions from the ``(receiver, exception)`` tuples returned by
:meth:`Signal.send_robust() <django.dispatch.Signal.send_robust>` now have
their traceback attached as a ``__traceback__`` attribute.
Templates
^^^^^^^^^

View File

@ -274,6 +274,11 @@ be notified of a signal in the face of an error.
and ensures all receivers are notified of the signal. If an error occurs, the
error instance is returned in the tuple pair for the receiver that raised the error.
.. versionadded:: 1.8
The tracebacks are present on the ``__traceback__`` attribute
of the errors returned when calling ``send_robust()``.
Disconnecting signals
=====================

View File

@ -3,6 +3,7 @@ import sys
import time
import unittest
import weakref
from types import TracebackType
from django.dispatch import Signal, receiver
@ -134,6 +135,8 @@ class DispatcherTests(unittest.TestCase):
err = result[0][1]
self.assertIsInstance(err, ValueError)
self.assertEqual(err.args, ('this',))
self.assertTrue(hasattr(err, '__traceback__'))
self.assertTrue(isinstance(err.__traceback__, TracebackType))
a_signal.disconnect(fails)
self._testIsClean(a_signal)