mirror of
https://github.com/python/cpython.git
synced 2025-07-15 23:35:23 +00:00

Completely get rid of StringIO.py and cStringIO.c. I had to fix a few tests and modules beyond what Christian did, and invent a few conventions. E.g. in elementtree, I chose to write/return Unicode strings whe no encoding is given, but bytes when an explicit encoding is given. Also mimetools was made to always assume binary files.
177 lines
5.4 KiB
Python
177 lines
5.4 KiB
Python
# Minimal tests for dis module
|
|
|
|
from test.test_support import verbose, run_unittest
|
|
import unittest
|
|
import sys
|
|
import dis
|
|
import io
|
|
|
|
|
|
def _f(a):
|
|
print(a)
|
|
return 1
|
|
|
|
dis_f = """\
|
|
%-4d 0 LOAD_GLOBAL 0 (print)
|
|
3 LOAD_FAST 0 (a)
|
|
6 CALL_FUNCTION 1
|
|
9 POP_TOP
|
|
|
|
%-4d 10 LOAD_CONST 1 (1)
|
|
13 RETURN_VALUE
|
|
"""%(_f.__code__.co_firstlineno + 1,
|
|
_f.__code__.co_firstlineno + 2)
|
|
|
|
|
|
def bug708901():
|
|
for res in range(1,
|
|
10):
|
|
pass
|
|
|
|
dis_bug708901 = """\
|
|
%-4d 0 SETUP_LOOP 23 (to 26)
|
|
3 LOAD_GLOBAL 0 (range)
|
|
6 LOAD_CONST 1 (1)
|
|
|
|
%-4d 9 LOAD_CONST 2 (10)
|
|
12 CALL_FUNCTION 2
|
|
15 GET_ITER
|
|
>> 16 FOR_ITER 6 (to 25)
|
|
19 STORE_FAST 0 (res)
|
|
|
|
%-4d 22 JUMP_ABSOLUTE 16
|
|
>> 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)
|
|
|
|
|
|
def bug1333982(x=[]):
|
|
assert 0, ([s for s in x] +
|
|
1)
|
|
pass
|
|
|
|
dis_bug1333982 = """\
|
|
%-4d 0 LOAD_CONST 1 (0)
|
|
3 JUMP_IF_TRUE 41 (to 47)
|
|
6 POP_TOP
|
|
7 LOAD_GLOBAL 0 (AssertionError)
|
|
10 BUILD_LIST 0
|
|
13 DUP_TOP
|
|
14 STORE_FAST 1 (_[1])
|
|
17 LOAD_FAST 0 (x)
|
|
20 GET_ITER
|
|
>> 21 FOR_ITER 13 (to 37)
|
|
24 STORE_FAST 2 (s)
|
|
27 LOAD_FAST 1 (_[1])
|
|
30 LOAD_FAST 2 (s)
|
|
33 LIST_APPEND
|
|
34 JUMP_ABSOLUTE 21
|
|
>> 37 DELETE_FAST 1 (_[1])
|
|
|
|
%-4d 40 LOAD_CONST 2 (1)
|
|
43 BINARY_ADD
|
|
44 RAISE_VARARGS 2
|
|
>> 47 POP_TOP
|
|
|
|
%-4d 48 LOAD_CONST 0 (None)
|
|
51 RETURN_VALUE
|
|
"""%(bug1333982.__code__.co_firstlineno + 1,
|
|
bug1333982.__code__.co_firstlineno + 2,
|
|
bug1333982.__code__.co_firstlineno + 3)
|
|
|
|
_BIG_LINENO_FORMAT = """\
|
|
%3d 0 LOAD_GLOBAL 0 (spam)
|
|
3 POP_TOP
|
|
4 LOAD_CONST 0 (None)
|
|
7 RETURN_VALUE
|
|
"""
|
|
|
|
dis_module_expected_results = """\
|
|
Disassembly of f:
|
|
4 0 LOAD_CONST 0 (None)
|
|
3 RETURN_VALUE
|
|
|
|
Disassembly of g:
|
|
5 0 LOAD_CONST 0 (None)
|
|
3 RETURN_VALUE
|
|
|
|
"""
|
|
|
|
|
|
class DisTests(unittest.TestCase):
|
|
def do_disassembly_test(self, func, expected):
|
|
s = io.StringIO()
|
|
save_stdout = sys.stdout
|
|
sys.stdout = s
|
|
dis.dis(func)
|
|
sys.stdout = save_stdout
|
|
got = s.getvalue()
|
|
# Trim trailing blanks (if any).
|
|
lines = got.split('\n')
|
|
lines = [line.rstrip() for line in lines]
|
|
expected = expected.split("\n")
|
|
import difflib
|
|
if expected != lines:
|
|
self.fail(
|
|
"events did not match expectation:\n" +
|
|
"\n".join(difflib.ndiff(expected,
|
|
lines)))
|
|
|
|
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)
|
|
|
|
def test_opname(self):
|
|
self.assertEqual(dis.opname[dis.opmap["LOAD_FAST"]], "LOAD_FAST")
|
|
|
|
def test_boundaries(self):
|
|
self.assertEqual(dis.opmap["EXTENDED_ARG"], dis.EXTENDED_ARG)
|
|
self.assertEqual(dis.opmap["STORE_NAME"], dis.HAVE_ARGUMENT)
|
|
|
|
def test_dis(self):
|
|
self.do_disassembly_test(_f, dis_f)
|
|
|
|
def test_bug_708901(self):
|
|
self.do_disassembly_test(bug708901, dis_bug708901)
|
|
|
|
def test_bug_1333982(self):
|
|
# XXX: re-enable this test!
|
|
# This one is checking bytecodes generated for an `assert` statement,
|
|
# so fails if the tests are run with -O. Skip this test then.
|
|
pass # Test has been disabled due to change in the way
|
|
# list comps are handled. The byte code now includes
|
|
# a memory address and a file location, so they change from
|
|
# run to run.
|
|
# if __debug__:
|
|
# self.do_disassembly_test(bug1333982, dis_bug1333982)
|
|
|
|
def test_big_linenos(self):
|
|
def func(count):
|
|
namespace = {}
|
|
func = "def foo():\n " + "".join(["\n "] * count + ["spam\n"])
|
|
exec(func, namespace)
|
|
return namespace['foo']
|
|
|
|
# Test all small ranges
|
|
for i in range(1, 300):
|
|
expected = _BIG_LINENO_FORMAT % (i + 2)
|
|
self.do_disassembly_test(func(i), expected)
|
|
|
|
# Test some larger ranges too
|
|
for i in range(300, 5000, 10):
|
|
expected = _BIG_LINENO_FORMAT % (i + 2)
|
|
self.do_disassembly_test(func(i), expected)
|
|
|
|
def test_big_linenos(self):
|
|
from test import dis_module
|
|
self.do_disassembly_test(dis_module, dis_module_expected_results)
|
|
|
|
def test_main():
|
|
run_unittest(DisTests)
|
|
|
|
if __name__ == "__main__":
|
|
test_main()
|