diff options
Diffstat (limited to 'Lib/test/test_dis.py')
-rw-r--r-- | Lib/test/test_dis.py | 221 |
1 files changed, 209 insertions, 12 deletions
diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index d82dc5a1e2..7a61493c10 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -1,6 +1,6 @@ # Minimal tests for dis module -from test.support import run_unittest +from test.support import run_unittest, captured_stdout import unittest import sys import dis @@ -19,8 +19,8 @@ dis_f = """\ %-4d 10 LOAD_CONST 1 (1) 13 RETURN_VALUE -"""%(_f.__code__.co_firstlineno + 1, - _f.__code__.co_firstlineno + 2) +""" % (_f.__code__.co_firstlineno + 1, + _f.__code__.co_firstlineno + 2) def bug708901(): @@ -43,9 +43,9 @@ dis_bug708901 = """\ >> 25 POP_BLOCK >> 26 LOAD_CONST 0 (None) 29 RETURN_VALUE -"""%(bug708901.__code__.co_firstlineno + 1, - bug708901.__code__.co_firstlineno + 2, - bug708901.__code__.co_firstlineno + 3) +""" % (bug708901.__code__.co_firstlineno + 1, + bug708901.__code__.co_firstlineno + 2, + bug708901.__code__.co_firstlineno + 3) def bug1333982(x=[]): @@ -74,9 +74,9 @@ dis_bug1333982 = """\ %-4d 40 LOAD_CONST 0 (None) 43 RETURN_VALUE -"""%(bug1333982.__code__.co_firstlineno + 1, - bug1333982.__code__.co_firstlineno + 2, - bug1333982.__code__.co_firstlineno + 3) +""" % (bug1333982.__code__.co_firstlineno + 1, + bug1333982.__code__.co_firstlineno + 2, + bug1333982.__code__.co_firstlineno + 3) _BIG_LINENO_FORMAT = """\ %3d 0 LOAD_GLOBAL 0 (spam) @@ -96,6 +96,46 @@ Disassembly of g: """ +expr_str = "x + 1" + +dis_expr_str = """\ + 1 0 LOAD_NAME 0 (x) + 3 LOAD_CONST 0 (1) + 6 BINARY_ADD + 7 RETURN_VALUE +""" + +simple_stmt_str = "x = x + 1" + +dis_simple_stmt_str = """\ + 1 0 LOAD_NAME 0 (x) + 3 LOAD_CONST 0 (1) + 6 BINARY_ADD + 7 STORE_NAME 0 (x) + 10 LOAD_CONST 1 (None) + 13 RETURN_VALUE +""" + +compound_stmt_str = """\ +x = 0 +while 1: + x += 1""" +# Trailing newline has been deliberately omitted + +dis_compound_stmt_str = """\ + 1 0 LOAD_CONST 0 (0) + 3 STORE_NAME 0 (x) + + 2 6 SETUP_LOOP 13 (to 22) + + 3 >> 9 LOAD_NAME 0 (x) + 12 LOAD_CONST 1 (1) + 15 INPLACE_ADD + 16 STORE_NAME 0 (x) + 19 JUMP_ABSOLUTE 9 + >> 22 LOAD_CONST 2 (None) + 25 RETURN_VALUE +""" class DisTests(unittest.TestCase): def do_disassembly_test(self, func, expected): @@ -118,8 +158,8 @@ class DisTests(unittest.TestCase): def test_opmap(self): self.assertEqual(dis.opmap["STOP_CODE"], 0) - self.assertEqual(dis.opmap["LOAD_CONST"] in dis.hasconst, True) - self.assertEqual(dis.opmap["STORE_NAME"] in dis.hasname, True) + self.assertIn(dis.opmap["LOAD_CONST"], dis.hasconst) + self.assertIn(dis.opmap["STORE_NAME"], dis.hasname) def test_opname(self): self.assertEqual(dis.opname[dis.opmap["LOAD_FAST"]], "LOAD_FAST") @@ -166,8 +206,165 @@ class DisTests(unittest.TestCase): from test import dis_module self.do_disassembly_test(dis_module, dis_module_expected_results) + def test_disassemble_str(self): + self.do_disassembly_test(expr_str, dis_expr_str) + self.do_disassembly_test(simple_stmt_str, dis_simple_stmt_str) + self.do_disassembly_test(compound_stmt_str, dis_compound_stmt_str) + +code_info_code_info = """\ +Name: code_info +Filename: (.*) +Argument count: 1 +Kw-only arguments: 0 +Number of locals: 1 +Stack size: 4 +Flags: OPTIMIZED, NEWLOCALS, NOFREE +Constants: + 0: %r + 1: '__func__' + 2: '__code__' + 3: '<code_info>' + 4: 'co_code' + 5: "don't know how to disassemble %%s objects" +%sNames: + 0: hasattr + 1: __func__ + 2: __code__ + 3: isinstance + 4: str + 5: _try_compile + 6: _format_code_info + 7: TypeError + 8: type + 9: __name__ +Variable names: + 0: x""" % (('Formatted details of methods, functions, or code.', ' 6: None\n') + if sys.flags.optimize < 2 else (None, '')) + +@staticmethod +def tricky(x, y, z=True, *args, c, d, e=[], **kwds): + def f(c=c): + print(x, y, z, c, d, e, f) + yield x, y, z, c, d, e, f + +code_info_tricky = """\ +Name: tricky +Filename: (.*) +Argument count: 3 +Kw-only arguments: 3 +Number of locals: 8 +Stack size: 7 +Flags: OPTIMIZED, NEWLOCALS, VARARGS, VARKEYWORDS, GENERATOR +Constants: + 0: None + 1: <code object f at (.*), file "(.*)", line (.*)> +Variable names: + 0: x + 1: y + 2: z + 3: c + 4: d + 5: e + 6: args + 7: kwds +Cell variables: + 0: e + 1: d + 2: f + 3: y + 4: x + 5: z""" + +co_tricky_nested_f = tricky.__func__.__code__.co_consts[1] + +code_info_tricky_nested_f = """\ +Name: f +Filename: (.*) +Argument count: 1 +Kw-only arguments: 0 +Number of locals: 1 +Stack size: 8 +Flags: OPTIMIZED, NEWLOCALS, NESTED +Constants: + 0: None +Names: + 0: print +Variable names: + 0: c +Free variables: + 0: e + 1: d + 2: f + 3: y + 4: x + 5: z""" + +code_info_expr_str = """\ +Name: <module> +Filename: <code_info> +Argument count: 0 +Kw-only arguments: 0 +Number of locals: 0 +Stack size: 2 +Flags: NOFREE +Constants: + 0: 1 +Names: + 0: x""" + +code_info_simple_stmt_str = """\ +Name: <module> +Filename: <code_info> +Argument count: 0 +Kw-only arguments: 0 +Number of locals: 0 +Stack size: 2 +Flags: NOFREE +Constants: + 0: 1 + 1: None +Names: + 0: x""" + +code_info_compound_stmt_str = """\ +Name: <module> +Filename: <code_info> +Argument count: 0 +Kw-only arguments: 0 +Number of locals: 0 +Stack size: 2 +Flags: NOFREE +Constants: + 0: 0 + 1: 1 + 2: None +Names: + 0: x""" + +class CodeInfoTests(unittest.TestCase): + test_pairs = [ + (dis.code_info, code_info_code_info), + (tricky, code_info_tricky), + (co_tricky_nested_f, code_info_tricky_nested_f), + (expr_str, code_info_expr_str), + (simple_stmt_str, code_info_simple_stmt_str), + (compound_stmt_str, code_info_compound_stmt_str), + ] + + def test_code_info(self): + self.maxDiff = 1000 + for x, expected in self.test_pairs: + self.assertRegex(dis.code_info(x), expected) + + def test_show_code(self): + self.maxDiff = 1000 + for x, expected in self.test_pairs: + with captured_stdout() as output: + dis.show_code(x) + self.assertRegex(output.getvalue(), expected+"\n") + def test_main(): - run_unittest(DisTests) + run_unittest(DisTests, CodeInfoTests) if __name__ == "__main__": test_main() |