1# Minimal tests for dis module 2 3from test.support import captured_stdout 4from test.bytecode_helper import BytecodeTestCase 5import difflib 6import unittest 7import sys 8import dis 9import io 10import re 11import types 12import contextlib 13 14def get_tb(): 15 def _error(): 16 try: 17 1 / 0 18 except Exception as e: 19 tb = e.__traceback__ 20 return tb 21 22 tb = _error() 23 while tb.tb_next: 24 tb = tb.tb_next 25 return tb 26 27TRACEBACK_CODE = get_tb().tb_frame.f_code 28 29class _C: 30 def __init__(self, x): 31 self.x = x == 1 32 33 @staticmethod 34 def sm(x): 35 x = x == 1 36 37 @classmethod 38 def cm(cls, x): 39 cls.x = x == 1 40 41dis_c_instance_method = """\ 42%3d 0 LOAD_FAST 1 (x) 43 2 LOAD_CONST 1 (1) 44 4 COMPARE_OP 2 (==) 45 6 LOAD_FAST 0 (self) 46 8 STORE_ATTR 0 (x) 47 10 LOAD_CONST 0 (None) 48 12 RETURN_VALUE 49""" % (_C.__init__.__code__.co_firstlineno + 1,) 50 51dis_c_instance_method_bytes = """\ 52 0 LOAD_FAST 1 (1) 53 2 LOAD_CONST 1 (1) 54 4 COMPARE_OP 2 (==) 55 6 LOAD_FAST 0 (0) 56 8 STORE_ATTR 0 (0) 57 10 LOAD_CONST 0 (0) 58 12 RETURN_VALUE 59""" 60 61dis_c_class_method = """\ 62%3d 0 LOAD_FAST 1 (x) 63 2 LOAD_CONST 1 (1) 64 4 COMPARE_OP 2 (==) 65 6 LOAD_FAST 0 (cls) 66 8 STORE_ATTR 0 (x) 67 10 LOAD_CONST 0 (None) 68 12 RETURN_VALUE 69""" % (_C.cm.__code__.co_firstlineno + 2,) 70 71dis_c_static_method = """\ 72%3d 0 LOAD_FAST 0 (x) 73 2 LOAD_CONST 1 (1) 74 4 COMPARE_OP 2 (==) 75 6 STORE_FAST 0 (x) 76 8 LOAD_CONST 0 (None) 77 10 RETURN_VALUE 78""" % (_C.sm.__code__.co_firstlineno + 2,) 79 80# Class disassembling info has an extra newline at end. 81dis_c = """\ 82Disassembly of %s: 83%s 84Disassembly of %s: 85%s 86Disassembly of %s: 87%s 88""" % (_C.__init__.__name__, dis_c_instance_method, 89 _C.cm.__name__, dis_c_class_method, 90 _C.sm.__name__, dis_c_static_method) 91 92def _f(a): 93 print(a) 94 return 1 95 96dis_f = """\ 97%3d 0 LOAD_GLOBAL 0 (print) 98 2 LOAD_FAST 0 (a) 99 4 CALL_FUNCTION 1 100 6 POP_TOP 101 102%3d 8 LOAD_CONST 1 (1) 103 10 RETURN_VALUE 104""" % (_f.__code__.co_firstlineno + 1, 105 _f.__code__.co_firstlineno + 2) 106 107 108dis_f_co_code = """\ 109 0 LOAD_GLOBAL 0 (0) 110 2 LOAD_FAST 0 (0) 111 4 CALL_FUNCTION 1 112 6 POP_TOP 113 8 LOAD_CONST 1 (1) 114 10 RETURN_VALUE 115""" 116 117 118def bug708901(): 119 for res in range(1, 120 10): 121 pass 122 123dis_bug708901 = """\ 124%3d 0 SETUP_LOOP 18 (to 20) 125 2 LOAD_GLOBAL 0 (range) 126 4 LOAD_CONST 1 (1) 127 128%3d 6 LOAD_CONST 2 (10) 129 8 CALL_FUNCTION 2 130 10 GET_ITER 131 >> 12 FOR_ITER 4 (to 18) 132 14 STORE_FAST 0 (res) 133 134%3d 16 JUMP_ABSOLUTE 12 135 >> 18 POP_BLOCK 136 >> 20 LOAD_CONST 0 (None) 137 22 RETURN_VALUE 138""" % (bug708901.__code__.co_firstlineno + 1, 139 bug708901.__code__.co_firstlineno + 2, 140 bug708901.__code__.co_firstlineno + 3) 141 142 143def bug1333982(x=[]): 144 assert 0, ([s for s in x] + 145 1) 146 pass 147 148dis_bug1333982 = """\ 149%3d 0 LOAD_CONST 1 (0) 150 2 POP_JUMP_IF_TRUE 26 151 4 LOAD_GLOBAL 0 (AssertionError) 152 6 LOAD_CONST 2 (<code object <listcomp> at 0x..., file "%s", line %d>) 153 8 LOAD_CONST 3 ('bug1333982.<locals>.<listcomp>') 154 10 MAKE_FUNCTION 0 155 12 LOAD_FAST 0 (x) 156 14 GET_ITER 157 16 CALL_FUNCTION 1 158 159%3d 18 LOAD_CONST 4 (1) 160 20 BINARY_ADD 161 22 CALL_FUNCTION 1 162 24 RAISE_VARARGS 1 163 164%3d >> 26 LOAD_CONST 0 (None) 165 28 RETURN_VALUE 166""" % (bug1333982.__code__.co_firstlineno + 1, 167 __file__, 168 bug1333982.__code__.co_firstlineno + 1, 169 bug1333982.__code__.co_firstlineno + 2, 170 bug1333982.__code__.co_firstlineno + 3) 171 172_BIG_LINENO_FORMAT = """\ 173%3d 0 LOAD_GLOBAL 0 (spam) 174 2 POP_TOP 175 4 LOAD_CONST 0 (None) 176 6 RETURN_VALUE 177""" 178 179dis_module_expected_results = """\ 180Disassembly of f: 181 4 0 LOAD_CONST 0 (None) 182 2 RETURN_VALUE 183 184Disassembly of g: 185 5 0 LOAD_CONST 0 (None) 186 2 RETURN_VALUE 187 188""" 189 190expr_str = "x + 1" 191 192dis_expr_str = """\ 193 1 0 LOAD_NAME 0 (x) 194 2 LOAD_CONST 0 (1) 195 4 BINARY_ADD 196 6 RETURN_VALUE 197""" 198 199simple_stmt_str = "x = x + 1" 200 201dis_simple_stmt_str = """\ 202 1 0 LOAD_NAME 0 (x) 203 2 LOAD_CONST 0 (1) 204 4 BINARY_ADD 205 6 STORE_NAME 0 (x) 206 8 LOAD_CONST 1 (None) 207 10 RETURN_VALUE 208""" 209 210annot_stmt_str = """\ 211 212x: int = 1 213y: fun(1) 214lst[fun(0)]: int = 1 215""" 216# leading newline is for a reason (tests lineno) 217 218dis_annot_stmt_str = """\ 219 2 0 SETUP_ANNOTATIONS 220 2 LOAD_CONST 0 (1) 221 4 STORE_NAME 0 (x) 222 6 LOAD_NAME 1 (int) 223 8 STORE_ANNOTATION 0 (x) 224 225 3 10 LOAD_NAME 2 (fun) 226 12 LOAD_CONST 0 (1) 227 14 CALL_FUNCTION 1 228 16 STORE_ANNOTATION 3 (y) 229 230 4 18 LOAD_CONST 0 (1) 231 20 LOAD_NAME 4 (lst) 232 22 LOAD_NAME 2 (fun) 233 24 LOAD_CONST 1 (0) 234 26 CALL_FUNCTION 1 235 28 STORE_SUBSCR 236 30 LOAD_NAME 1 (int) 237 32 POP_TOP 238 34 LOAD_CONST 2 (None) 239 36 RETURN_VALUE 240""" 241 242compound_stmt_str = """\ 243x = 0 244while 1: 245 x += 1""" 246# Trailing newline has been deliberately omitted 247 248dis_compound_stmt_str = """\ 249 1 0 LOAD_CONST 0 (0) 250 2 STORE_NAME 0 (x) 251 252 2 4 SETUP_LOOP 12 (to 18) 253 254 3 >> 6 LOAD_NAME 0 (x) 255 8 LOAD_CONST 1 (1) 256 10 INPLACE_ADD 257 12 STORE_NAME 0 (x) 258 14 JUMP_ABSOLUTE 6 259 16 POP_BLOCK 260 >> 18 LOAD_CONST 2 (None) 261 20 RETURN_VALUE 262""" 263 264dis_traceback = """\ 265%3d 0 SETUP_EXCEPT 12 (to 14) 266 267%3d 2 LOAD_CONST 1 (1) 268 4 LOAD_CONST 2 (0) 269 --> 6 BINARY_TRUE_DIVIDE 270 8 POP_TOP 271 10 POP_BLOCK 272 12 JUMP_FORWARD 40 (to 54) 273 274%3d >> 14 DUP_TOP 275 16 LOAD_GLOBAL 0 (Exception) 276 18 COMPARE_OP 10 (exception match) 277 20 POP_JUMP_IF_FALSE 52 278 22 POP_TOP 279 24 STORE_FAST 0 (e) 280 26 POP_TOP 281 28 SETUP_FINALLY 12 (to 42) 282 283%3d 30 LOAD_FAST 0 (e) 284 32 LOAD_ATTR 1 (__traceback__) 285 34 STORE_FAST 1 (tb) 286 36 POP_BLOCK 287 38 POP_EXCEPT 288 40 LOAD_CONST 0 (None) 289 >> 42 LOAD_CONST 0 (None) 290 44 STORE_FAST 0 (e) 291 46 DELETE_FAST 0 (e) 292 48 END_FINALLY 293 50 JUMP_FORWARD 2 (to 54) 294 >> 52 END_FINALLY 295 296%3d >> 54 LOAD_FAST 1 (tb) 297 56 RETURN_VALUE 298""" % (TRACEBACK_CODE.co_firstlineno + 1, 299 TRACEBACK_CODE.co_firstlineno + 2, 300 TRACEBACK_CODE.co_firstlineno + 3, 301 TRACEBACK_CODE.co_firstlineno + 4, 302 TRACEBACK_CODE.co_firstlineno + 5) 303 304def _fstring(a, b, c, d): 305 return f'{a} {b:4} {c!r} {d!r:4}' 306 307dis_fstring = """\ 308%3d 0 LOAD_FAST 0 (a) 309 2 FORMAT_VALUE 0 310 4 LOAD_CONST 1 (' ') 311 6 LOAD_FAST 1 (b) 312 8 LOAD_CONST 2 ('4') 313 10 FORMAT_VALUE 4 (with format) 314 12 LOAD_CONST 1 (' ') 315 14 LOAD_FAST 2 (c) 316 16 FORMAT_VALUE 2 (repr) 317 18 LOAD_CONST 1 (' ') 318 20 LOAD_FAST 3 (d) 319 22 LOAD_CONST 2 ('4') 320 24 FORMAT_VALUE 6 (repr, with format) 321 26 BUILD_STRING 7 322 28 RETURN_VALUE 323""" % (_fstring.__code__.co_firstlineno + 1,) 324 325def _g(x): 326 yield x 327 328class DisTests(unittest.TestCase): 329 330 def get_disassembly(self, func, lasti=-1, wrapper=True): 331 # We want to test the default printing behaviour, not the file arg 332 output = io.StringIO() 333 with contextlib.redirect_stdout(output): 334 if wrapper: 335 dis.dis(func) 336 else: 337 dis.disassemble(func, lasti) 338 return output.getvalue() 339 340 def get_disassemble_as_string(self, func, lasti=-1): 341 return self.get_disassembly(func, lasti, False) 342 343 def strip_addresses(self, text): 344 return re.sub(r'\b0x[0-9A-Fa-f]+\b', '0x...', text) 345 346 def do_disassembly_test(self, func, expected): 347 got = self.get_disassembly(func) 348 if got != expected: 349 got = self.strip_addresses(got) 350 self.assertEqual(got, expected) 351 352 def test_opmap(self): 353 self.assertEqual(dis.opmap["NOP"], 9) 354 self.assertIn(dis.opmap["LOAD_CONST"], dis.hasconst) 355 self.assertIn(dis.opmap["STORE_NAME"], dis.hasname) 356 357 def test_opname(self): 358 self.assertEqual(dis.opname[dis.opmap["LOAD_FAST"]], "LOAD_FAST") 359 360 def test_boundaries(self): 361 self.assertEqual(dis.opmap["EXTENDED_ARG"], dis.EXTENDED_ARG) 362 self.assertEqual(dis.opmap["STORE_NAME"], dis.HAVE_ARGUMENT) 363 364 def test_dis(self): 365 self.do_disassembly_test(_f, dis_f) 366 367 def test_bug_708901(self): 368 self.do_disassembly_test(bug708901, dis_bug708901) 369 370 def test_bug_1333982(self): 371 # This one is checking bytecodes generated for an `assert` statement, 372 # so fails if the tests are run with -O. Skip this test then. 373 if not __debug__: 374 self.skipTest('need asserts, run without -O') 375 376 self.do_disassembly_test(bug1333982, dis_bug1333982) 377 378 def test_big_linenos(self): 379 def func(count): 380 namespace = {} 381 func = "def foo():\n " + "".join(["\n "] * count + ["spam\n"]) 382 exec(func, namespace) 383 return namespace['foo'] 384 385 # Test all small ranges 386 for i in range(1, 300): 387 expected = _BIG_LINENO_FORMAT % (i + 2) 388 self.do_disassembly_test(func(i), expected) 389 390 # Test some larger ranges too 391 for i in range(300, 5000, 10): 392 expected = _BIG_LINENO_FORMAT % (i + 2) 393 self.do_disassembly_test(func(i), expected) 394 395 from test import dis_module 396 self.do_disassembly_test(dis_module, dis_module_expected_results) 397 398 def test_disassemble_str(self): 399 self.do_disassembly_test(expr_str, dis_expr_str) 400 self.do_disassembly_test(simple_stmt_str, dis_simple_stmt_str) 401 self.do_disassembly_test(annot_stmt_str, dis_annot_stmt_str) 402 self.do_disassembly_test(compound_stmt_str, dis_compound_stmt_str) 403 404 def test_disassemble_bytes(self): 405 self.do_disassembly_test(_f.__code__.co_code, dis_f_co_code) 406 407 def test_disassemble_class(self): 408 self.do_disassembly_test(_C, dis_c) 409 410 def test_disassemble_instance_method(self): 411 self.do_disassembly_test(_C(1).__init__, dis_c_instance_method) 412 413 def test_disassemble_instance_method_bytes(self): 414 method_bytecode = _C(1).__init__.__code__.co_code 415 self.do_disassembly_test(method_bytecode, dis_c_instance_method_bytes) 416 417 def test_disassemble_static_method(self): 418 self.do_disassembly_test(_C.sm, dis_c_static_method) 419 420 def test_disassemble_class_method(self): 421 self.do_disassembly_test(_C.cm, dis_c_class_method) 422 423 def test_disassemble_generator(self): 424 gen_func_disas = self.get_disassembly(_g) # Disassemble generator function 425 gen_disas = self.get_disassembly(_g(1)) # Disassemble generator itself 426 self.assertEqual(gen_disas, gen_func_disas) 427 428 def test_disassemble_fstring(self): 429 self.do_disassembly_test(_fstring, dis_fstring) 430 431 def test_dis_none(self): 432 try: 433 del sys.last_traceback 434 except AttributeError: 435 pass 436 self.assertRaises(RuntimeError, dis.dis, None) 437 438 def test_dis_traceback(self): 439 try: 440 del sys.last_traceback 441 except AttributeError: 442 pass 443 444 try: 445 1/0 446 except Exception as e: 447 tb = e.__traceback__ 448 sys.last_traceback = tb 449 450 tb_dis = self.get_disassemble_as_string(tb.tb_frame.f_code, tb.tb_lasti) 451 self.do_disassembly_test(None, tb_dis) 452 453 def test_dis_object(self): 454 self.assertRaises(TypeError, dis.dis, object()) 455 456class DisWithFileTests(DisTests): 457 458 # Run the tests again, using the file arg instead of print 459 def get_disassembly(self, func, lasti=-1, wrapper=True): 460 output = io.StringIO() 461 if wrapper: 462 dis.dis(func, file=output) 463 else: 464 dis.disassemble(func, lasti, file=output) 465 return output.getvalue() 466 467 468 469code_info_code_info = """\ 470Name: code_info 471Filename: (.*) 472Argument count: 1 473Kw-only arguments: 0 474Number of locals: 1 475Stack size: 3 476Flags: OPTIMIZED, NEWLOCALS, NOFREE 477Constants: 478 0: %r 479Names: 480 0: _format_code_info 481 1: _get_code_object 482Variable names: 483 0: x""" % (('Formatted details of methods, functions, or code.',) 484 if sys.flags.optimize < 2 else (None,)) 485 486@staticmethod 487def tricky(x, y, z=True, *args, c, d, e=[], **kwds): 488 def f(c=c): 489 print(x, y, z, c, d, e, f) 490 yield x, y, z, c, d, e, f 491 492code_info_tricky = """\ 493Name: tricky 494Filename: (.*) 495Argument count: 3 496Kw-only arguments: 3 497Number of locals: 8 498Stack size: 7 499Flags: OPTIMIZED, NEWLOCALS, VARARGS, VARKEYWORDS, GENERATOR 500Constants: 501 0: None 502 1: <code object f at (.*), file "(.*)", line (.*)> 503 2: 'tricky.<locals>.f' 504Variable names: 505 0: x 506 1: y 507 2: z 508 3: c 509 4: d 510 5: e 511 6: args 512 7: kwds 513Cell variables: 514 0: [edfxyz] 515 1: [edfxyz] 516 2: [edfxyz] 517 3: [edfxyz] 518 4: [edfxyz] 519 5: [edfxyz]""" 520# NOTE: the order of the cell variables above depends on dictionary order! 521 522co_tricky_nested_f = tricky.__func__.__code__.co_consts[1] 523 524code_info_tricky_nested_f = """\ 525Name: f 526Filename: (.*) 527Argument count: 1 528Kw-only arguments: 0 529Number of locals: 1 530Stack size: 8 531Flags: OPTIMIZED, NEWLOCALS, NESTED 532Constants: 533 0: None 534Names: 535 0: print 536Variable names: 537 0: c 538Free variables: 539 0: [edfxyz] 540 1: [edfxyz] 541 2: [edfxyz] 542 3: [edfxyz] 543 4: [edfxyz] 544 5: [edfxyz]""" 545 546code_info_expr_str = """\ 547Name: <module> 548Filename: <disassembly> 549Argument count: 0 550Kw-only arguments: 0 551Number of locals: 0 552Stack size: 2 553Flags: NOFREE 554Constants: 555 0: 1 556Names: 557 0: x""" 558 559code_info_simple_stmt_str = """\ 560Name: <module> 561Filename: <disassembly> 562Argument count: 0 563Kw-only arguments: 0 564Number of locals: 0 565Stack size: 2 566Flags: NOFREE 567Constants: 568 0: 1 569 1: None 570Names: 571 0: x""" 572 573code_info_compound_stmt_str = """\ 574Name: <module> 575Filename: <disassembly> 576Argument count: 0 577Kw-only arguments: 0 578Number of locals: 0 579Stack size: 2 580Flags: NOFREE 581Constants: 582 0: 0 583 1: 1 584 2: None 585Names: 586 0: x""" 587 588 589async def async_def(): 590 await 1 591 async for a in b: pass 592 async with c as d: pass 593 594code_info_async_def = """\ 595Name: async_def 596Filename: (.*) 597Argument count: 0 598Kw-only arguments: 0 599Number of locals: 2 600Stack size: 17 601Flags: OPTIMIZED, NEWLOCALS, NOFREE, COROUTINE 602Constants: 603 0: None 604 1: 1""" 605 606class CodeInfoTests(unittest.TestCase): 607 test_pairs = [ 608 (dis.code_info, code_info_code_info), 609 (tricky, code_info_tricky), 610 (co_tricky_nested_f, code_info_tricky_nested_f), 611 (expr_str, code_info_expr_str), 612 (simple_stmt_str, code_info_simple_stmt_str), 613 (compound_stmt_str, code_info_compound_stmt_str), 614 (async_def, code_info_async_def) 615 ] 616 617 def test_code_info(self): 618 self.maxDiff = 1000 619 for x, expected in self.test_pairs: 620 self.assertRegex(dis.code_info(x), expected) 621 622 def test_show_code(self): 623 self.maxDiff = 1000 624 for x, expected in self.test_pairs: 625 with captured_stdout() as output: 626 dis.show_code(x) 627 self.assertRegex(output.getvalue(), expected+"\n") 628 output = io.StringIO() 629 dis.show_code(x, file=output) 630 self.assertRegex(output.getvalue(), expected) 631 632 def test_code_info_object(self): 633 self.assertRaises(TypeError, dis.code_info, object()) 634 635 def test_pretty_flags_no_flags(self): 636 self.assertEqual(dis.pretty_flags(0), '0x0') 637 638 639# Fodder for instruction introspection tests 640# Editing any of these may require recalculating the expected output 641def outer(a=1, b=2): 642 def f(c=3, d=4): 643 def inner(e=5, f=6): 644 print(a, b, c, d, e, f) 645 print(a, b, c, d) 646 return inner 647 print(a, b, '', 1, [], {}, "Hello world!") 648 return f 649 650def jumpy(): 651 # This won't actually run (but that's OK, we only disassemble it) 652 for i in range(10): 653 print(i) 654 if i < 4: 655 continue 656 if i > 6: 657 break 658 else: 659 print("I can haz else clause?") 660 while i: 661 print(i) 662 i -= 1 663 if i > 6: 664 continue 665 if i < 4: 666 break 667 else: 668 print("Who let lolcatz into this test suite?") 669 try: 670 1 / 0 671 except ZeroDivisionError: 672 print("Here we go, here we go, here we go...") 673 else: 674 with i as dodgy: 675 print("Never reach this") 676 finally: 677 print("OK, now we're done") 678 679# End fodder for opinfo generation tests 680expected_outer_line = 1 681_line_offset = outer.__code__.co_firstlineno - 1 682code_object_f = outer.__code__.co_consts[3] 683expected_f_line = code_object_f.co_firstlineno - _line_offset 684code_object_inner = code_object_f.co_consts[3] 685expected_inner_line = code_object_inner.co_firstlineno - _line_offset 686expected_jumpy_line = 1 687 688# The following lines are useful to regenerate the expected results after 689# either the fodder is modified or the bytecode generation changes 690# After regeneration, update the references to code_object_f and 691# code_object_inner before rerunning the tests 692 693#_instructions = dis.get_instructions(outer, first_line=expected_outer_line) 694#print('expected_opinfo_outer = [\n ', 695 #',\n '.join(map(str, _instructions)), ',\n]', sep='') 696#_instructions = dis.get_instructions(outer(), first_line=expected_f_line) 697#print('expected_opinfo_f = [\n ', 698 #',\n '.join(map(str, _instructions)), ',\n]', sep='') 699#_instructions = dis.get_instructions(outer()(), first_line=expected_inner_line) 700#print('expected_opinfo_inner = [\n ', 701 #',\n '.join(map(str, _instructions)), ',\n]', sep='') 702#_instructions = dis.get_instructions(jumpy, first_line=expected_jumpy_line) 703#print('expected_opinfo_jumpy = [\n ', 704 #',\n '.join(map(str, _instructions)), ',\n]', sep='') 705 706 707Instruction = dis.Instruction 708expected_opinfo_outer = [ 709 Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval=(3, 4), argrepr='(3, 4)', offset=0, starts_line=2, is_jump_target=False), 710 Instruction(opname='LOAD_CLOSURE', opcode=135, arg=0, argval='a', argrepr='a', offset=2, starts_line=None, is_jump_target=False), 711 Instruction(opname='LOAD_CLOSURE', opcode=135, arg=1, argval='b', argrepr='b', offset=4, starts_line=None, is_jump_target=False), 712 Instruction(opname='BUILD_TUPLE', opcode=102, arg=2, argval=2, argrepr='', offset=6, starts_line=None, is_jump_target=False), 713 Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=code_object_f, argrepr=repr(code_object_f), offset=8, starts_line=None, is_jump_target=False), 714 Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='outer.<locals>.f', argrepr="'outer.<locals>.f'", offset=10, starts_line=None, is_jump_target=False), 715 Instruction(opname='MAKE_FUNCTION', opcode=132, arg=9, argval=9, argrepr='', offset=12, starts_line=None, is_jump_target=False), 716 Instruction(opname='STORE_FAST', opcode=125, arg=2, argval='f', argrepr='f', offset=14, starts_line=None, is_jump_target=False), 717 Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='print', argrepr='print', offset=16, starts_line=7, is_jump_target=False), 718 Instruction(opname='LOAD_DEREF', opcode=136, arg=0, argval='a', argrepr='a', offset=18, starts_line=None, is_jump_target=False), 719 Instruction(opname='LOAD_DEREF', opcode=136, arg=1, argval='b', argrepr='b', offset=20, starts_line=None, is_jump_target=False), 720 Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval='', argrepr="''", offset=22, starts_line=None, is_jump_target=False), 721 Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval=1, argrepr='1', offset=24, starts_line=None, is_jump_target=False), 722 Instruction(opname='BUILD_LIST', opcode=103, arg=0, argval=0, argrepr='', offset=26, starts_line=None, is_jump_target=False), 723 Instruction(opname='BUILD_MAP', opcode=105, arg=0, argval=0, argrepr='', offset=28, starts_line=None, is_jump_target=False), 724 Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval='Hello world!', argrepr="'Hello world!'", offset=30, starts_line=None, is_jump_target=False), 725 Instruction(opname='CALL_FUNCTION', opcode=131, arg=7, argval=7, argrepr='', offset=32, starts_line=None, is_jump_target=False), 726 Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=34, starts_line=None, is_jump_target=False), 727 Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='f', argrepr='f', offset=36, starts_line=8, is_jump_target=False), 728 Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=38, starts_line=None, is_jump_target=False), 729] 730 731expected_opinfo_f = [ 732 Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=(5, 6), argrepr='(5, 6)', offset=0, starts_line=3, is_jump_target=False), 733 Instruction(opname='LOAD_CLOSURE', opcode=135, arg=2, argval='a', argrepr='a', offset=2, starts_line=None, is_jump_target=False), 734 Instruction(opname='LOAD_CLOSURE', opcode=135, arg=3, argval='b', argrepr='b', offset=4, starts_line=None, is_jump_target=False), 735 Instruction(opname='LOAD_CLOSURE', opcode=135, arg=0, argval='c', argrepr='c', offset=6, starts_line=None, is_jump_target=False), 736 Instruction(opname='LOAD_CLOSURE', opcode=135, arg=1, argval='d', argrepr='d', offset=8, starts_line=None, is_jump_target=False), 737 Instruction(opname='BUILD_TUPLE', opcode=102, arg=4, argval=4, argrepr='', offset=10, starts_line=None, is_jump_target=False), 738 Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=code_object_inner, argrepr=repr(code_object_inner), offset=12, starts_line=None, is_jump_target=False), 739 Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='outer.<locals>.f.<locals>.inner', argrepr="'outer.<locals>.f.<locals>.inner'", offset=14, starts_line=None, is_jump_target=False), 740 Instruction(opname='MAKE_FUNCTION', opcode=132, arg=9, argval=9, argrepr='', offset=16, starts_line=None, is_jump_target=False), 741 Instruction(opname='STORE_FAST', opcode=125, arg=2, argval='inner', argrepr='inner', offset=18, starts_line=None, is_jump_target=False), 742 Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='print', argrepr='print', offset=20, starts_line=5, is_jump_target=False), 743 Instruction(opname='LOAD_DEREF', opcode=136, arg=2, argval='a', argrepr='a', offset=22, starts_line=None, is_jump_target=False), 744 Instruction(opname='LOAD_DEREF', opcode=136, arg=3, argval='b', argrepr='b', offset=24, starts_line=None, is_jump_target=False), 745 Instruction(opname='LOAD_DEREF', opcode=136, arg=0, argval='c', argrepr='c', offset=26, starts_line=None, is_jump_target=False), 746 Instruction(opname='LOAD_DEREF', opcode=136, arg=1, argval='d', argrepr='d', offset=28, starts_line=None, is_jump_target=False), 747 Instruction(opname='CALL_FUNCTION', opcode=131, arg=4, argval=4, argrepr='', offset=30, starts_line=None, is_jump_target=False), 748 Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=32, starts_line=None, is_jump_target=False), 749 Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='inner', argrepr='inner', offset=34, starts_line=6, is_jump_target=False), 750 Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=36, starts_line=None, is_jump_target=False), 751] 752 753expected_opinfo_inner = [ 754 Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='print', argrepr='print', offset=0, starts_line=4, is_jump_target=False), 755 Instruction(opname='LOAD_DEREF', opcode=136, arg=0, argval='a', argrepr='a', offset=2, starts_line=None, is_jump_target=False), 756 Instruction(opname='LOAD_DEREF', opcode=136, arg=1, argval='b', argrepr='b', offset=4, starts_line=None, is_jump_target=False), 757 Instruction(opname='LOAD_DEREF', opcode=136, arg=2, argval='c', argrepr='c', offset=6, starts_line=None, is_jump_target=False), 758 Instruction(opname='LOAD_DEREF', opcode=136, arg=3, argval='d', argrepr='d', offset=8, starts_line=None, is_jump_target=False), 759 Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='e', argrepr='e', offset=10, starts_line=None, is_jump_target=False), 760 Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='f', argrepr='f', offset=12, starts_line=None, is_jump_target=False), 761 Instruction(opname='CALL_FUNCTION', opcode=131, arg=6, argval=6, argrepr='', offset=14, starts_line=None, is_jump_target=False), 762 Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=16, starts_line=None, is_jump_target=False), 763 Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=18, starts_line=None, is_jump_target=False), 764 Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=20, starts_line=None, is_jump_target=False), 765] 766 767expected_opinfo_jumpy = [ 768 Instruction(opname='SETUP_LOOP', opcode=120, arg=52, argval=54, argrepr='to 54', offset=0, starts_line=3, is_jump_target=False), 769 Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='range', argrepr='range', offset=2, starts_line=None, is_jump_target=False), 770 Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=4, starts_line=None, is_jump_target=False), 771 Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=6, starts_line=None, is_jump_target=False), 772 Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=8, starts_line=None, is_jump_target=False), 773 Instruction(opname='FOR_ITER', opcode=93, arg=32, argval=44, argrepr='to 44', offset=10, starts_line=None, is_jump_target=True), 774 Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=12, starts_line=None, is_jump_target=False), 775 Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=14, starts_line=4, is_jump_target=False), 776 Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=16, starts_line=None, is_jump_target=False), 777 Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=18, starts_line=None, is_jump_target=False), 778 Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=20, starts_line=None, is_jump_target=False), 779 Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=22, starts_line=5, is_jump_target=False), 780 Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=24, starts_line=None, is_jump_target=False), 781 Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=26, starts_line=None, is_jump_target=False), 782 Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=32, argval=32, argrepr='', offset=28, starts_line=None, is_jump_target=False), 783 Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=10, argval=10, argrepr='', offset=30, starts_line=6, is_jump_target=False), 784 Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=32, starts_line=7, is_jump_target=True), 785 Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=34, starts_line=None, is_jump_target=False), 786 Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=36, starts_line=None, is_jump_target=False), 787 Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=10, argval=10, argrepr='', offset=38, starts_line=None, is_jump_target=False), 788 Instruction(opname='BREAK_LOOP', opcode=80, arg=None, argval=None, argrepr='', offset=40, starts_line=8, is_jump_target=False), 789 Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=10, argval=10, argrepr='', offset=42, starts_line=None, is_jump_target=False), 790 Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=44, starts_line=None, is_jump_target=True), 791 Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=46, starts_line=10, is_jump_target=False), 792 Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=48, starts_line=None, is_jump_target=False), 793 Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=50, starts_line=None, is_jump_target=False), 794 Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=52, starts_line=None, is_jump_target=False), 795 Instruction(opname='SETUP_LOOP', opcode=120, arg=52, argval=108, argrepr='to 108', offset=54, starts_line=11, is_jump_target=True), 796 Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=56, starts_line=None, is_jump_target=True), 797 Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=98, argval=98, argrepr='', offset=58, starts_line=None, is_jump_target=False), 798 Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=60, starts_line=12, is_jump_target=False), 799 Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=62, starts_line=None, is_jump_target=False), 800 Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=64, starts_line=None, is_jump_target=False), 801 Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=66, starts_line=None, is_jump_target=False), 802 Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=68, starts_line=13, is_jump_target=False), 803 Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=70, starts_line=None, is_jump_target=False), 804 Instruction(opname='INPLACE_SUBTRACT', opcode=56, arg=None, argval=None, argrepr='', offset=72, starts_line=None, is_jump_target=False), 805 Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=74, starts_line=None, is_jump_target=False), 806 Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=76, starts_line=14, is_jump_target=False), 807 Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=78, starts_line=None, is_jump_target=False), 808 Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=80, starts_line=None, is_jump_target=False), 809 Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=86, argval=86, argrepr='', offset=82, starts_line=None, is_jump_target=False), 810 Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=56, argval=56, argrepr='', offset=84, starts_line=15, is_jump_target=False), 811 Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=86, starts_line=16, is_jump_target=True), 812 Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=88, starts_line=None, is_jump_target=False), 813 Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=90, starts_line=None, is_jump_target=False), 814 Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=56, argval=56, argrepr='', offset=92, starts_line=None, is_jump_target=False), 815 Instruction(opname='BREAK_LOOP', opcode=80, arg=None, argval=None, argrepr='', offset=94, starts_line=17, is_jump_target=False), 816 Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=56, argval=56, argrepr='', offset=96, starts_line=None, is_jump_target=False), 817 Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=98, starts_line=None, is_jump_target=True), 818 Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=100, starts_line=19, is_jump_target=False), 819 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=102, starts_line=None, is_jump_target=False), 820 Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=104, starts_line=None, is_jump_target=False), 821 Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=106, starts_line=None, is_jump_target=False), 822 Instruction(opname='SETUP_FINALLY', opcode=122, arg=70, argval=180, argrepr='to 180', offset=108, starts_line=20, is_jump_target=True), 823 Instruction(opname='SETUP_EXCEPT', opcode=121, arg=12, argval=124, argrepr='to 124', offset=110, starts_line=None, is_jump_target=False), 824 Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=112, starts_line=21, is_jump_target=False), 825 Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=114, starts_line=None, is_jump_target=False), 826 Instruction(opname='BINARY_TRUE_DIVIDE', opcode=27, arg=None, argval=None, argrepr='', offset=116, starts_line=None, is_jump_target=False), 827 Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=118, starts_line=None, is_jump_target=False), 828 Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=120, starts_line=None, is_jump_target=False), 829 Instruction(opname='JUMP_FORWARD', opcode=110, arg=28, argval=152, argrepr='to 152', offset=122, starts_line=None, is_jump_target=False), 830 Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=124, starts_line=22, is_jump_target=True), 831 Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=126, starts_line=None, is_jump_target=False), 832 Instruction(opname='COMPARE_OP', opcode=107, arg=10, argval='exception match', argrepr='exception match', offset=128, starts_line=None, is_jump_target=False), 833 Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=150, argval=150, argrepr='', offset=130, starts_line=None, is_jump_target=False), 834 Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=132, starts_line=None, is_jump_target=False), 835 Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=134, starts_line=None, is_jump_target=False), 836 Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=136, starts_line=None, is_jump_target=False), 837 Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=138, starts_line=23, is_jump_target=False), 838 Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=140, starts_line=None, is_jump_target=False), 839 Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=142, starts_line=None, is_jump_target=False), 840 Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=144, starts_line=None, is_jump_target=False), 841 Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=146, starts_line=None, is_jump_target=False), 842 Instruction(opname='JUMP_FORWARD', opcode=110, arg=26, argval=176, argrepr='to 176', offset=148, starts_line=None, is_jump_target=False), 843 Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=150, starts_line=None, is_jump_target=True), 844 Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=152, starts_line=25, is_jump_target=True), 845 Instruction(opname='SETUP_WITH', opcode=143, arg=14, argval=170, argrepr='to 170', offset=154, starts_line=None, is_jump_target=False), 846 Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=156, starts_line=None, is_jump_target=False), 847 Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=158, starts_line=26, is_jump_target=False), 848 Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=160, starts_line=None, is_jump_target=False), 849 Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=162, starts_line=None, is_jump_target=False), 850 Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=164, starts_line=None, is_jump_target=False), 851 Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=166, starts_line=None, is_jump_target=False), 852 Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=168, starts_line=None, is_jump_target=False), 853 Instruction(opname='WITH_CLEANUP_START', opcode=81, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=True), 854 Instruction(opname='WITH_CLEANUP_FINISH', opcode=82, arg=None, argval=None, argrepr='', offset=172, starts_line=None, is_jump_target=False), 855 Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=174, starts_line=None, is_jump_target=False), 856 Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=176, starts_line=None, is_jump_target=True), 857 Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=178, starts_line=None, is_jump_target=False), 858 Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=180, starts_line=28, is_jump_target=True), 859 Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=182, starts_line=None, is_jump_target=False), 860 Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=184, starts_line=None, is_jump_target=False), 861 Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False), 862 Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=188, starts_line=None, is_jump_target=False), 863 Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=190, starts_line=None, is_jump_target=False), 864 Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=192, starts_line=None, is_jump_target=False), 865] 866 867# One last piece of inspect fodder to check the default line number handling 868def simple(): pass 869expected_opinfo_simple = [ 870 Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=0, starts_line=simple.__code__.co_firstlineno, is_jump_target=False), 871 Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=2, starts_line=None, is_jump_target=False) 872] 873 874 875class InstructionTests(BytecodeTestCase): 876 877 def test_default_first_line(self): 878 actual = dis.get_instructions(simple) 879 self.assertEqual(list(actual), expected_opinfo_simple) 880 881 def test_first_line_set_to_None(self): 882 actual = dis.get_instructions(simple, first_line=None) 883 self.assertEqual(list(actual), expected_opinfo_simple) 884 885 def test_outer(self): 886 actual = dis.get_instructions(outer, first_line=expected_outer_line) 887 self.assertEqual(list(actual), expected_opinfo_outer) 888 889 def test_nested(self): 890 with captured_stdout(): 891 f = outer() 892 actual = dis.get_instructions(f, first_line=expected_f_line) 893 self.assertEqual(list(actual), expected_opinfo_f) 894 895 def test_doubly_nested(self): 896 with captured_stdout(): 897 inner = outer()() 898 actual = dis.get_instructions(inner, first_line=expected_inner_line) 899 self.assertEqual(list(actual), expected_opinfo_inner) 900 901 def test_jumpy(self): 902 actual = dis.get_instructions(jumpy, first_line=expected_jumpy_line) 903 self.assertEqual(list(actual), expected_opinfo_jumpy) 904 905# get_instructions has its own tests above, so can rely on it to validate 906# the object oriented API 907class BytecodeTests(unittest.TestCase): 908 def test_instantiation(self): 909 # Test with function, method, code string and code object 910 for obj in [_f, _C(1).__init__, "a=1", _f.__code__]: 911 with self.subTest(obj=obj): 912 b = dis.Bytecode(obj) 913 self.assertIsInstance(b.codeobj, types.CodeType) 914 915 self.assertRaises(TypeError, dis.Bytecode, object()) 916 917 def test_iteration(self): 918 for obj in [_f, _C(1).__init__, "a=1", _f.__code__]: 919 with self.subTest(obj=obj): 920 via_object = list(dis.Bytecode(obj)) 921 via_generator = list(dis.get_instructions(obj)) 922 self.assertEqual(via_object, via_generator) 923 924 def test_explicit_first_line(self): 925 actual = dis.Bytecode(outer, first_line=expected_outer_line) 926 self.assertEqual(list(actual), expected_opinfo_outer) 927 928 def test_source_line_in_disassembly(self): 929 # Use the line in the source code 930 actual = dis.Bytecode(simple).dis()[:3] 931 expected = "{:>3}".format(simple.__code__.co_firstlineno) 932 self.assertEqual(actual, expected) 933 # Use an explicit first line number 934 actual = dis.Bytecode(simple, first_line=350).dis()[:3] 935 self.assertEqual(actual, "350") 936 937 def test_info(self): 938 self.maxDiff = 1000 939 for x, expected in CodeInfoTests.test_pairs: 940 b = dis.Bytecode(x) 941 self.assertRegex(b.info(), expected) 942 943 def test_disassembled(self): 944 actual = dis.Bytecode(_f).dis() 945 self.assertEqual(actual, dis_f) 946 947 def test_from_traceback(self): 948 tb = get_tb() 949 b = dis.Bytecode.from_traceback(tb) 950 while tb.tb_next: tb = tb.tb_next 951 952 self.assertEqual(b.current_offset, tb.tb_lasti) 953 954 def test_from_traceback_dis(self): 955 tb = get_tb() 956 b = dis.Bytecode.from_traceback(tb) 957 self.assertEqual(b.dis(), dis_traceback) 958 959if __name__ == "__main__": 960 unittest.main() 961