Ticket #5854: inlineCallbacks-extra-traceback-info.2.patch

File inlineCallbacks-extra-traceback-info.2.patch, 3.4 KB (added by talljosh, 6 years ago)

Updated patch that includes a test.

  • twisted/internet/defer.py

     
    10921092            return deferred
    10931093
    10941094        if isinstance(result, Deferred):
     1095            def extendErrbackStack(r):
     1096                """
     1097                A failure was yielded by the generator, so for the failure's
     1098                traceback to be useful insert the current yield line into the
     1099                stack of frames.
     1100                """
     1101                f = g.gi_frame
     1102
     1103                # The following code is lifted almost straight from
     1104                # twisted.python.failure.Failure.__init__()
     1105                localz = f.f_locals.copy()
     1106                if f.f_locals is f.f_globals:
     1107                    globalz = {}
     1108                else:
     1109                    globalz = f.f_globals.copy()
     1110                for d in globalz, localz:
     1111                    if d.has_key("__builtins__"):
     1112                        del d["__builtins__"]
     1113
     1114                r.frames.insert(0, [
     1115                    f.f_code.co_name,
     1116                    f.f_code.co_filename,
     1117                    f.f_lineno,
     1118                    localz.items(),
     1119                    globalz.items(),
     1120                    ])
     1121                return r
     1122            result.addErrback(extendErrbackStack)
     1123
    10951124            # a deferred was yielded, get the result.
    10961125            def gotResult(r):
    10971126                if waiting[0]:
  • twisted/internet/test/inlinecb_tests.py

     
    1515
    1616from twisted.trial.unittest import TestCase
    1717from twisted.internet.defer import Deferred, returnValue, inlineCallbacks
     18from twisted.python.failure import Failure
    1819
    1920class NonLocalExitTests(TestCase):
    2021    """
     
    9091        self.assertMistakenMethodWarning(results)
    9192
    9293
     94class FrameStackTests(TestCase):
     95    def test_failureContainsCallingFrames(self):
     96        """
     97        When L{inlineCallbacks} yields a failure, it should add itself to the
     98        failure's frames so that the traceback is more useful.
     99        """
     100        @inlineCallbacks
     101        def inline1():
     102            yield 1/0
     103
     104        @inlineCallbacks
     105        def inline2():
     106            yield inline1()
     107
     108        @inlineCallbacks
     109        def inline3():
     110            yield inline2()
     111
     112        d = inline3()
     113        results = []
     114        d.addBoth(results.append)
     115
     116        failure = results[0]
     117        self.assertIsInstance(failure, Failure)
     118
     119        functionNames = []
     120        for funcName, filename, lineno, localVars, globalVars in failure.frames:
     121            functionNames.append(funcName)
     122        self.assertIn('inline1', functionNames)
     123        self.assertIn('inline2', functionNames)
     124        self.assertIn('inline3', functionNames)
     125
  • twisted/internet/test/test_inlinecb.py

     
    99__all__ = ['NonLocalExitTests']
    1010
    1111if sys.version_info[:2] >= (2, 5):
    12     from twisted.internet.test.inlinecb_tests import NonLocalExitTests
     12    from twisted.internet.test.inlinecb_tests import (NonLocalExitTests,
     13            FrameStackTests)
    1314