• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:..." could be optimized
57# away.  Make sure that those lines aren't skipped.
58def arigo_example0():
59    x = 1
60    del x
61    while 0:
62        pass
63    x = 1
64
65arigo_example0.events = [(0, 'call'),
66                        (1, 'line'),
67                        (2, 'line'),
68                        (3, '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                        (3, 'line'),
83                        (5, 'line'),
84                        (5, 'return')]
85
86def arigo_example2():
87    x = 1
88    del x
89    if 1:
90        x = 1
91    else:
92        pass
93    return None
94
95arigo_example2.events = [(0, 'call'),
96                        (1, 'line'),
97                        (2, 'line'),
98                        (3, 'line'),
99                        (4, 'line'),
100                        (7, 'line'),
101                        (7, 'return')]
102
103
104# check that lines consisting of just one instruction get traced:
105def one_instr_line():
106    x = 1
107    del x
108    x = 1
109
110one_instr_line.events = [(0, 'call'),
111                         (1, 'line'),
112                         (2, 'line'),
113                         (3, 'line'),
114                         (3, 'return')]
115
116def no_pop_tops():      # 0
117    x = 1               # 1
118    for a in range(2):  # 2
119        if a:           # 3
120            x = 1       # 4
121        else:           # 5
122            x = 1       # 6
123
124no_pop_tops.events = [(0, 'call'),
125                      (1, 'line'),
126                      (2, 'line'),
127                      (3, 'line'),
128                      (6, 'line'),
129                      (2, 'line'),
130                      (3, 'line'),
131                      (4, 'line'),
132                      (2, 'line'),
133                      (2, 'return')]
134
135def no_pop_blocks():
136    y = 1
137    while not y:
138        bla
139    x = 1
140
141no_pop_blocks.events = [(0, 'call'),
142                        (1, 'line'),
143                        (2, 'line'),
144                        (4, 'line'),
145                        (4, 'return')]
146
147def called(): # line -3
148    x = 1
149
150def call():   # line 0
151    called()
152
153call.events = [(0, 'call'),
154               (1, 'line'),
155               (-3, 'call'),
156               (-2, 'line'),
157               (-2, 'return'),
158               (1, 'return')]
159
160def raises():
161    raise Exception
162
163def test_raise():
164    try:
165        raises()
166    except Exception:
167        pass
168
169test_raise.events = [(0, 'call'),
170                     (1, 'line'),
171                     (2, 'line'),
172                     (-3, 'call'),
173                     (-2, 'line'),
174                     (-2, 'exception'),
175                     (-2, 'return'),
176                     (2, 'exception'),
177                     (3, 'line'),
178                     (4, 'line'),
179                     (4, 'return')]
180
181def _settrace_and_return(tracefunc):
182    sys.settrace(tracefunc)
183    sys._getframe().f_back.f_trace = tracefunc
184def settrace_and_return(tracefunc):
185    _settrace_and_return(tracefunc)
186
187settrace_and_return.events = [(1, 'return')]
188
189def _settrace_and_raise(tracefunc):
190    sys.settrace(tracefunc)
191    sys._getframe().f_back.f_trace = tracefunc
192    raise RuntimeError
193def settrace_and_raise(tracefunc):
194    try:
195        _settrace_and_raise(tracefunc)
196    except RuntimeError:
197        pass
198
199settrace_and_raise.events = [(2, 'exception'),
200                             (3, 'line'),
201                             (4, 'line'),
202                             (4, 'return')]
203
204# implicit return example
205# This test is interesting because of the else: pass
206# part of the code.  The code generate for the true
207# part of the if contains a jump past the else branch.
208# The compiler then generates an implicit "return None"
209# Internally, the compiler visits the pass statement
210# and stores its line number for use on the next instruction.
211# The next instruction is the implicit return None.
212def ireturn_example():
213    a = 5
214    b = 5
215    if a == b:
216        b = a+1
217    else:
218        pass
219
220ireturn_example.events = [(0, 'call'),
221                          (1, 'line'),
222                          (2, 'line'),
223                          (3, 'line'),
224                          (4, 'line'),
225                          (4, 'return')]
226
227# Tight loop with while(1) example (SF #765624)
228def tightloop_example():
229    items = range(0, 3)
230    try:
231        i = 0
232        while 1:
233            b = items[i]; i+=1
234    except IndexError:
235        pass
236
237tightloop_example.events = [(0, 'call'),
238                            (1, 'line'),
239                            (2, 'line'),
240                            (3, 'line'),
241                            (4, 'line'),
242                            (5, 'line'),
243                            (4, 'line'),
244                            (5, 'line'),
245                            (4, 'line'),
246                            (5, 'line'),
247                            (4, 'line'),
248                            (5, 'line'),
249                            (5, 'exception'),
250                            (6, 'line'),
251                            (7, 'line'),
252                            (7, 'return')]
253
254def tighterloop_example():
255    items = range(1, 4)
256    try:
257        i = 0
258        while 1: i = items[i]
259    except IndexError:
260        pass
261
262tighterloop_example.events = [(0, 'call'),
263                            (1, 'line'),
264                            (2, 'line'),
265                            (3, 'line'),
266                            (4, 'line'),
267                            (4, 'line'),
268                            (4, 'line'),
269                            (4, 'line'),
270                            (4, 'exception'),
271                            (5, 'line'),
272                            (6, 'line'),
273                            (6, 'return')]
274
275def generator_function():
276    try:
277        yield True
278        "continued"
279    finally:
280        "finally"
281def generator_example():
282    # any() will leave the generator before its end
283    x = any(generator_function())
284
285    # the following lines were not traced
286    for x in range(10):
287        y = x
288
289generator_example.events = ([(0, 'call'),
290                             (2, 'line'),
291                             (-6, 'call'),
292                             (-5, 'line'),
293                             (-4, 'line'),
294                             (-4, 'return'),
295                             (-4, 'call'),
296                             (-4, 'exception'),
297                             (-1, 'line'),
298                             (-1, 'return')] +
299                            [(5, 'line'), (6, 'line')] * 10 +
300                            [(5, 'line'), (5, 'return')])
301
302
303class Tracer:
304    def __init__(self, trace_line_events=None, trace_opcode_events=None):
305        self.trace_line_events = trace_line_events
306        self.trace_opcode_events = trace_opcode_events
307        self.events = []
308
309    def _reconfigure_frame(self, frame):
310        if self.trace_line_events is not None:
311            frame.f_trace_lines = self.trace_line_events
312        if self.trace_opcode_events is not None:
313            frame.f_trace_opcodes = self.trace_opcode_events
314
315    def trace(self, frame, event, arg):
316        self._reconfigure_frame(frame)
317        self.events.append((frame.f_lineno, event))
318        return self.trace
319
320    def traceWithGenexp(self, frame, event, arg):
321        self._reconfigure_frame(frame)
322        (o for o in [1])
323        self.events.append((frame.f_lineno, event))
324        return self.trace
325
326
327class TraceTestCase(unittest.TestCase):
328
329    # Disable gc collection when tracing, otherwise the
330    # deallocators may be traced as well.
331    def setUp(self):
332        self.using_gc = gc.isenabled()
333        gc.disable()
334        self.addCleanup(sys.settrace, sys.gettrace())
335
336    def tearDown(self):
337        if self.using_gc:
338            gc.enable()
339
340    @staticmethod
341    def make_tracer():
342        """Helper to allow test subclasses to configure tracers differently"""
343        return Tracer()
344
345    def compare_events(self, line_offset, events, expected_events):
346        events = [(l - line_offset, e) for (l, e) in events]
347        if events != expected_events:
348            self.fail(
349                "events did not match expectation:\n" +
350                "\n".join(difflib.ndiff([str(x) for x in expected_events],
351                                        [str(x) for x in events])))
352
353    def run_and_compare(self, func, events):
354        tracer = self.make_tracer()
355        sys.settrace(tracer.trace)
356        func()
357        sys.settrace(None)
358        self.compare_events(func.__code__.co_firstlineno,
359                            tracer.events, events)
360
361    def run_test(self, func):
362        self.run_and_compare(func, func.events)
363
364    def run_test2(self, func):
365        tracer = self.make_tracer()
366        func(tracer.trace)
367        sys.settrace(None)
368        self.compare_events(func.__code__.co_firstlineno,
369                            tracer.events, func.events)
370
371    def test_set_and_retrieve_none(self):
372        sys.settrace(None)
373        assert sys.gettrace() is None
374
375    def test_set_and_retrieve_func(self):
376        def fn(*args):
377            pass
378
379        sys.settrace(fn)
380        try:
381            assert sys.gettrace() is fn
382        finally:
383            sys.settrace(None)
384
385    def test_01_basic(self):
386        self.run_test(basic)
387    def test_02_arigo0(self):
388        self.run_test(arigo_example0)
389    def test_02_arigo1(self):
390        self.run_test(arigo_example1)
391    def test_02_arigo2(self):
392        self.run_test(arigo_example2)
393    def test_03_one_instr(self):
394        self.run_test(one_instr_line)
395    def test_04_no_pop_blocks(self):
396        self.run_test(no_pop_blocks)
397    def test_05_no_pop_tops(self):
398        self.run_test(no_pop_tops)
399    def test_06_call(self):
400        self.run_test(call)
401    def test_07_raise(self):
402        self.run_test(test_raise)
403
404    def test_08_settrace_and_return(self):
405        self.run_test2(settrace_and_return)
406    def test_09_settrace_and_raise(self):
407        self.run_test2(settrace_and_raise)
408    def test_10_ireturn(self):
409        self.run_test(ireturn_example)
410    def test_11_tightloop(self):
411        self.run_test(tightloop_example)
412    def test_12_tighterloop(self):
413        self.run_test(tighterloop_example)
414
415    def test_13_genexp(self):
416        self.run_test(generator_example)
417        # issue1265: if the trace function contains a generator,
418        # and if the traced function contains another generator
419        # that is not completely exhausted, the trace stopped.
420        # Worse: the 'finally' clause was not invoked.
421        tracer = self.make_tracer()
422        sys.settrace(tracer.traceWithGenexp)
423        generator_example()
424        sys.settrace(None)
425        self.compare_events(generator_example.__code__.co_firstlineno,
426                            tracer.events, generator_example.events)
427
428    def test_14_onliner_if(self):
429        def onliners():
430            if True: x=False
431            else: x=True
432            return 0
433        self.run_and_compare(
434            onliners,
435            [(0, 'call'),
436             (1, 'line'),
437             (3, 'line'),
438             (3, 'return')])
439
440    def test_15_loops(self):
441        # issue1750076: "while" expression is skipped by debugger
442        def for_example():
443            for x in range(2):
444                pass
445        self.run_and_compare(
446            for_example,
447            [(0, 'call'),
448             (1, 'line'),
449             (2, 'line'),
450             (1, 'line'),
451             (2, 'line'),
452             (1, 'line'),
453             (1, 'return')])
454
455        def while_example():
456            # While expression should be traced on every loop
457            x = 2
458            while x > 0:
459                x -= 1
460        self.run_and_compare(
461            while_example,
462            [(0, 'call'),
463             (2, 'line'),
464             (3, 'line'),
465             (4, 'line'),
466             (3, 'line'),
467             (4, 'line'),
468             (3, 'line'),
469             (3, 'return')])
470
471    def test_16_blank_lines(self):
472        namespace = {}
473        exec("def f():\n" + "\n" * 256 + "    pass", namespace)
474        self.run_and_compare(
475            namespace["f"],
476            [(0, 'call'),
477             (257, 'line'),
478             (257, 'return')])
479
480    def test_17_none_f_trace(self):
481        # Issue 20041: fix TypeError when f_trace is set to None.
482        def func():
483            sys._getframe().f_trace = None
484            lineno = 2
485        self.run_and_compare(func,
486            [(0, 'call'),
487             (1, 'line')])
488
489    def test_18_except_with_name(self):
490        def func():
491            try:
492                try:
493                    raise Exception
494                except Exception as e:
495                    raise
496                    x = "Something"
497                    y = "Something"
498            except Exception:
499                pass
500
501        self.run_and_compare(func,
502            [(0, 'call'),
503             (1, 'line'),
504             (2, 'line'),
505             (3, 'line'),
506             (3, 'exception'),
507             (4, 'line'),
508             (5, 'line'),
509             (8, 'line'),
510             (9, 'line'),
511             (9, 'return')])
512
513    def test_19_except_with_finally(self):
514        def func():
515            try:
516                try:
517                    raise Exception
518                finally:
519                    y = "Something"
520            except Exception:
521                b = 23
522
523        self.run_and_compare(func,
524            [(0, 'call'),
525             (1, 'line'),
526             (2, 'line'),
527             (3, 'line'),
528             (3, 'exception'),
529             (5, 'line'),
530             (6, 'line'),
531             (7, 'line'),
532             (7, 'return')])
533
534    def test_20_async_for_loop(self):
535        class AsyncIteratorWrapper:
536            def __init__(self, obj):
537                self._it = iter(obj)
538
539            def __aiter__(self):
540                return self
541
542            async def __anext__(self):
543                try:
544                    return next(self._it)
545                except StopIteration:
546                    raise StopAsyncIteration
547
548        async def doit_async():
549            async for letter in AsyncIteratorWrapper("abc"):
550                x = letter
551            y = 42
552
553        def run(tracer):
554            x = doit_async()
555            try:
556                sys.settrace(tracer)
557                x.send(None)
558            finally:
559                sys.settrace(None)
560
561        tracer = self.make_tracer()
562        events = [
563                (0, 'call'),
564                (1, 'line'),
565                (-12, 'call'),
566                (-11, 'line'),
567                (-11, 'return'),
568                (-9, 'call'),
569                (-8, 'line'),
570                (-8, 'return'),
571                (-6, 'call'),
572                (-5, 'line'),
573                (-4, 'line'),
574                (-4, 'return'),
575                (1, 'exception'),
576                (2, 'line'),
577                (1, 'line'),
578                (-6, 'call'),
579                (-5, 'line'),
580                (-4, 'line'),
581                (-4, 'return'),
582                (1, 'exception'),
583                (2, 'line'),
584                (1, 'line'),
585                (-6, 'call'),
586                (-5, 'line'),
587                (-4, 'line'),
588                (-4, 'return'),
589                (1, 'exception'),
590                (2, 'line'),
591                (1, 'line'),
592                (-6, 'call'),
593                (-5, 'line'),
594                (-4, 'line'),
595                (-4, 'exception'),
596                (-3, 'line'),
597                (-2, 'line'),
598                (-2, 'exception'),
599                (-2, 'return'),
600                (1, 'exception'),
601                (3, 'line'),
602                (3, 'return')]
603        try:
604            run(tracer.trace)
605        except Exception:
606            pass
607        self.compare_events(doit_async.__code__.co_firstlineno,
608                            tracer.events, events)
609
610    def test_21_repeated_pass(self):
611        def func():
612            pass
613            pass
614
615        self.run_and_compare(func,
616            [(0, 'call'),
617             (1, 'line'),
618             (2, 'line'),
619             (2, 'return')])
620
621    def test_loop_in_try_except(self):
622        # https://bugs.python.org/issue41670
623
624        def func():
625            try:
626                for i in []: pass
627                return 1
628            except:
629                return 2
630
631        self.run_and_compare(func,
632            [(0, 'call'),
633             (1, 'line'),
634             (2, 'line'),
635             (3, 'line'),
636             (3, 'return')])
637
638    def test_try_except_no_exception(self):
639
640        def func():
641            try:
642                2
643            except:
644                4
645            finally:
646                6
647
648        self.run_and_compare(func,
649            [(0, 'call'),
650             (1, 'line'),
651             (2, 'line'),
652             (6, 'line'),
653             (6, 'return')])
654
655    def test_nested_loops(self):
656
657        def func():
658            for i in range(2):
659                for j in range(2):
660                    a = i + j
661            return a == 1
662
663        self.run_and_compare(func,
664            [(0, 'call'),
665             (1, 'line'),
666             (2, 'line'),
667             (3, 'line'),
668             (2, 'line'),
669             (3, 'line'),
670             (2, 'line'),
671             (1, 'line'),
672             (2, 'line'),
673             (3, 'line'),
674             (2, 'line'),
675             (3, 'line'),
676             (2, 'line'),
677             (1, 'line'),
678             (4, 'line'),
679             (4, 'return')])
680
681    def test_if_break(self):
682
683        def func():
684            seq = [1, 0]
685            while seq:
686                n = seq.pop()
687                if n:
688                    break   # line 5
689            else:
690                n = 99
691            return n        # line 8
692
693        self.run_and_compare(func,
694            [(0, 'call'),
695             (1, 'line'),
696             (2, 'line'),
697             (3, 'line'),
698             (4, 'line'),
699             (2, 'line'),
700             (3, 'line'),
701             (4, 'line'),
702             (5, 'line'),
703             (8, 'line'),
704             (8, 'return')])
705
706    def test_break_through_finally(self):
707
708        def func():
709            a, c, d, i = 1, 1, 1, 99
710            try:
711                for i in range(3):
712                    try:
713                        a = 5
714                        if i > 0:
715                            break                   # line 7
716                        a = 8
717                    finally:
718                        c = 10
719            except:
720                d = 12                              # line 12
721            assert a == 5 and c == 10 and d == 1    # line 13
722
723        self.run_and_compare(func,
724            [(0, 'call'),
725             (1, 'line'),
726             (2, 'line'),
727             (3, 'line'),
728             (4, 'line'),
729             (5, 'line'),
730             (6, 'line'),
731             (8, 'line'),
732             (10, 'line'),
733             (3, 'line'),
734             (4, 'line'),
735             (5, 'line'),
736             (6, 'line'),
737             (7, 'line'),
738             (10, 'line'),
739             (13, 'line'),
740             (13, 'return')])
741
742    def test_continue_through_finally(self):
743
744        def func():
745            a, b, c, d, i = 1, 1, 1, 1, 99
746            try:
747                for i in range(2):
748                    try:
749                        a = 5
750                        if i > 0:
751                            continue                # line 7
752                        b = 8
753                    finally:
754                        c = 10
755            except:
756                d = 12                              # line 12
757            assert (a, b, c, d) == (5, 8, 10, 1)    # line 13
758
759        self.run_and_compare(func,
760            [(0, 'call'),
761             (1, 'line'),
762             (2, 'line'),
763             (3, 'line'),
764             (4, 'line'),
765             (5, 'line'),
766             (6, 'line'),
767             (8, 'line'),
768             (10, 'line'),
769             (3, 'line'),
770             (4, 'line'),
771             (5, 'line'),
772             (6, 'line'),
773             (7, 'line'),
774             (10, 'line'),
775             (3, 'line'),
776             (13, 'line'),
777             (13, 'return')])
778
779    def test_return_through_finally(self):
780
781        def func():
782            try:
783                return 2
784            finally:
785                4
786
787        self.run_and_compare(func,
788            [(0, 'call'),
789             (1, 'line'),
790             (2, 'line'),
791             (4, 'line'),
792             (4, 'return')])
793
794    def test_try_except_with_wrong_type(self):
795
796        def func():
797            try:
798                2/0
799            except IndexError:
800                4
801            finally:
802                return 6
803
804        self.run_and_compare(func,
805            [(0, 'call'),
806             (1, 'line'),
807             (2, 'line'),
808             (2, 'exception'),
809             (3, 'line'),
810             (6, 'line'),
811             (6, 'return')])
812
813    def test_break_to_continue1(self):
814
815        def func():
816            TRUE = 1
817            x = [1]
818            while x:
819                x.pop()
820                while TRUE:
821                    break
822                continue
823
824        self.run_and_compare(func,
825            [(0, 'call'),
826             (1, 'line'),
827             (2, 'line'),
828             (3, 'line'),
829             (4, 'line'),
830             (5, 'line'),
831             (6, 'line'),
832             (7, 'line'),
833             (3, 'line'),
834             (3, 'return')])
835
836    def test_break_to_continue2(self):
837
838        def func():
839            TRUE = 1
840            x = [1]
841            while x:
842                x.pop()
843                while TRUE:
844                    break
845                else:
846                    continue
847
848        self.run_and_compare(func,
849            [(0, 'call'),
850             (1, 'line'),
851             (2, 'line'),
852             (3, 'line'),
853             (4, 'line'),
854             (5, 'line'),
855             (6, 'line'),
856             (3, 'line'),
857             (3, 'return')])
858
859    def test_break_to_break(self):
860
861        def func():
862            TRUE = 1
863            while TRUE:
864                while TRUE:
865                    break
866                break
867
868        self.run_and_compare(func,
869            [(0, 'call'),
870             (1, 'line'),
871             (2, 'line'),
872             (3, 'line'),
873             (4, 'line'),
874             (5, 'line'),
875             (5, 'return')])
876
877    def test_nested_ifs(self):
878
879        def func():
880            a = b = 1
881            if a == 1:
882                if b == 1:
883                    x = 4
884                else:
885                    y = 6
886            else:
887                z = 8
888
889        self.run_and_compare(func,
890            [(0, 'call'),
891             (1, 'line'),
892             (2, 'line'),
893             (3, 'line'),
894             (4, 'line'),
895             (4, 'return')])
896
897    def test_nested_ifs_with_and(self):
898
899        def func():
900            if A:
901                if B:
902                    if C:
903                        if D:
904                            return False
905                else:
906                    return False
907            elif E and F:
908                return True
909
910        A = B = True
911        C = False
912
913        self.run_and_compare(func,
914            [(0, 'call'),
915             (1, 'line'),
916             (2, 'line'),
917             (3, 'line'),
918             (3, 'return')])
919
920    def test_nested_try_if(self):
921
922        def func():
923            x = "hello"
924            try:
925                3/0
926            except ZeroDivisionError:
927                if x == 'raise':
928                    raise ValueError()   # line 6
929            f = 7
930
931        self.run_and_compare(func,
932            [(0, 'call'),
933             (1, 'line'),
934             (2, 'line'),
935             (3, 'line'),
936             (3, 'exception'),
937             (4, 'line'),
938             (5, 'line'),
939             (7, 'line'),
940             (7, 'return')])
941
942    def test_if_false_in_with(self):
943
944        class C:
945            def __enter__(self):
946                return self
947            def __exit__(*args):
948                pass
949
950        def func():
951            with C():
952                if False:
953                    pass
954
955        self.run_and_compare(func,
956            [(0, 'call'),
957             (1, 'line'),
958             (-5, 'call'),
959             (-4, 'line'),
960             (-4, 'return'),
961             (2, 'line'),
962             (1, 'line'),
963             (-3, 'call'),
964             (-2, 'line'),
965             (-2, 'return'),
966             (1, 'return')])
967
968    def test_if_false_in_try_except(self):
969
970        def func():
971            try:
972                if False:
973                    pass
974            except Exception:
975                X
976
977        self.run_and_compare(func,
978            [(0, 'call'),
979             (1, 'line'),
980             (2, 'line'),
981             (2, 'return')])
982
983    def test_implicit_return_in_class(self):
984
985        def func():
986            class A:
987                if 3 < 9:
988                    a = 1
989                else:
990                    a = 2
991
992        self.run_and_compare(func,
993            [(0, 'call'),
994             (1, 'line'),
995             (1, 'call'),
996             (1, 'line'),
997             (2, 'line'),
998             (3, 'line'),
999             (3, 'return'),
1000             (1, 'return')])
1001
1002    def test_try_in_try(self):
1003        def func():
1004            try:
1005                try:
1006                    pass
1007                except Exception as ex:
1008                    pass
1009            except Exception:
1010                pass
1011
1012        self.run_and_compare(func,
1013            [(0, 'call'),
1014             (1, 'line'),
1015             (2, 'line'),
1016             (3, 'line'),
1017             (3, 'return')])
1018
1019    def test_if_in_if_in_if(self):
1020        def func(a=0, p=1, z=1):
1021            if p:
1022                if a:
1023                    if z:
1024                        pass
1025                    else:
1026                        pass
1027            else:
1028                pass
1029
1030        self.run_and_compare(func,
1031            [(0, 'call'),
1032             (1, 'line'),
1033             (2, 'line'),
1034             (2, 'return')])
1035
1036    def test_early_exit_with(self):
1037
1038        class C:
1039            def __enter__(self):
1040                return self
1041            def __exit__(*args):
1042                pass
1043
1044        def func_break():
1045            for i in (1,2):
1046                with C():
1047                    break
1048            pass
1049
1050        def func_return():
1051            with C():
1052                return
1053
1054        self.run_and_compare(func_break,
1055            [(0, 'call'),
1056             (1, 'line'),
1057             (2, 'line'),
1058             (-5, 'call'),
1059             (-4, 'line'),
1060             (-4, 'return'),
1061             (3, 'line'),
1062             (2, 'line'),
1063             (-3, 'call'),
1064             (-2, 'line'),
1065             (-2, 'return'),
1066             (4, 'line'),
1067             (4, 'return')])
1068
1069        self.run_and_compare(func_return,
1070            [(0, 'call'),
1071             (1, 'line'),
1072             (-11, 'call'),
1073             (-10, 'line'),
1074             (-10, 'return'),
1075             (2, 'line'),
1076             (1, 'line'),
1077             (-9, 'call'),
1078             (-8, 'line'),
1079             (-8, 'return'),
1080             (1, 'return')])
1081
1082    def test_flow_converges_on_same_line(self):
1083
1084        def foo(x):
1085            if x:
1086                try:
1087                    1/(x - 1)
1088                except ZeroDivisionError:
1089                    pass
1090            return x
1091
1092        def func():
1093            for i in range(2):
1094                foo(i)
1095
1096        self.run_and_compare(func,
1097            [(0, 'call'),
1098             (1, 'line'),
1099             (2, 'line'),
1100             (-8, 'call'),
1101             (-7, 'line'),
1102             (-2, 'line'),
1103             (-2, 'return'),
1104             (1, 'line'),
1105             (2, 'line'),
1106             (-8, 'call'),
1107             (-7, 'line'),
1108             (-6, 'line'),
1109             (-5, 'line'),
1110             (-5, 'exception'),
1111             (-4, 'line'),
1112             (-3, 'line'),
1113             (-2, 'line'),
1114             (-2, 'return'),
1115             (1, 'line'),
1116             (1, 'return')])
1117
1118    def test_no_tracing_of_named_except_cleanup(self):
1119
1120        def func():
1121            x = 0
1122            try:
1123                1/x
1124            except ZeroDivisionError as error:
1125                if x:
1126                    raise
1127            return "done"
1128
1129        self.run_and_compare(func,
1130        [(0, 'call'),
1131            (1, 'line'),
1132            (2, 'line'),
1133            (3, 'line'),
1134            (3, 'exception'),
1135            (4, 'line'),
1136            (5, 'line'),
1137            (7, 'line'),
1138            (7, 'return')])
1139
1140
1141class SkipLineEventsTraceTestCase(TraceTestCase):
1142    """Repeat the trace tests, but with per-line events skipped"""
1143
1144    def compare_events(self, line_offset, events, expected_events):
1145        skip_line_events = [e for e in expected_events if e[1] != 'line']
1146        super().compare_events(line_offset, events, skip_line_events)
1147
1148    @staticmethod
1149    def make_tracer():
1150        return Tracer(trace_line_events=False)
1151
1152
1153@support.cpython_only
1154class TraceOpcodesTestCase(TraceTestCase):
1155    """Repeat the trace tests, but with per-opcodes events enabled"""
1156
1157    def compare_events(self, line_offset, events, expected_events):
1158        skip_opcode_events = [e for e in events if e[1] != 'opcode']
1159        if len(events) > 1:
1160            self.assertLess(len(skip_opcode_events), len(events),
1161                            msg="No 'opcode' events received by the tracer")
1162        super().compare_events(line_offset, skip_opcode_events, expected_events)
1163
1164    @staticmethod
1165    def make_tracer():
1166        return Tracer(trace_opcode_events=True)
1167
1168
1169class RaisingTraceFuncTestCase(unittest.TestCase):
1170    def setUp(self):
1171        self.addCleanup(sys.settrace, sys.gettrace())
1172
1173    def trace(self, frame, event, arg):
1174        """A trace function that raises an exception in response to a
1175        specific trace event."""
1176        if event == self.raiseOnEvent:
1177            raise ValueError # just something that isn't RuntimeError
1178        else:
1179            return self.trace
1180
1181    def f(self):
1182        """The function to trace; raises an exception if that's the case
1183        we're testing, so that the 'exception' trace event fires."""
1184        if self.raiseOnEvent == 'exception':
1185            x = 0
1186            y = 1/x
1187        else:
1188            return 1
1189
1190    def run_test_for_event(self, event):
1191        """Tests that an exception raised in response to the given event is
1192        handled OK."""
1193        self.raiseOnEvent = event
1194        try:
1195            for i in range(sys.getrecursionlimit() + 1):
1196                sys.settrace(self.trace)
1197                try:
1198                    self.f()
1199                except ValueError:
1200                    pass
1201                else:
1202                    self.fail("exception not raised!")
1203        except RuntimeError:
1204            self.fail("recursion counter not reset")
1205
1206    # Test the handling of exceptions raised by each kind of trace event.
1207    def test_call(self):
1208        self.run_test_for_event('call')
1209    def test_line(self):
1210        self.run_test_for_event('line')
1211    def test_return(self):
1212        self.run_test_for_event('return')
1213    def test_exception(self):
1214        self.run_test_for_event('exception')
1215
1216    def test_trash_stack(self):
1217        def f():
1218            for i in range(5):
1219                print(i)  # line tracing will raise an exception at this line
1220
1221        def g(frame, why, extra):
1222            if (why == 'line' and
1223                frame.f_lineno == f.__code__.co_firstlineno + 2):
1224                raise RuntimeError("i am crashing")
1225            return g
1226
1227        sys.settrace(g)
1228        try:
1229            f()
1230        except RuntimeError:
1231            # the test is really that this doesn't segfault:
1232            import gc
1233            gc.collect()
1234        else:
1235            self.fail("exception not propagated")
1236
1237
1238    def test_exception_arguments(self):
1239        def f():
1240            x = 0
1241            # this should raise an error
1242            x.no_such_attr
1243        def g(frame, event, arg):
1244            if (event == 'exception'):
1245                type, exception, trace = arg
1246                self.assertIsInstance(exception, Exception)
1247            return g
1248
1249        existing = sys.gettrace()
1250        try:
1251            sys.settrace(g)
1252            try:
1253                f()
1254            except AttributeError:
1255                # this is expected
1256                pass
1257        finally:
1258            sys.settrace(existing)
1259
1260
1261# 'Jump' tests: assigning to frame.f_lineno within a trace function
1262# moves the execution position - it's how debuggers implement a Jump
1263# command (aka. "Set next statement").
1264
1265class JumpTracer:
1266    """Defines a trace function that jumps from one place to another."""
1267
1268    def __init__(self, function, jumpFrom, jumpTo, event='line',
1269                 decorated=False):
1270        self.code = function.__code__
1271        self.jumpFrom = jumpFrom
1272        self.jumpTo = jumpTo
1273        self.event = event
1274        self.firstLine = None if decorated else self.code.co_firstlineno
1275        self.done = False
1276
1277    def trace(self, frame, event, arg):
1278        if self.done:
1279            return
1280        # frame.f_code.co_firstlineno is the first line of the decorator when
1281        # 'function' is decorated and the decorator may be written using
1282        # multiple physical lines when it is too long. Use the first line
1283        # trace event in 'function' to find the first line of 'function'.
1284        if (self.firstLine is None and frame.f_code == self.code and
1285                event == 'line'):
1286            self.firstLine = frame.f_lineno - 1
1287        if (event == self.event and self.firstLine is not None and
1288                frame.f_lineno == self.firstLine + self.jumpFrom):
1289            f = frame
1290            while f is not None and f.f_code != self.code:
1291                f = f.f_back
1292            if f is not None:
1293                # Cope with non-integer self.jumpTo (because of
1294                # no_jump_to_non_integers below).
1295                try:
1296                    frame.f_lineno = self.firstLine + self.jumpTo
1297                except TypeError:
1298                    frame.f_lineno = self.jumpTo
1299                self.done = True
1300        return self.trace
1301
1302# This verifies the line-numbers-must-be-integers rule.
1303def no_jump_to_non_integers(output):
1304    try:
1305        output.append(2)
1306    except ValueError as e:
1307        output.append('integer' in str(e))
1308
1309# This verifies that you can't set f_lineno via _getframe or similar
1310# trickery.
1311def no_jump_without_trace_function():
1312    try:
1313        previous_frame = sys._getframe().f_back
1314        previous_frame.f_lineno = previous_frame.f_lineno
1315    except ValueError as e:
1316        # This is the exception we wanted; make sure the error message
1317        # talks about trace functions.
1318        if 'trace' not in str(e):
1319            raise
1320    else:
1321        # Something's wrong - the expected exception wasn't raised.
1322        raise AssertionError("Trace-function-less jump failed to fail")
1323
1324
1325class JumpTestCase(unittest.TestCase):
1326    def setUp(self):
1327        self.addCleanup(sys.settrace, sys.gettrace())
1328        sys.settrace(None)
1329
1330    def compare_jump_output(self, expected, received):
1331        if received != expected:
1332            self.fail( "Outputs don't match:\n" +
1333                       "Expected: " + repr(expected) + "\n" +
1334                       "Received: " + repr(received))
1335
1336    def run_test(self, func, jumpFrom, jumpTo, expected, error=None,
1337                 event='line', decorated=False):
1338        tracer = JumpTracer(func, jumpFrom, jumpTo, event, decorated)
1339        sys.settrace(tracer.trace)
1340        output = []
1341        if error is None:
1342            func(output)
1343        else:
1344            with self.assertRaisesRegex(*error):
1345                func(output)
1346        sys.settrace(None)
1347        self.compare_jump_output(expected, output)
1348
1349    def run_async_test(self, func, jumpFrom, jumpTo, expected, error=None,
1350                 event='line', decorated=False):
1351        tracer = JumpTracer(func, jumpFrom, jumpTo, event, decorated)
1352        sys.settrace(tracer.trace)
1353        output = []
1354        if error is None:
1355            asyncio.run(func(output))
1356        else:
1357            with self.assertRaisesRegex(*error):
1358                asyncio.run(func(output))
1359        sys.settrace(None)
1360        asyncio.set_event_loop_policy(None)
1361        self.compare_jump_output(expected, output)
1362
1363    def jump_test(jumpFrom, jumpTo, expected, error=None, event='line'):
1364        """Decorator that creates a test that makes a jump
1365        from one place to another in the following code.
1366        """
1367        def decorator(func):
1368            @wraps(func)
1369            def test(self):
1370                self.run_test(func, jumpFrom, jumpTo, expected,
1371                              error=error, event=event, decorated=True)
1372            return test
1373        return decorator
1374
1375    def async_jump_test(jumpFrom, jumpTo, expected, error=None, event='line'):
1376        """Decorator that creates a test that makes a jump
1377        from one place to another in the following asynchronous code.
1378        """
1379        def decorator(func):
1380            @wraps(func)
1381            def test(self):
1382                self.run_async_test(func, jumpFrom, jumpTo, expected,
1383                              error=error, event=event, decorated=True)
1384            return test
1385        return decorator
1386
1387    ## The first set of 'jump' tests are for things that are allowed:
1388
1389    @jump_test(1, 3, [3])
1390    def test_jump_simple_forwards(output):
1391        output.append(1)
1392        output.append(2)
1393        output.append(3)
1394
1395    @jump_test(2, 1, [1, 1, 2])
1396    def test_jump_simple_backwards(output):
1397        output.append(1)
1398        output.append(2)
1399
1400    @jump_test(3, 5, [2, 5])
1401    def test_jump_out_of_block_forwards(output):
1402        for i in 1, 2:
1403            output.append(2)
1404            for j in [3]:  # Also tests jumping over a block
1405                output.append(4)
1406        output.append(5)
1407
1408    @jump_test(6, 1, [1, 3, 5, 1, 3, 5, 6, 7])
1409    def test_jump_out_of_block_backwards(output):
1410        output.append(1)
1411        for i in [1]:
1412            output.append(3)
1413            for j in [2]:  # Also tests jumping over a block
1414                output.append(5)
1415            output.append(6)
1416        output.append(7)
1417
1418    @async_jump_test(4, 5, [3, 5])
1419    async def test_jump_out_of_async_for_block_forwards(output):
1420        for i in [1]:
1421            async for i in asynciter([1, 2]):
1422                output.append(3)
1423                output.append(4)
1424            output.append(5)
1425
1426    @async_jump_test(5, 2, [2, 4, 2, 4, 5, 6])
1427    async def test_jump_out_of_async_for_block_backwards(output):
1428        for i in [1]:
1429            output.append(2)
1430            async for i in asynciter([1]):
1431                output.append(4)
1432                output.append(5)
1433            output.append(6)
1434
1435    @jump_test(1, 2, [3])
1436    def test_jump_to_codeless_line(output):
1437        output.append(1)
1438        # Jumping to this line should skip to the next one.
1439        output.append(3)
1440
1441    @jump_test(2, 2, [1, 2, 3])
1442    def test_jump_to_same_line(output):
1443        output.append(1)
1444        output.append(2)
1445        output.append(3)
1446
1447    # Tests jumping within a finally block, and over one.
1448    @jump_test(4, 9, [2, 9])
1449    def test_jump_in_nested_finally(output):
1450        try:
1451            output.append(2)
1452        finally:
1453            output.append(4)
1454            try:
1455                output.append(6)
1456            finally:
1457                output.append(8)
1458            output.append(9)
1459
1460    @jump_test(6, 7, [2, 7], (ZeroDivisionError, ''))
1461    def test_jump_in_nested_finally_2(output):
1462        try:
1463            output.append(2)
1464            1/0
1465            return
1466        finally:
1467            output.append(6)
1468            output.append(7)
1469        output.append(8)
1470
1471    @jump_test(6, 11, [2, 11], (ZeroDivisionError, ''))
1472    def test_jump_in_nested_finally_3(output):
1473        try:
1474            output.append(2)
1475            1/0
1476            return
1477        finally:
1478            output.append(6)
1479            try:
1480                output.append(8)
1481            finally:
1482                output.append(10)
1483            output.append(11)
1484        output.append(12)
1485
1486    @jump_test(5, 11, [2, 4], (ValueError, 'after'))
1487    def test_no_jump_over_return_try_finally_in_finally_block(output):
1488        try:
1489            output.append(2)
1490        finally:
1491            output.append(4)
1492            output.append(5)
1493            return
1494            try:
1495                output.append(8)
1496            finally:
1497                output.append(10)
1498            pass
1499        output.append(12)
1500
1501    @jump_test(3, 4, [1], (ValueError, 'after'))
1502    def test_no_jump_infinite_while_loop(output):
1503        output.append(1)
1504        while True:
1505            output.append(3)
1506        output.append(4)
1507
1508    @jump_test(2, 4, [4, 4])
1509    def test_jump_forwards_into_while_block(output):
1510        i = 1
1511        output.append(2)
1512        while i <= 2:
1513            output.append(4)
1514            i += 1
1515
1516    @jump_test(5, 3, [3, 3, 3, 5])
1517    def test_jump_backwards_into_while_block(output):
1518        i = 1
1519        while i <= 2:
1520            output.append(3)
1521            i += 1
1522        output.append(5)
1523
1524    @jump_test(2, 3, [1, 3])
1525    def test_jump_forwards_out_of_with_block(output):
1526        with tracecontext(output, 1):
1527            output.append(2)
1528        output.append(3)
1529
1530    @async_jump_test(2, 3, [1, 3])
1531    async def test_jump_forwards_out_of_async_with_block(output):
1532        async with asynctracecontext(output, 1):
1533            output.append(2)
1534        output.append(3)
1535
1536    @jump_test(3, 1, [1, 2, 1, 2, 3, -2])
1537    def test_jump_backwards_out_of_with_block(output):
1538        output.append(1)
1539        with tracecontext(output, 2):
1540            output.append(3)
1541
1542    @async_jump_test(3, 1, [1, 2, 1, 2, 3, -2])
1543    async def test_jump_backwards_out_of_async_with_block(output):
1544        output.append(1)
1545        async with asynctracecontext(output, 2):
1546            output.append(3)
1547
1548    @jump_test(2, 5, [5])
1549    def test_jump_forwards_out_of_try_finally_block(output):
1550        try:
1551            output.append(2)
1552        finally:
1553            output.append(4)
1554        output.append(5)
1555
1556    @jump_test(3, 1, [1, 1, 3, 5])
1557    def test_jump_backwards_out_of_try_finally_block(output):
1558        output.append(1)
1559        try:
1560            output.append(3)
1561        finally:
1562            output.append(5)
1563
1564    @jump_test(2, 6, [6])
1565    def test_jump_forwards_out_of_try_except_block(output):
1566        try:
1567            output.append(2)
1568        except:
1569            output.append(4)
1570            raise
1571        output.append(6)
1572
1573    @jump_test(3, 1, [1, 1, 3])
1574    def test_jump_backwards_out_of_try_except_block(output):
1575        output.append(1)
1576        try:
1577            output.append(3)
1578        except:
1579            output.append(5)
1580            raise
1581
1582    @jump_test(5, 7, [4, 7, 8])
1583    def test_jump_between_except_blocks(output):
1584        try:
1585            1/0
1586        except ZeroDivisionError:
1587            output.append(4)
1588            output.append(5)
1589        except FloatingPointError:
1590            output.append(7)
1591        output.append(8)
1592
1593    @jump_test(5, 6, [4, 6, 7])
1594    def test_jump_within_except_block(output):
1595        try:
1596            1/0
1597        except:
1598            output.append(4)
1599            output.append(5)
1600            output.append(6)
1601        output.append(7)
1602
1603    @jump_test(2, 4, [1, 4, 5, -4])
1604    def test_jump_across_with(output):
1605        output.append(1)
1606        with tracecontext(output, 2):
1607            output.append(3)
1608        with tracecontext(output, 4):
1609            output.append(5)
1610
1611    @async_jump_test(2, 4, [1, 4, 5, -4])
1612    async def test_jump_across_async_with(output):
1613        output.append(1)
1614        async with asynctracecontext(output, 2):
1615            output.append(3)
1616        async with asynctracecontext(output, 4):
1617            output.append(5)
1618
1619    @jump_test(4, 5, [1, 3, 5, 6])
1620    def test_jump_out_of_with_block_within_for_block(output):
1621        output.append(1)
1622        for i in [1]:
1623            with tracecontext(output, 3):
1624                output.append(4)
1625            output.append(5)
1626        output.append(6)
1627
1628    @async_jump_test(4, 5, [1, 3, 5, 6])
1629    async def test_jump_out_of_async_with_block_within_for_block(output):
1630        output.append(1)
1631        for i in [1]:
1632            async with asynctracecontext(output, 3):
1633                output.append(4)
1634            output.append(5)
1635        output.append(6)
1636
1637    @jump_test(4, 5, [1, 2, 3, 5, -2, 6])
1638    def test_jump_out_of_with_block_within_with_block(output):
1639        output.append(1)
1640        with tracecontext(output, 2):
1641            with tracecontext(output, 3):
1642                output.append(4)
1643            output.append(5)
1644        output.append(6)
1645
1646    @async_jump_test(4, 5, [1, 2, 3, 5, -2, 6])
1647    async def test_jump_out_of_async_with_block_within_with_block(output):
1648        output.append(1)
1649        with tracecontext(output, 2):
1650            async with asynctracecontext(output, 3):
1651                output.append(4)
1652            output.append(5)
1653        output.append(6)
1654
1655    @jump_test(5, 6, [2, 4, 6, 7])
1656    def test_jump_out_of_with_block_within_finally_block(output):
1657        try:
1658            output.append(2)
1659        finally:
1660            with tracecontext(output, 4):
1661                output.append(5)
1662            output.append(6)
1663        output.append(7)
1664
1665    @async_jump_test(5, 6, [2, 4, 6, 7])
1666    async def test_jump_out_of_async_with_block_within_finally_block(output):
1667        try:
1668            output.append(2)
1669        finally:
1670            async with asynctracecontext(output, 4):
1671                output.append(5)
1672            output.append(6)
1673        output.append(7)
1674
1675    @jump_test(8, 11, [1, 3, 5, 11, 12])
1676    def test_jump_out_of_complex_nested_blocks(output):
1677        output.append(1)
1678        for i in [1]:
1679            output.append(3)
1680            for j in [1, 2]:
1681                output.append(5)
1682                try:
1683                    for k in [1, 2]:
1684                        output.append(8)
1685                finally:
1686                    output.append(10)
1687            output.append(11)
1688        output.append(12)
1689
1690    @jump_test(3, 5, [1, 2, 5])
1691    def test_jump_out_of_with_assignment(output):
1692        output.append(1)
1693        with tracecontext(output, 2) \
1694                as x:
1695            output.append(4)
1696        output.append(5)
1697
1698    @async_jump_test(3, 5, [1, 2, 5])
1699    async def test_jump_out_of_async_with_assignment(output):
1700        output.append(1)
1701        async with asynctracecontext(output, 2) \
1702                as x:
1703            output.append(4)
1704        output.append(5)
1705
1706    @jump_test(3, 6, [1, 6, 8, 9])
1707    def test_jump_over_return_in_try_finally_block(output):
1708        output.append(1)
1709        try:
1710            output.append(3)
1711            if not output: # always false
1712                return
1713            output.append(6)
1714        finally:
1715            output.append(8)
1716        output.append(9)
1717
1718    @jump_test(5, 8, [1, 3, 8, 10, 11, 13])
1719    def test_jump_over_break_in_try_finally_block(output):
1720        output.append(1)
1721        while True:
1722            output.append(3)
1723            try:
1724                output.append(5)
1725                if not output: # always false
1726                    break
1727                output.append(8)
1728            finally:
1729                output.append(10)
1730            output.append(11)
1731            break
1732        output.append(13)
1733
1734    @jump_test(1, 7, [7, 8])
1735    def test_jump_over_for_block_before_else(output):
1736        output.append(1)
1737        if not output:  # always false
1738            for i in [3]:
1739                output.append(4)
1740        else:
1741            output.append(6)
1742            output.append(7)
1743        output.append(8)
1744
1745    @async_jump_test(1, 7, [7, 8])
1746    async def test_jump_over_async_for_block_before_else(output):
1747        output.append(1)
1748        if not output:  # always false
1749            async for i in asynciter([3]):
1750                output.append(4)
1751        else:
1752            output.append(6)
1753            output.append(7)
1754        output.append(8)
1755
1756    # The second set of 'jump' tests are for things that are not allowed:
1757
1758    @jump_test(2, 3, [1], (ValueError, 'after'))
1759    def test_no_jump_too_far_forwards(output):
1760        output.append(1)
1761        output.append(2)
1762
1763    @jump_test(2, -2, [1], (ValueError, 'before'))
1764    def test_no_jump_too_far_backwards(output):
1765        output.append(1)
1766        output.append(2)
1767
1768    # Test each kind of 'except' line.
1769    @jump_test(2, 3, [4], (ValueError, 'except'))
1770    def test_no_jump_to_except_1(output):
1771        try:
1772            output.append(2)
1773        except:
1774            output.append(4)
1775            raise
1776
1777    @jump_test(2, 3, [4], (ValueError, 'except'))
1778    def test_no_jump_to_except_2(output):
1779        try:
1780            output.append(2)
1781        except ValueError:
1782            output.append(4)
1783            raise
1784
1785    @jump_test(2, 3, [4], (ValueError, 'except'))
1786    def test_no_jump_to_except_3(output):
1787        try:
1788            output.append(2)
1789        except ValueError as e:
1790            output.append(4)
1791            raise e
1792
1793    @jump_test(2, 3, [4], (ValueError, 'except'))
1794    def test_no_jump_to_except_4(output):
1795        try:
1796            output.append(2)
1797        except (ValueError, RuntimeError) as e:
1798            output.append(4)
1799            raise e
1800
1801    @jump_test(1, 3, [], (ValueError, 'into'))
1802    def test_no_jump_forwards_into_for_block(output):
1803        output.append(1)
1804        for i in 1, 2:
1805            output.append(3)
1806
1807    @async_jump_test(1, 3, [], (ValueError, 'into'))
1808    async def test_no_jump_forwards_into_async_for_block(output):
1809        output.append(1)
1810        async for i in asynciter([1, 2]):
1811            output.append(3)
1812        pass
1813
1814    @jump_test(3, 2, [2, 2], (ValueError, 'into'))
1815    def test_no_jump_backwards_into_for_block(output):
1816        for i in 1, 2:
1817            output.append(2)
1818        output.append(3)
1819
1820    @async_jump_test(3, 2, [2, 2], (ValueError, 'into'))
1821    async def test_no_jump_backwards_into_async_for_block(output):
1822        async for i in asynciter([1, 2]):
1823            output.append(2)
1824        output.append(3)
1825
1826    @jump_test(1, 3, [], (ValueError, 'into'))
1827    def test_no_jump_forwards_into_with_block(output):
1828        output.append(1)
1829        with tracecontext(output, 2):
1830            output.append(3)
1831
1832    @async_jump_test(1, 3, [], (ValueError, 'into'))
1833    async def test_no_jump_forwards_into_async_with_block(output):
1834        output.append(1)
1835        async with asynctracecontext(output, 2):
1836            output.append(3)
1837
1838    @jump_test(3, 2, [1, 2, -1], (ValueError, 'into'))
1839    def test_no_jump_backwards_into_with_block(output):
1840        with tracecontext(output, 1):
1841            output.append(2)
1842        output.append(3)
1843
1844    @async_jump_test(3, 2, [1, 2, -1], (ValueError, 'into'))
1845    async def test_no_jump_backwards_into_async_with_block(output):
1846        async with asynctracecontext(output, 1):
1847            output.append(2)
1848        output.append(3)
1849
1850    @jump_test(1, 3, [], (ValueError, 'into'))
1851    def test_no_jump_forwards_into_try_finally_block(output):
1852        output.append(1)
1853        try:
1854            output.append(3)
1855        finally:
1856            output.append(5)
1857
1858    @jump_test(5, 2, [2, 4], (ValueError, 'into'))
1859    def test_no_jump_backwards_into_try_finally_block(output):
1860        try:
1861            output.append(2)
1862        finally:
1863            output.append(4)
1864        output.append(5)
1865
1866    @jump_test(1, 3, [], (ValueError, 'into'))
1867    def test_no_jump_forwards_into_try_except_block(output):
1868        output.append(1)
1869        try:
1870            output.append(3)
1871        except:
1872            output.append(5)
1873            raise
1874
1875    @jump_test(6, 2, [2], (ValueError, 'into'))
1876    def test_no_jump_backwards_into_try_except_block(output):
1877        try:
1878            output.append(2)
1879        except:
1880            output.append(4)
1881            raise
1882        output.append(6)
1883
1884    # 'except' with a variable creates an implicit finally block
1885    @jump_test(5, 7, [4], (ValueError, 'into'))
1886    def test_no_jump_between_except_blocks_2(output):
1887        try:
1888            1/0
1889        except ZeroDivisionError:
1890            output.append(4)
1891            output.append(5)
1892        except FloatingPointError as e:
1893            output.append(7)
1894        output.append(8)
1895
1896    @jump_test(1, 5, [5])
1897    def test_jump_into_finally_block(output):
1898        output.append(1)
1899        try:
1900            output.append(3)
1901        finally:
1902            output.append(5)
1903
1904    @jump_test(3, 6, [2, 6, 7])
1905    def test_jump_into_finally_block_from_try_block(output):
1906        try:
1907            output.append(2)
1908            output.append(3)
1909        finally:  # still executed if the jump is failed
1910            output.append(5)
1911            output.append(6)
1912        output.append(7)
1913
1914    @jump_test(5, 1, [1, 3, 1, 3, 5])
1915    def test_jump_out_of_finally_block(output):
1916        output.append(1)
1917        try:
1918            output.append(3)
1919        finally:
1920            output.append(5)
1921
1922    @jump_test(1, 5, [], (ValueError, "into an 'except'"))
1923    def test_no_jump_into_bare_except_block(output):
1924        output.append(1)
1925        try:
1926            output.append(3)
1927        except:
1928            output.append(5)
1929
1930    @jump_test(1, 5, [], (ValueError, "into an 'except'"))
1931    def test_no_jump_into_qualified_except_block(output):
1932        output.append(1)
1933        try:
1934            output.append(3)
1935        except Exception:
1936            output.append(5)
1937
1938    @jump_test(3, 6, [2, 5, 6], (ValueError, "into an 'except'"))
1939    def test_no_jump_into_bare_except_block_from_try_block(output):
1940        try:
1941            output.append(2)
1942            output.append(3)
1943        except:  # executed if the jump is failed
1944            output.append(5)
1945            output.append(6)
1946            raise
1947        output.append(8)
1948
1949    @jump_test(3, 6, [2], (ValueError, "into an 'except'"))
1950    def test_no_jump_into_qualified_except_block_from_try_block(output):
1951        try:
1952            output.append(2)
1953            output.append(3)
1954        except ZeroDivisionError:
1955            output.append(5)
1956            output.append(6)
1957            raise
1958        output.append(8)
1959
1960    @jump_test(7, 1, [1, 3, 6], (ValueError, "out of an 'except'"))
1961    def test_no_jump_out_of_bare_except_block(output):
1962        output.append(1)
1963        try:
1964            output.append(3)
1965            1/0
1966        except:
1967            output.append(6)
1968            output.append(7)
1969
1970    @jump_test(7, 1, [1, 3, 6], (ValueError, "out of an 'except'"))
1971    def test_no_jump_out_of_qualified_except_block(output):
1972        output.append(1)
1973        try:
1974            output.append(3)
1975            1/0
1976        except Exception:
1977            output.append(6)
1978            output.append(7)
1979
1980    @jump_test(3, 5, [1, 2, 5, -2])
1981    def test_jump_between_with_blocks(output):
1982        output.append(1)
1983        with tracecontext(output, 2):
1984            output.append(3)
1985        with tracecontext(output, 4):
1986            output.append(5)
1987
1988    @async_jump_test(3, 5, [1, 2, 5, -2])
1989    async def test_jump_between_async_with_blocks(output):
1990        output.append(1)
1991        async with asynctracecontext(output, 2):
1992            output.append(3)
1993        async with asynctracecontext(output, 4):
1994            output.append(5)
1995
1996    @jump_test(5, 7, [2, 4], (ValueError, "after"))
1997    def test_no_jump_over_return_out_of_finally_block(output):
1998        try:
1999            output.append(2)
2000        finally:
2001            output.append(4)
2002            output.append(5)
2003            return
2004        output.append(7)
2005
2006    @jump_test(7, 4, [1, 6], (ValueError, 'into'))
2007    def test_no_jump_into_for_block_before_else(output):
2008        output.append(1)
2009        if not output:  # always false
2010            for i in [3]:
2011                output.append(4)
2012        else:
2013            output.append(6)
2014            output.append(7)
2015        output.append(8)
2016
2017    @async_jump_test(7, 4, [1, 6], (ValueError, 'into'))
2018    async def test_no_jump_into_async_for_block_before_else(output):
2019        output.append(1)
2020        if not output:  # always false
2021            async for i in asynciter([3]):
2022                output.append(4)
2023        else:
2024            output.append(6)
2025            output.append(7)
2026        output.append(8)
2027
2028    def test_no_jump_to_non_integers(self):
2029        self.run_test(no_jump_to_non_integers, 2, "Spam", [True])
2030
2031    def test_no_jump_without_trace_function(self):
2032        # Must set sys.settrace(None) in setUp(), else condition is not
2033        # triggered.
2034        no_jump_without_trace_function()
2035
2036    def test_large_function(self):
2037        d = {}
2038        exec("""def f(output):        # line 0
2039            x = 0                     # line 1
2040            y = 1                     # line 2
2041            '''                       # line 3
2042            %s                        # lines 4-1004
2043            '''                       # line 1005
2044            x += 1                    # line 1006
2045            output.append(x)          # line 1007
2046            return""" % ('\n' * 1000,), d)
2047        f = d['f']
2048        self.run_test(f, 2, 1007, [0])
2049
2050    def test_jump_to_firstlineno(self):
2051        # This tests that PDB can jump back to the first line in a
2052        # file.  See issue #1689458.  It can only be triggered in a
2053        # function call if the function is defined on a single line.
2054        code = compile("""
2055# Comments don't count.
2056output.append(2)  # firstlineno is here.
2057output.append(3)
2058output.append(4)
2059""", "<fake module>", "exec")
2060        class fake_function:
2061            __code__ = code
2062        tracer = JumpTracer(fake_function, 4, 1)
2063        sys.settrace(tracer.trace)
2064        namespace = {"output": []}
2065        exec(code, namespace)
2066        sys.settrace(None)
2067        self.compare_jump_output([2, 3, 2, 3, 4], namespace["output"])
2068
2069    @jump_test(2, 3, [1], event='call', error=(ValueError, "can't jump from"
2070               " the 'call' trace event of a new frame"))
2071    def test_no_jump_from_call(output):
2072        output.append(1)
2073        def nested():
2074            output.append(3)
2075        nested()
2076        output.append(5)
2077
2078    @jump_test(2, 1, [1], event='return', error=(ValueError,
2079               "can only jump from a 'line' trace event"))
2080    def test_no_jump_from_return_event(output):
2081        output.append(1)
2082        return
2083
2084    @jump_test(2, 1, [1], event='exception', error=(ValueError,
2085               "can only jump from a 'line' trace event"))
2086    def test_no_jump_from_exception_event(output):
2087        output.append(1)
2088        1 / 0
2089
2090    @jump_test(3, 2, [2, 5], event='return')
2091    def test_jump_from_yield(output):
2092        def gen():
2093            output.append(2)
2094            yield 3
2095        next(gen())
2096        output.append(5)
2097
2098
2099if __name__ == "__main__":
2100    unittest.main()
2101