(root)/
Python-3.11.7/
Lib/
test/
test_dis.py
       1  # Minimal tests for dis module
       2  
       3  import contextlib
       4  import dis
       5  import io
       6  import re
       7  import sys
       8  import types
       9  import unittest
      10  from test.support import captured_stdout, requires_debug_ranges, cpython_only
      11  from test.support.bytecode_helper import BytecodeTestCase
      12  
      13  import opcode
      14  
      15  
      16  def get_tb():
      17      def _error():
      18          try:
      19              1 / 0
      20          except Exception as e:
      21              tb = e.__traceback__
      22          return tb
      23  
      24      tb = _error()
      25      while tb.tb_next:
      26          tb = tb.tb_next
      27      return tb
      28  
      29  TRACEBACK_CODE = get_tb().tb_frame.f_code
      30  
      31  class ESC[4;38;5;81m_C:
      32      def __init__(self, x):
      33          self.x = x == 1
      34  
      35      @staticmethod
      36      def sm(x):
      37          x = x == 1
      38  
      39      @classmethod
      40      def cm(cls, x):
      41          cls.x = x == 1
      42  
      43  dis_c_instance_method = """\
      44  %3d        RESUME                   0
      45  
      46  %3d        LOAD_FAST                1 (x)
      47             LOAD_CONST               1 (1)
      48             COMPARE_OP               2 (==)
      49             LOAD_FAST                0 (self)
      50             STORE_ATTR               0 (x)
      51             LOAD_CONST               0 (None)
      52             RETURN_VALUE
      53  """ % (_C.__init__.__code__.co_firstlineno, _C.__init__.__code__.co_firstlineno + 1,)
      54  
      55  dis_c_instance_method_bytes = """\
      56         RESUME                   0
      57         LOAD_FAST                1
      58         LOAD_CONST               1
      59         COMPARE_OP               2 (==)
      60         LOAD_FAST                0
      61         STORE_ATTR               0
      62         LOAD_CONST               0
      63         RETURN_VALUE
      64  """
      65  
      66  dis_c_class_method = """\
      67  %3d        RESUME                   0
      68  
      69  %3d        LOAD_FAST                1 (x)
      70             LOAD_CONST               1 (1)
      71             COMPARE_OP               2 (==)
      72             LOAD_FAST                0 (cls)
      73             STORE_ATTR               0 (x)
      74             LOAD_CONST               0 (None)
      75             RETURN_VALUE
      76  """ % (_C.cm.__code__.co_firstlineno, _C.cm.__code__.co_firstlineno + 2,)
      77  
      78  dis_c_static_method = """\
      79  %3d        RESUME                   0
      80  
      81  %3d        LOAD_FAST                0 (x)
      82             LOAD_CONST               1 (1)
      83             COMPARE_OP               2 (==)
      84             STORE_FAST               0 (x)
      85             LOAD_CONST               0 (None)
      86             RETURN_VALUE
      87  """ % (_C.sm.__code__.co_firstlineno, _C.sm.__code__.co_firstlineno + 2,)
      88  
      89  # Class disassembling info has an extra newline at end.
      90  dis_c = """\
      91  Disassembly of %s:
      92  %s
      93  Disassembly of %s:
      94  %s
      95  Disassembly of %s:
      96  %s
      97  """ % (_C.__init__.__name__, dis_c_instance_method,
      98         _C.cm.__name__, dis_c_class_method,
      99         _C.sm.__name__, dis_c_static_method)
     100  
     101  def _f(a):
     102      print(a)
     103      return 1
     104  
     105  dis_f = """\
     106  %3d        RESUME                   0
     107  
     108  %3d        LOAD_GLOBAL              1 (NULL + print)
     109             LOAD_FAST                0 (a)
     110             PRECALL                  1
     111             CALL                     1
     112             POP_TOP
     113  
     114  %3d        LOAD_CONST               1 (1)
     115             RETURN_VALUE
     116  """ % (_f.__code__.co_firstlineno,
     117         _f.__code__.co_firstlineno + 1,
     118         _f.__code__.co_firstlineno + 2)
     119  
     120  
     121  dis_f_co_code = """\
     122         RESUME                   0
     123         LOAD_GLOBAL              1
     124         LOAD_FAST                0
     125         PRECALL                  1
     126         CALL                     1
     127         POP_TOP
     128         LOAD_CONST               1
     129         RETURN_VALUE
     130  """
     131  
     132  
     133  def bug708901():
     134      for res in range(1,
     135                       10):
     136          pass
     137  
     138  dis_bug708901 = """\
     139  %3d        RESUME                   0
     140  
     141  %3d        LOAD_GLOBAL              1 (NULL + range)
     142             LOAD_CONST               1 (1)
     143  
     144  %3d        LOAD_CONST               2 (10)
     145  
     146  %3d        PRECALL                  2
     147             CALL                     2
     148             GET_ITER
     149          >> FOR_ITER                 2 (to 40)
     150             STORE_FAST               0 (res)
     151  
     152  %3d        JUMP_BACKWARD            3 (to 34)
     153  
     154  %3d     >> LOAD_CONST               0 (None)
     155             RETURN_VALUE
     156  """ % (bug708901.__code__.co_firstlineno,
     157         bug708901.__code__.co_firstlineno + 1,
     158         bug708901.__code__.co_firstlineno + 2,
     159         bug708901.__code__.co_firstlineno + 1,
     160         bug708901.__code__.co_firstlineno + 3,
     161         bug708901.__code__.co_firstlineno + 1)
     162  
     163  
     164  def bug1333982(x=[]):
     165      assert 0, ([s for s in x] +
     166                1)
     167      pass
     168  
     169  dis_bug1333982 = """\
     170  %3d        RESUME                   0
     171  
     172  %3d        LOAD_ASSERTION_ERROR
     173             LOAD_CONST               2 (<code object <listcomp> at 0x..., file "%s", line %d>)
     174             MAKE_FUNCTION            0
     175             LOAD_FAST                0 (x)
     176             GET_ITER
     177             PRECALL                  0
     178             CALL                     0
     179  
     180  %3d        LOAD_CONST               3 (1)
     181  
     182  %3d        BINARY_OP                0 (+)
     183             PRECALL                  0
     184             CALL                     0
     185             RAISE_VARARGS            1
     186  """ % (bug1333982.__code__.co_firstlineno,
     187         bug1333982.__code__.co_firstlineno + 1,
     188         __file__,
     189         bug1333982.__code__.co_firstlineno + 1,
     190         bug1333982.__code__.co_firstlineno + 2,
     191         bug1333982.__code__.co_firstlineno + 1)
     192  
     193  
     194  def bug42562():
     195      pass
     196  
     197  
     198  # Set line number for 'pass' to None
     199  bug42562.__code__ = bug42562.__code__.replace(co_linetable=b'\xf8')
     200  
     201  
     202  dis_bug42562 = """\
     203         RESUME                   0
     204         LOAD_CONST               0 (None)
     205         RETURN_VALUE
     206  """
     207  
     208  # Extended arg followed by NOP
     209  code_bug_45757 = bytes([
     210          0x90, 0x01,  # EXTENDED_ARG 0x01
     211          0x09, 0xFF,  # NOP 0xFF
     212          0x90, 0x01,  # EXTENDED_ARG 0x01
     213          0x64, 0x29,  # LOAD_CONST 0x29
     214          0x53, 0x00,  # RETURN_VALUE 0x00
     215      ])
     216  
     217  dis_bug_45757 = """\
     218         EXTENDED_ARG             1
     219         NOP
     220         EXTENDED_ARG             1
     221         LOAD_CONST             297
     222         RETURN_VALUE
     223  """
     224  
     225  # [255, 255, 255, 252] is -4 in a 4 byte signed integer
     226  bug46724 = bytes([
     227      opcode.EXTENDED_ARG, 255,
     228      opcode.EXTENDED_ARG, 255,
     229      opcode.EXTENDED_ARG, 255,
     230      opcode.opmap['JUMP_FORWARD'], 252,
     231  ])
     232  
     233  
     234  dis_bug46724 = """\
     235      >> EXTENDED_ARG           255
     236         EXTENDED_ARG         65535
     237         EXTENDED_ARG         16777215
     238         JUMP_FORWARD            -4 (to 0)
     239  """
     240  
     241  _BIG_LINENO_FORMAT = """\
     242    1        RESUME                   0
     243  
     244  %3d        LOAD_GLOBAL              0 (spam)
     245             POP_TOP
     246             LOAD_CONST               0 (None)
     247             RETURN_VALUE
     248  """
     249  
     250  _BIG_LINENO_FORMAT2 = """\
     251     1        RESUME                   0
     252  
     253  %4d        LOAD_GLOBAL              0 (spam)
     254              POP_TOP
     255              LOAD_CONST               0 (None)
     256              RETURN_VALUE
     257  """
     258  
     259  dis_module_expected_results = """\
     260  Disassembly of f:
     261    4        RESUME                   0
     262             LOAD_CONST               0 (None)
     263             RETURN_VALUE
     264  
     265  Disassembly of g:
     266    5        RESUME                   0
     267             LOAD_CONST               0 (None)
     268             RETURN_VALUE
     269  
     270  """
     271  
     272  expr_str = "x + 1"
     273  
     274  dis_expr_str = """\
     275    0        RESUME                   0
     276  
     277    1        LOAD_NAME                0 (x)
     278             LOAD_CONST               0 (1)
     279             BINARY_OP                0 (+)
     280             RETURN_VALUE
     281  """
     282  
     283  simple_stmt_str = "x = x + 1"
     284  
     285  dis_simple_stmt_str = """\
     286    0        RESUME                   0
     287  
     288    1        LOAD_NAME                0 (x)
     289             LOAD_CONST               0 (1)
     290             BINARY_OP                0 (+)
     291             STORE_NAME               0 (x)
     292             LOAD_CONST               1 (None)
     293             RETURN_VALUE
     294  """
     295  
     296  annot_stmt_str = """\
     297  
     298  x: int = 1
     299  y: fun(1)
     300  lst[fun(0)]: int = 1
     301  """
     302  # leading newline is for a reason (tests lineno)
     303  
     304  dis_annot_stmt_str = """\
     305    0        RESUME                   0
     306  
     307    2        SETUP_ANNOTATIONS
     308             LOAD_CONST               0 (1)
     309             STORE_NAME               0 (x)
     310             LOAD_NAME                1 (int)
     311             LOAD_NAME                2 (__annotations__)
     312             LOAD_CONST               1 ('x')
     313             STORE_SUBSCR
     314  
     315    3        PUSH_NULL
     316             LOAD_NAME                3 (fun)
     317             LOAD_CONST               0 (1)
     318             PRECALL                  1
     319             CALL                     1
     320             LOAD_NAME                2 (__annotations__)
     321             LOAD_CONST               2 ('y')
     322             STORE_SUBSCR
     323  
     324    4        LOAD_CONST               0 (1)
     325             LOAD_NAME                4 (lst)
     326             PUSH_NULL
     327             LOAD_NAME                3 (fun)
     328             LOAD_CONST               3 (0)
     329             PRECALL                  1
     330             CALL                     1
     331             STORE_SUBSCR
     332             LOAD_NAME                1 (int)
     333             POP_TOP
     334             LOAD_CONST               4 (None)
     335             RETURN_VALUE
     336  """
     337  
     338  compound_stmt_str = """\
     339  x = 0
     340  while 1:
     341      x += 1"""
     342  # Trailing newline has been deliberately omitted
     343  
     344  dis_compound_stmt_str = """\
     345    0        RESUME                   0
     346  
     347    1        LOAD_CONST               0 (0)
     348             STORE_NAME               0 (x)
     349  
     350    2        NOP
     351  
     352    3     >> LOAD_NAME                0 (x)
     353             LOAD_CONST               1 (1)
     354             BINARY_OP               13 (+=)
     355             STORE_NAME               0 (x)
     356  
     357    2        JUMP_BACKWARD            6 (to 8)
     358  """
     359  
     360  dis_traceback = """\
     361  %3d        RESUME                   0
     362  
     363  %3d        NOP
     364  
     365  %3d        LOAD_CONST               1 (1)
     366             LOAD_CONST               2 (0)
     367      -->    BINARY_OP               11 (/)
     368             POP_TOP
     369             JUMP_FORWARD            30 (to 76)
     370          >> PUSH_EXC_INFO
     371  
     372  %3d        LOAD_GLOBAL              0 (Exception)
     373             CHECK_EXC_MATCH
     374             POP_JUMP_FORWARD_IF_FALSE    17 (to 68)
     375             STORE_FAST               0 (e)
     376  
     377  %3d        LOAD_FAST                0 (e)
     378             LOAD_ATTR                1 (__traceback__)
     379             STORE_FAST               1 (tb)
     380             POP_EXCEPT
     381             LOAD_CONST               0 (None)
     382             STORE_FAST               0 (e)
     383             DELETE_FAST              0 (e)
     384             JUMP_FORWARD             8 (to 76)
     385          >> LOAD_CONST               0 (None)
     386             STORE_FAST               0 (e)
     387             DELETE_FAST              0 (e)
     388             RERAISE                  1
     389  
     390  %3d     >> RERAISE                  0
     391          >> COPY                     3
     392             POP_EXCEPT
     393             RERAISE                  1
     394  
     395  %3d     >> LOAD_FAST                1 (tb)
     396             RETURN_VALUE
     397  ExceptionTable:
     398  """ % (TRACEBACK_CODE.co_firstlineno,
     399         TRACEBACK_CODE.co_firstlineno + 1,
     400         TRACEBACK_CODE.co_firstlineno + 2,
     401         TRACEBACK_CODE.co_firstlineno + 3,
     402         TRACEBACK_CODE.co_firstlineno + 4,
     403         TRACEBACK_CODE.co_firstlineno + 3,
     404         TRACEBACK_CODE.co_firstlineno + 5)
     405  
     406  def _fstring(a, b, c, d):
     407      return f'{a} {b:4} {c!r} {d!r:4}'
     408  
     409  dis_fstring = """\
     410  %3d        RESUME                   0
     411  
     412  %3d        LOAD_FAST                0 (a)
     413             FORMAT_VALUE             0
     414             LOAD_CONST               1 (' ')
     415             LOAD_FAST                1 (b)
     416             LOAD_CONST               2 ('4')
     417             FORMAT_VALUE             4 (with format)
     418             LOAD_CONST               1 (' ')
     419             LOAD_FAST                2 (c)
     420             FORMAT_VALUE             2 (repr)
     421             LOAD_CONST               1 (' ')
     422             LOAD_FAST                3 (d)
     423             LOAD_CONST               2 ('4')
     424             FORMAT_VALUE             6 (repr, with format)
     425             BUILD_STRING             7
     426             RETURN_VALUE
     427  """ % (_fstring.__code__.co_firstlineno, _fstring.__code__.co_firstlineno + 1)
     428  
     429  def _tryfinally(a, b):
     430      try:
     431          return a
     432      finally:
     433          b()
     434  
     435  def _tryfinallyconst(b):
     436      try:
     437          return 1
     438      finally:
     439          b()
     440  
     441  dis_tryfinally = """\
     442  %3d        RESUME                   0
     443  
     444  %3d        NOP
     445  
     446  %3d        LOAD_FAST                0 (a)
     447  
     448  %3d        PUSH_NULL
     449             LOAD_FAST                1 (b)
     450             PRECALL                  0
     451             CALL                     0
     452             POP_TOP
     453             RETURN_VALUE
     454          >> PUSH_EXC_INFO
     455             PUSH_NULL
     456             LOAD_FAST                1 (b)
     457             PRECALL                  0
     458             CALL                     0
     459             POP_TOP
     460             RERAISE                  0
     461          >> COPY                     3
     462             POP_EXCEPT
     463             RERAISE                  1
     464  ExceptionTable:
     465  """ % (_tryfinally.__code__.co_firstlineno,
     466         _tryfinally.__code__.co_firstlineno + 1,
     467         _tryfinally.__code__.co_firstlineno + 2,
     468         _tryfinally.__code__.co_firstlineno + 4,
     469         )
     470  
     471  dis_tryfinallyconst = """\
     472  %3d        RESUME                   0
     473  
     474  %3d        NOP
     475  
     476  %3d        NOP
     477  
     478  %3d        PUSH_NULL
     479             LOAD_FAST                0 (b)
     480             PRECALL                  0
     481             CALL                     0
     482             POP_TOP
     483             LOAD_CONST               1 (1)
     484             RETURN_VALUE
     485             PUSH_EXC_INFO
     486             PUSH_NULL
     487             LOAD_FAST                0 (b)
     488             PRECALL                  0
     489             CALL                     0
     490             POP_TOP
     491             RERAISE                  0
     492          >> COPY                     3
     493             POP_EXCEPT
     494             RERAISE                  1
     495  ExceptionTable:
     496  """ % (_tryfinallyconst.__code__.co_firstlineno,
     497         _tryfinallyconst.__code__.co_firstlineno + 1,
     498         _tryfinallyconst.__code__.co_firstlineno + 2,
     499         _tryfinallyconst.__code__.co_firstlineno + 4,
     500         )
     501  
     502  def _g(x):
     503      yield x
     504  
     505  async def _ag(x):
     506      yield x
     507  
     508  async def _co(x):
     509      async for item in _ag(x):
     510          pass
     511  
     512  def _h(y):
     513      def foo(x):
     514          '''funcdoc'''
     515          return [x + z for z in y]
     516      return foo
     517  
     518  dis_nested_0 = """\
     519             MAKE_CELL                0 (y)
     520  
     521  %3d        RESUME                   0
     522  
     523  %3d        LOAD_CLOSURE             0 (y)
     524             BUILD_TUPLE              1
     525             LOAD_CONST               1 (<code object foo at 0x..., file "%s", line %d>)
     526             MAKE_FUNCTION            8 (closure)
     527             STORE_FAST               1 (foo)
     528  
     529  %3d        LOAD_FAST                1 (foo)
     530             RETURN_VALUE
     531  """ % (_h.__code__.co_firstlineno,
     532         _h.__code__.co_firstlineno + 1,
     533         __file__,
     534         _h.__code__.co_firstlineno + 1,
     535         _h.__code__.co_firstlineno + 4,
     536  )
     537  
     538  dis_nested_1 = """%s
     539  Disassembly of <code object foo at 0x..., file "%s", line %d>:
     540             COPY_FREE_VARS           1
     541             MAKE_CELL                0 (x)
     542  
     543  %3d        RESUME                   0
     544  
     545  %3d        LOAD_CLOSURE             0 (x)
     546             BUILD_TUPLE              1
     547             LOAD_CONST               1 (<code object <listcomp> at 0x..., file "%s", line %d>)
     548             MAKE_FUNCTION            8 (closure)
     549             LOAD_DEREF               1 (y)
     550             GET_ITER
     551             PRECALL                  0
     552             CALL                     0
     553             RETURN_VALUE
     554  """ % (dis_nested_0,
     555         __file__,
     556         _h.__code__.co_firstlineno + 1,
     557         _h.__code__.co_firstlineno + 1,
     558         _h.__code__.co_firstlineno + 3,
     559         __file__,
     560         _h.__code__.co_firstlineno + 3,
     561  )
     562  
     563  dis_nested_2 = """%s
     564  Disassembly of <code object <listcomp> at 0x..., file "%s", line %d>:
     565             COPY_FREE_VARS           1
     566  
     567  %3d        RESUME                   0
     568             BUILD_LIST               0
     569             LOAD_FAST                0 (.0)
     570          >> FOR_ITER                 7 (to 24)
     571             STORE_FAST               1 (z)
     572             LOAD_DEREF               2 (x)
     573             LOAD_FAST                1 (z)
     574             BINARY_OP                0 (+)
     575             LIST_APPEND              2
     576             JUMP_BACKWARD            8 (to 8)
     577          >> RETURN_VALUE
     578  """ % (dis_nested_1,
     579         __file__,
     580         _h.__code__.co_firstlineno + 3,
     581         _h.__code__.co_firstlineno + 3,
     582  )
     583  
     584  def load_test(x, y=0):
     585      a, b = x, y
     586      return a, b
     587  
     588  dis_load_test_quickened_code = """\
     589  %3d           0 RESUME_QUICK             0
     590  
     591  %3d           2 LOAD_FAST__LOAD_FAST     0 (x)
     592                4 LOAD_FAST                1 (y)
     593                6 STORE_FAST__STORE_FAST     3 (b)
     594                8 STORE_FAST__LOAD_FAST     2 (a)
     595  
     596  %3d          10 LOAD_FAST__LOAD_FAST     2 (a)
     597               12 LOAD_FAST                3 (b)
     598               14 BUILD_TUPLE              2
     599               16 RETURN_VALUE
     600  """ % (load_test.__code__.co_firstlineno,
     601         load_test.__code__.co_firstlineno + 1,
     602         load_test.__code__.co_firstlineno + 2)
     603  
     604  def loop_test():
     605      for i in [1, 2, 3] * 3:
     606          load_test(i)
     607  
     608  dis_loop_test_quickened_code = """\
     609  %3d           0 RESUME_QUICK             0
     610  
     611  %3d           2 BUILD_LIST               0
     612                4 LOAD_CONST               1 ((1, 2, 3))
     613                6 LIST_EXTEND              1
     614                8 LOAD_CONST               2 (3)
     615               10 BINARY_OP_ADAPTIVE       5 (*)
     616               14 GET_ITER
     617               16 FOR_ITER                17 (to 52)
     618               18 STORE_FAST               0 (i)
     619  
     620  %3d          20 LOAD_GLOBAL_MODULE       1 (NULL + load_test)
     621               32 LOAD_FAST                0 (i)
     622               34 PRECALL_PYFUNC           1
     623               38 CALL_PY_WITH_DEFAULTS     1
     624               48 POP_TOP
     625               50 JUMP_BACKWARD_QUICK     18 (to 16)
     626  
     627  %3d     >>   52 LOAD_CONST               0 (None)
     628               54 RETURN_VALUE
     629  """ % (loop_test.__code__.co_firstlineno,
     630         loop_test.__code__.co_firstlineno + 1,
     631         loop_test.__code__.co_firstlineno + 2,
     632         loop_test.__code__.co_firstlineno + 1,)
     633  
     634  def extended_arg_quick():
     635      *_, _ = ...
     636  
     637  dis_extended_arg_quick_code = """\
     638  %3d           0 RESUME                   0
     639  
     640  %3d           2 LOAD_CONST               1 (Ellipsis)
     641                4 EXTENDED_ARG             1
     642                6 UNPACK_EX              256
     643                8 STORE_FAST               0 (_)
     644               10 STORE_FAST               0 (_)
     645               12 LOAD_CONST               0 (None)
     646               14 RETURN_VALUE
     647  """% (extended_arg_quick.__code__.co_firstlineno,
     648        extended_arg_quick.__code__.co_firstlineno + 1,)
     649  
     650  QUICKENING_WARMUP_DELAY = 8
     651  
     652  class ESC[4;38;5;81mDisTestBase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     653      "Common utilities for DisTests and TestDisTraceback"
     654  
     655      def strip_addresses(self, text):
     656          return re.sub(r'\b0x[0-9A-Fa-f]+\b', '0x...', text)
     657  
     658      def find_offset_column(self, lines):
     659          for line in lines:
     660              if line and not line.startswith("Disassembly"):
     661                  break
     662          else:
     663              return 0, 0
     664          offset = 5
     665          while (line[offset] == " "):
     666              offset += 1
     667          if (line[offset] == ">"):
     668              offset += 2
     669          while (line[offset] == " "):
     670              offset += 1
     671          end = offset
     672          while line[end] in "0123456789":
     673              end += 1
     674          return end-5, end
     675  
     676      def assert_offsets_increasing(self, text, delta):
     677          expected_offset = 0
     678          lines = text.splitlines()
     679          start, end = self.find_offset_column(lines)
     680          for line in lines:
     681              if not line:
     682                  continue
     683              if line.startswith("Disassembly"):
     684                  expected_offset = 0
     685                  continue
     686              if line.startswith("Exception"):
     687                  break
     688              offset = int(line[start:end])
     689              self.assertGreaterEqual(offset, expected_offset, line)
     690              expected_offset = offset + delta
     691  
     692      def strip_offsets(self, text):
     693          lines = text.splitlines(True)
     694          start, end = self.find_offset_column(lines)
     695          res = []
     696          lines = iter(lines)
     697          for line in lines:
     698              if line.startswith("Exception"):
     699                  res.append(line)
     700                  break
     701              if not line or line.startswith("Disassembly"):
     702                  res.append(line)
     703              else:
     704                  res.append(line[:start] + line[end:])
     705          return "".join(res)
     706  
     707      def do_disassembly_compare(self, got, expected, with_offsets=False):
     708          if not with_offsets:
     709              self.assert_offsets_increasing(got, 2)
     710              got = self.strip_offsets(got)
     711          if got != expected:
     712              got = self.strip_addresses(got)
     713          self.assertEqual(got, expected)
     714  
     715  
     716  class ESC[4;38;5;81mDisTests(ESC[4;38;5;149mDisTestBase):
     717  
     718      maxDiff = None
     719  
     720      def get_disassembly(self, func, lasti=-1, wrapper=True, **kwargs):
     721          # We want to test the default printing behaviour, not the file arg
     722          output = io.StringIO()
     723          with contextlib.redirect_stdout(output):
     724              if wrapper:
     725                  dis.dis(func, **kwargs)
     726              else:
     727                  dis.disassemble(func, lasti, **kwargs)
     728          return output.getvalue()
     729  
     730      def get_disassemble_as_string(self, func, lasti=-1):
     731          return self.get_disassembly(func, lasti, False)
     732  
     733      def do_disassembly_test(self, func, expected, with_offsets=False):
     734          self.maxDiff = None
     735          got = self.get_disassembly(func, depth=0)
     736          self.do_disassembly_compare(got, expected, with_offsets)
     737  
     738      def test_opmap(self):
     739          self.assertEqual(dis.opmap["NOP"], 9)
     740          self.assertIn(dis.opmap["LOAD_CONST"], dis.hasconst)
     741          self.assertIn(dis.opmap["STORE_NAME"], dis.hasname)
     742  
     743      def test_opname(self):
     744          self.assertEqual(dis.opname[dis.opmap["LOAD_FAST"]], "LOAD_FAST")
     745  
     746      def test_boundaries(self):
     747          self.assertEqual(dis.opmap["EXTENDED_ARG"], dis.EXTENDED_ARG)
     748          self.assertEqual(dis.opmap["STORE_NAME"], dis.HAVE_ARGUMENT)
     749  
     750      def test_widths(self):
     751          long_opcodes = set(['POP_JUMP_FORWARD_IF_FALSE',
     752                              'POP_JUMP_FORWARD_IF_TRUE',
     753                              'POP_JUMP_FORWARD_IF_NOT_NONE',
     754                              'POP_JUMP_FORWARD_IF_NONE',
     755                              'POP_JUMP_BACKWARD_IF_FALSE',
     756                              'POP_JUMP_BACKWARD_IF_TRUE',
     757                              'POP_JUMP_BACKWARD_IF_NOT_NONE',
     758                              'POP_JUMP_BACKWARD_IF_NONE',
     759                              'JUMP_BACKWARD_NO_INTERRUPT',
     760                             ])
     761          for opcode, opname in enumerate(dis.opname):
     762              if opname in long_opcodes:
     763                  continue
     764              with self.subTest(opname=opname):
     765                  width = dis._OPNAME_WIDTH
     766                  if opcode < dis.HAVE_ARGUMENT:
     767                      width += 1 + dis._OPARG_WIDTH
     768                  self.assertLessEqual(len(opname), width)
     769  
     770      def test_dis(self):
     771          self.do_disassembly_test(_f, dis_f)
     772  
     773      def test_bug_708901(self):
     774          self.do_disassembly_test(bug708901, dis_bug708901)
     775  
     776      def test_bug_1333982(self):
     777          # This one is checking bytecodes generated for an `assert` statement,
     778          # so fails if the tests are run with -O.  Skip this test then.
     779          if not __debug__:
     780              self.skipTest('need asserts, run without -O')
     781  
     782          self.do_disassembly_test(bug1333982, dis_bug1333982)
     783  
     784      def test_bug_42562(self):
     785          self.do_disassembly_test(bug42562, dis_bug42562)
     786  
     787      def test_bug_45757(self):
     788          # Extended arg followed by NOP
     789          self.do_disassembly_test(code_bug_45757, dis_bug_45757)
     790  
     791      def test_bug_46724(self):
     792          # Test that negative operargs are handled properly
     793          self.do_disassembly_test(bug46724, dis_bug46724)
     794  
     795      def test_big_linenos(self):
     796          def func(count):
     797              namespace = {}
     798              func = "def foo():\n " + "".join(["\n "] * count + ["spam\n"])
     799              exec(func, namespace)
     800              return namespace['foo']
     801  
     802          # Test all small ranges
     803          for i in range(1, 300):
     804              expected = _BIG_LINENO_FORMAT % (i + 2)
     805              self.do_disassembly_test(func(i), expected)
     806  
     807          # Test some larger ranges too
     808          for i in range(300, 1000, 10):
     809              expected = _BIG_LINENO_FORMAT % (i + 2)
     810              self.do_disassembly_test(func(i), expected)
     811  
     812          for i in range(1000, 5000, 10):
     813              expected = _BIG_LINENO_FORMAT2 % (i + 2)
     814              self.do_disassembly_test(func(i), expected)
     815  
     816          from test import dis_module
     817          self.do_disassembly_test(dis_module, dis_module_expected_results)
     818  
     819      def test_big_offsets(self):
     820          self.maxDiff = None
     821          def func(count):
     822              namespace = {}
     823              func = "def foo(x):\n " + ";".join(["x = x + 1"] * count) + "\n return x"
     824              exec(func, namespace)
     825              return namespace['foo']
     826  
     827          def expected(count, w):
     828              s = ['''\
     829    1        %*d RESUME                   0
     830  
     831  ''' % (w, 0)]
     832              s += ['''\
     833             %*d LOAD_FAST                0 (x)
     834             %*d LOAD_CONST               1 (1)
     835             %*d BINARY_OP                0 (+)
     836             %*d STORE_FAST               0 (x)
     837  ''' % (w, 10*i + 2, w, 10*i + 4, w, 10*i + 6, w, 10*i + 10)
     838                   for i in range(count)]
     839              s += ['''\
     840  
     841    3        %*d LOAD_FAST                0 (x)
     842             %*d RETURN_VALUE
     843  ''' % (w, 10*count + 2, w, 10*count + 4)]
     844              s[1] = '  2' + s[1][3:]
     845              return ''.join(s)
     846  
     847          for i in range(1, 5):
     848              self.do_disassembly_test(func(i), expected(i, 4), True)
     849          self.do_disassembly_test(func(999), expected(999, 4), True)
     850          self.do_disassembly_test(func(1000), expected(1000, 5), True)
     851  
     852      def test_disassemble_str(self):
     853          self.do_disassembly_test(expr_str, dis_expr_str)
     854          self.do_disassembly_test(simple_stmt_str, dis_simple_stmt_str)
     855          self.do_disassembly_test(annot_stmt_str, dis_annot_stmt_str)
     856          self.do_disassembly_test(compound_stmt_str, dis_compound_stmt_str)
     857  
     858      def test_disassemble_bytes(self):
     859          self.do_disassembly_test(_f.__code__.co_code, dis_f_co_code)
     860  
     861      def test_disassemble_class(self):
     862          self.do_disassembly_test(_C, dis_c)
     863  
     864      def test_disassemble_instance_method(self):
     865          self.do_disassembly_test(_C(1).__init__, dis_c_instance_method)
     866  
     867      def test_disassemble_instance_method_bytes(self):
     868          method_bytecode = _C(1).__init__.__code__.co_code
     869          self.do_disassembly_test(method_bytecode, dis_c_instance_method_bytes)
     870  
     871      def test_disassemble_static_method(self):
     872          self.do_disassembly_test(_C.sm, dis_c_static_method)
     873  
     874      def test_disassemble_class_method(self):
     875          self.do_disassembly_test(_C.cm, dis_c_class_method)
     876  
     877      def test_disassemble_generator(self):
     878          gen_func_disas = self.get_disassembly(_g)  # Generator function
     879          gen_disas = self.get_disassembly(_g(1))  # Generator iterator
     880          self.assertEqual(gen_disas, gen_func_disas)
     881  
     882      def test_disassemble_async_generator(self):
     883          agen_func_disas = self.get_disassembly(_ag)  # Async generator function
     884          agen_disas = self.get_disassembly(_ag(1))  # Async generator iterator
     885          self.assertEqual(agen_disas, agen_func_disas)
     886  
     887      def test_disassemble_coroutine(self):
     888          coro_func_disas = self.get_disassembly(_co)  # Coroutine function
     889          coro = _co(1)  # Coroutine object
     890          coro.close()  # Avoid a RuntimeWarning (never awaited)
     891          coro_disas = self.get_disassembly(coro)
     892          self.assertEqual(coro_disas, coro_func_disas)
     893  
     894      def test_disassemble_fstring(self):
     895          self.do_disassembly_test(_fstring, dis_fstring)
     896  
     897      def test_disassemble_try_finally(self):
     898          self.do_disassembly_test(_tryfinally, dis_tryfinally)
     899          self.do_disassembly_test(_tryfinallyconst, dis_tryfinallyconst)
     900  
     901      def test_dis_none(self):
     902          try:
     903              del sys.last_traceback
     904          except AttributeError:
     905              pass
     906          self.assertRaises(RuntimeError, dis.dis, None)
     907  
     908      def test_dis_traceback(self):
     909          self.maxDiff = None
     910          try:
     911              del sys.last_traceback
     912          except AttributeError:
     913              pass
     914  
     915          try:
     916              1/0
     917          except Exception as e:
     918              tb = e.__traceback__
     919              sys.last_traceback = tb
     920  
     921          tb_dis = self.get_disassemble_as_string(tb.tb_frame.f_code, tb.tb_lasti)
     922          self.do_disassembly_test(None, tb_dis, True)
     923  
     924      def test_dis_object(self):
     925          self.assertRaises(TypeError, dis.dis, object())
     926  
     927      def test_disassemble_recursive(self):
     928          def check(expected, **kwargs):
     929              dis = self.get_disassembly(_h, **kwargs)
     930              dis = self.strip_addresses(dis)
     931              dis = self.strip_offsets(dis)
     932              self.assertEqual(dis, expected)
     933  
     934          check(dis_nested_0, depth=0)
     935          check(dis_nested_1, depth=1)
     936          check(dis_nested_2, depth=2)
     937          check(dis_nested_2, depth=3)
     938          check(dis_nested_2, depth=None)
     939          check(dis_nested_2)
     940  
     941      @staticmethod
     942      def code_quicken(f, times=QUICKENING_WARMUP_DELAY):
     943          for _ in range(times):
     944              f()
     945  
     946      @cpython_only
     947      def test_super_instructions(self):
     948          self.code_quicken(lambda: load_test(0, 0))
     949          got = self.get_disassembly(load_test, adaptive=True)
     950          self.do_disassembly_compare(got, dis_load_test_quickened_code, True)
     951  
     952      @cpython_only
     953      def test_binary_specialize(self):
     954          binary_op_quicken = """\
     955    0           0 RESUME_QUICK             0
     956  
     957    1           2 LOAD_NAME                0 (a)
     958                4 LOAD_NAME                1 (b)
     959                6 %s
     960               10 RETURN_VALUE
     961  """
     962          co_int = compile('a + b', "<int>", "eval")
     963          self.code_quicken(lambda: exec(co_int, {}, {'a': 1, 'b': 2}))
     964          got = self.get_disassembly(co_int, adaptive=True)
     965          self.do_disassembly_compare(got, binary_op_quicken % "BINARY_OP_ADD_INT        0 (+)", True)
     966  
     967          co_unicode = compile('a + b', "<unicode>", "eval")
     968          self.code_quicken(lambda: exec(co_unicode, {}, {'a': 'a', 'b': 'b'}))
     969          got = self.get_disassembly(co_unicode, adaptive=True)
     970          self.do_disassembly_compare(got, binary_op_quicken % "BINARY_OP_ADD_UNICODE     0 (+)", True)
     971  
     972          binary_subscr_quicken = """\
     973    0           0 RESUME_QUICK             0
     974  
     975    1           2 LOAD_NAME                0 (a)
     976                4 LOAD_CONST               0 (0)
     977                6 %s
     978               16 RETURN_VALUE
     979  """
     980          co_list = compile('a[0]', "<list>", "eval")
     981          self.code_quicken(lambda: exec(co_list, {}, {'a': [0]}))
     982          got = self.get_disassembly(co_list, adaptive=True)
     983          self.do_disassembly_compare(got, binary_subscr_quicken % "BINARY_SUBSCR_LIST_INT", True)
     984  
     985          co_dict = compile('a[0]', "<dict>", "eval")
     986          self.code_quicken(lambda: exec(co_dict, {}, {'a': {0: '1'}}))
     987          got = self.get_disassembly(co_dict, adaptive=True)
     988          self.do_disassembly_compare(got, binary_subscr_quicken % "BINARY_SUBSCR_DICT", True)
     989  
     990      @cpython_only
     991      def test_load_attr_specialize(self):
     992          load_attr_quicken = """\
     993    0           0 RESUME_QUICK             0
     994  
     995    1           2 LOAD_CONST               0 ('a')
     996                4 LOAD_ATTR_SLOT           0 (__class__)
     997               14 RETURN_VALUE
     998  """
     999          co = compile("'a'.__class__", "", "eval")
    1000          self.code_quicken(lambda: exec(co, {}, {}))
    1001          got = self.get_disassembly(co, adaptive=True)
    1002          self.do_disassembly_compare(got, load_attr_quicken, True)
    1003  
    1004      @cpython_only
    1005      def test_call_specialize(self):
    1006          call_quicken = """\
    1007    0           0 RESUME_QUICK             0
    1008  
    1009    1           2 PUSH_NULL
    1010                4 LOAD_NAME                0 (str)
    1011                6 LOAD_CONST               0 (1)
    1012                8 PRECALL_NO_KW_STR_1      1
    1013               12 CALL_ADAPTIVE            1
    1014               22 RETURN_VALUE
    1015  """
    1016          co = compile("str(1)", "", "eval")
    1017          self.code_quicken(lambda: exec(co, {}, {}))
    1018          got = self.get_disassembly(co, adaptive=True)
    1019          self.do_disassembly_compare(got, call_quicken, True)
    1020  
    1021      @cpython_only
    1022      def test_loop_quicken(self):
    1023          # Loop can trigger a quicken where the loop is located
    1024          self.code_quicken(loop_test, 1)
    1025          got = self.get_disassembly(loop_test, adaptive=True)
    1026          self.do_disassembly_compare(got, dis_loop_test_quickened_code, True)
    1027  
    1028      @cpython_only
    1029      def test_extended_arg_quick(self):
    1030          got = self.get_disassembly(extended_arg_quick)
    1031          self.do_disassembly_compare(got, dis_extended_arg_quick_code, True)
    1032  
    1033      def get_cached_values(self, quickened, adaptive):
    1034          def f():
    1035              l = []
    1036              for i in range(42):
    1037                  l.append(i)
    1038          if quickened:
    1039              self.code_quicken(f)
    1040          else:
    1041              # "copy" the code to un-quicken it:
    1042              f.__code__ = f.__code__.replace()
    1043          for instruction in dis.get_instructions(
    1044              f, show_caches=True, adaptive=adaptive
    1045          ):
    1046              if instruction.opname == "CACHE":
    1047                  yield instruction.argrepr
    1048  
    1049      @cpython_only
    1050      def test_show_caches(self):
    1051          for quickened in (False, True):
    1052              for adaptive in (False, True):
    1053                  with self.subTest(f"{quickened=}, {adaptive=}"):
    1054                      if quickened and adaptive:
    1055                          pattern = r"^(\w+: \d+)?$"
    1056                      else:
    1057                          pattern = r"^(\w+: 0)?$"
    1058                      caches = list(self.get_cached_values(quickened, adaptive))
    1059                      for cache in caches:
    1060                          self.assertRegex(cache, pattern)
    1061                      total_caches = 25
    1062                      empty_caches = 8 if adaptive and quickened else total_caches
    1063                      self.assertEqual(caches.count(""), empty_caches)
    1064                      self.assertEqual(len(caches), total_caches)
    1065  
    1066  
    1067  class ESC[4;38;5;81mDisWithFileTests(ESC[4;38;5;149mDisTests):
    1068  
    1069      # Run the tests again, using the file arg instead of print
    1070      def get_disassembly(self, func, lasti=-1, wrapper=True, **kwargs):
    1071          output = io.StringIO()
    1072          if wrapper:
    1073              dis.dis(func, file=output, **kwargs)
    1074          else:
    1075              dis.disassemble(func, lasti, file=output, **kwargs)
    1076          return output.getvalue()
    1077  
    1078  
    1079  if dis.code_info.__doc__ is None:
    1080      code_info_consts = "0: None"
    1081  else:
    1082      code_info_consts = "0: 'Formatted details of methods, functions, or code.'"
    1083  
    1084  code_info_code_info = f"""\
    1085  Name:              code_info
    1086  Filename:          (.*)
    1087  Argument count:    1
    1088  Positional-only arguments: 0
    1089  Kw-only arguments: 0
    1090  Number of locals:  1
    1091  Stack size:        \\d+
    1092  Flags:             OPTIMIZED, NEWLOCALS
    1093  Constants:
    1094     {code_info_consts}
    1095  Names:
    1096     0: _format_code_info
    1097     1: _get_code_object
    1098  Variable names:
    1099     0: x"""
    1100  
    1101  
    1102  @staticmethod
    1103  def tricky(a, b, /, x, y, z=True, *args, c, d, e=[], **kwds):
    1104      def f(c=c):
    1105          print(a, b, x, y, z, c, d, e, f)
    1106      yield a, b, x, y, z, c, d, e, f
    1107  
    1108  code_info_tricky = """\
    1109  Name:              tricky
    1110  Filename:          (.*)
    1111  Argument count:    5
    1112  Positional-only arguments: 2
    1113  Kw-only arguments: 3
    1114  Number of locals:  10
    1115  Stack size:        \\d+
    1116  Flags:             OPTIMIZED, NEWLOCALS, VARARGS, VARKEYWORDS, GENERATOR
    1117  Constants:
    1118     0: None
    1119     1: <code object f at (.*), file "(.*)", line (.*)>
    1120  Variable names:
    1121     0: a
    1122     1: b
    1123     2: x
    1124     3: y
    1125     4: z
    1126     5: c
    1127     6: d
    1128     7: e
    1129     8: args
    1130     9: kwds
    1131  Cell variables:
    1132     0: [abedfxyz]
    1133     1: [abedfxyz]
    1134     2: [abedfxyz]
    1135     3: [abedfxyz]
    1136     4: [abedfxyz]
    1137     5: [abedfxyz]"""
    1138  # NOTE: the order of the cell variables above depends on dictionary order!
    1139  
    1140  co_tricky_nested_f = tricky.__func__.__code__.co_consts[1]
    1141  
    1142  code_info_tricky_nested_f = """\
    1143  Filename:          (.*)
    1144  Argument count:    1
    1145  Positional-only arguments: 0
    1146  Kw-only arguments: 0
    1147  Number of locals:  1
    1148  Stack size:        \\d+
    1149  Flags:             OPTIMIZED, NEWLOCALS, NESTED
    1150  Constants:
    1151     0: None
    1152  Names:
    1153     0: print
    1154  Variable names:
    1155     0: c
    1156  Free variables:
    1157     0: [abedfxyz]
    1158     1: [abedfxyz]
    1159     2: [abedfxyz]
    1160     3: [abedfxyz]
    1161     4: [abedfxyz]
    1162     5: [abedfxyz]"""
    1163  
    1164  code_info_expr_str = """\
    1165  Name:              <module>
    1166  Filename:          <disassembly>
    1167  Argument count:    0
    1168  Positional-only arguments: 0
    1169  Kw-only arguments: 0
    1170  Number of locals:  0
    1171  Stack size:        \\d+
    1172  Flags:             0x0
    1173  Constants:
    1174     0: 1
    1175  Names:
    1176     0: x"""
    1177  
    1178  code_info_simple_stmt_str = """\
    1179  Name:              <module>
    1180  Filename:          <disassembly>
    1181  Argument count:    0
    1182  Positional-only arguments: 0
    1183  Kw-only arguments: 0
    1184  Number of locals:  0
    1185  Stack size:        \\d+
    1186  Flags:             0x0
    1187  Constants:
    1188     0: 1
    1189     1: None
    1190  Names:
    1191     0: x"""
    1192  
    1193  code_info_compound_stmt_str = """\
    1194  Name:              <module>
    1195  Filename:          <disassembly>
    1196  Argument count:    0
    1197  Positional-only arguments: 0
    1198  Kw-only arguments: 0
    1199  Number of locals:  0
    1200  Stack size:        \\d+
    1201  Flags:             0x0
    1202  Constants:
    1203     0: 0
    1204     1: 1
    1205  Names:
    1206     0: x"""
    1207  
    1208  
    1209  async def async_def():
    1210      await 1
    1211      async for a in b: pass
    1212      async with c as d: pass
    1213  
    1214  code_info_async_def = """\
    1215  Name:              async_def
    1216  Filename:          (.*)
    1217  Argument count:    0
    1218  Positional-only arguments: 0
    1219  Kw-only arguments: 0
    1220  Number of locals:  2
    1221  Stack size:        \\d+
    1222  Flags:             OPTIMIZED, NEWLOCALS, COROUTINE
    1223  Constants:
    1224     0: None
    1225     1: 1
    1226  Names:
    1227     0: b
    1228     1: c
    1229  Variable names:
    1230     0: a
    1231     1: d"""
    1232  
    1233  class ESC[4;38;5;81mCodeInfoTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
    1234      test_pairs = [
    1235        (dis.code_info, code_info_code_info),
    1236        (tricky, code_info_tricky),
    1237        (co_tricky_nested_f, code_info_tricky_nested_f),
    1238        (expr_str, code_info_expr_str),
    1239        (simple_stmt_str, code_info_simple_stmt_str),
    1240        (compound_stmt_str, code_info_compound_stmt_str),
    1241        (async_def, code_info_async_def)
    1242      ]
    1243  
    1244      def test_code_info(self):
    1245          self.maxDiff = 1000
    1246          for x, expected in self.test_pairs:
    1247              self.assertRegex(dis.code_info(x), expected)
    1248  
    1249      def test_show_code(self):
    1250          self.maxDiff = 1000
    1251          for x, expected in self.test_pairs:
    1252              with captured_stdout() as output:
    1253                  dis.show_code(x)
    1254              self.assertRegex(output.getvalue(), expected+"\n")
    1255              output = io.StringIO()
    1256              dis.show_code(x, file=output)
    1257              self.assertRegex(output.getvalue(), expected)
    1258  
    1259      def test_code_info_object(self):
    1260          self.assertRaises(TypeError, dis.code_info, object())
    1261  
    1262      def test_pretty_flags_no_flags(self):
    1263          self.assertEqual(dis.pretty_flags(0), '0x0')
    1264  
    1265  
    1266  # Fodder for instruction introspection tests
    1267  #   Editing any of these may require recalculating the expected output
    1268  def outer(a=1, b=2):
    1269      def f(c=3, d=4):
    1270          def inner(e=5, f=6):
    1271              print(a, b, c, d, e, f)
    1272          print(a, b, c, d)
    1273          return inner
    1274      print(a, b, '', 1, [], {}, "Hello world!")
    1275      return f
    1276  
    1277  def jumpy():
    1278      # This won't actually run (but that's OK, we only disassemble it)
    1279      for i in range(10):
    1280          print(i)
    1281          if i < 4:
    1282              continue
    1283          if i > 6:
    1284              break
    1285      else:
    1286          print("I can haz else clause?")
    1287      while i:
    1288          print(i)
    1289          i -= 1
    1290          if i > 6:
    1291              continue
    1292          if i < 4:
    1293              break
    1294      else:
    1295          print("Who let lolcatz into this test suite?")
    1296      try:
    1297          1 / 0
    1298      except ZeroDivisionError:
    1299          print("Here we go, here we go, here we go...")
    1300      else:
    1301          with i as dodgy:
    1302              print("Never reach this")
    1303      finally:
    1304          print("OK, now we're done")
    1305  
    1306  # End fodder for opinfo generation tests
    1307  expected_outer_line = 1
    1308  _line_offset = outer.__code__.co_firstlineno - 1
    1309  code_object_f = outer.__code__.co_consts[3]
    1310  expected_f_line = code_object_f.co_firstlineno - _line_offset
    1311  code_object_inner = code_object_f.co_consts[3]
    1312  expected_inner_line = code_object_inner.co_firstlineno - _line_offset
    1313  expected_jumpy_line = 1
    1314  
    1315  # The following lines are useful to regenerate the expected results after
    1316  # either the fodder is modified or the bytecode generation changes
    1317  # After regeneration, update the references to code_object_f and
    1318  # code_object_inner before rerunning the tests
    1319  
    1320  def _stringify_instruction(instr):
    1321      # Since line numbers and other offsets change a lot for these
    1322      # test cases, ignore them.
    1323      return str(instr._replace(positions=None))
    1324  
    1325  def _prepare_test_cases():
    1326      _instructions = dis.get_instructions(outer, first_line=expected_outer_line)
    1327      print('expected_opinfo_outer = [\n  ',
    1328            ',\n  '.join(map(_stringify_instruction, _instructions)), ',\n]', sep='')
    1329      _instructions = dis.get_instructions(outer(), first_line=expected_f_line)
    1330      print('expected_opinfo_f = [\n  ',
    1331            ',\n  '.join(map(_stringify_instruction, _instructions)), ',\n]', sep='')
    1332      _instructions = dis.get_instructions(outer()(), first_line=expected_inner_line)
    1333      print('expected_opinfo_inner = [\n  ',
    1334            ',\n  '.join(map(_stringify_instruction, _instructions)), ',\n]', sep='')
    1335      _instructions = dis.get_instructions(jumpy, first_line=expected_jumpy_line)
    1336      print('expected_opinfo_jumpy = [\n  ',
    1337            ',\n  '.join(map(_stringify_instruction, _instructions)), ',\n]', sep='')
    1338      dis.dis(outer)
    1339  
    1340  #_prepare_test_cases()
    1341  
    1342  Instruction = dis.Instruction
    1343  expected_opinfo_outer = [
    1344    Instruction(opname='MAKE_CELL', opcode=135, arg=0, argval='a', argrepr='a', offset=0, starts_line=None, is_jump_target=False, positions=None),
    1345    Instruction(opname='MAKE_CELL', opcode=135, arg=1, argval='b', argrepr='b', offset=2, starts_line=None, is_jump_target=False, positions=None),
    1346    Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=4, starts_line=1, is_jump_target=False, positions=None),
    1347    Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=(3, 4), argrepr='(3, 4)', offset=6, starts_line=2, is_jump_target=False, positions=None),
    1348    Instruction(opname='LOAD_CLOSURE', opcode=136, arg=0, argval='a', argrepr='a', offset=8, starts_line=None, is_jump_target=False, positions=None),
    1349    Instruction(opname='LOAD_CLOSURE', opcode=136, arg=1, argval='b', argrepr='b', offset=10, starts_line=None, is_jump_target=False, positions=None),
    1350    Instruction(opname='BUILD_TUPLE', opcode=102, arg=2, argval=2, argrepr='', offset=12, starts_line=None, is_jump_target=False, positions=None),
    1351    Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=code_object_f, argrepr=repr(code_object_f), offset=14, starts_line=None, is_jump_target=False, positions=None),
    1352    Instruction(opname='MAKE_FUNCTION', opcode=132, arg=9, argval=9, argrepr='defaults, closure', offset=16, starts_line=None, is_jump_target=False, positions=None),
    1353    Instruction(opname='STORE_FAST', opcode=125, arg=2, argval='f', argrepr='f', offset=18, starts_line=None, is_jump_target=False, positions=None),
    1354    Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='NULL + print', offset=20, starts_line=7, is_jump_target=False, positions=None),
    1355    Instruction(opname='LOAD_DEREF', opcode=137, arg=0, argval='a', argrepr='a', offset=32, starts_line=None, is_jump_target=False, positions=None),
    1356    Instruction(opname='LOAD_DEREF', opcode=137, arg=1, argval='b', argrepr='b', offset=34, starts_line=None, is_jump_target=False, positions=None),
    1357    Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='', argrepr="''", offset=36, starts_line=None, is_jump_target=False, positions=None),
    1358    Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=38, starts_line=None, is_jump_target=False, positions=None),
    1359    Instruction(opname='BUILD_LIST', opcode=103, arg=0, argval=0, argrepr='', offset=40, starts_line=None, is_jump_target=False, positions=None),
    1360    Instruction(opname='BUILD_MAP', opcode=105, arg=0, argval=0, argrepr='', offset=42, starts_line=None, is_jump_target=False, positions=None),
    1361    Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Hello world!', argrepr="'Hello world!'", offset=44, starts_line=None, is_jump_target=False, positions=None),
    1362    Instruction(opname='PRECALL', opcode=166, arg=7, argval=7, argrepr='', offset=46, starts_line=None, is_jump_target=False, positions=None),
    1363    Instruction(opname='CALL', opcode=171, arg=7, argval=7, argrepr='', offset=50, starts_line=None, is_jump_target=False, positions=None),
    1364    Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=60, starts_line=None, is_jump_target=False, positions=None),
    1365    Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='f', argrepr='f', offset=62, starts_line=8, is_jump_target=False, positions=None),
    1366    Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=64, starts_line=None, is_jump_target=False, positions=None),
    1367  ]
    1368  
    1369  expected_opinfo_f = [
    1370    Instruction(opname='COPY_FREE_VARS', opcode=149, arg=2, argval=2, argrepr='', offset=0, starts_line=None, is_jump_target=False, positions=None),
    1371    Instruction(opname='MAKE_CELL', opcode=135, arg=0, argval='c', argrepr='c', offset=2, starts_line=None, is_jump_target=False, positions=None),
    1372    Instruction(opname='MAKE_CELL', opcode=135, arg=1, argval='d', argrepr='d', offset=4, starts_line=None, is_jump_target=False, positions=None),
    1373    Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=6, starts_line=2, is_jump_target=False, positions=None),
    1374    Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval=(5, 6), argrepr='(5, 6)', offset=8, starts_line=3, is_jump_target=False, positions=None),
    1375    Instruction(opname='LOAD_CLOSURE', opcode=136, arg=3, argval='a', argrepr='a', offset=10, starts_line=None, is_jump_target=False, positions=None),
    1376    Instruction(opname='LOAD_CLOSURE', opcode=136, arg=4, argval='b', argrepr='b', offset=12, starts_line=None, is_jump_target=False, positions=None),
    1377    Instruction(opname='LOAD_CLOSURE', opcode=136, arg=0, argval='c', argrepr='c', offset=14, starts_line=None, is_jump_target=False, positions=None),
    1378    Instruction(opname='LOAD_CLOSURE', opcode=136, arg=1, argval='d', argrepr='d', offset=16, starts_line=None, is_jump_target=False, positions=None),
    1379    Instruction(opname='BUILD_TUPLE', opcode=102, arg=4, argval=4, argrepr='', offset=18, starts_line=None, is_jump_target=False, positions=None),
    1380    Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=code_object_inner, argrepr=repr(code_object_inner), offset=20, starts_line=None, is_jump_target=False, positions=None),
    1381    Instruction(opname='MAKE_FUNCTION', opcode=132, arg=9, argval=9, argrepr='defaults, closure', offset=22, starts_line=None, is_jump_target=False, positions=None),
    1382    Instruction(opname='STORE_FAST', opcode=125, arg=2, argval='inner', argrepr='inner', offset=24, starts_line=None, is_jump_target=False, positions=None),
    1383    Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='NULL + print', offset=26, starts_line=5, is_jump_target=False, positions=None),
    1384    Instruction(opname='LOAD_DEREF', opcode=137, arg=3, argval='a', argrepr='a', offset=38, starts_line=None, is_jump_target=False, positions=None),
    1385    Instruction(opname='LOAD_DEREF', opcode=137, arg=4, argval='b', argrepr='b', offset=40, starts_line=None, is_jump_target=False, positions=None),
    1386    Instruction(opname='LOAD_DEREF', opcode=137, arg=0, argval='c', argrepr='c', offset=42, starts_line=None, is_jump_target=False, positions=None),
    1387    Instruction(opname='LOAD_DEREF', opcode=137, arg=1, argval='d', argrepr='d', offset=44, starts_line=None, is_jump_target=False, positions=None),
    1388    Instruction(opname='PRECALL', opcode=166, arg=4, argval=4, argrepr='', offset=46, starts_line=None, is_jump_target=False, positions=None),
    1389    Instruction(opname='CALL', opcode=171, arg=4, argval=4, argrepr='', offset=50, starts_line=None, is_jump_target=False, positions=None),
    1390    Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=60, starts_line=None, is_jump_target=False, positions=None),
    1391    Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='inner', argrepr='inner', offset=62, starts_line=6, is_jump_target=False, positions=None),
    1392    Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=64, starts_line=None, is_jump_target=False, positions=None),
    1393  ]
    1394  
    1395  expected_opinfo_inner = [
    1396    Instruction(opname='COPY_FREE_VARS', opcode=149, arg=4, argval=4, argrepr='', offset=0, starts_line=None, is_jump_target=False, positions=None),
    1397    Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=2, starts_line=3, is_jump_target=False, positions=None),
    1398    Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='NULL + print', offset=4, starts_line=4, is_jump_target=False, positions=None),
    1399    Instruction(opname='LOAD_DEREF', opcode=137, arg=2, argval='a', argrepr='a', offset=16, starts_line=None, is_jump_target=False, positions=None),
    1400    Instruction(opname='LOAD_DEREF', opcode=137, arg=3, argval='b', argrepr='b', offset=18, starts_line=None, is_jump_target=False, positions=None),
    1401    Instruction(opname='LOAD_DEREF', opcode=137, arg=4, argval='c', argrepr='c', offset=20, starts_line=None, is_jump_target=False, positions=None),
    1402    Instruction(opname='LOAD_DEREF', opcode=137, arg=5, argval='d', argrepr='d', offset=22, starts_line=None, is_jump_target=False, positions=None),
    1403    Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='e', argrepr='e', offset=24, starts_line=None, is_jump_target=False, positions=None),
    1404    Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='f', argrepr='f', offset=26, starts_line=None, is_jump_target=False, positions=None),
    1405    Instruction(opname='PRECALL', opcode=166, arg=6, argval=6, argrepr='', offset=28, starts_line=None, is_jump_target=False, positions=None),
    1406    Instruction(opname='CALL', opcode=171, arg=6, argval=6, argrepr='', offset=32, starts_line=None, is_jump_target=False, positions=None),
    1407    Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=42, starts_line=None, is_jump_target=False, positions=None),
    1408    Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=44, starts_line=None, is_jump_target=False, positions=None),
    1409    Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=46, starts_line=None, is_jump_target=False, positions=None),
    1410  ]
    1411  
    1412  expected_opinfo_jumpy = [
    1413    Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=0, starts_line=1, is_jump_target=False, positions=None),
    1414    Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='range', argrepr='NULL + range', offset=2, starts_line=3, is_jump_target=False, positions=None),
    1415    Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=14, starts_line=None, is_jump_target=False, positions=None),
    1416    Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=16, starts_line=None, is_jump_target=False, positions=None),
    1417    Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=20, starts_line=None, is_jump_target=False, positions=None),
    1418    Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=30, starts_line=None, is_jump_target=False, positions=None),
    1419    Instruction(opname='FOR_ITER', opcode=93, arg=32, argval=98, argrepr='to 98', offset=32, starts_line=None, is_jump_target=True, positions=None),
    1420    Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=34, starts_line=None, is_jump_target=False, positions=None),
    1421    Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=36, starts_line=4, is_jump_target=False, positions=None),
    1422    Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=48, starts_line=None, is_jump_target=False, positions=None),
    1423    Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=50, starts_line=None, is_jump_target=False, positions=None),
    1424    Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=54, starts_line=None, is_jump_target=False, positions=None),
    1425    Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=64, starts_line=None, is_jump_target=False, positions=None),
    1426    Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=66, starts_line=5, is_jump_target=False, positions=None),
    1427    Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=68, starts_line=None, is_jump_target=False, positions=None),
    1428    Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=70, starts_line=None, is_jump_target=False, positions=None),
    1429    Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=80, argrepr='to 80', offset=76, starts_line=None, is_jump_target=False, positions=None),
    1430    Instruction(opname='JUMP_BACKWARD', opcode=140, arg=24, argval=32, argrepr='to 32', offset=78, starts_line=6, is_jump_target=False, positions=None),
    1431    Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=80, starts_line=7, is_jump_target=True, positions=None),
    1432    Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=82, starts_line=None, is_jump_target=False, positions=None),
    1433    Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=84, starts_line=None, is_jump_target=False, positions=None),
    1434    Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=2, argval=96, argrepr='to 96', offset=90, starts_line=None, is_jump_target=False, positions=None),
    1435    Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=92, starts_line=8, is_jump_target=False, positions=None),
    1436    Instruction(opname='JUMP_FORWARD', opcode=110, arg=16, argval=128, argrepr='to 128', offset=94, starts_line=None, is_jump_target=False, positions=None),
    1437    Instruction(opname='JUMP_BACKWARD', opcode=140, arg=33, argval=32, argrepr='to 32', offset=96, starts_line=7, is_jump_target=True, positions=None),
    1438    Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=98, starts_line=10, is_jump_target=True, positions=None),
    1439    Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=110, starts_line=None, is_jump_target=False, positions=None),
    1440    Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=112, starts_line=None, is_jump_target=False, positions=None),
    1441    Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=116, starts_line=None, is_jump_target=False, positions=None),
    1442    Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=126, starts_line=None, is_jump_target=False, positions=None),
    1443    Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=128, starts_line=11, is_jump_target=True, positions=None),
    1444    Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=36, argval=204, argrepr='to 204', offset=130, starts_line=None, is_jump_target=False, positions=None),
    1445    Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=132, starts_line=12, is_jump_target=True, positions=None),
    1446    Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=144, starts_line=None, is_jump_target=False, positions=None),
    1447    Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=146, starts_line=None, is_jump_target=False, positions=None),
    1448    Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=150, starts_line=None, is_jump_target=False, positions=None),
    1449    Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=160, starts_line=None, is_jump_target=False, positions=None),
    1450    Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=162, starts_line=13, is_jump_target=False, positions=None),
    1451    Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=164, starts_line=None, is_jump_target=False, positions=None),
    1452    Instruction(opname='BINARY_OP', opcode=122, arg=23, argval=23, argrepr='-=', offset=166, starts_line=None, is_jump_target=False, positions=None),
    1453    Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=170, starts_line=None, is_jump_target=False, positions=None),
    1454    Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=172, starts_line=14, is_jump_target=False, positions=None),
    1455    Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=174, starts_line=None, is_jump_target=False, positions=None),
    1456    Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=176, starts_line=None, is_jump_target=False, positions=None),
    1457    Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=186, argrepr='to 186', offset=182, starts_line=None, is_jump_target=False, positions=None),
    1458    Instruction(opname='JUMP_BACKWARD', opcode=140, arg=29, argval=128, argrepr='to 128', offset=184, starts_line=15, is_jump_target=False, positions=None),
    1459    Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=186, starts_line=16, is_jump_target=True, positions=None),
    1460    Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=188, starts_line=None, is_jump_target=False, positions=None),
    1461    Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=190, starts_line=None, is_jump_target=False, positions=None),
    1462    Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=200, argrepr='to 200', offset=196, starts_line=None, is_jump_target=False, positions=None),
    1463    Instruction(opname='JUMP_FORWARD', opcode=110, arg=17, argval=234, argrepr='to 234', offset=198, starts_line=17, is_jump_target=False, positions=None),
    1464    Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=200, starts_line=11, is_jump_target=True, positions=None),
    1465    Instruction(opname='POP_JUMP_BACKWARD_IF_TRUE', opcode=176, arg=36, argval=132, argrepr='to 132', offset=202, starts_line=None, is_jump_target=False, positions=None),
    1466    Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=204, starts_line=19, is_jump_target=True, positions=None),
    1467    Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=216, starts_line=None, is_jump_target=False, positions=None),
    1468    Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=218, starts_line=None, is_jump_target=False, positions=None),
    1469    Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=222, starts_line=None, is_jump_target=False, positions=None),
    1470    Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=232, starts_line=None, is_jump_target=False, positions=None),
    1471    Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=234, starts_line=20, is_jump_target=True, positions=None),
    1472    Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=236, starts_line=21, is_jump_target=False, positions=None),
    1473    Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=238, starts_line=None, is_jump_target=False, positions=None),
    1474    Instruction(opname='BINARY_OP', opcode=122, arg=11, argval=11, argrepr='/', offset=240, starts_line=None, is_jump_target=False, positions=None),
    1475    Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=244, starts_line=None, is_jump_target=False, positions=None),
    1476    Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=246, starts_line=25, is_jump_target=False, positions=None),
    1477    Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=248, starts_line=None, is_jump_target=False, positions=None),
    1478    Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=250, starts_line=None, is_jump_target=False, positions=None),
    1479    Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=252, starts_line=26, is_jump_target=False, positions=None),
    1480    Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Never reach this', argrepr="'Never reach this'", offset=264, starts_line=None, is_jump_target=False, positions=None),
    1481    Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=266, starts_line=None, is_jump_target=False, positions=None),
    1482    Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=270, starts_line=None, is_jump_target=False, positions=None),
    1483    Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=280, starts_line=None, is_jump_target=False, positions=None),
    1484    Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=282, starts_line=25, is_jump_target=False, positions=None),
    1485    Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=284, starts_line=None, is_jump_target=False, positions=None),
    1486    Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=286, starts_line=None, is_jump_target=False, positions=None),
    1487    Instruction(opname='PRECALL', opcode=166, arg=2, argval=2, argrepr='', offset=288, starts_line=None, is_jump_target=False, positions=None),
    1488    Instruction(opname='CALL', opcode=171, arg=2, argval=2, argrepr='', offset=292, starts_line=None, is_jump_target=False, positions=None),
    1489    Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=302, starts_line=None, is_jump_target=False, positions=None),
    1490    Instruction(opname='JUMP_FORWARD', opcode=110, arg=11, argval=328, argrepr='to 328', offset=304, starts_line=None, is_jump_target=False, positions=None),
    1491    Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=306, starts_line=None, is_jump_target=False, positions=None),
    1492    Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=308, starts_line=None, is_jump_target=False, positions=None),
    1493    Instruction(opname='POP_JUMP_FORWARD_IF_TRUE', opcode=115, arg=4, argval=320, argrepr='to 320', offset=310, starts_line=None, is_jump_target=False, positions=None),
    1494    Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=312, starts_line=None, is_jump_target=False, positions=None),
    1495    Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=314, starts_line=None, is_jump_target=False, positions=None),
    1496    Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=316, starts_line=None, is_jump_target=False, positions=None),
    1497    Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=318, starts_line=None, is_jump_target=False, positions=None),
    1498    Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=320, starts_line=None, is_jump_target=True, positions=None),
    1499    Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=322, starts_line=None, is_jump_target=False, positions=None),
    1500    Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=324, starts_line=None, is_jump_target=False, positions=None),
    1501    Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=326, starts_line=None, is_jump_target=False, positions=None),
    1502    Instruction(opname='JUMP_FORWARD', opcode=110, arg=31, argval=392, argrepr='to 392', offset=328, starts_line=None, is_jump_target=True, positions=None),
    1503    Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=330, starts_line=None, is_jump_target=False, positions=None),
    1504    Instruction(opname='LOAD_GLOBAL', opcode=116, arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=332, starts_line=22, is_jump_target=False, positions=None),
    1505    Instruction(opname='CHECK_EXC_MATCH', opcode=36, arg=None, argval=None, argrepr='', offset=344, starts_line=None, is_jump_target=False, positions=None),
    1506    Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=18, argval=384, argrepr='to 384', offset=346, starts_line=None, is_jump_target=False, positions=None),
    1507    Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=348, starts_line=None, is_jump_target=False, positions=None),
    1508    Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=350, starts_line=23, is_jump_target=False, positions=None),
    1509    Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=362, starts_line=None, is_jump_target=False, positions=None),
    1510    Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=364, starts_line=None, is_jump_target=False, positions=None),
    1511    Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=368, starts_line=None, is_jump_target=False, positions=None),
    1512    Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=378, starts_line=None, is_jump_target=False, positions=None),
    1513    Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=380, starts_line=None, is_jump_target=False, positions=None),
    1514    Instruction(opname='JUMP_FORWARD', opcode=110, arg=4, argval=392, argrepr='to 392', offset=382, starts_line=None, is_jump_target=False, positions=None),
    1515    Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=384, starts_line=22, is_jump_target=True, positions=None),
    1516    Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=386, starts_line=None, is_jump_target=False, positions=None),
    1517    Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=388, starts_line=None, is_jump_target=False, positions=None),
    1518    Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=390, starts_line=None, is_jump_target=False, positions=None),
    1519    Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=392, starts_line=28, is_jump_target=True, positions=None),
    1520    Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=404, starts_line=None, is_jump_target=False, positions=None),
    1521    Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=406, starts_line=None, is_jump_target=False, positions=None),
    1522    Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=410, starts_line=None, is_jump_target=False, positions=None),
    1523    Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=420, starts_line=None, is_jump_target=False, positions=None),
    1524    Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=422, starts_line=None, is_jump_target=False, positions=None),
    1525    Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=424, starts_line=None, is_jump_target=False, positions=None),
    1526    Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=426, starts_line=None, is_jump_target=False, positions=None),
    1527    Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=428, starts_line=None, is_jump_target=False, positions=None),
    1528    Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=440, starts_line=None, is_jump_target=False, positions=None),
    1529    Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=442, starts_line=None, is_jump_target=False, positions=None),
    1530    Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=446, starts_line=None, is_jump_target=False, positions=None),
    1531    Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=456, starts_line=None, is_jump_target=False, positions=None),
    1532    Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=458, starts_line=None, is_jump_target=False, positions=None),
    1533    Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=460, starts_line=None, is_jump_target=False, positions=None),
    1534    Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=462, starts_line=None, is_jump_target=False, positions=None),
    1535    Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=464, starts_line=None, is_jump_target=False, positions=None),
    1536  ]
    1537  
    1538  # One last piece of inspect fodder to check the default line number handling
    1539  def simple(): pass
    1540  expected_opinfo_simple = [
    1541    Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=0, starts_line=simple.__code__.co_firstlineno, is_jump_target=False, positions=None),
    1542    Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=2, starts_line=None, is_jump_target=False),
    1543    Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=4, starts_line=None, is_jump_target=False)
    1544  ]
    1545  
    1546  
    1547  class ESC[4;38;5;81mInstructionTestCase(ESC[4;38;5;149mBytecodeTestCase):
    1548  
    1549      def assertInstructionsEqual(self, instrs_1, instrs_2, /):
    1550          instrs_1 = [instr_1._replace(positions=None) for instr_1 in instrs_1]
    1551          instrs_2 = [instr_2._replace(positions=None) for instr_2 in instrs_2]
    1552          self.assertEqual(instrs_1, instrs_2)
    1553  
    1554  class ESC[4;38;5;81mInstructionTests(ESC[4;38;5;149mInstructionTestCase):
    1555  
    1556      def __init__(self, *args):
    1557          super().__init__(*args)
    1558          self.maxDiff = None
    1559  
    1560      def test_default_first_line(self):
    1561          actual = dis.get_instructions(simple)
    1562          self.assertInstructionsEqual(list(actual), expected_opinfo_simple)
    1563  
    1564      def test_first_line_set_to_None(self):
    1565          actual = dis.get_instructions(simple, first_line=None)
    1566          self.assertInstructionsEqual(list(actual), expected_opinfo_simple)
    1567  
    1568      def test_outer(self):
    1569          actual = dis.get_instructions(outer, first_line=expected_outer_line)
    1570          self.assertInstructionsEqual(list(actual), expected_opinfo_outer)
    1571  
    1572      def test_nested(self):
    1573          with captured_stdout():
    1574              f = outer()
    1575          actual = dis.get_instructions(f, first_line=expected_f_line)
    1576          self.assertInstructionsEqual(list(actual), expected_opinfo_f)
    1577  
    1578      def test_doubly_nested(self):
    1579          with captured_stdout():
    1580              inner = outer()()
    1581          actual = dis.get_instructions(inner, first_line=expected_inner_line)
    1582          self.assertInstructionsEqual(list(actual), expected_opinfo_inner)
    1583  
    1584      def test_jumpy(self):
    1585          actual = dis.get_instructions(jumpy, first_line=expected_jumpy_line)
    1586          self.assertInstructionsEqual(list(actual), expected_opinfo_jumpy)
    1587  
    1588      @requires_debug_ranges()
    1589      def test_co_positions(self):
    1590          code = compile('f(\n  x, y, z\n)', '<test>', 'exec')
    1591          positions = [
    1592              instr.positions
    1593              for instr in dis.get_instructions(code)
    1594          ]
    1595          expected = [
    1596              (0, 1, 0, 0),
    1597              (1, 1, 0, 1),
    1598              (1, 1, 0, 1),
    1599              (2, 2, 2, 3),
    1600              (2, 2, 5, 6),
    1601              (2, 2, 8, 9),
    1602              (1, 3, 0, 1),
    1603              (1, 3, 0, 1),
    1604              (1, 3, 0, 1),
    1605              (1, 3, 0, 1),
    1606              (1, 3, 0, 1)
    1607          ]
    1608          self.assertEqual(positions, expected)
    1609  
    1610          named_positions = [
    1611              (pos.lineno, pos.end_lineno, pos.col_offset, pos.end_col_offset)
    1612              for pos in positions
    1613          ]
    1614          self.assertEqual(named_positions, expected)
    1615  
    1616      @requires_debug_ranges()
    1617      def test_co_positions_missing_info(self):
    1618          code = compile('x, y, z', '<test>', 'exec')
    1619          code_without_location_table = code.replace(co_linetable=b'')
    1620          actual = dis.get_instructions(code_without_location_table)
    1621          for instruction in actual:
    1622              with self.subTest(instruction=instruction):
    1623                  positions = instruction.positions
    1624                  self.assertEqual(len(positions), 4)
    1625                  if instruction.opname == "RESUME":
    1626                      continue
    1627                  self.assertIsNone(positions.lineno)
    1628                  self.assertIsNone(positions.end_lineno)
    1629                  self.assertIsNone(positions.col_offset)
    1630                  self.assertIsNone(positions.end_col_offset)
    1631  
    1632      @requires_debug_ranges()
    1633      def test_co_positions_with_lots_of_caches(self):
    1634          def roots(a, b, c):
    1635              d = b**2 - 4 * a * c
    1636              yield (-b - cmath.sqrt(d)) / (2 * a)
    1637              if d:
    1638                  yield (-b + cmath.sqrt(d)) / (2 * a)
    1639          code = roots.__code__
    1640          ops = code.co_code[::2]
    1641          cache_opcode = opcode.opmap["CACHE"]
    1642          caches = sum(op == cache_opcode for op in ops)
    1643          non_caches = len(ops) - caches
    1644          # Make sure we have "lots of caches". If not, roots should be changed:
    1645          assert 1 / 3 <= caches / non_caches, "this test needs more caches!"
    1646          for show_caches in (False, True):
    1647              for adaptive in (False, True):
    1648                  with self.subTest(f"{adaptive=}, {show_caches=}"):
    1649                      co_positions = [
    1650                          positions
    1651                          for op, positions in zip(ops, code.co_positions(), strict=True)
    1652                          if show_caches or op != cache_opcode
    1653                      ]
    1654                      dis_positions = [
    1655                          instruction.positions
    1656                          for instruction in dis.get_instructions(
    1657                              code, adaptive=adaptive, show_caches=show_caches
    1658                          )
    1659                      ]
    1660                      self.assertEqual(co_positions, dis_positions)
    1661  
    1662  # get_instructions has its own tests above, so can rely on it to validate
    1663  # the object oriented API
    1664  class ESC[4;38;5;81mBytecodeTests(ESC[4;38;5;149mInstructionTestCase, ESC[4;38;5;149mDisTestBase):
    1665  
    1666      def test_instantiation(self):
    1667          # Test with function, method, code string and code object
    1668          for obj in [_f, _C(1).__init__, "a=1", _f.__code__]:
    1669              with self.subTest(obj=obj):
    1670                  b = dis.Bytecode(obj)
    1671                  self.assertIsInstance(b.codeobj, types.CodeType)
    1672  
    1673          self.assertRaises(TypeError, dis.Bytecode, object())
    1674  
    1675      def test_iteration(self):
    1676          for obj in [_f, _C(1).__init__, "a=1", _f.__code__]:
    1677              with self.subTest(obj=obj):
    1678                  via_object = list(dis.Bytecode(obj))
    1679                  via_generator = list(dis.get_instructions(obj))
    1680                  self.assertInstructionsEqual(via_object, via_generator)
    1681  
    1682      def test_explicit_first_line(self):
    1683          actual = dis.Bytecode(outer, first_line=expected_outer_line)
    1684          self.assertInstructionsEqual(list(actual), expected_opinfo_outer)
    1685  
    1686      def test_source_line_in_disassembly(self):
    1687          # Use the line in the source code
    1688          actual = dis.Bytecode(simple).dis()
    1689          actual = actual.strip().partition(" ")[0]  # extract the line no
    1690          expected = str(simple.__code__.co_firstlineno)
    1691          self.assertEqual(actual, expected)
    1692          # Use an explicit first line number
    1693          actual = dis.Bytecode(simple, first_line=350).dis()
    1694          actual = actual.strip().partition(" ")[0]  # extract the line no
    1695          self.assertEqual(actual, "350")
    1696  
    1697      def test_info(self):
    1698          self.maxDiff = 1000
    1699          for x, expected in CodeInfoTests.test_pairs:
    1700              b = dis.Bytecode(x)
    1701              self.assertRegex(b.info(), expected)
    1702  
    1703      def test_disassembled(self):
    1704          actual = dis.Bytecode(_f).dis()
    1705          self.do_disassembly_compare(actual, dis_f)
    1706  
    1707      def test_from_traceback(self):
    1708          tb = get_tb()
    1709          b = dis.Bytecode.from_traceback(tb)
    1710          while tb.tb_next: tb = tb.tb_next
    1711  
    1712          self.assertEqual(b.current_offset, tb.tb_lasti)
    1713  
    1714      def test_from_traceback_dis(self):
    1715          self.maxDiff = None
    1716          tb = get_tb()
    1717          b = dis.Bytecode.from_traceback(tb)
    1718          self.assertEqual(self.strip_offsets(b.dis()), dis_traceback)
    1719  
    1720      @requires_debug_ranges()
    1721      def test_bytecode_co_positions(self):
    1722          bytecode = dis.Bytecode("a=1")
    1723          for instr, positions in zip(bytecode, bytecode.codeobj.co_positions()):
    1724              assert instr.positions == positions
    1725  
    1726  class ESC[4;38;5;81mTestBytecodeTestCase(ESC[4;38;5;149mBytecodeTestCase):
    1727      def test_assert_not_in_with_op_not_in_bytecode(self):
    1728          code = compile("a = 1", "<string>", "exec")
    1729          self.assertInBytecode(code, "LOAD_CONST", 1)
    1730          self.assertNotInBytecode(code, "LOAD_NAME")
    1731          self.assertNotInBytecode(code, "LOAD_NAME", "a")
    1732  
    1733      def test_assert_not_in_with_arg_not_in_bytecode(self):
    1734          code = compile("a = 1", "<string>", "exec")
    1735          self.assertInBytecode(code, "LOAD_CONST")
    1736          self.assertInBytecode(code, "LOAD_CONST", 1)
    1737          self.assertNotInBytecode(code, "LOAD_CONST", 2)
    1738  
    1739      def test_assert_not_in_with_arg_in_bytecode(self):
    1740          code = compile("a = 1", "<string>", "exec")
    1741          with self.assertRaises(AssertionError):
    1742              self.assertNotInBytecode(code, "LOAD_CONST", 1)
    1743  
    1744  class ESC[4;38;5;81mTestFinderMethods(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
    1745      def test__find_imports(self):
    1746          cases = [
    1747              ("import a.b.c", ('a.b.c', 0, None)),
    1748              ("from a.b import c", ('a.b', 0, ('c',))),
    1749              ("from a.b import c as d", ('a.b', 0, ('c',))),
    1750              ("from a.b import *", ('a.b', 0, ('*',))),
    1751              ("from ...a.b import c as d", ('a.b', 3, ('c',))),
    1752              ("from ..a.b import c as d, e as f", ('a.b', 2, ('c', 'e'))),
    1753              ("from ..a.b import *", ('a.b', 2, ('*',))),
    1754          ]
    1755          for src, expected in cases:
    1756              with self.subTest(src=src):
    1757                  code = compile(src, "<string>", "exec")
    1758                  res = tuple(dis._find_imports(code))
    1759                  self.assertEqual(len(res), 1)
    1760                  self.assertEqual(res[0], expected)
    1761  
    1762      def test__find_store_names(self):
    1763          cases = [
    1764              ("x+y", ()),
    1765              ("x=y=1", ('x', 'y')),
    1766              ("x+=y", ('x',)),
    1767              ("global x\nx=y=1", ('x', 'y')),
    1768              ("global x\nz=x", ('z',)),
    1769          ]
    1770          for src, expected in cases:
    1771              with self.subTest(src=src):
    1772                  code = compile(src, "<string>", "exec")
    1773                  res = tuple(dis._find_store_names(code))
    1774                  self.assertEqual(res, expected)
    1775  
    1776      def test_findlabels(self):
    1777          labels = dis.findlabels(jumpy.__code__.co_code)
    1778          jumps = [
    1779              instr.offset
    1780              for instr in expected_opinfo_jumpy
    1781              if instr.is_jump_target
    1782          ]
    1783  
    1784          self.assertEqual(sorted(labels), sorted(jumps))
    1785  
    1786  
    1787  class ESC[4;38;5;81mTestDisTraceback(ESC[4;38;5;149mDisTestBase):
    1788      def setUp(self) -> None:
    1789          try:  # We need to clean up existing tracebacks
    1790              del sys.last_traceback
    1791          except AttributeError:
    1792              pass
    1793          return super().setUp()
    1794  
    1795      def get_disassembly(self, tb):
    1796          output = io.StringIO()
    1797          with contextlib.redirect_stdout(output):
    1798              dis.distb(tb)
    1799          return output.getvalue()
    1800  
    1801      def test_distb_empty(self):
    1802          with self.assertRaises(RuntimeError):
    1803              dis.distb()
    1804  
    1805      def test_distb_last_traceback(self):
    1806          self.maxDiff = None
    1807          # We need to have an existing last traceback in `sys`:
    1808          tb = get_tb()
    1809          sys.last_traceback = tb
    1810  
    1811          self.do_disassembly_compare(self.get_disassembly(None), dis_traceback)
    1812  
    1813      def test_distb_explicit_arg(self):
    1814          self.maxDiff = None
    1815          tb = get_tb()
    1816  
    1817          self.do_disassembly_compare(self.get_disassembly(tb), dis_traceback)
    1818  
    1819  
    1820  class ESC[4;38;5;81mTestDisTracebackWithFile(ESC[4;38;5;149mTestDisTraceback):
    1821      # Run the `distb` tests again, using the file arg instead of print
    1822      def get_disassembly(self, tb):
    1823          output = io.StringIO()
    1824          with contextlib.redirect_stdout(output):
    1825              dis.distb(tb, file=output)
    1826          return output.getvalue()
    1827  
    1828  
    1829  if __name__ == "__main__":
    1830      unittest.main()