python (3.12.0)

(root)/
lib/
python3.12/
test/
test_sys_settrace.py
       1  # Testing the line trace facility.
       2  
       3  from test import support
       4  import unittest
       5  import sys
       6  import difflib
       7  import gc
       8  from functools import wraps
       9  import asyncio
      10  from test.support import import_helper
      11  import contextlib
      12  
      13  support.requires_working_socket(module=True)
      14  
      15  class ESC[4;38;5;81mtracecontext:
      16      """Context manager that traces its enter and exit."""
      17      def __init__(self, output, value):
      18          self.output = output
      19          self.value = value
      20  
      21      def __enter__(self):
      22          self.output.append(self.value)
      23  
      24      def __exit__(self, *exc_info):
      25          self.output.append(-self.value)
      26  
      27  class ESC[4;38;5;81masynctracecontext:
      28      """Asynchronous context manager that traces its aenter and aexit."""
      29      def __init__(self, output, value):
      30          self.output = output
      31          self.value = value
      32  
      33      async def __aenter__(self):
      34          self.output.append(self.value)
      35  
      36      async def __aexit__(self, *exc_info):
      37          self.output.append(-self.value)
      38  
      39  async def asynciter(iterable):
      40      """Convert an iterable to an asynchronous iterator."""
      41      for x in iterable:
      42          yield x
      43  
      44  def clean_asynciter(test):
      45      @wraps(test)
      46      async def wrapper(*args, **kwargs):
      47          cleanups = []
      48          def wrapped_asynciter(iterable):
      49              it = asynciter(iterable)
      50              cleanups.append(it.aclose)
      51              return it
      52          try:
      53              return await test(*args, **kwargs, asynciter=wrapped_asynciter)
      54          finally:
      55              while cleanups:
      56                  await cleanups.pop()()
      57      return wrapper
      58  
      59  # A very basic example.  If this fails, we're in deep trouble.
      60  def basic():
      61      return 1
      62  
      63  basic.events = [(0, 'call'),
      64                  (1, 'line'),
      65                  (1, 'return')]
      66  
      67  # Many of the tests below are tricky because they involve pass statements.
      68  # If there is implicit control flow around a pass statement (in an except
      69  # clause or else clause) under what conditions do you set a line number
      70  # following that clause?
      71  
      72  
      73  # Some constructs like "while 0:", "if 0:" or "if 1:...else:..." could be optimized
      74  # away.  Make sure that those lines aren't skipped.
      75  def arigo_example0():
      76      x = 1
      77      del x
      78      while 0:
      79          pass
      80      x = 1
      81  
      82  arigo_example0.events = [(0, 'call'),
      83                          (1, 'line'),
      84                          (2, 'line'),
      85                          (3, 'line'),
      86                          (5, 'line'),
      87                          (5, 'return')]
      88  
      89  def arigo_example1():
      90      x = 1
      91      del x
      92      if 0:
      93          pass
      94      x = 1
      95  
      96  arigo_example1.events = [(0, 'call'),
      97                          (1, 'line'),
      98                          (2, 'line'),
      99                          (3, 'line'),
     100                          (5, 'line'),
     101                          (5, 'return')]
     102  
     103  def arigo_example2():
     104      x = 1
     105      del x
     106      if 1:
     107          x = 1
     108      else:
     109          pass
     110      return None
     111  
     112  arigo_example2.events = [(0, 'call'),
     113                          (1, 'line'),
     114                          (2, 'line'),
     115                          (3, 'line'),
     116                          (4, 'line'),
     117                          (7, 'line'),
     118                          (7, 'return')]
     119  
     120  
     121  # check that lines consisting of just one instruction get traced:
     122  def one_instr_line():
     123      x = 1
     124      del x
     125      x = 1
     126  
     127  one_instr_line.events = [(0, 'call'),
     128                           (1, 'line'),
     129                           (2, 'line'),
     130                           (3, 'line'),
     131                           (3, 'return')]
     132  
     133  def no_pop_tops():      # 0
     134      x = 1               # 1
     135      for a in range(2):  # 2
     136          if a:           # 3
     137              x = 1       # 4
     138          else:           # 5
     139              x = 1       # 6
     140  
     141  no_pop_tops.events = [(0, 'call'),
     142                        (1, 'line'),
     143                        (2, 'line'),
     144                        (3, 'line'),
     145                        (6, 'line'),
     146                        (2, 'line'),
     147                        (3, 'line'),
     148                        (4, 'line'),
     149                        (2, 'line'),
     150                        (2, 'return')]
     151  
     152  def no_pop_blocks():
     153      y = 1
     154      while not y:
     155          bla
     156      x = 1
     157  
     158  no_pop_blocks.events = [(0, 'call'),
     159                          (1, 'line'),
     160                          (2, 'line'),
     161                          (4, 'line'),
     162                          (4, 'return')]
     163  
     164  def called(): # line -3
     165      x = 1
     166  
     167  def call():   # line 0
     168      called()
     169  
     170  call.events = [(0, 'call'),
     171                 (1, 'line'),
     172                 (-3, 'call'),
     173                 (-2, 'line'),
     174                 (-2, 'return'),
     175                 (1, 'return')]
     176  
     177  def raises():
     178      raise Exception
     179  
     180  def test_raise():
     181      try:
     182          raises()
     183      except Exception:
     184          pass
     185  
     186  test_raise.events = [(0, 'call'),
     187                       (1, 'line'),
     188                       (2, 'line'),
     189                       (-3, 'call'),
     190                       (-2, 'line'),
     191                       (-2, 'exception'),
     192                       (-2, 'return'),
     193                       (2, 'exception'),
     194                       (3, 'line'),
     195                       (4, 'line'),
     196                       (4, 'return')]
     197  
     198  def _settrace_and_return(tracefunc):
     199      sys.settrace(tracefunc)
     200      sys._getframe().f_back.f_trace = tracefunc
     201  def settrace_and_return(tracefunc):
     202      _settrace_and_return(tracefunc)
     203  
     204  settrace_and_return.events = [(1, 'return')]
     205  
     206  def _settrace_and_raise(tracefunc):
     207      sys.settrace(tracefunc)
     208      sys._getframe().f_back.f_trace = tracefunc
     209      raise RuntimeError
     210  def settrace_and_raise(tracefunc):
     211      try:
     212          _settrace_and_raise(tracefunc)
     213      except RuntimeError:
     214          pass
     215  
     216  settrace_and_raise.events = [(2, 'exception'),
     217                               (3, 'line'),
     218                               (4, 'line'),
     219                               (4, 'return')]
     220  
     221  # implicit return example
     222  # This test is interesting because of the else: pass
     223  # part of the code.  The code generate for the true
     224  # part of the if contains a jump past the else branch.
     225  # The compiler then generates an implicit "return None"
     226  # Internally, the compiler visits the pass statement
     227  # and stores its line number for use on the next instruction.
     228  # The next instruction is the implicit return None.
     229  def ireturn_example():
     230      a = 5
     231      b = 5
     232      if a == b:
     233          b = a+1
     234      else:
     235          pass
     236  
     237  ireturn_example.events = [(0, 'call'),
     238                            (1, 'line'),
     239                            (2, 'line'),
     240                            (3, 'line'),
     241                            (4, 'line'),
     242                            (4, 'return')]
     243  
     244  # Tight loop with while(1) example (SF #765624)
     245  def tightloop_example():
     246      items = range(0, 3)
     247      try:
     248          i = 0
     249          while 1:
     250              b = items[i]; i+=1
     251      except IndexError:
     252          pass
     253  
     254  tightloop_example.events = [(0, 'call'),
     255                              (1, 'line'),
     256                              (2, 'line'),
     257                              (3, 'line'),
     258                              (4, 'line'),
     259                              (5, 'line'),
     260                              (4, 'line'),
     261                              (5, 'line'),
     262                              (4, 'line'),
     263                              (5, 'line'),
     264                              (4, 'line'),
     265                              (5, 'line'),
     266                              (5, 'exception'),
     267                              (6, 'line'),
     268                              (7, 'line'),
     269                              (7, 'return')]
     270  
     271  def tighterloop_example():
     272      items = range(1, 4)
     273      try:
     274          i = 0
     275          while 1: i = items[i]
     276      except IndexError:
     277          pass
     278  
     279  tighterloop_example.events = [(0, 'call'),
     280                              (1, 'line'),
     281                              (2, 'line'),
     282                              (3, 'line'),
     283                              (4, 'line'),
     284                              (4, 'line'),
     285                              (4, 'line'),
     286                              (4, 'line'),
     287                              (4, 'exception'),
     288                              (5, 'line'),
     289                              (6, 'line'),
     290                              (6, 'return')]
     291  
     292  def generator_function():
     293      try:
     294          yield True
     295          "continued"
     296      finally:
     297          "finally"
     298  def generator_example():
     299      # any() will leave the generator before its end
     300      x = any(generator_function())
     301  
     302      # the following lines were not traced
     303      for x in range(10):
     304          y = x
     305  
     306  generator_example.events = ([(0, 'call'),
     307                               (2, 'line'),
     308                               (-6, 'call'),
     309                               (-5, 'line'),
     310                               (-4, 'line'),
     311                               (-4, 'return'),
     312                               (-4, 'call'),
     313                               (-4, 'exception'),
     314                               (-1, 'line'),
     315                               (-1, 'return')] +
     316                              [(5, 'line'), (6, 'line')] * 10 +
     317                              [(5, 'line'), (5, 'return')])
     318  
     319  
     320  class ESC[4;38;5;81mTracer:
     321      def __init__(self, trace_line_events=None, trace_opcode_events=None):
     322          self.trace_line_events = trace_line_events
     323          self.trace_opcode_events = trace_opcode_events
     324          self.events = []
     325  
     326      def _reconfigure_frame(self, frame):
     327          if self.trace_line_events is not None:
     328              frame.f_trace_lines = self.trace_line_events
     329          if self.trace_opcode_events is not None:
     330              frame.f_trace_opcodes = self.trace_opcode_events
     331  
     332      def trace(self, frame, event, arg):
     333          self._reconfigure_frame(frame)
     334          self.events.append((frame.f_lineno, event))
     335          return self.trace
     336  
     337      def traceWithGenexp(self, frame, event, arg):
     338          self._reconfigure_frame(frame)
     339          (o for o in [1])
     340          self.events.append((frame.f_lineno, event))
     341          return self.trace
     342  
     343  
     344  class ESC[4;38;5;81mTraceTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     345  
     346      # Disable gc collection when tracing, otherwise the
     347      # deallocators may be traced as well.
     348      def setUp(self):
     349          self.using_gc = gc.isenabled()
     350          gc.disable()
     351          self.addCleanup(sys.settrace, sys.gettrace())
     352  
     353      def tearDown(self):
     354          if self.using_gc:
     355              gc.enable()
     356  
     357      @staticmethod
     358      def make_tracer():
     359          """Helper to allow test subclasses to configure tracers differently"""
     360          return Tracer()
     361  
     362      def compare_events(self, line_offset, events, expected_events):
     363          events = [(l - line_offset if l is not None else None, e) for (l, e) in events]
     364          if events != expected_events:
     365              self.fail(
     366                  "events did not match expectation:\n" +
     367                  "\n".join(difflib.ndiff([str(x) for x in expected_events],
     368                                          [str(x) for x in events])))
     369  
     370      def run_and_compare(self, func, events):
     371          tracer = self.make_tracer()
     372          sys.settrace(tracer.trace)
     373          func()
     374          sys.settrace(None)
     375          self.compare_events(func.__code__.co_firstlineno,
     376                              tracer.events, events)
     377  
     378      def run_test(self, func):
     379          self.run_and_compare(func, func.events)
     380  
     381      def run_test2(self, func):
     382          tracer = self.make_tracer()
     383          func(tracer.trace)
     384          sys.settrace(None)
     385          self.compare_events(func.__code__.co_firstlineno,
     386                              tracer.events, func.events)
     387  
     388      def test_set_and_retrieve_none(self):
     389          sys.settrace(None)
     390          assert sys.gettrace() is None
     391  
     392      def test_set_and_retrieve_func(self):
     393          def fn(*args):
     394              pass
     395  
     396          sys.settrace(fn)
     397          try:
     398              assert sys.gettrace() is fn
     399          finally:
     400              sys.settrace(None)
     401  
     402      def test_01_basic(self):
     403          self.run_test(basic)
     404      def test_02_arigo0(self):
     405          self.run_test(arigo_example0)
     406      def test_02_arigo1(self):
     407          self.run_test(arigo_example1)
     408      def test_02_arigo2(self):
     409          self.run_test(arigo_example2)
     410      def test_03_one_instr(self):
     411          self.run_test(one_instr_line)
     412      def test_04_no_pop_blocks(self):
     413          self.run_test(no_pop_blocks)
     414      def test_05_no_pop_tops(self):
     415          self.run_test(no_pop_tops)
     416      def test_06_call(self):
     417          self.run_test(call)
     418      def test_07_raise(self):
     419          self.run_test(test_raise)
     420  
     421      def test_08_settrace_and_return(self):
     422          self.run_test2(settrace_and_return)
     423      def test_09_settrace_and_raise(self):
     424          self.run_test2(settrace_and_raise)
     425      def test_10_ireturn(self):
     426          self.run_test(ireturn_example)
     427      def test_11_tightloop(self):
     428          self.run_test(tightloop_example)
     429      def test_12_tighterloop(self):
     430          self.run_test(tighterloop_example)
     431  
     432      def test_13_genexp(self):
     433          self.run_test(generator_example)
     434          # issue1265: if the trace function contains a generator,
     435          # and if the traced function contains another generator
     436          # that is not completely exhausted, the trace stopped.
     437          # Worse: the 'finally' clause was not invoked.
     438          tracer = self.make_tracer()
     439          sys.settrace(tracer.traceWithGenexp)
     440          generator_example()
     441          sys.settrace(None)
     442          self.compare_events(generator_example.__code__.co_firstlineno,
     443                              tracer.events, generator_example.events)
     444  
     445      def test_14_onliner_if(self):
     446          def onliners():
     447              if True: x=False
     448              else: x=True
     449              return 0
     450          self.run_and_compare(
     451              onliners,
     452              [(0, 'call'),
     453               (1, 'line'),
     454               (3, 'line'),
     455               (3, 'return')])
     456  
     457      def test_15_loops(self):
     458          # issue1750076: "while" expression is skipped by debugger
     459          def for_example():
     460              for x in range(2):
     461                  pass
     462          self.run_and_compare(
     463              for_example,
     464              [(0, 'call'),
     465               (1, 'line'),
     466               (2, 'line'),
     467               (1, 'line'),
     468               (2, 'line'),
     469               (1, 'line'),
     470               (1, 'return')])
     471  
     472          def while_example():
     473              # While expression should be traced on every loop
     474              x = 2
     475              while x > 0:
     476                  x -= 1
     477          self.run_and_compare(
     478              while_example,
     479              [(0, 'call'),
     480               (2, 'line'),
     481               (3, 'line'),
     482               (4, 'line'),
     483               (3, 'line'),
     484               (4, 'line'),
     485               (3, 'line'),
     486               (3, 'return')])
     487  
     488      def test_16_blank_lines(self):
     489          namespace = {}
     490          exec("def f():\n" + "\n" * 256 + "    pass", namespace)
     491          self.run_and_compare(
     492              namespace["f"],
     493              [(0, 'call'),
     494               (257, 'line'),
     495               (257, 'return')])
     496  
     497      def test_17_none_f_trace(self):
     498          # Issue 20041: fix TypeError when f_trace is set to None.
     499          def func():
     500              sys._getframe().f_trace = None
     501              lineno = 2
     502          self.run_and_compare(func,
     503              [(0, 'call'),
     504               (1, 'line')])
     505  
     506      def test_18_except_with_name(self):
     507          def func():
     508              try:
     509                  try:
     510                      raise Exception
     511                  except Exception as e:
     512                      raise
     513                      x = "Something"
     514                      y = "Something"
     515              except Exception:
     516                  pass
     517  
     518          self.run_and_compare(func,
     519              [(0, 'call'),
     520               (1, 'line'),
     521               (2, 'line'),
     522               (3, 'line'),
     523               (3, 'exception'),
     524               (4, 'line'),
     525               (5, 'line'),
     526               (8, 'line'),
     527               (9, 'line'),
     528               (9, 'return')])
     529  
     530      def test_19_except_with_finally(self):
     531          def func():
     532              try:
     533                  try:
     534                      raise Exception
     535                  finally:
     536                      y = "Something"
     537              except Exception:
     538                  b = 23
     539  
     540          self.run_and_compare(func,
     541              [(0, 'call'),
     542               (1, 'line'),
     543               (2, 'line'),
     544               (3, 'line'),
     545               (3, 'exception'),
     546               (5, 'line'),
     547               (6, 'line'),
     548               (7, 'line'),
     549               (7, 'return')])
     550  
     551      def test_20_async_for_loop(self):
     552          class ESC[4;38;5;81mAsyncIteratorWrapper:
     553              def __init__(self, obj):
     554                  self._it = iter(obj)
     555  
     556              def __aiter__(self):
     557                  return self
     558  
     559              async def __anext__(self):
     560                  try:
     561                      return next(self._it)
     562                  except StopIteration:
     563                      raise StopAsyncIteration
     564  
     565          async def doit_async():
     566              async for letter in AsyncIteratorWrapper("abc"):
     567                  x = letter
     568              y = 42
     569  
     570          def run(tracer):
     571              x = doit_async()
     572              try:
     573                  sys.settrace(tracer)
     574                  x.send(None)
     575              finally:
     576                  sys.settrace(None)
     577  
     578          tracer = self.make_tracer()
     579          events = [
     580                  (0, 'call'),
     581                  (1, 'line'),
     582                  (-12, 'call'),
     583                  (-11, 'line'),
     584                  (-11, 'return'),
     585                  (-9, 'call'),
     586                  (-8, 'line'),
     587                  (-8, 'return'),
     588                  (-6, 'call'),
     589                  (-5, 'line'),
     590                  (-4, 'line'),
     591                  (-4, 'return'),
     592                  (1, 'exception'),
     593                  (2, 'line'),
     594                  (1, 'line'),
     595                  (-6, 'call'),
     596                  (-5, 'line'),
     597                  (-4, 'line'),
     598                  (-4, 'return'),
     599                  (1, 'exception'),
     600                  (2, 'line'),
     601                  (1, 'line'),
     602                  (-6, 'call'),
     603                  (-5, 'line'),
     604                  (-4, 'line'),
     605                  (-4, 'return'),
     606                  (1, 'exception'),
     607                  (2, 'line'),
     608                  (1, 'line'),
     609                  (-6, 'call'),
     610                  (-5, 'line'),
     611                  (-4, 'line'),
     612                  (-4, 'exception'),
     613                  (-3, 'line'),
     614                  (-2, 'line'),
     615                  (-2, 'exception'),
     616                  (-2, 'return'),
     617                  (1, 'exception'),
     618                  (3, 'line'),
     619                  (3, 'return')]
     620          try:
     621              run(tracer.trace)
     622          except Exception:
     623              pass
     624          self.compare_events(doit_async.__code__.co_firstlineno,
     625                              tracer.events, events)
     626  
     627      def test_async_for_backwards_jump_has_no_line(self):
     628          async def arange(n):
     629              for i in range(n):
     630                  yield i
     631          async def f():
     632              async for i in arange(3):
     633                  if i > 100:
     634                      break # should never be traced
     635  
     636          tracer = self.make_tracer()
     637          coro = f()
     638          try:
     639              sys.settrace(tracer.trace)
     640              coro.send(None)
     641          except Exception:
     642              pass
     643          finally:
     644              sys.settrace(None)
     645  
     646          events = [
     647              (0, 'call'),
     648              (1, 'line'),
     649              (-3, 'call'),
     650              (-2, 'line'),
     651              (-1, 'line'),
     652              (-1, 'return'),
     653              (1, 'exception'),
     654              (2, 'line'),
     655              (1, 'line'),
     656              (-1, 'call'),
     657              (-2, 'line'),
     658              (-1, 'line'),
     659              (-1, 'return'),
     660              (1, 'exception'),
     661              (2, 'line'),
     662              (1, 'line'),
     663              (-1, 'call'),
     664              (-2, 'line'),
     665              (-1, 'line'),
     666              (-1, 'return'),
     667              (1, 'exception'),
     668              (2, 'line'),
     669              (1, 'line'),
     670              (-1, 'call'),
     671              (-2, 'line'),
     672              (-2, 'return'),
     673              (1, 'exception'),
     674              (1, 'return'),
     675          ]
     676          self.compare_events(f.__code__.co_firstlineno,
     677                              tracer.events, events)
     678  
     679      def test_21_repeated_pass(self):
     680          def func():
     681              pass
     682              pass
     683  
     684          self.run_and_compare(func,
     685              [(0, 'call'),
     686               (1, 'line'),
     687               (2, 'line'),
     688               (2, 'return')])
     689  
     690      def test_loop_in_try_except(self):
     691          # https://bugs.python.org/issue41670
     692  
     693          def func():
     694              try:
     695                  for i in []: pass
     696                  return 1
     697              except:
     698                  return 2
     699  
     700          self.run_and_compare(func,
     701              [(0, 'call'),
     702               (1, 'line'),
     703               (2, 'line'),
     704               (3, 'line'),
     705               (3, 'return')])
     706  
     707      def test_try_except_no_exception(self):
     708  
     709          def func():
     710              try:
     711                  2
     712              except:
     713                  4
     714              else:
     715                  6
     716                  if False:
     717                      8
     718                  else:
     719                      10
     720                  if func.__name__ == 'Fred':
     721                      12
     722              finally:
     723                  14
     724  
     725          self.run_and_compare(func,
     726              [(0, 'call'),
     727               (1, 'line'),
     728               (2, 'line'),
     729               (6, 'line'),
     730               (7, 'line'),
     731               (10, 'line'),
     732               (11, 'line'),
     733               (14, 'line'),
     734               (14, 'return')])
     735  
     736      def test_try_exception_in_else(self):
     737  
     738          def func():
     739              try:
     740                  try:
     741                      3
     742                  except:
     743                      5
     744                  else:
     745                      7
     746                      raise Exception
     747                  finally:
     748                      10
     749              except:
     750                  12
     751              finally:
     752                  14
     753  
     754          self.run_and_compare(func,
     755              [(0, 'call'),
     756               (1, 'line'),
     757               (2, 'line'),
     758               (3, 'line'),
     759               (7, 'line'),
     760               (8, 'line'),
     761               (8, 'exception'),
     762               (10, 'line'),
     763               (11, 'line'),
     764               (12, 'line'),
     765               (14, 'line'),
     766               (14, 'return')])
     767  
     768      def test_nested_loops(self):
     769  
     770          def func():
     771              for i in range(2):
     772                  for j in range(2):
     773                      a = i + j
     774              return a == 1
     775  
     776          self.run_and_compare(func,
     777              [(0, 'call'),
     778               (1, 'line'),
     779               (2, 'line'),
     780               (3, 'line'),
     781               (2, 'line'),
     782               (3, 'line'),
     783               (2, 'line'),
     784               (1, 'line'),
     785               (2, 'line'),
     786               (3, 'line'),
     787               (2, 'line'),
     788               (3, 'line'),
     789               (2, 'line'),
     790               (1, 'line'),
     791               (4, 'line'),
     792               (4, 'return')])
     793  
     794      def test_if_break(self):
     795  
     796          def func():
     797              seq = [1, 0]
     798              while seq:
     799                  n = seq.pop()
     800                  if n:
     801                      break   # line 5
     802              else:
     803                  n = 99
     804              return n        # line 8
     805  
     806          self.run_and_compare(func,
     807              [(0, 'call'),
     808               (1, 'line'),
     809               (2, 'line'),
     810               (3, 'line'),
     811               (4, 'line'),
     812               (2, 'line'),
     813               (3, 'line'),
     814               (4, 'line'),
     815               (5, 'line'),
     816               (8, 'line'),
     817               (8, 'return')])
     818  
     819      def test_break_through_finally(self):
     820  
     821          def func():
     822              a, c, d, i = 1, 1, 1, 99
     823              try:
     824                  for i in range(3):
     825                      try:
     826                          a = 5
     827                          if i > 0:
     828                              break                   # line 7
     829                          a = 8
     830                      finally:
     831                          c = 10
     832              except:
     833                  d = 12                              # line 12
     834              assert a == 5 and c == 10 and d == 1    # line 13
     835  
     836          self.run_and_compare(func,
     837              [(0, 'call'),
     838               (1, 'line'),
     839               (2, 'line'),
     840               (3, 'line'),
     841               (4, 'line'),
     842               (5, 'line'),
     843               (6, 'line'),
     844               (8, 'line'),
     845               (10, 'line'),
     846               (3, 'line'),
     847               (4, 'line'),
     848               (5, 'line'),
     849               (6, 'line'),
     850               (7, 'line'),
     851               (10, 'line')] +
     852               ([(13, 'line'), (13, 'return')] if __debug__ else [(10, 'return')]))
     853  
     854      def test_continue_through_finally(self):
     855  
     856          def func():
     857              a, b, c, d, i = 1, 1, 1, 1, 99
     858              try:
     859                  for i in range(2):
     860                      try:
     861                          a = 5
     862                          if i > 0:
     863                              continue                # line 7
     864                          b = 8
     865                      finally:
     866                          c = 10
     867              except:
     868                  d = 12                              # line 12
     869              assert (a, b, c, d) == (5, 8, 10, 1)    # line 13
     870  
     871          self.run_and_compare(func,
     872              [(0, 'call'),
     873               (1, 'line'),
     874               (2, 'line'),
     875               (3, 'line'),
     876               (4, 'line'),
     877               (5, 'line'),
     878               (6, 'line'),
     879               (8, 'line'),
     880               (10, 'line'),
     881               (3, 'line'),
     882               (4, 'line'),
     883               (5, 'line'),
     884               (6, 'line'),
     885               (7, 'line'),
     886               (10, 'line'),
     887               (3, 'line')] +
     888               ([(13, 'line'), (13, 'return')] if __debug__ else [(3, 'return')]))
     889  
     890      def test_return_through_finally(self):
     891  
     892          def func():
     893              try:
     894                  return 2
     895              finally:
     896                  4
     897  
     898          self.run_and_compare(func,
     899              [(0, 'call'),
     900               (1, 'line'),
     901               (2, 'line'),
     902               (4, 'line'),
     903               (4, 'return')])
     904  
     905      def test_try_except_with_wrong_type(self):
     906  
     907          def func():
     908              try:
     909                  2/0
     910              except IndexError:
     911                  4
     912              finally:
     913                  return 6
     914  
     915          self.run_and_compare(func,
     916              [(0, 'call'),
     917               (1, 'line'),
     918               (2, 'line'),
     919               (2, 'exception'),
     920               (3, 'line'),
     921               (6, 'line'),
     922               (6, 'return')])
     923  
     924      def test_finally_with_conditional(self):
     925  
     926          # See gh-105658
     927          condition = True
     928          def func():
     929              try:
     930                  try:
     931                      raise Exception
     932                  finally:
     933                      if condition:
     934                          result = 1
     935                  result = 2
     936              except:
     937                  result = 3
     938              return result
     939  
     940          self.run_and_compare(func,
     941              [(0, 'call'),
     942               (1, 'line'),
     943               (2, 'line'),
     944               (3, 'line'),
     945               (3, 'exception'),
     946               (5, 'line'),
     947               (6, 'line'),
     948               (8, 'line'),
     949               (9, 'line'),
     950               (10, 'line'),
     951               (10, 'return')])
     952  
     953      def test_break_to_continue1(self):
     954  
     955          def func():
     956              TRUE = 1
     957              x = [1]
     958              while x:
     959                  x.pop()
     960                  while TRUE:
     961                      break
     962                  continue
     963  
     964          self.run_and_compare(func,
     965              [(0, 'call'),
     966               (1, 'line'),
     967               (2, 'line'),
     968               (3, 'line'),
     969               (4, 'line'),
     970               (5, 'line'),
     971               (6, 'line'),
     972               (7, 'line'),
     973               (3, 'line'),
     974               (3, 'return')])
     975  
     976      def test_break_to_continue2(self):
     977  
     978          def func():
     979              TRUE = 1
     980              x = [1]
     981              while x:
     982                  x.pop()
     983                  while TRUE:
     984                      break
     985                  else:
     986                      continue
     987  
     988          self.run_and_compare(func,
     989              [(0, 'call'),
     990               (1, 'line'),
     991               (2, 'line'),
     992               (3, 'line'),
     993               (4, 'line'),
     994               (5, 'line'),
     995               (6, 'line'),
     996               (3, 'line'),
     997               (3, 'return')])
     998  
     999      def test_break_to_break(self):
    1000  
    1001          def func():
    1002              TRUE = 1
    1003              while TRUE:
    1004                  while TRUE:
    1005                      break
    1006                  break
    1007  
    1008          self.run_and_compare(func,
    1009              [(0, 'call'),
    1010               (1, 'line'),
    1011               (2, 'line'),
    1012               (3, 'line'),
    1013               (4, 'line'),
    1014               (5, 'line'),
    1015               (5, 'return')])
    1016  
    1017      def test_nested_ifs(self):
    1018  
    1019          def func():
    1020              a = b = 1
    1021              if a == 1:
    1022                  if b == 1:
    1023                      x = 4
    1024                  else:
    1025                      y = 6
    1026              else:
    1027                  z = 8
    1028  
    1029          self.run_and_compare(func,
    1030              [(0, 'call'),
    1031               (1, 'line'),
    1032               (2, 'line'),
    1033               (3, 'line'),
    1034               (4, 'line'),
    1035               (4, 'return')])
    1036  
    1037      def test_nested_ifs_with_and(self):
    1038  
    1039          def func():
    1040              if A:
    1041                  if B:
    1042                      if C:
    1043                          if D:
    1044                              return False
    1045                  else:
    1046                      return False
    1047              elif E and F:
    1048                  return True
    1049  
    1050          A = B = True
    1051          C = False
    1052  
    1053          self.run_and_compare(func,
    1054              [(0, 'call'),
    1055               (1, 'line'),
    1056               (2, 'line'),
    1057               (3, 'line'),
    1058               (3, 'return')])
    1059  
    1060      def test_nested_try_if(self):
    1061  
    1062          def func():
    1063              x = "hello"
    1064              try:
    1065                  3/0
    1066              except ZeroDivisionError:
    1067                  if x == 'raise':
    1068                      raise ValueError()   # line 6
    1069              f = 7
    1070  
    1071          self.run_and_compare(func,
    1072              [(0, 'call'),
    1073               (1, 'line'),
    1074               (2, 'line'),
    1075               (3, 'line'),
    1076               (3, 'exception'),
    1077               (4, 'line'),
    1078               (5, 'line'),
    1079               (7, 'line'),
    1080               (7, 'return')])
    1081  
    1082      def test_if_false_in_with(self):
    1083  
    1084          class ESC[4;38;5;81mC:
    1085              def __enter__(self):
    1086                  return self
    1087              def __exit__(*args):
    1088                  pass
    1089  
    1090          def func():
    1091              with C():
    1092                  if False:
    1093                      pass
    1094  
    1095          self.run_and_compare(func,
    1096              [(0, 'call'),
    1097               (1, 'line'),
    1098               (-5, 'call'),
    1099               (-4, 'line'),
    1100               (-4, 'return'),
    1101               (2, 'line'),
    1102               (1, 'line'),
    1103               (-3, 'call'),
    1104               (-2, 'line'),
    1105               (-2, 'return'),
    1106               (1, 'return')])
    1107  
    1108      def test_if_false_in_try_except(self):
    1109  
    1110          def func():
    1111              try:
    1112                  if False:
    1113                      pass
    1114              except Exception:
    1115                  X
    1116  
    1117          self.run_and_compare(func,
    1118              [(0, 'call'),
    1119               (1, 'line'),
    1120               (2, 'line'),
    1121               (2, 'return')])
    1122  
    1123      def test_implicit_return_in_class(self):
    1124  
    1125          def func():
    1126              class ESC[4;38;5;81mA:
    1127                  if 3 < 9:
    1128                      a = 1
    1129                  else:
    1130                      a = 2
    1131  
    1132          self.run_and_compare(func,
    1133              [(0, 'call'),
    1134               (1, 'line'),
    1135               (1, 'call'),
    1136               (1, 'line'),
    1137               (2, 'line'),
    1138               (3, 'line'),
    1139               (3, 'return'),
    1140               (1, 'return')])
    1141  
    1142      def test_try_in_try(self):
    1143          def func():
    1144              try:
    1145                  try:
    1146                      pass
    1147                  except Exception as ex:
    1148                      pass
    1149              except Exception:
    1150                  pass
    1151  
    1152          self.run_and_compare(func,
    1153              [(0, 'call'),
    1154               (1, 'line'),
    1155               (2, 'line'),
    1156               (3, 'line'),
    1157               (3, 'return')])
    1158  
    1159      def test_try_in_try_with_exception(self):
    1160  
    1161          def func():
    1162              try:
    1163                  try:
    1164                      raise TypeError
    1165                  except ValueError as ex:
    1166                      5
    1167              except TypeError:
    1168                  7
    1169  
    1170          self.run_and_compare(func,
    1171              [(0, 'call'),
    1172               (1, 'line'),
    1173               (2, 'line'),
    1174               (3, 'line'),
    1175               (3, 'exception'),
    1176               (4, 'line'),
    1177               (6, 'line'),
    1178               (7, 'line'),
    1179               (7, 'return')])
    1180  
    1181          def func():
    1182              try:
    1183                  try:
    1184                      raise ValueError
    1185                  except ValueError as ex:
    1186                      5
    1187              except TypeError:
    1188                  7
    1189  
    1190          self.run_and_compare(func,
    1191              [(0, 'call'),
    1192               (1, 'line'),
    1193               (2, 'line'),
    1194               (3, 'line'),
    1195               (3, 'exception'),
    1196               (4, 'line'),
    1197               (5, 'line'),
    1198               (5, 'return')])
    1199  
    1200      def test_if_in_if_in_if(self):
    1201          def func(a=0, p=1, z=1):
    1202              if p:
    1203                  if a:
    1204                      if z:
    1205                          pass
    1206                      else:
    1207                          pass
    1208              else:
    1209                  pass
    1210  
    1211          self.run_and_compare(func,
    1212              [(0, 'call'),
    1213               (1, 'line'),
    1214               (2, 'line'),
    1215               (2, 'return')])
    1216  
    1217      def test_early_exit_with(self):
    1218  
    1219          class ESC[4;38;5;81mC:
    1220              def __enter__(self):
    1221                  return self
    1222              def __exit__(*args):
    1223                  pass
    1224  
    1225          def func_break():
    1226              for i in (1,2):
    1227                  with C():
    1228                      break
    1229              pass
    1230  
    1231          def func_return():
    1232              with C():
    1233                  return
    1234  
    1235          self.run_and_compare(func_break,
    1236              [(0, 'call'),
    1237               (1, 'line'),
    1238               (2, 'line'),
    1239               (-5, 'call'),
    1240               (-4, 'line'),
    1241               (-4, 'return'),
    1242               (3, 'line'),
    1243               (2, 'line'),
    1244               (-3, 'call'),
    1245               (-2, 'line'),
    1246               (-2, 'return'),
    1247               (4, 'line'),
    1248               (4, 'return')])
    1249  
    1250          self.run_and_compare(func_return,
    1251              [(0, 'call'),
    1252               (1, 'line'),
    1253               (-11, 'call'),
    1254               (-10, 'line'),
    1255               (-10, 'return'),
    1256               (2, 'line'),
    1257               (1, 'line'),
    1258               (-9, 'call'),
    1259               (-8, 'line'),
    1260               (-8, 'return'),
    1261               (1, 'return')])
    1262  
    1263      def test_flow_converges_on_same_line(self):
    1264  
    1265          def foo(x):
    1266              if x:
    1267                  try:
    1268                      1/(x - 1)
    1269                  except ZeroDivisionError:
    1270                      pass
    1271              return x
    1272  
    1273          def func():
    1274              for i in range(2):
    1275                  foo(i)
    1276  
    1277          self.run_and_compare(func,
    1278              [(0, 'call'),
    1279               (1, 'line'),
    1280               (2, 'line'),
    1281               (-8, 'call'),
    1282               (-7, 'line'),
    1283               (-2, 'line'),
    1284               (-2, 'return'),
    1285               (1, 'line'),
    1286               (2, 'line'),
    1287               (-8, 'call'),
    1288               (-7, 'line'),
    1289               (-6, 'line'),
    1290               (-5, 'line'),
    1291               (-5, 'exception'),
    1292               (-4, 'line'),
    1293               (-3, 'line'),
    1294               (-2, 'line'),
    1295               (-2, 'return'),
    1296               (1, 'line'),
    1297               (1, 'return')])
    1298  
    1299      def test_no_tracing_of_named_except_cleanup(self):
    1300  
    1301          def func():
    1302              x = 0
    1303              try:
    1304                  1/x
    1305              except ZeroDivisionError as error:
    1306                  if x:
    1307                      raise
    1308              return "done"
    1309  
    1310          self.run_and_compare(func,
    1311          [(0, 'call'),
    1312              (1, 'line'),
    1313              (2, 'line'),
    1314              (3, 'line'),
    1315              (3, 'exception'),
    1316              (4, 'line'),
    1317              (5, 'line'),
    1318              (7, 'line'),
    1319              (7, 'return')])
    1320  
    1321      def test_tracing_exception_raised_in_with(self):
    1322  
    1323          class ESC[4;38;5;81mNullCtx:
    1324              def __enter__(self):
    1325                  return self
    1326              def __exit__(self, *excinfo):
    1327                  pass
    1328  
    1329          def func():
    1330              try:
    1331                  with NullCtx():
    1332                      1/0
    1333              except ZeroDivisionError:
    1334                  pass
    1335  
    1336          self.run_and_compare(func,
    1337              [(0, 'call'),
    1338               (1, 'line'),
    1339               (2, 'line'),
    1340               (-5, 'call'),
    1341               (-4, 'line'),
    1342               (-4, 'return'),
    1343               (3, 'line'),
    1344               (3, 'exception'),
    1345               (2, 'line'),
    1346               (-3, 'call'),
    1347               (-2, 'line'),
    1348               (-2, 'return'),
    1349               (4, 'line'),
    1350               (5, 'line'),
    1351               (5, 'return')])
    1352  
    1353      def test_try_except_star_no_exception(self):
    1354  
    1355          def func():
    1356              try:
    1357                  2
    1358              except* Exception:
    1359                  4
    1360              else:
    1361                  6
    1362                  if False:
    1363                      8
    1364                  else:
    1365                      10
    1366                  if func.__name__ == 'Fred':
    1367                      12
    1368              finally:
    1369                  14
    1370  
    1371          self.run_and_compare(func,
    1372              [(0, 'call'),
    1373               (1, 'line'),
    1374               (2, 'line'),
    1375               (6, 'line'),
    1376               (7, 'line'),
    1377               (10, 'line'),
    1378               (11, 'line'),
    1379               (14, 'line'),
    1380               (14, 'return')])
    1381  
    1382      def test_try_except_star_named_no_exception(self):
    1383  
    1384          def func():
    1385              try:
    1386                  2
    1387              except* Exception as e:
    1388                  4
    1389              else:
    1390                  6
    1391              finally:
    1392                  8
    1393  
    1394          self.run_and_compare(func,
    1395              [(0, 'call'),
    1396               (1, 'line'),
    1397               (2, 'line'),
    1398               (6, 'line'),
    1399               (8, 'line'),
    1400               (8, 'return')])
    1401  
    1402      def test_try_except_star_exception_caught(self):
    1403  
    1404          def func():
    1405              try:
    1406                  raise ValueError(2)
    1407              except* ValueError:
    1408                  4
    1409              else:
    1410                  6
    1411              finally:
    1412                  8
    1413  
    1414          self.run_and_compare(func,
    1415              [(0, 'call'),
    1416               (1, 'line'),
    1417               (2, 'line'),
    1418               (2, 'exception'),
    1419               (3, 'line'),
    1420               (4, 'line'),
    1421               (8, 'line'),
    1422               (8, 'return')])
    1423  
    1424      def test_try_except_star_named_exception_caught(self):
    1425  
    1426          def func():
    1427              try:
    1428                  raise ValueError(2)
    1429              except* ValueError as e:
    1430                  4
    1431              else:
    1432                  6
    1433              finally:
    1434                  8
    1435  
    1436          self.run_and_compare(func,
    1437              [(0, 'call'),
    1438               (1, 'line'),
    1439               (2, 'line'),
    1440               (2, 'exception'),
    1441               (3, 'line'),
    1442               (4, 'line'),
    1443               (8, 'line'),
    1444               (8, 'return')])
    1445  
    1446      def test_try_except_star_exception_not_caught(self):
    1447  
    1448          def func():
    1449              try:
    1450                  try:
    1451                      raise ValueError(3)
    1452                  except* TypeError:
    1453                      5
    1454              except ValueError:
    1455                  7
    1456  
    1457          self.run_and_compare(func,
    1458              [(0, 'call'),
    1459               (1, 'line'),
    1460               (2, 'line'),
    1461               (3, 'line'),
    1462               (3, 'exception'),
    1463               (4, 'line'),
    1464               (6, 'line'),
    1465               (7, 'line'),
    1466               (7, 'return')])
    1467  
    1468      def test_try_except_star_named_exception_not_caught(self):
    1469  
    1470          def func():
    1471              try:
    1472                  try:
    1473                      raise ValueError(3)
    1474                  except* TypeError as e:
    1475                      5
    1476              except ValueError:
    1477                  7
    1478  
    1479          self.run_and_compare(func,
    1480              [(0, 'call'),
    1481               (1, 'line'),
    1482               (2, 'line'),
    1483               (3, 'line'),
    1484               (3, 'exception'),
    1485               (4, 'line'),
    1486               (6, 'line'),
    1487               (7, 'line'),
    1488               (7, 'return')])
    1489  
    1490      def test_try_except_star_nested(self):
    1491  
    1492          def func():
    1493              try:
    1494                  try:
    1495                      raise ExceptionGroup(
    1496                          'eg',
    1497                          [ValueError(5), TypeError('bad type')])
    1498                  except* TypeError as e:
    1499                      7
    1500                  except* OSError:
    1501                      9
    1502                  except* ValueError:
    1503                      raise
    1504              except* ValueError:
    1505                  try:
    1506                      raise TypeError(14)
    1507                  except* OSError:
    1508                      16
    1509                  except* TypeError as e:
    1510                      18
    1511              return 0
    1512  
    1513          self.run_and_compare(func,
    1514              [(0, 'call'),
    1515               (1, 'line'),
    1516               (2, 'line'),
    1517               (3, 'line'),
    1518               (4, 'line'),
    1519               (5, 'line'),
    1520               (3, 'line'),
    1521               (3, 'exception'),
    1522               (6, 'line'),
    1523               (7, 'line'),
    1524               (8, 'line'),
    1525               (10, 'line'),
    1526               (11, 'line'),
    1527               (12, 'line'),
    1528               (13, 'line'),
    1529               (14, 'line'),
    1530               (14, 'exception'),
    1531               (15, 'line'),
    1532               (17, 'line'),
    1533               (18, 'line'),
    1534               (19, 'line'),
    1535               (19, 'return')])
    1536  
    1537      def test_notrace_lambda(self):
    1538          #Regression test for issue 46314
    1539  
    1540          def func():
    1541              1
    1542              lambda x: 2
    1543              3
    1544  
    1545          self.run_and_compare(func,
    1546              [(0, 'call'),
    1547               (1, 'line'),
    1548               (2, 'line'),
    1549               (3, 'line'),
    1550               (3, 'return')])
    1551  
    1552      def test_class_creation_with_docstrings(self):
    1553  
    1554          def func():
    1555              class ESC[4;38;5;81mClass_1:
    1556                  ''' the docstring. 2'''
    1557                  def __init__(self):
    1558                      ''' Another docstring. 4'''
    1559                      self.a = 5
    1560  
    1561          self.run_and_compare(func,
    1562              [(0, 'call'),
    1563               (1, 'line'),
    1564               (1, 'call'),
    1565               (1, 'line'),
    1566               (2, 'line'),
    1567               (3, 'line'),
    1568               (3, 'return'),
    1569               (1, 'return')])
    1570  
    1571      def test_class_creation_with_decorator(self):
    1572          def func():
    1573              def decorator(arg):
    1574                  def _dec(c):
    1575                      return c
    1576                  return _dec
    1577  
    1578              @decorator(6)
    1579              @decorator(
    1580                  len([8]),
    1581              )
    1582              class ESC[4;38;5;81mMyObject:
    1583                  pass
    1584  
    1585          self.run_and_compare(func, [
    1586              (0, 'call'),
    1587              (1, 'line'),
    1588              (6, 'line'),
    1589              (1, 'call'),
    1590              (2, 'line'),
    1591              (4, 'line'),
    1592              (4, 'return'),
    1593              (7, 'line'),
    1594              (8, 'line'),
    1595              (7, 'line'),
    1596              (1, 'call'),
    1597              (2, 'line'),
    1598              (4, 'line'),
    1599              (4, 'return'),
    1600              (10, 'line'),
    1601              (6, 'call'),
    1602              (6, 'line'),
    1603              (11, 'line'),
    1604              (11, 'return'),
    1605              (7, 'line'),
    1606              (2, 'call'),
    1607              (3, 'line'),
    1608              (3, 'return'),
    1609              (6, 'line'),
    1610              (2, 'call'),
    1611              (3, 'line'),
    1612              (3, 'return'),
    1613              (10, 'line'),
    1614              (10, 'return'),
    1615          ])
    1616  
    1617      @support.cpython_only
    1618      def test_no_line_event_after_creating_generator(self):
    1619          # Spurious line events before call events only show up with C tracer
    1620  
    1621          # Skip this test if the _testcapi module isn't available.
    1622          _testcapi = import_helper.import_module('_testcapi')
    1623  
    1624          def gen():
    1625              yield 1
    1626  
    1627          def func():
    1628              for _ in (
    1629                  gen()
    1630              ):
    1631                  pass
    1632  
    1633          EXPECTED_EVENTS = [
    1634              (0, 'call'),
    1635              (2, 'line'),
    1636              (1, 'line'),
    1637              (-3, 'call'),
    1638              (-2, 'line'),
    1639              (-2, 'return'),
    1640              (4, 'line'),
    1641              (1, 'line'),
    1642              (-2, 'call'),
    1643              (-2, 'return'),
    1644              (1, 'return'),
    1645          ]
    1646  
    1647          # C level events should be the same as expected and the same as Python level.
    1648  
    1649          events = []
    1650          # Turning on and off tracing must be on same line to avoid unwanted LINE events.
    1651          _testcapi.settrace_to_record(events); func(); sys.settrace(None)
    1652          start_line = func.__code__.co_firstlineno
    1653          events = [
    1654              (line-start_line, EVENT_NAMES[what])
    1655              for (what, line, arg) in events
    1656          ]
    1657          self.assertEqual(events, EXPECTED_EVENTS)
    1658  
    1659          self.run_and_compare(func, EXPECTED_EVENTS)
    1660  
    1661      def test_settrace_error(self):
    1662  
    1663          raised = False
    1664          def error_once(frame, event, arg):
    1665              nonlocal raised
    1666              if not raised:
    1667                  raised = True
    1668                  raise Exception
    1669              return error
    1670  
    1671          try:
    1672              sys._getframe().f_trace = error_once
    1673              sys.settrace(error_once)
    1674              len([])
    1675          except Exception as ex:
    1676              count = 0
    1677              tb = ex.__traceback__
    1678              while tb:
    1679                  if tb.tb_frame.f_code.co_name == "test_settrace_error":
    1680                      count += 1
    1681                  tb = tb.tb_next
    1682              if count == 0:
    1683                  self.fail("Traceback is missing frame")
    1684              elif count > 1:
    1685                  self.fail("Traceback has frame more than once")
    1686          else:
    1687              self.fail("No exception raised")
    1688          finally:
    1689              sys.settrace(None)
    1690  
    1691      @support.cpython_only
    1692      def test_testcapi_settrace_error(self):
    1693  
    1694          # Skip this test if the _testcapi module isn't available.
    1695          _testcapi = import_helper.import_module('_testcapi')
    1696  
    1697          try:
    1698              _testcapi.settrace_to_error([])
    1699              len([])
    1700          except Exception as ex:
    1701              count = 0
    1702              tb = ex.__traceback__
    1703              while tb:
    1704                  if tb.tb_frame.f_code.co_name == "test_testcapi_settrace_error":
    1705                      count += 1
    1706                  tb = tb.tb_next
    1707              if count == 0:
    1708                  self.fail("Traceback is missing frame")
    1709              elif count > 1:
    1710                  self.fail("Traceback has frame more than once")
    1711          else:
    1712              self.fail("No exception raised")
    1713          finally:
    1714              sys.settrace(None)
    1715  
    1716      def test_very_large_function(self):
    1717          # There is a separate code path when the number of lines > (1 << 15).
    1718          d = {}
    1719          exec("""def f():              # line 0
    1720              x = 0                     # line 1
    1721              y = 1                     # line 2
    1722              %s                        # lines 3 through (1 << 16)
    1723              x += 1                    #
    1724              return""" % ('\n' * (1 << 16),), d)
    1725          f = d['f']
    1726  
    1727          EXPECTED_EVENTS = [
    1728              (0, 'call'),
    1729              (1, 'line'),
    1730              (2, 'line'),
    1731              (65540, 'line'),
    1732              (65541, 'line'),
    1733              (65541, 'return'),
    1734          ]
    1735  
    1736          self.run_and_compare(f, EXPECTED_EVENTS)
    1737  
    1738  
    1739  EVENT_NAMES = [
    1740      'call',
    1741      'exception',
    1742      'line',
    1743      'return'
    1744  ]
    1745  
    1746  
    1747  class ESC[4;38;5;81mSkipLineEventsTraceTestCase(ESC[4;38;5;149mTraceTestCase):
    1748      """Repeat the trace tests, but with per-line events skipped"""
    1749  
    1750      def compare_events(self, line_offset, events, expected_events):
    1751          skip_line_events = [e for e in expected_events if e[1] != 'line']
    1752          super().compare_events(line_offset, events, skip_line_events)
    1753  
    1754      @staticmethod
    1755      def make_tracer():
    1756          return Tracer(trace_line_events=False)
    1757  
    1758  
    1759  @support.cpython_only
    1760  class ESC[4;38;5;81mTraceOpcodesTestCase(ESC[4;38;5;149mTraceTestCase):
    1761      """Repeat the trace tests, but with per-opcodes events enabled"""
    1762  
    1763      def compare_events(self, line_offset, events, expected_events):
    1764          skip_opcode_events = [e for e in events if e[1] != 'opcode']
    1765          if len(events) > 1:
    1766              self.assertLess(len(skip_opcode_events), len(events),
    1767                              msg="No 'opcode' events received by the tracer")
    1768          super().compare_events(line_offset, skip_opcode_events, expected_events)
    1769  
    1770      @staticmethod
    1771      def make_tracer():
    1772          return Tracer(trace_opcode_events=True)
    1773  
    1774  
    1775  class ESC[4;38;5;81mRaisingTraceFuncTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
    1776      def setUp(self):
    1777          self.addCleanup(sys.settrace, sys.gettrace())
    1778  
    1779      def trace(self, frame, event, arg):
    1780          """A trace function that raises an exception in response to a
    1781          specific trace event."""
    1782          if event == self.raiseOnEvent:
    1783              raise ValueError # just something that isn't RuntimeError
    1784          else:
    1785              return self.trace
    1786  
    1787      def f(self):
    1788          """The function to trace; raises an exception if that's the case
    1789          we're testing, so that the 'exception' trace event fires."""
    1790          if self.raiseOnEvent == 'exception':
    1791              x = 0
    1792              y = 1/x
    1793          else:
    1794              return 1
    1795  
    1796      def run_test_for_event(self, event):
    1797          """Tests that an exception raised in response to the given event is
    1798          handled OK."""
    1799          self.raiseOnEvent = event
    1800          try:
    1801              for i in range(sys.getrecursionlimit() + 1):
    1802                  sys.settrace(self.trace)
    1803                  try:
    1804                      self.f()
    1805                  except ValueError:
    1806                      pass
    1807                  else:
    1808                      self.fail("exception not raised!")
    1809          except RuntimeError:
    1810              self.fail("recursion counter not reset")
    1811  
    1812      # Test the handling of exceptions raised by each kind of trace event.
    1813      def test_call(self):
    1814          self.run_test_for_event('call')
    1815      def test_line(self):
    1816          self.run_test_for_event('line')
    1817      def test_return(self):
    1818          self.run_test_for_event('return')
    1819      def test_exception(self):
    1820          self.run_test_for_event('exception')
    1821  
    1822      def test_trash_stack(self):
    1823          def f():
    1824              for i in range(5):
    1825                  print(i)  # line tracing will raise an exception at this line
    1826  
    1827          def g(frame, why, extra):
    1828              if (why == 'line' and
    1829                  frame.f_lineno == f.__code__.co_firstlineno + 2):
    1830                  raise RuntimeError("i am crashing")
    1831              return g
    1832  
    1833          sys.settrace(g)
    1834          try:
    1835              f()
    1836          except RuntimeError:
    1837              # the test is really that this doesn't segfault:
    1838              import gc
    1839              gc.collect()
    1840          else:
    1841              self.fail("exception not propagated")
    1842  
    1843  
    1844      def test_exception_arguments(self):
    1845          def f():
    1846              x = 0
    1847              # this should raise an error
    1848              x.no_such_attr
    1849          def g(frame, event, arg):
    1850              if (event == 'exception'):
    1851                  type, exception, trace = arg
    1852                  self.assertIsInstance(exception, Exception)
    1853              return g
    1854  
    1855          existing = sys.gettrace()
    1856          try:
    1857              sys.settrace(g)
    1858              try:
    1859                  f()
    1860              except AttributeError:
    1861                  # this is expected
    1862                  pass
    1863          finally:
    1864              sys.settrace(existing)
    1865  
    1866      def test_line_event_raises_before_opcode_event(self):
    1867          exception = ValueError("BOOM!")
    1868          def trace(frame, event, arg):
    1869              if event == "line":
    1870                  raise exception
    1871              frame.f_trace_opcodes = True
    1872              return trace
    1873          def f():
    1874              pass
    1875          with self.assertRaises(ValueError) as caught:
    1876              sys.settrace(trace)
    1877              f()
    1878          self.assertIs(caught.exception, exception)
    1879  
    1880  
    1881  # 'Jump' tests: assigning to frame.f_lineno within a trace function
    1882  # moves the execution position - it's how debuggers implement a Jump
    1883  # command (aka. "Set next statement").
    1884  
    1885  class ESC[4;38;5;81mJumpTracer:
    1886      """Defines a trace function that jumps from one place to another."""
    1887  
    1888      def __init__(self, function, jumpFrom, jumpTo, event='line',
    1889                   decorated=False):
    1890          self.code = function.__code__
    1891          self.jumpFrom = jumpFrom
    1892          self.jumpTo = jumpTo
    1893          self.event = event
    1894          self.firstLine = None if decorated else self.code.co_firstlineno
    1895          self.done = False
    1896  
    1897      def trace(self, frame, event, arg):
    1898          if self.done:
    1899              return
    1900          # frame.f_code.co_firstlineno is the first line of the decorator when
    1901          # 'function' is decorated and the decorator may be written using
    1902          # multiple physical lines when it is too long. Use the first line
    1903          # trace event in 'function' to find the first line of 'function'.
    1904          if (self.firstLine is None and frame.f_code == self.code and
    1905                  event == 'line'):
    1906              self.firstLine = frame.f_lineno - 1
    1907          if (event == self.event and self.firstLine is not None and
    1908                  frame.f_lineno == self.firstLine + self.jumpFrom):
    1909              f = frame
    1910              while f is not None and f.f_code != self.code:
    1911                  f = f.f_back
    1912              if f is not None:
    1913                  # Cope with non-integer self.jumpTo (because of
    1914                  # no_jump_to_non_integers below).
    1915                  try:
    1916                      frame.f_lineno = self.firstLine + self.jumpTo
    1917                  except TypeError:
    1918                      frame.f_lineno = self.jumpTo
    1919                  self.done = True
    1920          return self.trace
    1921  
    1922  # This verifies the line-numbers-must-be-integers rule.
    1923  def no_jump_to_non_integers(output):
    1924      try:
    1925          output.append(2)
    1926      except ValueError as e:
    1927          output.append('integer' in str(e))
    1928  
    1929  # This verifies that you can't set f_lineno via _getframe or similar
    1930  # trickery.
    1931  def no_jump_without_trace_function():
    1932      try:
    1933          previous_frame = sys._getframe().f_back
    1934          previous_frame.f_lineno = previous_frame.f_lineno
    1935      except ValueError as e:
    1936          # This is the exception we wanted; make sure the error message
    1937          # talks about trace functions.
    1938          if 'trace' not in str(e):
    1939              raise
    1940      else:
    1941          # Something's wrong - the expected exception wasn't raised.
    1942          raise AssertionError("Trace-function-less jump failed to fail")
    1943  
    1944  
    1945  class ESC[4;38;5;81mJumpTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
    1946      unbound_locals = r"assigning None to [0-9]+ unbound local"
    1947  
    1948      def setUp(self):
    1949          self.addCleanup(sys.settrace, sys.gettrace())
    1950          sys.settrace(None)
    1951  
    1952      def compare_jump_output(self, expected, received):
    1953          if received != expected:
    1954              self.fail( "Outputs don't match:\n" +
    1955                         "Expected: " + repr(expected) + "\n" +
    1956                         "Received: " + repr(received))
    1957  
    1958      def run_test(self, func, jumpFrom, jumpTo, expected, error=None,
    1959                   event='line', decorated=False, warning=None):
    1960          wrapped = func
    1961          while hasattr(wrapped, '__wrapped__'):
    1962              wrapped = wrapped.__wrapped__
    1963  
    1964          tracer = JumpTracer(wrapped, jumpFrom, jumpTo, event, decorated)
    1965          sys.settrace(tracer.trace)
    1966          output = []
    1967  
    1968          with contextlib.ExitStack() as stack:
    1969              if error is not None:
    1970                  stack.enter_context(self.assertRaisesRegex(*error))
    1971              if warning is not None:
    1972                  stack.enter_context(self.assertWarnsRegex(*warning))
    1973              func(output)
    1974  
    1975          sys.settrace(None)
    1976          self.compare_jump_output(expected, output)
    1977  
    1978      def run_async_test(self, func, jumpFrom, jumpTo, expected, error=None,
    1979                   event='line', decorated=False, warning=None):
    1980          wrapped = func
    1981          while hasattr(wrapped, '__wrapped__'):
    1982              wrapped = wrapped.__wrapped__
    1983  
    1984          tracer = JumpTracer(wrapped, jumpFrom, jumpTo, event, decorated)
    1985          sys.settrace(tracer.trace)
    1986          output = []
    1987  
    1988          with contextlib.ExitStack() as stack:
    1989              if error is not None:
    1990                  stack.enter_context(self.assertRaisesRegex(*error))
    1991              if warning is not None:
    1992                  stack.enter_context(self.assertWarnsRegex(*warning))
    1993              asyncio.run(func(output))
    1994  
    1995          sys.settrace(None)
    1996          asyncio.set_event_loop_policy(None)
    1997          self.compare_jump_output(expected, output)
    1998  
    1999      def jump_test(jumpFrom, jumpTo, expected, error=None, event='line', warning=None):
    2000          """Decorator that creates a test that makes a jump
    2001          from one place to another in the following code.
    2002          """
    2003          def decorator(func):
    2004              @wraps(func)
    2005              def test(self):
    2006                  self.run_test(func, jumpFrom, jumpTo, expected,
    2007                                error=error, event=event, decorated=True, warning=warning)
    2008              return test
    2009          return decorator
    2010  
    2011      def async_jump_test(jumpFrom, jumpTo, expected, error=None, event='line', warning=None):
    2012          """Decorator that creates a test that makes a jump
    2013          from one place to another in the following asynchronous code.
    2014          """
    2015          def decorator(func):
    2016              @wraps(func)
    2017              def test(self):
    2018                  self.run_async_test(func, jumpFrom, jumpTo, expected,
    2019                                error=error, event=event, decorated=True, warning=warning)
    2020              return test
    2021          return decorator
    2022  
    2023      ## The first set of 'jump' tests are for things that are allowed:
    2024  
    2025      @jump_test(1, 3, [3])
    2026      def test_jump_simple_forwards(output):
    2027          output.append(1)
    2028          output.append(2)
    2029          output.append(3)
    2030  
    2031      @jump_test(2, 1, [1, 1, 2])
    2032      def test_jump_simple_backwards(output):
    2033          output.append(1)
    2034          output.append(2)
    2035  
    2036      @jump_test(3, 5, [2, 5], warning=(RuntimeWarning, unbound_locals))
    2037      def test_jump_out_of_block_forwards(output):
    2038          for i in 1, 2:
    2039              output.append(2)
    2040              for j in [3]:  # Also tests jumping over a block
    2041                  output.append(4)
    2042          output.append(5)
    2043  
    2044      @jump_test(6, 1, [1, 3, 5, 1, 3, 5, 6, 7])
    2045      def test_jump_out_of_block_backwards(output):
    2046          output.append(1)
    2047          for i in [1]:
    2048              output.append(3)
    2049              for j in [2]:  # Also tests jumping over a block
    2050                  output.append(5)
    2051              output.append(6)
    2052          output.append(7)
    2053  
    2054      @async_jump_test(4, 5, [3, 5])
    2055      @clean_asynciter
    2056      async def test_jump_out_of_async_for_block_forwards(output, asynciter):
    2057          for i in [1]:
    2058              async for i in asynciter([1, 2]):
    2059                  output.append(3)
    2060                  output.append(4)
    2061              output.append(5)
    2062  
    2063      @async_jump_test(5, 2, [2, 4, 2, 4, 5, 6])
    2064      @clean_asynciter
    2065      async def test_jump_out_of_async_for_block_backwards(output, asynciter):
    2066          for i in [1]:
    2067              output.append(2)
    2068              async for i in asynciter([1]):
    2069                  output.append(4)
    2070                  output.append(5)
    2071              output.append(6)
    2072  
    2073      @jump_test(1, 2, [3])
    2074      def test_jump_to_codeless_line(output):
    2075          output.append(1)
    2076          # Jumping to this line should skip to the next one.
    2077          output.append(3)
    2078  
    2079      @jump_test(2, 2, [1, 2, 3])
    2080      def test_jump_to_same_line(output):
    2081          output.append(1)
    2082          output.append(2)
    2083          output.append(3)
    2084  
    2085      # Tests jumping within a finally block, and over one.
    2086      @jump_test(4, 9, [2, 9])
    2087      def test_jump_in_nested_finally(output):
    2088          try:
    2089              output.append(2)
    2090          finally:
    2091              output.append(4)
    2092              try:
    2093                  output.append(6)
    2094              finally:
    2095                  output.append(8)
    2096              output.append(9)
    2097  
    2098      @jump_test(6, 7, [2, 7], (ZeroDivisionError, ''))
    2099      def test_jump_in_nested_finally_2(output):
    2100          try:
    2101              output.append(2)
    2102              1/0
    2103              return
    2104          finally:
    2105              output.append(6)
    2106              output.append(7)
    2107          output.append(8)
    2108  
    2109      @jump_test(6, 11, [2, 11], (ZeroDivisionError, ''))
    2110      def test_jump_in_nested_finally_3(output):
    2111          try:
    2112              output.append(2)
    2113              1/0
    2114              return
    2115          finally:
    2116              output.append(6)
    2117              try:
    2118                  output.append(8)
    2119              finally:
    2120                  output.append(10)
    2121              output.append(11)
    2122          output.append(12)
    2123  
    2124      @jump_test(5, 11, [2, 4], (ValueError, 'comes after the current code block'))
    2125      def test_no_jump_over_return_try_finally_in_finally_block(output):
    2126          try:
    2127              output.append(2)
    2128          finally:
    2129              output.append(4)
    2130              output.append(5)
    2131              return
    2132              try:
    2133                  output.append(8)
    2134              finally:
    2135                  output.append(10)
    2136              pass
    2137          output.append(12)
    2138  
    2139      @jump_test(3, 4, [1], (ValueError, 'after'))
    2140      def test_no_jump_infinite_while_loop(output):
    2141          output.append(1)
    2142          while True:
    2143              output.append(3)
    2144          output.append(4)
    2145  
    2146      @jump_test(2, 4, [4, 4])
    2147      def test_jump_forwards_into_while_block(output):
    2148          i = 1
    2149          output.append(2)
    2150          while i <= 2:
    2151              output.append(4)
    2152              i += 1
    2153  
    2154      @jump_test(5, 3, [3, 3, 3, 5])
    2155      def test_jump_backwards_into_while_block(output):
    2156          i = 1
    2157          while i <= 2:
    2158              output.append(3)
    2159              i += 1
    2160          output.append(5)
    2161  
    2162      @jump_test(2, 3, [1, 3])
    2163      def test_jump_forwards_out_of_with_block(output):
    2164          with tracecontext(output, 1):
    2165              output.append(2)
    2166          output.append(3)
    2167  
    2168      @async_jump_test(2, 3, [1, 3])
    2169      async def test_jump_forwards_out_of_async_with_block(output):
    2170          async with asynctracecontext(output, 1):
    2171              output.append(2)
    2172          output.append(3)
    2173  
    2174      @jump_test(3, 1, [1, 2, 1, 2, 3, -2])
    2175      def test_jump_backwards_out_of_with_block(output):
    2176          output.append(1)
    2177          with tracecontext(output, 2):
    2178              output.append(3)
    2179  
    2180      @async_jump_test(3, 1, [1, 2, 1, 2, 3, -2])
    2181      async def test_jump_backwards_out_of_async_with_block(output):
    2182          output.append(1)
    2183          async with asynctracecontext(output, 2):
    2184              output.append(3)
    2185  
    2186      @jump_test(2, 5, [5])
    2187      def test_jump_forwards_out_of_try_finally_block(output):
    2188          try:
    2189              output.append(2)
    2190          finally:
    2191              output.append(4)
    2192          output.append(5)
    2193  
    2194      @jump_test(3, 1, [1, 1, 3, 5])
    2195      def test_jump_backwards_out_of_try_finally_block(output):
    2196          output.append(1)
    2197          try:
    2198              output.append(3)
    2199          finally:
    2200              output.append(5)
    2201  
    2202      @jump_test(2, 6, [6])
    2203      def test_jump_forwards_out_of_try_except_block(output):
    2204          try:
    2205              output.append(2)
    2206          except:
    2207              output.append(4)
    2208              raise
    2209          output.append(6)
    2210  
    2211      @jump_test(3, 1, [1, 1, 3])
    2212      def test_jump_backwards_out_of_try_except_block(output):
    2213          output.append(1)
    2214          try:
    2215              output.append(3)
    2216          except:
    2217              output.append(5)
    2218              raise
    2219  
    2220      @jump_test(5, 7, [4, 7, 8])
    2221      def test_jump_between_except_blocks(output):
    2222          try:
    2223              1/0
    2224          except ZeroDivisionError:
    2225              output.append(4)
    2226              output.append(5)
    2227          except FloatingPointError:
    2228              output.append(7)
    2229          output.append(8)
    2230  
    2231      @jump_test(5, 7, [4, 7, 8])
    2232      def test_jump_from_except_to_finally(output):
    2233          try:
    2234              1/0
    2235          except ZeroDivisionError:
    2236              output.append(4)
    2237              output.append(5)
    2238          finally:
    2239              output.append(7)
    2240          output.append(8)
    2241  
    2242      @jump_test(5, 6, [4, 6, 7])
    2243      def test_jump_within_except_block(output):
    2244          try:
    2245              1/0
    2246          except:
    2247              output.append(4)
    2248              output.append(5)
    2249              output.append(6)
    2250          output.append(7)
    2251  
    2252      @jump_test(6, 1, [1, 5, 1, 5], warning=(RuntimeWarning, unbound_locals))
    2253      def test_jump_over_try_except(output):
    2254          output.append(1)
    2255          try:
    2256              1 / 0
    2257          except ZeroDivisionError as e:
    2258              output.append(5)
    2259          x = 42  # has to be a two-instruction block
    2260  
    2261      @jump_test(2, 4, [1, 4, 5, -4])
    2262      def test_jump_across_with(output):
    2263          output.append(1)
    2264          with tracecontext(output, 2):
    2265              output.append(3)
    2266          with tracecontext(output, 4):
    2267              output.append(5)
    2268  
    2269      @async_jump_test(2, 4, [1, 4, 5, -4])
    2270      async def test_jump_across_async_with(output):
    2271          output.append(1)
    2272          async with asynctracecontext(output, 2):
    2273              output.append(3)
    2274          async with asynctracecontext(output, 4):
    2275              output.append(5)
    2276  
    2277      @jump_test(4, 5, [1, 3, 5, 6])
    2278      def test_jump_out_of_with_block_within_for_block(output):
    2279          output.append(1)
    2280          for i in [1]:
    2281              with tracecontext(output, 3):
    2282                  output.append(4)
    2283              output.append(5)
    2284          output.append(6)
    2285  
    2286      @async_jump_test(4, 5, [1, 3, 5, 6])
    2287      async def test_jump_out_of_async_with_block_within_for_block(output):
    2288          output.append(1)
    2289          for i in [1]:
    2290              async with asynctracecontext(output, 3):
    2291                  output.append(4)
    2292              output.append(5)
    2293          output.append(6)
    2294  
    2295      @jump_test(4, 5, [1, 2, 3, 5, -2, 6])
    2296      def test_jump_out_of_with_block_within_with_block(output):
    2297          output.append(1)
    2298          with tracecontext(output, 2):
    2299              with tracecontext(output, 3):
    2300                  output.append(4)
    2301              output.append(5)
    2302          output.append(6)
    2303  
    2304      @async_jump_test(4, 5, [1, 2, 3, 5, -2, 6])
    2305      async def test_jump_out_of_async_with_block_within_with_block(output):
    2306          output.append(1)
    2307          with tracecontext(output, 2):
    2308              async with asynctracecontext(output, 3):
    2309                  output.append(4)
    2310              output.append(5)
    2311          output.append(6)
    2312  
    2313      @jump_test(5, 6, [2, 4, 6, 7])
    2314      def test_jump_out_of_with_block_within_finally_block(output):
    2315          try:
    2316              output.append(2)
    2317          finally:
    2318              with tracecontext(output, 4):
    2319                  output.append(5)
    2320              output.append(6)
    2321          output.append(7)
    2322  
    2323      @async_jump_test(5, 6, [2, 4, 6, 7])
    2324      async def test_jump_out_of_async_with_block_within_finally_block(output):
    2325          try:
    2326              output.append(2)
    2327          finally:
    2328              async with asynctracecontext(output, 4):
    2329                  output.append(5)
    2330              output.append(6)
    2331          output.append(7)
    2332  
    2333      @jump_test(8, 11, [1, 3, 5, 11, 12])
    2334      def test_jump_out_of_complex_nested_blocks(output):
    2335          output.append(1)
    2336          for i in [1]:
    2337              output.append(3)
    2338              for j in [1, 2]:
    2339                  output.append(5)
    2340                  try:
    2341                      for k in [1, 2]:
    2342                          output.append(8)
    2343                  finally:
    2344                      output.append(10)
    2345              output.append(11)
    2346          output.append(12)
    2347  
    2348      @jump_test(3, 5, [1, 2, 5], warning=(RuntimeWarning, unbound_locals))
    2349      def test_jump_out_of_with_assignment(output):
    2350          output.append(1)
    2351          with tracecontext(output, 2) \
    2352                  as x:
    2353              output.append(4)
    2354          output.append(5)
    2355  
    2356      @async_jump_test(3, 5, [1, 2, 5], warning=(RuntimeWarning, unbound_locals))
    2357      async def test_jump_out_of_async_with_assignment(output):
    2358          output.append(1)
    2359          async with asynctracecontext(output, 2) \
    2360                  as x:
    2361              output.append(4)
    2362          output.append(5)
    2363  
    2364      @jump_test(3, 6, [1, 6, 8, 9])
    2365      def test_jump_over_return_in_try_finally_block(output):
    2366          output.append(1)
    2367          try:
    2368              output.append(3)
    2369              if not output: # always false
    2370                  return
    2371              output.append(6)
    2372          finally:
    2373              output.append(8)
    2374          output.append(9)
    2375  
    2376      @jump_test(5, 8, [1, 3, 8, 10, 11, 13])
    2377      def test_jump_over_break_in_try_finally_block(output):
    2378          output.append(1)
    2379          while True:
    2380              output.append(3)
    2381              try:
    2382                  output.append(5)
    2383                  if not output: # always false
    2384                      break
    2385                  output.append(8)
    2386              finally:
    2387                  output.append(10)
    2388              output.append(11)
    2389              break
    2390          output.append(13)
    2391  
    2392      @jump_test(1, 7, [7, 8], warning=(RuntimeWarning, unbound_locals))
    2393      def test_jump_over_for_block_before_else(output):
    2394          output.append(1)
    2395          if not output:  # always false
    2396              for i in [3]:
    2397                  output.append(4)
    2398          else:
    2399              output.append(6)
    2400              output.append(7)
    2401          output.append(8)
    2402  
    2403      @async_jump_test(1, 7, [7, 8], warning=(RuntimeWarning, unbound_locals))
    2404      async def test_jump_over_async_for_block_before_else(output):
    2405          output.append(1)
    2406          if not output:  # always false
    2407              async for i in asynciter([3]):
    2408                  output.append(4)
    2409          else:
    2410              output.append(6)
    2411              output.append(7)
    2412          output.append(8)
    2413  
    2414      # The second set of 'jump' tests are for things that are not allowed:
    2415  
    2416      @jump_test(2, 3, [1], (ValueError, 'after'))
    2417      def test_no_jump_too_far_forwards(output):
    2418          output.append(1)
    2419          output.append(2)
    2420  
    2421      @jump_test(2, -2, [1], (ValueError, 'before'))
    2422      def test_no_jump_too_far_backwards(output):
    2423          output.append(1)
    2424          output.append(2)
    2425  
    2426      # Test each kind of 'except' line.
    2427      @jump_test(2, 3, [4], (ValueError, 'except'))
    2428      def test_no_jump_to_except_1(output):
    2429          try:
    2430              output.append(2)
    2431          except:
    2432              output.append(4)
    2433              raise
    2434  
    2435      @jump_test(2, 3, [4], (ValueError, 'except'))
    2436      def test_no_jump_to_except_2(output):
    2437          try:
    2438              output.append(2)
    2439          except ValueError:
    2440              output.append(4)
    2441              raise
    2442  
    2443      @jump_test(2, 3, [4], (ValueError, 'except'))
    2444      def test_no_jump_to_except_3(output):
    2445          try:
    2446              output.append(2)
    2447          except ValueError as e:
    2448              output.append(4)
    2449              raise e
    2450  
    2451      @jump_test(2, 3, [4], (ValueError, 'except'))
    2452      def test_no_jump_to_except_4(output):
    2453          try:
    2454              output.append(2)
    2455          except (ValueError, RuntimeError) as e:
    2456              output.append(4)
    2457              raise e
    2458  
    2459      @jump_test(1, 3, [], (ValueError, 'into'))
    2460      def test_no_jump_forwards_into_for_block(output):
    2461          output.append(1)
    2462          for i in 1, 2:
    2463              output.append(3)
    2464  
    2465      @async_jump_test(1, 3, [], (ValueError, 'into'))
    2466      async def test_no_jump_forwards_into_async_for_block(output):
    2467          output.append(1)
    2468          async for i in asynciter([1, 2]):
    2469              output.append(3)
    2470          pass
    2471  
    2472      @jump_test(3, 2, [2, 2], (ValueError, 'into'))
    2473      def test_no_jump_backwards_into_for_block(output):
    2474          for i in 1, 2:
    2475              output.append(2)
    2476          output.append(3)
    2477  
    2478  
    2479      @async_jump_test(3, 2, [2, 2], (ValueError, "can't jump into the body of a for loop"))
    2480      async def test_no_jump_backwards_into_async_for_block(output):
    2481          async for i in asynciter([1, 2]):
    2482              output.append(2)
    2483          output.append(3)
    2484  
    2485      @jump_test(1, 3, [], (ValueError, 'stack'))
    2486      def test_no_jump_forwards_into_with_block(output):
    2487          output.append(1)
    2488          with tracecontext(output, 2):
    2489              output.append(3)
    2490  
    2491      @async_jump_test(1, 3, [], (ValueError, 'stack'))
    2492      async def test_no_jump_forwards_into_async_with_block(output):
    2493          output.append(1)
    2494          async with asynctracecontext(output, 2):
    2495              output.append(3)
    2496  
    2497      @jump_test(3, 2, [1, 2, -1], (ValueError, 'stack'))
    2498      def test_no_jump_backwards_into_with_block(output):
    2499          with tracecontext(output, 1):
    2500              output.append(2)
    2501          output.append(3)
    2502  
    2503      @async_jump_test(3, 2, [1, 2, -1], (ValueError, 'stack'))
    2504      async def test_no_jump_backwards_into_async_with_block(output):
    2505          async with asynctracecontext(output, 1):
    2506              output.append(2)
    2507          output.append(3)
    2508  
    2509      @jump_test(1, 3, [3, 5])
    2510      def test_jump_forwards_into_try_finally_block(output):
    2511          output.append(1)
    2512          try:
    2513              output.append(3)
    2514          finally:
    2515              output.append(5)
    2516  
    2517      @jump_test(5, 2, [2, 4, 2, 4, 5])
    2518      def test_jump_backwards_into_try_finally_block(output):
    2519          try:
    2520              output.append(2)
    2521          finally:
    2522              output.append(4)
    2523          output.append(5)
    2524  
    2525      @jump_test(1, 3, [3])
    2526      def test_jump_forwards_into_try_except_block(output):
    2527          output.append(1)
    2528          try:
    2529              output.append(3)
    2530          except:
    2531              output.append(5)
    2532              raise
    2533  
    2534      @jump_test(6, 2, [2, 2, 6])
    2535      def test_jump_backwards_into_try_except_block(output):
    2536          try:
    2537              output.append(2)
    2538          except:
    2539              output.append(4)
    2540              raise
    2541          output.append(6)
    2542  
    2543      # 'except' with a variable creates an implicit finally block
    2544      @jump_test(5, 7, [4, 7, 8], warning=(RuntimeWarning, unbound_locals))
    2545      def test_jump_between_except_blocks_2(output):
    2546          try:
    2547              1/0
    2548          except ZeroDivisionError:
    2549              output.append(4)
    2550              output.append(5)
    2551          except FloatingPointError as e:
    2552              output.append(7)
    2553          output.append(8)
    2554  
    2555      @jump_test(1, 5, [5])
    2556      def test_jump_into_finally_block(output):
    2557          output.append(1)
    2558          try:
    2559              output.append(3)
    2560          finally:
    2561              output.append(5)
    2562  
    2563      @jump_test(3, 6, [2, 6, 7])
    2564      def test_jump_into_finally_block_from_try_block(output):
    2565          try:
    2566              output.append(2)
    2567              output.append(3)
    2568          finally:  # still executed if the jump is failed
    2569              output.append(5)
    2570              output.append(6)
    2571          output.append(7)
    2572  
    2573      @jump_test(5, 1, [1, 3, 1, 3, 5])
    2574      def test_jump_out_of_finally_block(output):
    2575          output.append(1)
    2576          try:
    2577              output.append(3)
    2578          finally:
    2579              output.append(5)
    2580  
    2581      @jump_test(1, 5, [], (ValueError, "can't jump into an 'except' block as there's no exception"))
    2582      def test_no_jump_into_bare_except_block(output):
    2583          output.append(1)
    2584          try:
    2585              output.append(3)
    2586          except:
    2587              output.append(5)
    2588  
    2589      @jump_test(1, 5, [], (ValueError, "can't jump into an 'except' block as there's no exception"))
    2590      def test_no_jump_into_qualified_except_block(output):
    2591          output.append(1)
    2592          try:
    2593              output.append(3)
    2594          except Exception:
    2595              output.append(5)
    2596  
    2597      @jump_test(3, 6, [2, 5, 6], (ValueError, "can't jump into an 'except' block as there's no exception"))
    2598      def test_no_jump_into_bare_except_block_from_try_block(output):
    2599          try:
    2600              output.append(2)
    2601              output.append(3)
    2602          except:  # executed if the jump is failed
    2603              output.append(5)
    2604              output.append(6)
    2605              raise
    2606          output.append(8)
    2607  
    2608      @jump_test(3, 6, [2], (ValueError, "can't jump into an 'except' block as there's no exception"))
    2609      def test_no_jump_into_qualified_except_block_from_try_block(output):
    2610          try:
    2611              output.append(2)
    2612              output.append(3)
    2613          except ZeroDivisionError:
    2614              output.append(5)
    2615              output.append(6)
    2616              raise
    2617          output.append(8)
    2618  
    2619      @jump_test(7, 1, [1, 3, 6, 1, 3, 6, 7])
    2620      def test_jump_out_of_bare_except_block(output):
    2621          output.append(1)
    2622          try:
    2623              output.append(3)
    2624              1/0
    2625          except:
    2626              output.append(6)
    2627              output.append(7)
    2628  
    2629      @jump_test(7, 1, [1, 3, 6, 1, 3, 6, 7])
    2630      def test_jump_out_of_qualified_except_block(output):
    2631          output.append(1)
    2632          try:
    2633              output.append(3)
    2634              1/0
    2635          except Exception:
    2636              output.append(6)
    2637              output.append(7)
    2638  
    2639      @jump_test(3, 5, [1, 2, 5, -2])
    2640      def test_jump_between_with_blocks(output):
    2641          output.append(1)
    2642          with tracecontext(output, 2):
    2643              output.append(3)
    2644          with tracecontext(output, 4):
    2645              output.append(5)
    2646  
    2647      @async_jump_test(3, 5, [1, 2, 5, -2])
    2648      async def test_jump_between_async_with_blocks(output):
    2649          output.append(1)
    2650          async with asynctracecontext(output, 2):
    2651              output.append(3)
    2652          async with asynctracecontext(output, 4):
    2653              output.append(5)
    2654  
    2655      @jump_test(5, 7, [2, 4], (ValueError, "after"))
    2656      def test_no_jump_over_return_out_of_finally_block(output):
    2657          try:
    2658              output.append(2)
    2659          finally:
    2660              output.append(4)
    2661              output.append(5)
    2662              return
    2663          output.append(7)
    2664  
    2665      @jump_test(7, 4, [1, 6], (ValueError, 'into'))
    2666      def test_no_jump_into_for_block_before_else(output):
    2667          output.append(1)
    2668          if not output:  # always false
    2669              for i in [3]:
    2670                  output.append(4)
    2671          else:
    2672              output.append(6)
    2673              output.append(7)
    2674          output.append(8)
    2675  
    2676      @async_jump_test(7, 4, [1, 6], (ValueError, 'into'))
    2677      async def test_no_jump_into_async_for_block_before_else(output):
    2678          output.append(1)
    2679          if not output:  # always false
    2680              async for i in asynciter([3]):
    2681                  output.append(4)
    2682          else:
    2683              output.append(6)
    2684              output.append(7)
    2685          output.append(8)
    2686  
    2687      def test_no_jump_to_non_integers(self):
    2688          self.run_test(no_jump_to_non_integers, 2, "Spam", [True])
    2689  
    2690      def test_no_jump_without_trace_function(self):
    2691          # Must set sys.settrace(None) in setUp(), else condition is not
    2692          # triggered.
    2693          no_jump_without_trace_function()
    2694  
    2695      def test_large_function(self):
    2696          d = {}
    2697          exec("""def f(output):        # line 0
    2698              x = 0                     # line 1
    2699              y = 1                     # line 2
    2700              '''                       # line 3
    2701              %s                        # lines 4-1004
    2702              '''                       # line 1005
    2703              x += 1                    # line 1006
    2704              output.append(x)          # line 1007
    2705              return""" % ('\n' * 1000,), d)
    2706          f = d['f']
    2707          self.run_test(f, 2, 1007, [0], warning=(RuntimeWarning, self.unbound_locals))
    2708  
    2709      def test_jump_to_firstlineno(self):
    2710          # This tests that PDB can jump back to the first line in a
    2711          # file.  See issue #1689458.  It can only be triggered in a
    2712          # function call if the function is defined on a single line.
    2713          code = compile("""
    2714  # Comments don't count.
    2715  output.append(2)  # firstlineno is here.
    2716  output.append(3)
    2717  output.append(4)
    2718  """, "<fake module>", "exec")
    2719          class ESC[4;38;5;81mfake_function:
    2720              __code__ = code
    2721          tracer = JumpTracer(fake_function, 4, 1)
    2722          sys.settrace(tracer.trace)
    2723          namespace = {"output": []}
    2724          exec(code, namespace)
    2725          sys.settrace(None)
    2726          self.compare_jump_output([2, 3, 2, 3, 4], namespace["output"])
    2727  
    2728      @jump_test(2, 3, [1], event='call', error=(ValueError, "can't jump from"
    2729                 " the 'call' trace event of a new frame"))
    2730      def test_no_jump_from_call(output):
    2731          output.append(1)
    2732          def nested():
    2733              output.append(3)
    2734          nested()
    2735          output.append(5)
    2736  
    2737      @jump_test(2, 1, [1], event='return', error=(ValueError,
    2738                 "can only jump from a 'line' trace event"))
    2739      def test_no_jump_from_return_event(output):
    2740          output.append(1)
    2741          return
    2742  
    2743      @jump_test(2, 1, [1], event='exception', error=(ValueError,
    2744                 "can only jump from a 'line' trace event"))
    2745      def test_no_jump_from_exception_event(output):
    2746          output.append(1)
    2747          1 / 0
    2748  
    2749      @jump_test(3, 2, [2, 5], event='return')
    2750      def test_jump_from_yield(output):
    2751          def gen():
    2752              output.append(2)
    2753              yield 3
    2754          next(gen())
    2755          output.append(5)
    2756  
    2757      @jump_test(2, 3, [1, 3], warning=(RuntimeWarning, unbound_locals))
    2758      def test_jump_forward_over_listcomp(output):
    2759          output.append(1)
    2760          x = [i for i in range(10)]
    2761          output.append(3)
    2762  
    2763      # checking for segfaults.
    2764      # See https://github.com/python/cpython/issues/92311
    2765      @jump_test(3, 1, [], warning=(RuntimeWarning, unbound_locals))
    2766      def test_jump_backward_over_listcomp(output):
    2767          a = 1
    2768          x = [i for i in range(10)]
    2769          c = 3
    2770  
    2771      @jump_test(8, 2, [2, 7, 2], warning=(RuntimeWarning, unbound_locals))
    2772      def test_jump_backward_over_listcomp_v2(output):
    2773          flag = False
    2774          output.append(2)
    2775          if flag:
    2776              return
    2777          x = [i for i in range(5)]
    2778          flag = 6
    2779          output.append(7)
    2780          output.append(8)
    2781  
    2782      @async_jump_test(2, 3, [1, 3], warning=(RuntimeWarning, unbound_locals))
    2783      async def test_jump_forward_over_async_listcomp(output):
    2784          output.append(1)
    2785          x = [i async for i in asynciter(range(10))]
    2786          output.append(3)
    2787  
    2788      @async_jump_test(3, 1, [], warning=(RuntimeWarning, unbound_locals))
    2789      async def test_jump_backward_over_async_listcomp(output):
    2790          a = 1
    2791          x = [i async for i in asynciter(range(10))]
    2792          c = 3
    2793  
    2794      @async_jump_test(8, 2, [2, 7, 2], warning=(RuntimeWarning, unbound_locals))
    2795      async def test_jump_backward_over_async_listcomp_v2(output):
    2796          flag = False
    2797          output.append(2)
    2798          if flag:
    2799              return
    2800          x = [i async for i in asynciter(range(5))]
    2801          flag = 6
    2802          output.append(7)
    2803          output.append(8)
    2804  
    2805      # checking for segfaults.
    2806      @jump_test(3, 7, [], error=(ValueError, "stack"))
    2807      def test_jump_with_null_on_stack_load_global(output):
    2808          a = 1
    2809          print(
    2810              output.append(3)
    2811          )
    2812          output.append(5)
    2813          (
    2814              ( # 7
    2815                  a
    2816                  +
    2817                  10
    2818              )
    2819              +
    2820              13
    2821          )
    2822          output.append(15)
    2823  
    2824      # checking for segfaults.
    2825      @jump_test(4, 8, [], error=(ValueError, "stack"))
    2826      def test_jump_with_null_on_stack_push_null(output):
    2827          a = 1
    2828          f = print
    2829          f(
    2830              output.append(4)
    2831          )
    2832          output.append(6)
    2833          (
    2834              ( # 8
    2835                  a
    2836                  +
    2837                  11
    2838              )
    2839              +
    2840              14
    2841          )
    2842          output.append(16)
    2843  
    2844      # checking for segfaults.
    2845      @jump_test(3, 7, [], error=(ValueError, "stack"))
    2846      def test_jump_with_null_on_stack_load_attr(output):
    2847          a = 1
    2848          list.append(
    2849              output, 3
    2850          )
    2851          output.append(5)
    2852          (
    2853              ( # 7
    2854                  a
    2855                  +
    2856                  10
    2857              )
    2858              +
    2859              13
    2860          )
    2861          output.append(15)
    2862  
    2863      @jump_test(2, 3, [1, 3], warning=(RuntimeWarning, unbound_locals))
    2864      def test_jump_extended_args_unpack_ex_simple(output):
    2865          output.append(1)
    2866          _, *_, _ = output.append(2) or "Spam"
    2867          output.append(3)
    2868  
    2869      @jump_test(3, 4, [1, 4, 4, 5], warning=(RuntimeWarning, unbound_locals))
    2870      def test_jump_extended_args_unpack_ex_tricky(output):
    2871          output.append(1)
    2872          (
    2873              _, *_, _
    2874          ) = output.append(4) or "Spam"
    2875          output.append(5)
    2876  
    2877      @support.requires_resource('cpu')
    2878      def test_jump_extended_args_for_iter(self):
    2879          # In addition to failing when extended arg handling is broken, this can
    2880          # also hang for a *very* long time:
    2881          source = [
    2882              "def f(output):",
    2883              "    output.append(1)",
    2884              "    for _ in spam:",
    2885              *(f"        output.append({i})" for i in range(3, 100_000)),
    2886              f"    output.append(100_000)",
    2887          ]
    2888          namespace = {}
    2889          exec("\n".join(source), namespace)
    2890          f = namespace["f"]
    2891          self.run_test(f,  2, 100_000, [1, 100_000], warning=(RuntimeWarning, self.unbound_locals))
    2892  
    2893      @jump_test(2, 3, [1, 3], warning=(RuntimeWarning, unbound_locals))
    2894      def test_jump_or_pop(output):
    2895          output.append(1)
    2896          _ = output.append(2) and "Spam"
    2897          output.append(3)
    2898  
    2899  
    2900  class ESC[4;38;5;81mTestExtendedArgs(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
    2901  
    2902      def setUp(self):
    2903          self.addCleanup(sys.settrace, sys.gettrace())
    2904          sys.settrace(None)
    2905  
    2906      def count_traces(self, func):
    2907          # warmup
    2908          for _ in range(20):
    2909              func()
    2910  
    2911          counts = {"call": 0, "line": 0, "return": 0}
    2912          def trace(frame, event, arg):
    2913              counts[event] += 1
    2914              return trace
    2915  
    2916          sys.settrace(trace)
    2917          func()
    2918          sys.settrace(None)
    2919  
    2920          return counts
    2921  
    2922      def test_trace_unpack_long_sequence(self):
    2923          ns = {}
    2924          code = "def f():\n  (" + "y,\n   "*300 + ") = range(300)"
    2925          exec(code, ns)
    2926          counts = self.count_traces(ns["f"])
    2927          self.assertEqual(counts, {'call': 1, 'line': 301, 'return': 1})
    2928  
    2929      def test_trace_lots_of_globals(self):
    2930          code = """if 1:
    2931              def f():
    2932                  return (
    2933                      {}
    2934                  )
    2935          """.format("\n+\n".join(f"var{i}\n" for i in range(1000)))
    2936          ns = {f"var{i}": i for i in range(1000)}
    2937          exec(code, ns)
    2938          counts = self.count_traces(ns["f"])
    2939          self.assertEqual(counts, {'call': 1, 'line': 2000, 'return': 1})
    2940  
    2941  
    2942  class ESC[4;38;5;81mTestEdgeCases(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
    2943  
    2944      def setUp(self):
    2945          self.addCleanup(sys.settrace, sys.gettrace())
    2946          sys.settrace(None)
    2947  
    2948      def test_reentrancy(self):
    2949          def foo(*args):
    2950              ...
    2951  
    2952          def bar(*args):
    2953              ...
    2954  
    2955          class ESC[4;38;5;81mA:
    2956              def __call__(self, *args):
    2957                  pass
    2958  
    2959              def __del__(self):
    2960                  sys.settrace(bar)
    2961  
    2962          sys.settrace(A())
    2963          sys.settrace(foo)
    2964          self.assertEqual(sys.gettrace(), bar)
    2965  
    2966  
    2967      def test_same_object(self):
    2968          def foo(*args):
    2969              ...
    2970  
    2971          sys.settrace(foo)
    2972          del foo
    2973          sys.settrace(sys.gettrace())
    2974  
    2975  
    2976  class ESC[4;38;5;81mTestLinesAfterTraceStarted(ESC[4;38;5;149mTraceTestCase):
    2977  
    2978      def test_events(self):
    2979          tracer = Tracer()
    2980          sys._getframe().f_trace = tracer.trace
    2981          sys.settrace(tracer.trace)
    2982          line = 4
    2983          line = 5
    2984          sys.settrace(None)
    2985          self.compare_events(
    2986              TestLinesAfterTraceStarted.test_events.__code__.co_firstlineno,
    2987              tracer.events, [
    2988                  (4, 'line'),
    2989                  (5, 'line'),
    2990                  (6, 'line')])
    2991  
    2992  
    2993  class ESC[4;38;5;81mTestSetLocalTrace(ESC[4;38;5;149mTraceTestCase):
    2994  
    2995      def test_with_branches(self):
    2996  
    2997          def tracefunc(frame, event, arg):
    2998              if frame.f_code.co_name == "func":
    2999                  frame.f_trace = tracefunc
    3000                  line = frame.f_lineno - frame.f_code.co_firstlineno
    3001                  events.append((line, event))
    3002              return tracefunc
    3003  
    3004          def func(arg = 1):
    3005              N = 1
    3006              if arg >= 2:
    3007                  not_reached = 3
    3008              else:
    3009                  reached = 5
    3010              if arg >= 3:
    3011                  not_reached = 7
    3012              else:
    3013                  reached = 9
    3014              the_end = 10
    3015  
    3016          EXPECTED_EVENTS = [
    3017              (0, 'call'),
    3018              (1, 'line'),
    3019              (2, 'line'),
    3020              (5, 'line'),
    3021              (6, 'line'),
    3022              (9, 'line'),
    3023              (10, 'line'),
    3024              (10, 'return'),
    3025          ]
    3026  
    3027          events = []
    3028          sys.settrace(tracefunc)
    3029          sys._getframe().f_trace = tracefunc
    3030          func()
    3031          self.assertEqual(events, EXPECTED_EVENTS)
    3032          sys.settrace(None)
    3033  
    3034  
    3035  if __name__ == "__main__":
    3036      unittest.main()