summaryrefslogtreecommitdiff
path: root/Lib/test/test_dis.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/test/test_dis.py')
-rw-r--r--Lib/test/test_dis.py221
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()