소스 검색

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.
Unai Zalakain 11 년 전
부모
커밋
ebb0279f4a
4개의 변경된 파일15개의 추가작업 그리고 2개의 파일을 삭제
  1. 4 1
      django/dispatch/dispatcher.py
  2. 3 1
      docs/releases/1.8.txt
  3. 5 0
      docs/topics/signals.txt
  4. 3 0
      tests/dispatch/tests/test_dispatcher.py

+ 4 - 1
django/dispatch/dispatcher.py

@@ -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))

+ 3 - 1
docs/releases/1.8.txt

@@ -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
 ^^^^^^^^^

+ 5 - 0
docs/topics/signals.txt

@@ -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
 =====================
 

+ 3 - 0
tests/dispatch/tests/test_dispatcher.py

@@ -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)