1# Testing the line trace facility.
2
3from test import support
4import unittest
5import sys
6import difflib
7import gc
8from functools import wraps
9import asyncio
10
11
12class tracecontext:
13    """Context manager that traces its enter and exit."""
14    def __init__(self, output, value):
15        self.output = output
16        self.value = value
17
18    def __enter__(self):
19        self.output.append(self.value)
20
21    def __exit__(self, *exc_info):
22        self.output.append(-self.value)
23
24class asynctracecontext:
25    """Asynchronous context manager that traces its aenter and aexit."""
26    def __init__(self, output, value):
27        self.output = output
28        self.value = value
29
30    async def __aenter__(self):
31        self.output.append(self.value)
32
33    async def __aexit__(self, *exc_info):
34        self.output.append(-self.value)
35
36async def asynciter(iterable):
37    """Convert an iterable to an asynchronous iterator."""
38    for x in iterable:
39        yield x
40
41
42# A very basic example.  If this fails, we're in deep trouble.
43def basic():
44    return 1
45
46basic.events = [(0, 'call'),
47                (1, 'line'),
48                (1, 'return')]
49
50# Many of the tests below are tricky because they involve pass statements.
51# If there is implicit control flow around a pass statement (in an except
52# clause or else clause) under what conditions do you set a line number
53# following that clause?
54
55
56# Some constructs like "while 0:", "if 0:" or "if 1:...else:..." are optimized
57# away.  No code # exists for them, so the line numbers skip directly from
58# "del x" to "x = 1".
59def arigo_example0():
60    x = 1
61    del x
62    while 0:
63        pass
64    x = 1
65
66arigo_example0.events = [(0, 'call'),
67                        (1, 'line'),
68                        (2, 'line'),
69                        (5, 'line'),
70                        (5, 'return')]
71
72def arigo_example1():
73    x = 1
74    del x
75    if 0:
76        pass
77    x = 1
78
79arigo_example1.events = [(0, 'call'),
80                        (1, 'line'),
81                        (2, 'line'),
82                        (5, 'line'),
83                        (5, 'return')]
84
85def arigo_example2():
86    x = 1
87    del x
88    if 1:
89        x = 1
90    else:
91        pass
92    return None
93
94arigo_example2.events = [(0, 'call'),
95                        (1, 'line'),
96                        (2, 'line'),
97                        (4, 'line'),
98                        (7, 'line'),
99                        (7, 'return')]
100
101
102# check that lines consisting of just one instruction get traced:
103def one_instr_line():
104    x = 1
105    del x
106    x = 1
107
108one_instr_line.events = [(0, 'call'),
109                         (1, 'line'),
110                         (2, 'line'),
111                         (3, 'line'),
112                         (3, 'return')]
113
114def no_pop_tops():      # 0
115    x = 1               # 1
116    for a in range(2):  # 2
117        if a:           # 3
118            x = 1       # 4
119        else:           # 5
120            x = 1       # 6
121
122no_pop_tops.events = [(0, 'call'),
123                      (1, 'line'),
124                      (2, 'line'),
125                      (3, 'line'),
126                      (6, 'line'),
127                      (2, 'line'),
128                      (3, 'line'),
129                      (4, 'line'),
130                      (2, 'line'),
131                      (2, 'return')]
132
133def no_pop_blocks():
134    y = 1
135    while not y:
136        bla
137    x = 1
138
139no_pop_blocks.events = [(0, 'call'),
140                        (1, 'line'),
141                        (2, 'line'),
142                        (4, 'line'),
143                        (4, 'return')]
144
145def called(): # line -3
146    x = 1
147
148def call():   # line 0
149    called()
150
151call.events = [(0, 'call'),
152               (1, 'line'),
153               (-3, 'call'),
154               (-2, 'line'),
155               (-2, 'return'),
156               (1, 'return')]
157
158def raises():
159    raise Exception
160
161def test_raise():
162    try:
163        raises()
164    except Exception as exc:
165        x = 1
166
167test_raise.events = [(0, 'call'),
168                     (1, 'line'),
169                     (2, 'line'),
170                     (-3, 'call'),
171                     (-2, 'line'),
172                     (-2, 'exception'),
173                     (-2, 'return'),
174                     (2, 'exception'),
175                     (3, 'line'),
176                     (4, 'line'),
177                     (4, 'return')]
178
179def _settrace_and_return(tracefunc):
180    sys.settrace(tracefunc)
181    sys._getframe().f_back.f_trace = tracefunc
182def settrace_and_return(tracefunc):
183    _settrace_and_return(tracefunc)
184
185settrace_and_return.events = [(1, 'return')]
186
187def _settrace_and_raise(tracefunc):
188    sys.settrace(tracefunc)
189    sys._getframe().f_back.f_trace = tracefunc
190    raise RuntimeError
191def settrace_and_raise(tracefunc):
192    try:
193        _settrace_and_raise(tracefunc)
194    except RuntimeError as exc:
195        pass
196
197settrace_and_raise.events = [(2, 'exception'),
198                             (3, 'line'),
199                             (4, 'line'),
200                             (4, 'return')]
201
202# implicit return example
203# This test is interesting because of the else: pass
204# part of the code.  The code generate for the true
205# part of the if contains a jump past the else branch.
206# The compiler then generates an implicit "return None"
207# Internally, the compiler visits the pass statement
208# and stores its line number for use on the next instruction.
209# The next instruction is the implicit return None.
210def ireturn_example():
211    a = 5
212    b = 5
213    if a == b:
214        b = a+1
215    else:
216        pass
217
218ireturn_example.events = [(0, 'call'),
219                          (1, 'line'),
220                          (2, 'line'),
221                          (3, 'line'),
222                          (4, 'line'),
223                          (6, 'line'),
224                          (6, 'return')]
225
226# Tight loop with while(1) example (SF #765624)
227def tightloop_example():
228    items = range(0, 3)
229    try:
230        i = 0
231        while 1:
232            b = items[i]; i+=1
233    except IndexError:
234        pass
235
236tightloop_example.events = [(0, 'call'),
237                            (1, 'line'),
238                            (2, 'line'),
239                            (3, 'line'),
240                            (5, 'line'),
241                            (5, 'line'),
242                            (5, 'line'),
243                            (5, 'line'),
244                            (5, 'exception'),
245                            (6, 'line'),
246                            (7, 'line'),
247                            (7, 'return')]
248
249def tighterloop_example():
250    items = range(1, 4)
251    try:
252        i = 0
253        while 1: i = items[i]
254    except IndexError:
255        pass
256
257tighterloop_example.events = [(0, 'call'),
258                            (1, 'line'),
259                            (2, 'line'),
260                            (3, 'line'),
261                            (4, 'line'),
262                            (4, 'line'),
263                            (4, 'line'),
264                            (4, 'line'),
265                            (4, 'exception'),
266                            (5, 'line'),
267                            (6, 'line'),
268                            (6, 'return')]
269
270def generator_function():
271    try:
272        yield True
273        "continued"
274    finally:
275        "finally"
276def generator_example():
277    # any() will leave the generator before its end
278    x = any(generator_function())
279
280    # the following lines were not traced
281    for x in range(10):
282        y = x
283
284generator_example.events = ([(0, 'call'),
285                             (2, 'line'),
286                             (-6, 'call'),
287                             (-5, 'line'),
288                             (-4, 'line'),
289                             (-4, 'return'),
290                             (-4, 'call'),
291                             (-4, 'exception'),
292                             (-1, 'line'),
293                             (-1, 'return')] +
294                            [(5, 'line'), (6, 'line')] * 10 +
295                            [(5, 'line'), (5, 'return')])
296
297
298class Tracer:
299    def __init__(self, trace_line_events=None, trace_opcode_events=None):
300        self.trace_line_events = trace_line_events
301        self.trace_opcode_events = trace_opcode_events
302        self.events = []
303
304    def _reconfigure_frame(self, frame):
305        if self.trace_line_events is not None:
306            frame.f_trace_lines = self.trace_line_events
307        if self.trace_opcode_events is not None:
308            frame.f_trace_opcodes = self.trace_opcode_events
309
310    def trace(self, frame, event, arg):
311        self._reconfigure_frame(frame)
312        self.events.append((frame.f_lineno, event))
313        return self.trace
314
315    def traceWithGenexp(self, frame, event, arg):
316        self._reconfigure_frame(frame)
317        (o for o in [1])
318        self.events.append((frame.f_lineno, event))
319        return self.trace
320
321
322class TraceTestCase(unittest.TestCase):
323
324    # Disable gc collection when tracing, otherwise the
325    # deallocators may be traced as well.
326    def setUp(self):
327        self.using_gc = gc.isenabled()
328        gc.disable()
329        self.addCleanup(sys.settrace, sys.gettrace())
330
331    def tearDown(self):
332        if self.using_gc:
333            gc.enable()
334
335    @staticmethod
336    def make_tracer():
337        """Helper to allow test subclasses to configure tracers differently"""
338        return Tracer()
339
340    def compare_events(self, line_offset, events, expected_events):
341        events = [(l - line_offset, e) for (l, e) in events]
342        if events != expected_events:
343            self.fail(
344                "events did not match expectation:\n" +
345                "\n".join(difflib.ndiff([str(x) for x in expected_events],
346                                        [str(x) for x in events])))
347
348    def run_and_compare(self, func, events):
349        tracer = self.make_tracer()
350        sys.settrace(tracer.trace)
351        func()
352        sys.settrace(None)
353        self.compare_events(func.__code__.co_firstlineno,
354                            tracer.events, events)
355
356    def run_test(self, func):
357        self.run_and_compare(func, func.events)
358
359    def run_test2(self, func):
360        tracer = self.make_tracer()
361        func(tracer.trace)
362        sys.settrace(None)
363        self.compare_events(func.__code__.co_firstlineno,
364                            tracer.events, func.events)
365
366    def test_set_and_retrieve_none(self):
367        sys.settrace(None)
368        assert sys.gettrace() is None
369
370    def test_set_and_retrieve_func(self):
371        def fn(*args):
372            pass
373
374        sys.settrace(fn)
375        try:
376            assert sys.gettrace() is fn
377        finally:
378            sys.settrace(None)
379
380    def test_01_basic(self):
381        self.run_test(basic)
382    def test_02_arigo0(self):
383        self.run_test(arigo_example0)
384    def test_02_arigo1(self):
385        self.run_test(arigo_example1)
386    def test_02_arigo2(self):
387        self.run_test(arigo_example2)
388    def test_03_one_instr(self):
389        self.run_test(one_instr_line)
390    def test_04_no_pop_blocks(self):
391        self.run_test(no_pop_blocks)
392    def test_05_no_pop_tops(self):
393        self.run_test(no_pop_tops)
394    def test_06_call(self):
395        self.run_test(call)
396    def test_07_raise(self):
397        self.run_test(test_raise)
398
399    def test_08_settrace_and_return(self):
400        self.run_test2(settrace_and_return)
401    def test_09_settrace_and_raise(self):
402        self.run_test2(settrace_and_raise)
403    def test_10_ireturn(self):
404        self.run_test(ireturn_example)
405    def test_11_tightloop(self):
406        self.run_test(tightloop_example)
407    def test_12_tighterloop(self):
408        self.run_test(tighterloop_example)
409
410    def test_13_genexp(self):
411        self.run_test(generator_example)
412        # issue1265: if the trace function contains a generator,
413        # and if the traced function contains another generator
414        # that is not completely exhausted, the trace stopped.
415        # Worse: the 'finally' clause was not invoked.
416        tracer = self.make_tracer()
417        sys.settrace(tracer.traceWithGenexp)
418        generator_example()
419        sys.settrace(None)
420        self.compare_events(generator_example.__code__.co_firstlineno,
421                            tracer.events, generator_example.events)
422
423    def test_14_onliner_if(self):
424        def onliners():
425            if True: x=False
426            else: x=True
427            return 0
428        self.run_and_compare(
429            onliners,
430            [(0, 'call'),
431             (1, 'line'),
432             (3, 'line'),
433             (3, 'return')])
434
435    def test_15_loops(self):
436        # issue1750076: "while" expression is skipped by debugger
437        def for_example():
438            for x in range(2):
439                pass
440        self.run_and_compare(
441            for_example,
442            [(0, 'call'),
443             (1, 'line'),
444             (2, 'line'),
445             (1, 'line'),
446             (2, 'line'),
447             (1, 'line'),
448             (1, 'return')])
449
450        def while_example():
451            # While expression should be traced on every loop
452            x = 2
453            while x > 0:
454                x -= 1
455        self.run_and_compare(
456            while_example,
457            [(0, 'call'),
458             (2, 'line'),
459             (3, 'line'),
460             (4, 'line'),
461             (3, 'line'),
462             (4, 'line'),
463             (3, 'line'),
464             (3, 'return')])
465
466    def test_16_blank_lines(self):
467        namespace = {}
468        exec("def f():\n" + "\n" * 256 + "    pass", namespace)
469        self.run_and_compare(
470            namespace["f"],
471            [(0, 'call'),
472             (257, 'line'),
473             (257, 'return')])
474
475    def test_17_none_f_trace(self):
476        # Issue 20041: fix TypeError when f_trace is set to None.
477        def func():
478            sys._getframe().f_trace = None
479            lineno = 2
480        self.run_and_compare(func,
481            [(0, 'call'),
482             (1, 'line')])
483
484
485class SkipLineEventsTraceTestCase(TraceTestCase):
486    """Repeat the trace tests, but with per-line events skipped"""
487
488    def compare_events(self, line_offset, events, expected_events):
489        skip_line_events = [e for e in expected_events if e[1] != 'line']
490        super().compare_events(line_offset, events, skip_line_events)
491
492    @staticmethod
493    def make_tracer():
494        return Tracer(trace_line_events=False)
495
496
497@support.cpython_only
498class TraceOpcodesTestCase(TraceTestCase):
499    """Repeat the trace tests, but with per-opcodes events enabled"""
500
501    def compare_events(self, line_offset, events, expected_events):
502        skip_opcode_events = [e for e in events if e[1] != 'opcode']
503        if len(events) > 1:
504            self.assertLess(len(skip_opcode_events), len(events),
505                            msg="No 'opcode' events received by the tracer")
506        super().compare_events(line_offset, skip_opcode_events, expected_events)
507
508    @staticmethod
509    def make_tracer():
510        return Tracer(trace_opcode_events=True)
511
512
513class RaisingTraceFuncTestCase(unittest.TestCase):
514    def setUp(self):
515        self.addCleanup(sys.settrace, sys.gettrace())
516
517    def trace(self, frame, event, arg):
518        """A trace function that raises an exception in response to a
519        specific trace event."""
520        if event == self.raiseOnEvent:
521            raise ValueError # just something that isn't RuntimeError
522        else:
523            return self.trace
524
525    def f(self):
526        """The function to trace; raises an exception if that's the case
527        we're testing, so that the 'exception' trace event fires."""
528        if self.raiseOnEvent == 'exception':
529            x = 0
530            y = 1/x
531        else:
532            return 1
533
534    def run_test_for_event(self, event):
535        """Tests that an exception raised in response to the given event is
536        handled OK."""
537        self.raiseOnEvent = event
538        try:
539            for i in range(sys.getrecursionlimit() + 1):
540                sys.settrace(self.trace)
541                try:
542                    self.f()
543                except ValueError:
544                    pass
545                else:
546                    self.fail("exception not raised!")
547        except RuntimeError:
548            self.fail("recursion counter not reset")
549
550    # Test the handling of exceptions raised by each kind of trace event.
551    def test_call(self):
552        self.run_test_for_event('call')
553    def test_line(self):
554        self.run_test_for_event('line')
555    def test_return(self):
556        self.run_test_for_event('return')
557    def test_exception(self):
558        self.run_test_for_event('exception')
559
560    def test_trash_stack(self):
561        def f():
562            for i in range(5):
563                print(i)  # line tracing will raise an exception at this line
564
565        def g(frame, why, extra):
566            if (why == 'line' and
567                frame.f_lineno == f.__code__.co_firstlineno + 2):
568                raise RuntimeError("i am crashing")
569            return g
570
571        sys.settrace(g)
572        try:
573            f()
574        except RuntimeError:
575            # the test is really that this doesn't segfault:
576            import gc
577            gc.collect()
578        else:
579            self.fail("exception not propagated")
580
581
582    def test_exception_arguments(self):
583        def f():
584            x = 0
585            # this should raise an error
586            x.no_such_attr
587        def g(frame, event, arg):
588            if (event == 'exception'):
589                type, exception, trace = arg
590                self.assertIsInstance(exception, Exception)
591            return g
592
593        existing = sys.gettrace()
594        try:
595            sys.settrace(g)
596            try:
597                f()
598            except AttributeError:
599                # this is expected
600                pass
601        finally:
602            sys.settrace(existing)
603
604
605# 'Jump' tests: assigning to frame.f_lineno within a trace function
606# moves the execution position - it's how debuggers implement a Jump
607# command (aka. "Set next statement").
608
609class JumpTracer:
610    """Defines a trace function that jumps from one place to another."""
611
612    def __init__(self, function, jumpFrom, jumpTo, event='line',
613                 decorated=False):
614        self.code = function.__code__
615        self.jumpFrom = jumpFrom
616        self.jumpTo = jumpTo
617        self.event = event
618        self.firstLine = None if decorated else self.code.co_firstlineno
619        self.done = False
620
621    def trace(self, frame, event, arg):
622        if self.done:
623            return
624        # frame.f_code.co_firstlineno is the first line of the decorator when
625        # 'function' is decorated and the decorator may be written using
626        # multiple physical lines when it is too long. Use the first line
627        # trace event in 'function' to find the first line of 'function'.
628        if (self.firstLine is None and frame.f_code == self.code and
629                event == 'line'):
630            self.firstLine = frame.f_lineno - 1
631        if (event == self.event and self.firstLine and
632                frame.f_lineno == self.firstLine + self.jumpFrom):
633            f = frame
634            while f is not None and f.f_code != self.code:
635                f = f.f_back
636            if f is not None:
637                # Cope with non-integer self.jumpTo (because of
638                # no_jump_to_non_integers below).
639                try:
640                    frame.f_lineno = self.firstLine + self.jumpTo
641                except TypeError:
642                    frame.f_lineno = self.jumpTo
643                self.done = True
644        return self.trace
645
646# This verifies the line-numbers-must-be-integers rule.
647def no_jump_to_non_integers(output):
648    try:
649        output.append(2)
650    except ValueError as e:
651        output.append('integer' in str(e))
652
653# This verifies that you can't set f_lineno via _getframe or similar
654# trickery.
655def no_jump_without_trace_function():
656    try:
657        previous_frame = sys._getframe().f_back
658        previous_frame.f_lineno = previous_frame.f_lineno
659    except ValueError as e:
660        # This is the exception we wanted; make sure the error message
661        # talks about trace functions.
662        if 'trace' not in str(e):
663            raise
664    else:
665        # Something's wrong - the expected exception wasn't raised.
666        raise AssertionError("Trace-function-less jump failed to fail")
667
668
669class JumpTestCase(unittest.TestCase):
670    def setUp(self):
671        self.addCleanup(sys.settrace, sys.gettrace())
672        sys.settrace(None)
673
674    def compare_jump_output(self, expected, received):
675        if received != expected:
676            self.fail( "Outputs don't match:\n" +
677                       "Expected: " + repr(expected) + "\n" +
678                       "Received: " + repr(received))
679
680    def run_test(self, func, jumpFrom, jumpTo, expected, error=None,
681                 event='line', decorated=False):
682        tracer = JumpTracer(func, jumpFrom, jumpTo, event, decorated)
683        sys.settrace(tracer.trace)
684        output = []
685        if error is None:
686            func(output)
687        else:
688            with self.assertRaisesRegex(*error):
689                func(output)
690        sys.settrace(None)
691        self.compare_jump_output(expected, output)
692
693    def run_async_test(self, func, jumpFrom, jumpTo, expected, error=None,
694                 event='line', decorated=False):
695        tracer = JumpTracer(func, jumpFrom, jumpTo, event, decorated)
696        sys.settrace(tracer.trace)
697        output = []
698        if error is None:
699            asyncio.run(func(output))
700        else:
701            with self.assertRaisesRegex(*error):
702                asyncio.run(func(output))
703        sys.settrace(None)
704        asyncio.set_event_loop_policy(None)
705        self.compare_jump_output(expected, output)
706
707    def jump_test(jumpFrom, jumpTo, expected, error=None, event='line'):
708        """Decorator that creates a test that makes a jump
709        from one place to another in the following code.
710        """
711        def decorator(func):
712            @wraps(func)
713            def test(self):
714                self.run_test(func, jumpFrom, jumpTo, expected,
715                              error=error, event=event, decorated=True)
716            return test
717        return decorator
718
719    def async_jump_test(jumpFrom, jumpTo, expected, error=None, event='line'):
720        """Decorator that creates a test that makes a jump
721        from one place to another in the following asynchronous code.
722        """
723        def decorator(func):
724            @wraps(func)
725            def test(self):
726                self.run_async_test(func, jumpFrom, jumpTo, expected,
727                              error=error, event=event, decorated=True)
728            return test
729        return decorator
730
731    ## The first set of 'jump' tests are for things that are allowed:
732
733    @jump_test(1, 3, [3])
734    def test_jump_simple_forwards(output):
735        output.append(1)
736        output.append(2)
737        output.append(3)
738
739    @jump_test(2, 1, [1, 1, 2])
740    def test_jump_simple_backwards(output):
741        output.append(1)
742        output.append(2)
743
744    @jump_test(3, 5, [2, 5])
745    def test_jump_out_of_block_forwards(output):
746        for i in 1, 2:
747            output.append(2)
748            for j in [3]:  # Also tests jumping over a block
749                output.append(4)
750        output.append(5)
751
752    @jump_test(6, 1, [1, 3, 5, 1, 3, 5, 6, 7])
753    def test_jump_out_of_block_backwards(output):
754        output.append(1)
755        for i in [1]:
756            output.append(3)
757            for j in [2]:  # Also tests jumping over a block
758                output.append(5)
759            output.append(6)
760        output.append(7)
761
762    @async_jump_test(4, 5, [3, 5])
763    async def test_jump_out_of_async_for_block_forwards(output):
764        for i in [1]:
765            async for i in asynciter([1, 2]):
766                output.append(3)
767                output.append(4)
768            output.append(5)
769
770    @async_jump_test(5, 2, [2, 4, 2, 4, 5, 6])
771    async def test_jump_out_of_async_for_block_backwards(output):
772        for i in [1]:
773            output.append(2)
774            async for i in asynciter([1]):
775                output.append(4)
776                output.append(5)
777            output.append(6)
778
779    @jump_test(1, 2, [3])
780    def test_jump_to_codeless_line(output):
781        output.append(1)
782        # Jumping to this line should skip to the next one.
783        output.append(3)
784
785    @jump_test(2, 2, [1, 2, 3])
786    def test_jump_to_same_line(output):
787        output.append(1)
788        output.append(2)
789        output.append(3)
790
791    # Tests jumping within a finally block, and over one.
792    @jump_test(4, 9, [2, 9])
793    def test_jump_in_nested_finally(output):
794        try:
795            output.append(2)
796        finally:
797            output.append(4)
798            try:
799                output.append(6)
800            finally:
801                output.append(8)
802            output.append(9)
803
804    @jump_test(6, 7, [2, 7], (ZeroDivisionError, ''))
805    def test_jump_in_nested_finally_2(output):
806        try:
807            output.append(2)
808            1/0
809            return
810        finally:
811            output.append(6)
812            output.append(7)
813        output.append(8)
814
815    @jump_test(6, 11, [2, 11], (ZeroDivisionError, ''))
816    def test_jump_in_nested_finally_3(output):
817        try:
818            output.append(2)
819            1/0
820            return
821        finally:
822            output.append(6)
823            try:
824                output.append(8)
825            finally:
826                output.append(10)
827            output.append(11)
828        output.append(12)
829
830    @jump_test(5, 11, [2, 4, 12])
831    def test_jump_over_return_try_finally_in_finally_block(output):
832        try:
833            output.append(2)
834        finally:
835            output.append(4)
836            output.append(5)
837            return
838            try:
839                output.append(8)
840            finally:
841                output.append(10)
842            pass
843        output.append(12)
844
845    @jump_test(3, 4, [1, 4])
846    def test_jump_infinite_while_loop(output):
847        output.append(1)
848        while True:
849            output.append(3)
850        output.append(4)
851
852    @jump_test(2, 4, [4, 4])
853    def test_jump_forwards_into_while_block(output):
854        i = 1
855        output.append(2)
856        while i <= 2:
857            output.append(4)
858            i += 1
859
860    @jump_test(5, 3, [3, 3, 3, 5])
861    def test_jump_backwards_into_while_block(output):
862        i = 1
863        while i <= 2:
864            output.append(3)
865            i += 1
866        output.append(5)
867
868    @jump_test(2, 3, [1, 3])
869    def test_jump_forwards_out_of_with_block(output):
870        with tracecontext(output, 1):
871            output.append(2)
872        output.append(3)
873
874    @async_jump_test(2, 3, [1, 3])
875    async def test_jump_forwards_out_of_async_with_block(output):
876        async with asynctracecontext(output, 1):
877            output.append(2)
878        output.append(3)
879
880    @jump_test(3, 1, [1, 2, 1, 2, 3, -2])
881    def test_jump_backwards_out_of_with_block(output):
882        output.append(1)
883        with tracecontext(output, 2):
884            output.append(3)
885
886    @async_jump_test(3, 1, [1, 2, 1, 2, 3, -2])
887    async def test_jump_backwards_out_of_async_with_block(output):
888        output.append(1)
889        async with asynctracecontext(output, 2):
890            output.append(3)
891
892    @jump_test(2, 5, [5])
893    def test_jump_forwards_out_of_try_finally_block(output):
894        try:
895            output.append(2)
896        finally:
897            output.append(4)
898        output.append(5)
899
900    @jump_test(3, 1, [1, 1, 3, 5])
901    def test_jump_backwards_out_of_try_finally_block(output):
902        output.append(1)
903        try:
904            output.append(3)
905        finally:
906            output.append(5)
907
908    @jump_test(2, 6, [6])
909    def test_jump_forwards_out_of_try_except_block(output):
910        try:
911            output.append(2)
912        except:
913            output.append(4)
914            raise
915        output.append(6)
916
917    @jump_test(3, 1, [1, 1, 3])
918    def test_jump_backwards_out_of_try_except_block(output):
919        output.append(1)
920        try:
921            output.append(3)
922        except:
923            output.append(5)
924            raise
925
926    @jump_test(5, 7, [4, 7, 8])
927    def test_jump_between_except_blocks(output):
928        try:
929            1/0
930        except ZeroDivisionError:
931            output.append(4)
932            output.append(5)
933        except FloatingPointError:
934            output.append(7)
935        output.append(8)
936
937    @jump_test(5, 6, [4, 6, 7])
938    def test_jump_within_except_block(output):
939        try:
940            1/0
941        except:
942            output.append(4)
943            output.append(5)
944            output.append(6)
945        output.append(7)
946
947    @jump_test(2, 4, [1, 4, 5, -4])
948    def test_jump_across_with(output):
949        output.append(1)
950        with tracecontext(output, 2):
951            output.append(3)
952        with tracecontext(output, 4):
953            output.append(5)
954
955    @async_jump_test(2, 4, [1, 4, 5, -4])
956    async def test_jump_across_async_with(output):
957        output.append(1)
958        async with asynctracecontext(output, 2):
959            output.append(3)
960        async with asynctracecontext(output, 4):
961            output.append(5)
962
963    @jump_test(4, 5, [1, 3, 5, 6])
964    def test_jump_out_of_with_block_within_for_block(output):
965        output.append(1)
966        for i in [1]:
967            with tracecontext(output, 3):
968                output.append(4)
969            output.append(5)
970        output.append(6)
971
972    @async_jump_test(4, 5, [1, 3, 5, 6])
973    async def test_jump_out_of_async_with_block_within_for_block(output):
974        output.append(1)
975        for i in [1]:
976            async with asynctracecontext(output, 3):
977                output.append(4)
978            output.append(5)
979        output.append(6)
980
981    @jump_test(4, 5, [1, 2, 3, 5, -2, 6])
982    def test_jump_out_of_with_block_within_with_block(output):
983        output.append(1)
984        with tracecontext(output, 2):
985            with tracecontext(output, 3):
986                output.append(4)
987            output.append(5)
988        output.append(6)
989
990    @async_jump_test(4, 5, [1, 2, 3, 5, -2, 6])
991    async def test_jump_out_of_async_with_block_within_with_block(output):
992        output.append(1)
993        with tracecontext(output, 2):
994            async with asynctracecontext(output, 3):
995                output.append(4)
996            output.append(5)
997        output.append(6)
998
999    @jump_test(5, 6, [2, 4, 6, 7])
1000    def test_jump_out_of_with_block_within_finally_block(output):
1001        try:
1002            output.append(2)
1003        finally:
1004            with tracecontext(output, 4):
1005                output.append(5)
1006            output.append(6)
1007        output.append(7)
1008
1009    @async_jump_test(5, 6, [2, 4, 6, 7])
1010    async def test_jump_out_of_async_with_block_within_finally_block(output):
1011        try:
1012            output.append(2)
1013        finally:
1014            async with asynctracecontext(output, 4):
1015                output.append(5)
1016            output.append(6)
1017        output.append(7)
1018
1019    @jump_test(8, 11, [1, 3, 5, 11, 12])
1020    def test_jump_out_of_complex_nested_blocks(output):
1021        output.append(1)
1022        for i in [1]:
1023            output.append(3)
1024            for j in [1, 2]:
1025                output.append(5)
1026                try:
1027                    for k in [1, 2]:
1028                        output.append(8)
1029                finally:
1030                    output.append(10)
1031            output.append(11)
1032        output.append(12)
1033
1034    @jump_test(3, 5, [1, 2, 5])
1035    def test_jump_out_of_with_assignment(output):
1036        output.append(1)
1037        with tracecontext(output, 2) \
1038                as x:
1039            output.append(4)
1040        output.append(5)
1041
1042    @async_jump_test(3, 5, [1, 2, 5])
1043    async def test_jump_out_of_async_with_assignment(output):
1044        output.append(1)
1045        async with asynctracecontext(output, 2) \
1046                as x:
1047            output.append(4)
1048        output.append(5)
1049
1050    @jump_test(3, 6, [1, 6, 8, 9])
1051    def test_jump_over_return_in_try_finally_block(output):
1052        output.append(1)
1053        try:
1054            output.append(3)
1055            if not output: # always false
1056                return
1057            output.append(6)
1058        finally:
1059            output.append(8)
1060        output.append(9)
1061
1062    @jump_test(5, 8, [1, 3, 8, 10, 11, 13])
1063    def test_jump_over_break_in_try_finally_block(output):
1064        output.append(1)
1065        while True:
1066            output.append(3)
1067            try:
1068                output.append(5)
1069                if not output: # always false
1070                    break
1071                output.append(8)
1072            finally:
1073                output.append(10)
1074            output.append(11)
1075            break
1076        output.append(13)
1077
1078    @jump_test(1, 7, [7, 8])
1079    def test_jump_over_for_block_before_else(output):
1080        output.append(1)
1081        if not output:  # always false
1082            for i in [3]:
1083                output.append(4)
1084        else:
1085            output.append(6)
1086            output.append(7)
1087        output.append(8)
1088
1089    @async_jump_test(1, 7, [7, 8])
1090    async def test_jump_over_async_for_block_before_else(output):
1091        output.append(1)
1092        if not output:  # always false
1093            async for i in asynciter([3]):
1094                output.append(4)
1095        else:
1096            output.append(6)
1097            output.append(7)
1098        output.append(8)
1099
1100    # The second set of 'jump' tests are for things that are not allowed:
1101
1102    @jump_test(2, 3, [1], (ValueError, 'after'))
1103    def test_no_jump_too_far_forwards(output):
1104        output.append(1)
1105        output.append(2)
1106
1107    @jump_test(2, -2, [1], (ValueError, 'before'))
1108    def test_no_jump_too_far_backwards(output):
1109        output.append(1)
1110        output.append(2)
1111
1112    # Test each kind of 'except' line.
1113    @jump_test(2, 3, [4], (ValueError, 'except'))
1114    def test_no_jump_to_except_1(output):
1115        try:
1116            output.append(2)
1117        except:
1118            output.append(4)
1119            raise
1120
1121    @jump_test(2, 3, [4], (ValueError, 'except'))
1122    def test_no_jump_to_except_2(output):
1123        try:
1124            output.append(2)
1125        except ValueError:
1126            output.append(4)
1127            raise
1128
1129    @jump_test(2, 3, [4], (ValueError, 'except'))
1130    def test_no_jump_to_except_3(output):
1131        try:
1132            output.append(2)
1133        except ValueError as e:
1134            output.append(4)
1135            raise e
1136
1137    @jump_test(2, 3, [4], (ValueError, 'except'))
1138    def test_no_jump_to_except_4(output):
1139        try:
1140            output.append(2)
1141        except (ValueError, RuntimeError) as e:
1142            output.append(4)
1143            raise e
1144
1145    @jump_test(1, 3, [], (ValueError, 'into'))
1146    def test_no_jump_forwards_into_for_block(output):
1147        output.append(1)
1148        for i in 1, 2:
1149            output.append(3)
1150
1151    @async_jump_test(1, 3, [], (ValueError, 'into'))
1152    async def test_no_jump_forwards_into_async_for_block(output):
1153        output.append(1)
1154        async for i in asynciter([1, 2]):
1155            output.append(3)
1156
1157    @jump_test(3, 2, [2, 2], (ValueError, 'into'))
1158    def test_no_jump_backwards_into_for_block(output):
1159        for i in 1, 2:
1160            output.append(2)
1161        output.append(3)
1162
1163    @async_jump_test(3, 2, [2, 2], (ValueError, 'into'))
1164    async def test_no_jump_backwards_into_async_for_block(output):
1165        async for i in asynciter([1, 2]):
1166            output.append(2)
1167        output.append(3)
1168
1169    @jump_test(1, 3, [], (ValueError, 'into'))
1170    def test_no_jump_forwards_into_with_block(output):
1171        output.append(1)
1172        with tracecontext(output, 2):
1173            output.append(3)
1174
1175    @async_jump_test(1, 3, [], (ValueError, 'into'))
1176    async def test_no_jump_forwards_into_async_with_block(output):
1177        output.append(1)
1178        async with asynctracecontext(output, 2):
1179            output.append(3)
1180
1181    @jump_test(3, 2, [1, 2, -1], (ValueError, 'into'))
1182    def test_no_jump_backwards_into_with_block(output):
1183        with tracecontext(output, 1):
1184            output.append(2)
1185        output.append(3)
1186
1187    @async_jump_test(3, 2, [1, 2, -1], (ValueError, 'into'))
1188    async def test_no_jump_backwards_into_async_with_block(output):
1189        async with asynctracecontext(output, 1):
1190            output.append(2)
1191        output.append(3)
1192
1193    @jump_test(1, 3, [], (ValueError, 'into'))
1194    def test_no_jump_forwards_into_try_finally_block(output):
1195        output.append(1)
1196        try:
1197            output.append(3)
1198        finally:
1199            output.append(5)
1200
1201    @jump_test(5, 2, [2, 4], (ValueError, 'into'))
1202    def test_no_jump_backwards_into_try_finally_block(output):
1203        try:
1204            output.append(2)
1205        finally:
1206            output.append(4)
1207        output.append(5)
1208
1209    @jump_test(1, 3, [], (ValueError, 'into'))
1210    def test_no_jump_forwards_into_try_except_block(output):
1211        output.append(1)
1212        try:
1213            output.append(3)
1214        except:
1215            output.append(5)
1216            raise
1217
1218    @jump_test(6, 2, [2], (ValueError, 'into'))
1219    def test_no_jump_backwards_into_try_except_block(output):
1220        try:
1221            output.append(2)
1222        except:
1223            output.append(4)
1224            raise
1225        output.append(6)
1226
1227    # 'except' with a variable creates an implicit finally block
1228    @jump_test(5, 7, [4], (ValueError, 'into'))
1229    def test_no_jump_between_except_blocks_2(output):
1230        try:
1231            1/0
1232        except ZeroDivisionError:
1233            output.append(4)
1234            output.append(5)
1235        except FloatingPointError as e:
1236            output.append(7)
1237        output.append(8)
1238
1239    @jump_test(1, 5, [], (ValueError, "into a 'finally'"))
1240    def test_no_jump_into_finally_block(output):
1241        output.append(1)
1242        try:
1243            output.append(3)
1244        finally:
1245            output.append(5)
1246
1247    @jump_test(3, 6, [2, 5, 6], (ValueError, "into a 'finally'"))
1248    def test_no_jump_into_finally_block_from_try_block(output):
1249        try:
1250            output.append(2)
1251            output.append(3)
1252        finally:  # still executed if the jump is failed
1253            output.append(5)
1254            output.append(6)
1255        output.append(7)
1256
1257    @jump_test(5, 1, [1, 3], (ValueError, "out of a 'finally'"))
1258    def test_no_jump_out_of_finally_block(output):
1259        output.append(1)
1260        try:
1261            output.append(3)
1262        finally:
1263            output.append(5)
1264
1265    @jump_test(1, 5, [], (ValueError, "into an 'except'"))
1266    def test_no_jump_into_bare_except_block(output):
1267        output.append(1)
1268        try:
1269            output.append(3)
1270        except:
1271            output.append(5)
1272
1273    @jump_test(1, 5, [], (ValueError, "into an 'except'"))
1274    def test_no_jump_into_qualified_except_block(output):
1275        output.append(1)
1276        try:
1277            output.append(3)
1278        except Exception:
1279            output.append(5)
1280
1281    @jump_test(3, 6, [2, 5, 6], (ValueError, "into an 'except'"))
1282    def test_no_jump_into_bare_except_block_from_try_block(output):
1283        try:
1284            output.append(2)
1285            output.append(3)
1286        except:  # executed if the jump is failed
1287            output.append(5)
1288            output.append(6)
1289            raise
1290        output.append(8)
1291
1292    @jump_test(3, 6, [2], (ValueError, "into an 'except'"))
1293    def test_no_jump_into_qualified_except_block_from_try_block(output):
1294        try:
1295            output.append(2)
1296            output.append(3)
1297        except ZeroDivisionError:
1298            output.append(5)
1299            output.append(6)
1300            raise
1301        output.append(8)
1302
1303    @jump_test(7, 1, [1, 3, 6], (ValueError, "out of an 'except'"))
1304    def test_no_jump_out_of_bare_except_block(output):
1305        output.append(1)
1306        try:
1307            output.append(3)
1308            1/0
1309        except:
1310            output.append(6)
1311            output.append(7)
1312
1313    @jump_test(7, 1, [1, 3, 6], (ValueError, "out of an 'except'"))
1314    def test_no_jump_out_of_qualified_except_block(output):
1315        output.append(1)
1316        try:
1317            output.append(3)
1318            1/0
1319        except Exception:
1320            output.append(6)
1321            output.append(7)
1322
1323    @jump_test(3, 5, [1, 2, -2], (ValueError, 'into'))
1324    def test_no_jump_between_with_blocks(output):
1325        output.append(1)
1326        with tracecontext(output, 2):
1327            output.append(3)
1328        with tracecontext(output, 4):
1329            output.append(5)
1330
1331    @async_jump_test(3, 5, [1, 2, -2], (ValueError, 'into'))
1332    async def test_no_jump_between_async_with_blocks(output):
1333        output.append(1)
1334        async with asynctracecontext(output, 2):
1335            output.append(3)
1336        async with asynctracecontext(output, 4):
1337            output.append(5)
1338
1339    @jump_test(5, 7, [2, 4], (ValueError, 'finally'))
1340    def test_no_jump_over_return_out_of_finally_block(output):
1341        try:
1342            output.append(2)
1343        finally:
1344            output.append(4)
1345            output.append(5)
1346            return
1347        output.append(7)
1348
1349    @jump_test(7, 4, [1, 6], (ValueError, 'into'))
1350    def test_no_jump_into_for_block_before_else(output):
1351        output.append(1)
1352        if not output:  # always false
1353            for i in [3]:
1354                output.append(4)
1355        else:
1356            output.append(6)
1357            output.append(7)
1358        output.append(8)
1359
1360    @async_jump_test(7, 4, [1, 6], (ValueError, 'into'))
1361    async def test_no_jump_into_async_for_block_before_else(output):
1362        output.append(1)
1363        if not output:  # always false
1364            async for i in asynciter([3]):
1365                output.append(4)
1366        else:
1367            output.append(6)
1368            output.append(7)
1369        output.append(8)
1370
1371    def test_no_jump_to_non_integers(self):
1372        self.run_test(no_jump_to_non_integers, 2, "Spam", [True])
1373
1374    def test_no_jump_without_trace_function(self):
1375        # Must set sys.settrace(None) in setUp(), else condition is not
1376        # triggered.
1377        no_jump_without_trace_function()
1378
1379    def test_large_function(self):
1380        d = {}
1381        exec("""def f(output):        # line 0
1382            x = 0                     # line 1
1383            y = 1                     # line 2
1384            '''                       # line 3
1385            %s                        # lines 4-1004
1386            '''                       # line 1005
1387            x += 1                    # line 1006
1388            output.append(x)          # line 1007
1389            return""" % ('\n' * 1000,), d)
1390        f = d['f']
1391        self.run_test(f, 2, 1007, [0])
1392
1393    def test_jump_to_firstlineno(self):
1394        # This tests that PDB can jump back to the first line in a
1395        # file.  See issue #1689458.  It can only be triggered in a
1396        # function call if the function is defined on a single line.
1397        code = compile("""
1398# Comments don't count.
1399output.append(2)  # firstlineno is here.
1400output.append(3)
1401output.append(4)
1402""", "<fake module>", "exec")
1403        class fake_function:
1404            __code__ = code
1405        tracer = JumpTracer(fake_function, 2, 0)
1406        sys.settrace(tracer.trace)
1407        namespace = {"output": []}
1408        exec(code, namespace)
1409        sys.settrace(None)
1410        self.compare_jump_output([2, 3, 2, 3, 4], namespace["output"])
1411
1412    @jump_test(2, 3, [1], event='call', error=(ValueError, "can't jump from"
1413               " the 'call' trace event of a new frame"))
1414    def test_no_jump_from_call(output):
1415        output.append(1)
1416        def nested():
1417            output.append(3)
1418        nested()
1419        output.append(5)
1420
1421    @jump_test(2, 1, [1], event='return', error=(ValueError,
1422               "can only jump from a 'line' trace event"))
1423    def test_no_jump_from_return_event(output):
1424        output.append(1)
1425        return
1426
1427    @jump_test(2, 1, [1], event='exception', error=(ValueError,
1428               "can only jump from a 'line' trace event"))
1429    def test_no_jump_from_exception_event(output):
1430        output.append(1)
1431        1 / 0
1432
1433    @jump_test(3, 2, [2], event='return', error=(ValueError,
1434               "can't jump from a yield statement"))
1435    def test_no_jump_from_yield(output):
1436        def gen():
1437            output.append(2)
1438            yield 3
1439        next(gen())
1440        output.append(5)
1441
1442
1443if __name__ == "__main__":
1444    unittest.main()
1445