blob: fd1ef612fd6131544b195391e8525716df3e5884 [file] [log] [blame]
Gregory P. Smith49fa4a92018-11-08 17:55:07 -08001import dis
Antoine Pitrou99614052014-05-23 11:46:03 +02002import math
Benjamin Petersond73aca72015-04-21 12:05:19 -04003import os
Raymond Hettinger8a99b502003-06-23 13:36:57 +00004import unittest
Raymond Hettinger8a99b502003-06-23 13:36:57 +00005import sys
Martin v. Löwis618dc5e2008-03-30 20:03:44 +00006import _ast
Benjamin Petersond73aca72015-04-21 12:05:19 -04007import tempfile
Benjamin Peterson43b06862011-05-27 09:08:01 -05008import types
Berker Peksag076dbd02015-05-06 07:01:52 +03009from test import support
Hai Shi847f94f2020-06-26 01:17:57 +080010from test.support import script_helper
11from test.support.os_helper import FakePath
12
Peter Schneider-Kampfdee0f02000-07-25 22:15:45 +000013
Raymond Hettinger8a99b502003-06-23 13:36:57 +000014class TestSpecifics(unittest.TestCase):
Jeremy Hylton778e2652001-11-09 19:50:08 +000015
Meador Ingefa21bf02012-01-19 01:08:41 -060016 def compile_single(self, source):
17 compile(source, "<single>", "single")
18
19 def assertInvalidSingle(self, source):
20 self.assertRaises(SyntaxError, self.compile_single, source)
21
Benjamin Petersonaeaa5922009-11-13 00:17:59 +000022 def test_no_ending_newline(self):
23 compile("hi", "<test>", "exec")
24 compile("hi\r", "<test>", "exec")
25
26 def test_empty(self):
27 compile("", "<test>", "exec")
28
29 def test_other_newlines(self):
30 compile("\r\n", "<test>", "exec")
31 compile("\r", "<test>", "exec")
32 compile("hi\r\nstuff\r\ndef f():\n pass\r", "<test>", "exec")
33 compile("this_is\rreally_old_mac\rdef f():\n pass", "<test>", "exec")
34
Raymond Hettinger8a99b502003-06-23 13:36:57 +000035 def test_debug_assignment(self):
36 # catch assignments to __debug__
37 self.assertRaises(SyntaxError, compile, '__debug__ = 1', '?', 'single')
Georg Brandl1a3284e2007-12-02 09:40:06 +000038 import builtins
39 prev = builtins.__debug__
40 setattr(builtins, '__debug__', 'sure')
Serhiy Storchaka3325a672017-12-15 12:35:48 +020041 self.assertEqual(__debug__, prev)
Georg Brandl1a3284e2007-12-02 09:40:06 +000042 setattr(builtins, '__debug__', prev)
Jeremy Hylton778e2652001-11-09 19:50:08 +000043
Raymond Hettinger8a99b502003-06-23 13:36:57 +000044 def test_argument_handling(self):
45 # detect duplicate positional and keyword arguments
46 self.assertRaises(SyntaxError, eval, 'lambda a,a:0')
47 self.assertRaises(SyntaxError, eval, 'lambda a,a=1:0')
48 self.assertRaises(SyntaxError, eval, 'lambda a=1,a=1:0')
Benjamin Petersonec19d952008-06-30 15:01:21 +000049 self.assertRaises(SyntaxError, exec, 'def f(a, a): pass')
50 self.assertRaises(SyntaxError, exec, 'def f(a = 0, a = 1): pass')
51 self.assertRaises(SyntaxError, exec, 'def f(a): global a; a = 1')
Jeremy Hylton778e2652001-11-09 19:50:08 +000052
Raymond Hettinger8a99b502003-06-23 13:36:57 +000053 def test_syntax_error(self):
54 self.assertRaises(SyntaxError, compile, "1+*3", "filename", "exec")
Peter Schneider-Kampfdee0f02000-07-25 22:15:45 +000055
Guido van Rossumcd16bf62007-06-13 18:07:49 +000056 def test_none_keyword_arg(self):
57 self.assertRaises(SyntaxError, compile, "f(None=1)", "<string>", "exec")
58
Raymond Hettinger8a99b502003-06-23 13:36:57 +000059 def test_duplicate_global_local(self):
Benjamin Petersonec19d952008-06-30 15:01:21 +000060 self.assertRaises(SyntaxError, exec, 'def f(a): global a; a = 1')
Peter Schneider-Kampfdee0f02000-07-25 22:15:45 +000061
Raymond Hettinger66bd2332004-08-02 08:30:07 +000062 def test_exec_with_general_mapping_for_locals(self):
63
64 class M:
65 "Test mapping interface versus possible calls from eval()."
66 def __getitem__(self, key):
67 if key == 'a':
68 return 12
69 raise KeyError
70 def __setitem__(self, key, value):
71 self.results = (key, value)
Guido van Rossum63eecc72007-02-22 23:55:25 +000072 def keys(self):
73 return list('xyz')
Raymond Hettinger66bd2332004-08-02 08:30:07 +000074
75 m = M()
76 g = globals()
Georg Brandl7cae87c2006-09-06 06:51:57 +000077 exec('z = a', g, m)
Raymond Hettinger66bd2332004-08-02 08:30:07 +000078 self.assertEqual(m.results, ('z', 12))
79 try:
Georg Brandl7cae87c2006-09-06 06:51:57 +000080 exec('z = b', g, m)
Raymond Hettinger66bd2332004-08-02 08:30:07 +000081 except NameError:
82 pass
83 else:
84 self.fail('Did not detect a KeyError')
Georg Brandl7cae87c2006-09-06 06:51:57 +000085 exec('z = dir()', g, m)
Raymond Hettinger66bd2332004-08-02 08:30:07 +000086 self.assertEqual(m.results, ('z', list('xyz')))
Georg Brandl7cae87c2006-09-06 06:51:57 +000087 exec('z = globals()', g, m)
Raymond Hettinger66bd2332004-08-02 08:30:07 +000088 self.assertEqual(m.results, ('z', g))
Georg Brandl7cae87c2006-09-06 06:51:57 +000089 exec('z = locals()', g, m)
Raymond Hettinger66bd2332004-08-02 08:30:07 +000090 self.assertEqual(m.results, ('z', m))
Benjamin Petersonec19d952008-06-30 15:01:21 +000091 self.assertRaises(TypeError, exec, 'z = b', m)
Raymond Hettinger66bd2332004-08-02 08:30:07 +000092
93 class A:
94 "Non-mapping"
95 pass
96 m = A()
Benjamin Petersonec19d952008-06-30 15:01:21 +000097 self.assertRaises(TypeError, exec, 'z = a', g, m)
Raymond Hettinger66bd2332004-08-02 08:30:07 +000098
99 # Verify that dict subclasses work as well
100 class D(dict):
101 def __getitem__(self, key):
102 if key == 'a':
103 return 12
104 return dict.__getitem__(self, key)
105 d = D()
Georg Brandl7cae87c2006-09-06 06:51:57 +0000106 exec('z = a', g, d)
Raymond Hettinger66bd2332004-08-02 08:30:07 +0000107 self.assertEqual(d['z'], 12)
108
Neal Norwitz6ab080c2005-10-24 00:08:10 +0000109 def test_extended_arg(self):
110 longexpr = 'x = x or ' + '-x' * 2500
Georg Brandl7cae87c2006-09-06 06:51:57 +0000111 g = {}
Neal Norwitz6ab080c2005-10-24 00:08:10 +0000112 code = '''
113def f(x):
114 %s
115 %s
116 %s
117 %s
118 %s
119 %s
120 %s
121 %s
122 %s
123 %s
124 # the expressions above have no effect, x == argument
125 while x:
126 x -= 1
127 # EXTENDED_ARG/JUMP_ABSOLUTE here
128 return x
129''' % ((longexpr,)*10)
Georg Brandl7cae87c2006-09-06 06:51:57 +0000130 exec(code, g)
131 self.assertEqual(g['f'](5), 0)
Neal Norwitz6ab080c2005-10-24 00:08:10 +0000132
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000133 def test_argument_order(self):
Benjamin Petersonec19d952008-06-30 15:01:21 +0000134 self.assertRaises(SyntaxError, exec, 'def f(a=1, b): pass')
Jeremy Hylton121b6eb2001-02-19 23:53:42 +0000135
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000136 def test_float_literals(self):
137 # testing bad float literals
138 self.assertRaises(SyntaxError, eval, "2e")
139 self.assertRaises(SyntaxError, eval, "2.0e+")
140 self.assertRaises(SyntaxError, eval, "1e-")
141 self.assertRaises(SyntaxError, eval, "3-4e/21")
Jeremy Hylton121b6eb2001-02-19 23:53:42 +0000142
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000143 def test_indentation(self):
144 # testing compile() of indented block w/o trailing newline"
145 s = """
Guido van Rossum4b499dd32003-02-13 22:07:59 +0000146if 1:
147 if 2:
148 pass"""
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000149 compile(s, "<string>", "exec")
150
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000151 # This test is probably specific to CPython and may not generalize
152 # to other implementations. We are trying to ensure that when
153 # the first line of code starts after 256, correct line numbers
154 # in tracebacks are still produced.
155 def test_leading_newlines(self):
156 s256 = "".join(["\n"] * 256 + ["spam"])
157 co = compile(s256, 'fn', 'exec')
Mark Shannon877df852020-11-12 09:43:29 +0000158 self.assertEqual(co.co_firstlineno, 1)
Mark Shannon5977a792020-12-02 13:31:40 +0000159 self.assertEqual(list(co.co_lines()), [(0, 8, 257)])
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000160
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000161 def test_literals_with_leading_zeroes(self):
162 for arg in ["077787", "0xj", "0x.", "0e", "090000000000000",
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000163 "080000000000000", "000000000000009", "000000000000008",
164 "0b42", "0BADCAFE", "0o123456789", "0b1.1", "0o4.2",
165 "0b101j2", "0o153j2", "0b100e1", "0o777e1", "0777",
166 "000777", "000000000000007"]:
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000167 self.assertRaises(SyntaxError, eval, arg)
168
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000169 self.assertEqual(eval("0xff"), 255)
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000170 self.assertEqual(eval("0777."), 777)
171 self.assertEqual(eval("0777.0"), 777)
172 self.assertEqual(eval("000000000000000000000000000000000000000000000000000777e0"), 777)
173 self.assertEqual(eval("0777e1"), 7770)
174 self.assertEqual(eval("0e0"), 0)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000175 self.assertEqual(eval("0000e-012"), 0)
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000176 self.assertEqual(eval("09.5"), 9.5)
177 self.assertEqual(eval("0777j"), 777j)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000178 self.assertEqual(eval("000"), 0)
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000179 self.assertEqual(eval("00j"), 0j)
180 self.assertEqual(eval("00.0"), 0)
181 self.assertEqual(eval("0e3"), 0)
182 self.assertEqual(eval("090000000000000."), 90000000000000.)
183 self.assertEqual(eval("090000000000000.0000000000000000000000"), 90000000000000.)
184 self.assertEqual(eval("090000000000000e0"), 90000000000000.)
185 self.assertEqual(eval("090000000000000e-0"), 90000000000000.)
186 self.assertEqual(eval("090000000000000j"), 90000000000000j)
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000187 self.assertEqual(eval("000000000000008."), 8.)
188 self.assertEqual(eval("000000000000009."), 9.)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000189 self.assertEqual(eval("0b101010"), 42)
190 self.assertEqual(eval("-0b000000000010"), -2)
191 self.assertEqual(eval("0o777"), 511)
192 self.assertEqual(eval("-0o0000010"), -8)
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000193
194 def test_unary_minus(self):
195 # Verify treatment of unary minus on negative numbers SF bug #660455
Christian Heimesa37d4c62007-12-04 23:02:19 +0000196 if sys.maxsize == 2147483647:
Guido van Rossum6c9e1302003-11-29 23:52:13 +0000197 # 32-bit machine
198 all_one_bits = '0xffffffff'
Guido van Rossume2a383d2007-01-15 16:59:06 +0000199 self.assertEqual(eval(all_one_bits), 4294967295)
200 self.assertEqual(eval("-" + all_one_bits), -4294967295)
Christian Heimesa37d4c62007-12-04 23:02:19 +0000201 elif sys.maxsize == 9223372036854775807:
Guido van Rossum6c9e1302003-11-29 23:52:13 +0000202 # 64-bit machine
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000203 all_one_bits = '0xffffffffffffffff'
Guido van Rossume2a383d2007-01-15 16:59:06 +0000204 self.assertEqual(eval(all_one_bits), 18446744073709551615)
205 self.assertEqual(eval("-" + all_one_bits), -18446744073709551615)
Guido van Rossum6c9e1302003-11-29 23:52:13 +0000206 else:
207 self.fail("How many bits *does* this machine have???")
Ezio Melotti42da6632011-03-15 05:18:48 +0200208 # Verify treatment of constant folding on -(sys.maxsize+1)
Serhiy Storchaka95949422013-08-27 19:40:23 +0300209 # i.e. -2147483648 on 32 bit platforms. Should return int.
Ezio Melottie9615932010-01-24 19:26:24 +0000210 self.assertIsInstance(eval("%s" % (-sys.maxsize - 1)), int)
211 self.assertIsInstance(eval("%s" % (-sys.maxsize - 2)), int)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000212
Christian Heimesa37d4c62007-12-04 23:02:19 +0000213 if sys.maxsize == 9223372036854775807:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000214 def test_32_63_bit_values(self):
215 a = +4294967296 # 1 << 32
216 b = -4294967296 # 1 << 32
217 c = +281474976710656 # 1 << 48
218 d = -281474976710656 # 1 << 48
219 e = +4611686018427387904 # 1 << 62
220 f = -4611686018427387904 # 1 << 62
221 g = +9223372036854775807 # 1 << 63 - 1
222 h = -9223372036854775807 # 1 << 63 - 1
223
Neal Norwitz221085d2007-02-25 20:55:47 +0000224 for variable in self.test_32_63_bit_values.__code__.co_consts:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000225 if variable is not None:
Ezio Melottie9615932010-01-24 19:26:24 +0000226 self.assertIsInstance(variable, int)
Raymond Hettinger8a99b502003-06-23 13:36:57 +0000227
228 def test_sequence_unpacking_error(self):
229 # Verify sequence packing/unpacking with "or". SF bug #757818
230 i,j = (1, -1) or (-1, 1)
231 self.assertEqual(i, 1)
232 self.assertEqual(j, -1)
Guido van Rossum4b499dd32003-02-13 22:07:59 +0000233
Raymond Hettinger11a70c72004-07-17 21:46:25 +0000234 def test_none_assignment(self):
235 stmts = [
236 'None = 0',
237 'None += 0',
238 '__builtins__.None = 0',
239 'def None(): pass',
240 'class None: pass',
241 '(a, None) = 0, 0',
242 'for None in range(10): pass',
243 'def f(None): pass',
Benjamin Peterson78565b22009-06-28 19:19:51 +0000244 'import None',
245 'import x as None',
246 'from x import None',
247 'from x import y as None'
Raymond Hettinger11a70c72004-07-17 21:46:25 +0000248 ]
249 for stmt in stmts:
250 stmt += "\n"
251 self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'single')
252 self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec')
Tim Petersd507dab2001-08-30 20:51:59 +0000253
Anthony Baxter1a4ddae2004-08-31 10:07:13 +0000254 def test_import(self):
255 succeed = [
256 'import sys',
257 'import os, sys',
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000258 'import os as bar',
259 'import os.path as bar',
Anthony Baxter1a4ddae2004-08-31 10:07:13 +0000260 'from __future__ import nested_scopes, generators',
261 'from __future__ import (nested_scopes,\ngenerators)',
262 'from __future__ import (nested_scopes,\ngenerators,)',
263 'from sys import stdin, stderr, stdout',
264 'from sys import (stdin, stderr,\nstdout)',
265 'from sys import (stdin, stderr,\nstdout,)',
266 'from sys import (stdin\n, stderr, stdout)',
267 'from sys import (stdin\n, stderr, stdout,)',
268 'from sys import stdin as si, stdout as so, stderr as se',
269 'from sys import (stdin as si, stdout as so, stderr as se)',
270 'from sys import (stdin as si, stdout as so, stderr as se,)',
271 ]
272 fail = [
273 'import (os, sys)',
274 'import (os), (sys)',
275 'import ((os), (sys))',
276 'import (sys',
277 'import sys)',
278 'import (os,)',
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000279 'import os As bar',
280 'import os.path a bar',
281 'from sys import stdin As stdout',
282 'from sys import stdin a stdout',
Anthony Baxter1a4ddae2004-08-31 10:07:13 +0000283 'from (sys) import stdin',
284 'from __future__ import (nested_scopes',
285 'from __future__ import nested_scopes)',
286 'from __future__ import nested_scopes,\ngenerators',
287 'from sys import (stdin',
288 'from sys import stdin)',
289 'from sys import stdin, stdout,\nstderr',
290 'from sys import stdin si',
Serhiy Storchaka34fd4c22018-11-05 16:20:25 +0200291 'from sys import stdin,',
Anthony Baxter1a4ddae2004-08-31 10:07:13 +0000292 'from sys import (*)',
293 'from sys import (stdin,, stdout, stderr)',
294 'from sys import (stdin, stdout),',
295 ]
296 for stmt in succeed:
297 compile(stmt, 'tmp', 'exec')
298 for stmt in fail:
299 self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec')
300
Raymond Hettinger9047c8f2004-10-24 00:10:06 +0000301 def test_for_distinct_code_objects(self):
302 # SF bug 1048870
303 def f():
304 f1 = lambda x=1: x
305 f2 = lambda x=2: x
306 return f1, f2
307 f1, f2 = f()
Neal Norwitz221085d2007-02-25 20:55:47 +0000308 self.assertNotEqual(id(f1.__code__), id(f2.__code__))
Raymond Hettinger9047c8f2004-10-24 00:10:06 +0000309
Benjamin Petersone6dd2cb2010-03-17 20:56:58 +0000310 def test_lambda_doc(self):
311 l = lambda: "foo"
312 self.assertIsNone(l.__doc__)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000313
Serhiy Storchaka607cb9c2014-09-05 11:00:56 +0300314 def test_encoding(self):
315 code = b'# -*- coding: badencoding -*-\npass\n'
316 self.assertRaises(SyntaxError, compile, code, 'tmp', 'exec')
317 code = '# -*- coding: badencoding -*-\n"\xc2\xa4"\n'
318 compile(code, 'tmp', 'exec')
319 self.assertEqual(eval(code), '\xc2\xa4')
320 code = '"\xc2\xa4"\n'
321 self.assertEqual(eval(code), '\xc2\xa4')
322 code = b'"\xc2\xa4"\n'
323 self.assertEqual(eval(code), '\xa4')
324 code = b'# -*- coding: latin1 -*-\n"\xc2\xa4"\n'
325 self.assertEqual(eval(code), '\xc2\xa4')
326 code = b'# -*- coding: utf-8 -*-\n"\xc2\xa4"\n'
327 self.assertEqual(eval(code), '\xa4')
328 code = b'# -*- coding: iso8859-15 -*-\n"\xc2\xa4"\n'
329 self.assertEqual(eval(code), '\xc2\u20ac')
330 code = '"""\\\n# -*- coding: iso8859-15 -*-\n\xc2\xa4"""\n'
331 self.assertEqual(eval(code), '# -*- coding: iso8859-15 -*-\n\xc2\xa4')
332 code = b'"""\\\n# -*- coding: iso8859-15 -*-\n\xc2\xa4"""\n'
333 self.assertEqual(eval(code), '# -*- coding: iso8859-15 -*-\n\xa4')
Benjamin Peterson5d2ad252010-03-17 20:57:32 +0000334
Nick Coghlaneadee9a2006-03-13 12:31:58 +0000335 def test_subscripts(self):
336 # SF bug 1448804
337 # Class to make testing subscript results easy
338 class str_map(object):
339 def __init__(self):
340 self.data = {}
341 def __getitem__(self, key):
342 return self.data[str(key)]
343 def __setitem__(self, key, value):
344 self.data[str(key)] = value
345 def __delitem__(self, key):
346 del self.data[str(key)]
347 def __contains__(self, key):
348 return str(key) in self.data
349 d = str_map()
350 # Index
351 d[1] = 1
352 self.assertEqual(d[1], 1)
353 d[1] += 1
354 self.assertEqual(d[1], 2)
355 del d[1]
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000356 self.assertNotIn(1, d)
Nick Coghlaneadee9a2006-03-13 12:31:58 +0000357 # Tuple of indices
358 d[1, 1] = 1
359 self.assertEqual(d[1, 1], 1)
360 d[1, 1] += 1
361 self.assertEqual(d[1, 1], 2)
362 del d[1, 1]
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000363 self.assertNotIn((1, 1), d)
Nick Coghlaneadee9a2006-03-13 12:31:58 +0000364 # Simple slice
365 d[1:2] = 1
366 self.assertEqual(d[1:2], 1)
367 d[1:2] += 1
368 self.assertEqual(d[1:2], 2)
369 del d[1:2]
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000370 self.assertNotIn(slice(1, 2), d)
Nick Coghlaneadee9a2006-03-13 12:31:58 +0000371 # Tuple of simple slices
372 d[1:2, 1:2] = 1
373 self.assertEqual(d[1:2, 1:2], 1)
374 d[1:2, 1:2] += 1
375 self.assertEqual(d[1:2, 1:2], 2)
376 del d[1:2, 1:2]
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000377 self.assertNotIn((slice(1, 2), slice(1, 2)), d)
Nick Coghlaneadee9a2006-03-13 12:31:58 +0000378 # Extended slice
379 d[1:2:3] = 1
380 self.assertEqual(d[1:2:3], 1)
381 d[1:2:3] += 1
382 self.assertEqual(d[1:2:3], 2)
383 del d[1:2:3]
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000384 self.assertNotIn(slice(1, 2, 3), d)
Nick Coghlaneadee9a2006-03-13 12:31:58 +0000385 # Tuple of extended slices
386 d[1:2:3, 1:2:3] = 1
387 self.assertEqual(d[1:2:3, 1:2:3], 1)
388 d[1:2:3, 1:2:3] += 1
389 self.assertEqual(d[1:2:3, 1:2:3], 2)
390 del d[1:2:3, 1:2:3]
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000391 self.assertNotIn((slice(1, 2, 3), slice(1, 2, 3)), d)
Nick Coghlaneadee9a2006-03-13 12:31:58 +0000392 # Ellipsis
393 d[...] = 1
394 self.assertEqual(d[...], 1)
395 d[...] += 1
396 self.assertEqual(d[...], 2)
397 del d[...]
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000398 self.assertNotIn(Ellipsis, d)
Nick Coghlaneadee9a2006-03-13 12:31:58 +0000399 # Tuple of Ellipses
400 d[..., ...] = 1
401 self.assertEqual(d[..., ...], 1)
402 d[..., ...] += 1
403 self.assertEqual(d[..., ...], 2)
404 del d[..., ...]
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000405 self.assertNotIn((Ellipsis, Ellipsis), d)
Nick Coghlaneadee9a2006-03-13 12:31:58 +0000406
Guido van Rossum0240b922007-02-26 21:23:50 +0000407 def test_annotation_limit(self):
Serhiy Storchaka5bb8b912016-12-16 19:19:02 +0200408 # more than 255 annotations, should compile ok
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000409 s = "def f(%s): pass"
Serhiy Storchaka5bb8b912016-12-16 19:19:02 +0200410 s %= ', '.join('a%d:%d' % (i,i) for i in range(300))
Guido van Rossum0240b922007-02-26 21:23:50 +0000411 compile(s, '?', 'exec')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000412
413 def test_mangling(self):
414 class A:
415 def f():
416 __mangled = 1
417 __not_mangled__ = 2
418 import __mangled_mod
419 import __package__.module
420
Benjamin Peterson577473f2010-01-19 00:09:57 +0000421 self.assertIn("_A__mangled", A.f.__code__.co_varnames)
422 self.assertIn("__not_mangled__", A.f.__code__.co_varnames)
423 self.assertIn("_A__mangled_mod", A.f.__code__.co_varnames)
424 self.assertIn("__package__", A.f.__code__.co_varnames)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000425
Martin v. Löwis618dc5e2008-03-30 20:03:44 +0000426 def test_compile_ast(self):
427 fname = __file__
Brett Cannonf299abd2015-04-13 14:21:02 -0400428 if fname.lower().endswith('pyc'):
Martin v. Löwis618dc5e2008-03-30 20:03:44 +0000429 fname = fname[:-1]
Inada Naoki35715d12021-04-04 09:01:23 +0900430 with open(fname, encoding='utf-8') as f:
Martin v. Löwis618dc5e2008-03-30 20:03:44 +0000431 fcontents = f.read()
432 sample_code = [
433 ['<assign>', 'x = 5'],
434 ['<ifblock>', """if True:\n pass\n"""],
435 ['<forblock>', """for n in [1, 2, 3]:\n print(n)\n"""],
436 ['<deffunc>', """def foo():\n pass\nfoo()\n"""],
437 [fname, fcontents],
438 ]
439
440 for fname, code in sample_code:
441 co1 = compile(code, '%s1' % fname, 'exec')
442 ast = compile(code, '%s2' % fname, 'exec', _ast.PyCF_ONLY_AST)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000443 self.assertTrue(type(ast) == _ast.Module)
Martin v. Löwis618dc5e2008-03-30 20:03:44 +0000444 co2 = compile(ast, '%s3' % fname, 'exec')
445 self.assertEqual(co1, co2)
Neal Norwitzdb4115f2008-03-31 04:20:05 +0000446 # the code object's filename comes from the second compilation step
447 self.assertEqual(co2.co_filename, '%s3' % fname)
448
449 # raise exception when node type doesn't match with compile mode
450 co1 = compile('print(1)', '<string>', 'exec', _ast.PyCF_ONLY_AST)
451 self.assertRaises(TypeError, compile, co1, '<ast>', 'eval')
452
453 # raise exception when node type is no start node
454 self.assertRaises(TypeError, compile, _ast.If(), '<ast>', 'exec')
455
456 # raise exception when node has invalid children
457 ast = _ast.Module()
458 ast.body = [_ast.BoolOp()]
459 self.assertRaises(TypeError, compile, ast, '<ast>', 'exec')
Martin v. Löwis618dc5e2008-03-30 20:03:44 +0000460
Benjamin Petersonee853392015-05-28 14:30:26 -0500461 def test_dict_evaluation_order(self):
462 i = 0
463
464 def f():
465 nonlocal i
466 i += 1
467 return i
468
469 d = {f(): f(), f(): f()}
470 self.assertEqual(d, {1: 2, 3: 4})
471
Serhiy Storchaka9305d832016-06-18 13:53:36 +0300472 def test_compile_filename(self):
Serhiy Storchakafebc3322016-08-06 23:29:29 +0300473 for filename in 'file.py', b'file.py':
Serhiy Storchaka9305d832016-06-18 13:53:36 +0300474 code = compile('pass', filename, 'exec')
475 self.assertEqual(code.co_filename, 'file.py')
Serhiy Storchakafebc3322016-08-06 23:29:29 +0300476 for filename in bytearray(b'file.py'), memoryview(b'file.py'):
477 with self.assertWarns(DeprecationWarning):
478 code = compile('pass', filename, 'exec')
479 self.assertEqual(code.co_filename, 'file.py')
Serhiy Storchaka9305d832016-06-18 13:53:36 +0300480 self.assertRaises(TypeError, compile, 'pass', list(b'file.py'), 'exec')
481
Benjamin Peterson43b06862011-05-27 09:08:01 -0500482 @support.cpython_only
483 def test_same_filename_used(self):
484 s = """def f(): pass\ndef g(): pass"""
485 c = compile(s, "myfile", "exec")
486 for obj in c.co_consts:
487 if isinstance(obj, types.CodeType):
488 self.assertIs(obj.co_filename, c.co_filename)
489
Meador Ingefa21bf02012-01-19 01:08:41 -0600490 def test_single_statement(self):
491 self.compile_single("1 + 2")
492 self.compile_single("\n1 + 2")
493 self.compile_single("1 + 2\n")
494 self.compile_single("1 + 2\n\n")
495 self.compile_single("1 + 2\t\t\n")
496 self.compile_single("1 + 2\t\t\n ")
497 self.compile_single("1 + 2 # one plus two")
498 self.compile_single("1; 2")
499 self.compile_single("import sys; sys")
500 self.compile_single("def f():\n pass")
501 self.compile_single("while False:\n pass")
502 self.compile_single("if x:\n f(x)")
503 self.compile_single("if x:\n f(x)\nelse:\n g(x)")
504 self.compile_single("class T:\n pass")
505
506 def test_bad_single_statement(self):
507 self.assertInvalidSingle('1\n2')
508 self.assertInvalidSingle('def f(): pass')
509 self.assertInvalidSingle('a = 13\nb = 187')
510 self.assertInvalidSingle('del x\ndel y')
511 self.assertInvalidSingle('f()\ng()')
Benjamin Petersoncff92372012-01-19 17:46:13 -0500512 self.assertInvalidSingle('f()\n# blah\nblah()')
513 self.assertInvalidSingle('f()\nxy # blah\nblah()')
Benjamin Peterson77fc1f32012-01-20 11:01:06 -0500514 self.assertInvalidSingle('x = 5 # comment\nx = 6\n')
Martin v. Löwis618dc5e2008-03-30 20:03:44 +0000515
Benjamin Petersond73aca72015-04-21 12:05:19 -0400516 def test_particularly_evil_undecodable(self):
517 # Issue 24022
518 src = b'0000\x00\n00000000000\n\x00\n\x9e\n'
519 with tempfile.TemporaryDirectory() as tmpd:
520 fn = os.path.join(tmpd, "bad.py")
521 with open(fn, "wb") as fp:
522 fp.write(src)
523 res = script_helper.run_python_until_end(fn)[0]
524 self.assertIn(b"Non-UTF-8", res.err)
525
Serhiy Storchaka0d441112015-11-14 15:10:35 +0200526 def test_yet_more_evil_still_undecodable(self):
527 # Issue #25388
528 src = b"#\x00\n#\xfd\n"
529 with tempfile.TemporaryDirectory() as tmpd:
530 fn = os.path.join(tmpd, "bad.py")
531 with open(fn, "wb") as fp:
532 fp.write(src)
533 res = script_helper.run_python_until_end(fn)[0]
534 self.assertIn(b"Non-UTF-8", res.err)
535
Nick Coghlanaab9c2b2012-11-04 23:14:34 +1000536 @support.cpython_only
537 def test_compiler_recursion_limit(self):
538 # Expected limit is sys.getrecursionlimit() * the scaling factor
539 # in symtable.c (currently 3)
540 # We expect to fail *at* that limit, because we use up some of
541 # the stack depth limit in the test suite code
542 # So we check the expected limit and 75% of that
543 # XXX (ncoghlan): duplicating the scaling factor here is a little
544 # ugly. Perhaps it should be exposed somewhere...
545 fail_depth = sys.getrecursionlimit() * 3
546 success_depth = int(fail_depth * 0.75)
547
548 def check_limit(prefix, repeated):
549 expect_ok = prefix + repeated * success_depth
550 self.compile_single(expect_ok)
551 broken = prefix + repeated * fail_depth
552 details = "Compiling ({!r} + {!r} * {})".format(
553 prefix, repeated, fail_depth)
Yury Selivanovf488fb42015-07-03 01:04:23 -0400554 with self.assertRaises(RecursionError, msg=details):
Nick Coghlanaab9c2b2012-11-04 23:14:34 +1000555 self.compile_single(broken)
556
557 check_limit("a", "()")
558 check_limit("a", ".b")
559 check_limit("a", "[0]")
560 check_limit("a", "*a")
561
Martin Pantereeb896c2015-11-07 02:32:21 +0000562 def test_null_terminated(self):
563 # The source code is null-terminated internally, but bytes-like
564 # objects are accepted, which could be not terminated.
Martin Panterd61d8602015-11-08 11:09:13 +0000565 with self.assertRaisesRegex(ValueError, "cannot contain null"):
Martin Pantereeb896c2015-11-07 02:32:21 +0000566 compile("123\x00", "<dummy>", "eval")
Martin Panterd61d8602015-11-08 11:09:13 +0000567 with self.assertRaisesRegex(ValueError, "cannot contain null"):
Martin Pantereeb896c2015-11-07 02:32:21 +0000568 compile(memoryview(b"123\x00"), "<dummy>", "eval")
569 code = compile(memoryview(b"123\x00")[1:-1], "<dummy>", "eval")
570 self.assertEqual(eval(code), 23)
571 code = compile(memoryview(b"1234")[1:-1], "<dummy>", "eval")
572 self.assertEqual(eval(code), 23)
573 code = compile(memoryview(b"$23$")[1:-1], "<dummy>", "eval")
574 self.assertEqual(eval(code), 23)
575
576 # Also test when eval() and exec() do the compilation step
577 self.assertEqual(eval(memoryview(b"1234")[1:-1]), 23)
578 namespace = dict()
579 exec(memoryview(b"ax = 123")[1:-1], namespace)
580 self.assertEqual(namespace['x'], 12)
581
Victor Stinner3cdd5fb2016-01-22 12:33:12 +0100582 def check_constant(self, func, expected):
583 for const in func.__code__.co_consts:
584 if repr(const) == repr(expected):
585 break
586 else:
587 self.fail("unable to find constant %r in %r"
588 % (expected, func.__code__.co_consts))
589
590 # Merging equal constants is not a strict requirement for the Python
591 # semantics, it's a more an implementation detail.
592 @support.cpython_only
593 def test_merge_constants(self):
594 # Issue #25843: compile() must merge constants which are equal
595 # and have the same type.
596
597 def check_same_constant(const):
598 ns = {}
599 code = "f1, f2 = lambda: %r, lambda: %r" % (const, const)
600 exec(code, ns)
601 f1 = ns['f1']
602 f2 = ns['f2']
603 self.assertIs(f1.__code__, f2.__code__)
604 self.check_constant(f1, const)
605 self.assertEqual(repr(f1()), repr(const))
606
607 check_same_constant(None)
608 check_same_constant(0)
609 check_same_constant(0.0)
610 check_same_constant(b'abc')
611 check_same_constant('abc')
612
613 # Note: "lambda: ..." emits "LOAD_CONST Ellipsis",
614 # whereas "lambda: Ellipsis" emits "LOAD_GLOBAL Ellipsis"
615 f1, f2 = lambda: ..., lambda: ...
616 self.assertIs(f1.__code__, f2.__code__)
617 self.check_constant(f1, Ellipsis)
618 self.assertEqual(repr(f1()), repr(Ellipsis))
619
INADA Naokif7e4d362018-11-29 00:58:46 +0900620 # Merge constants in tuple or frozenset
621 f1, f2 = lambda: "not a name", lambda: ("not a name",)
622 f3 = lambda x: x in {("not a name",)}
623 self.assertIs(f1.__code__.co_consts[1],
624 f2.__code__.co_consts[1][0])
625 self.assertIs(next(iter(f3.__code__.co_consts[1])),
626 f2.__code__.co_consts[1])
627
Victor Stinner3cdd5fb2016-01-22 12:33:12 +0100628 # {0} is converted to a constant frozenset({0}) by the peephole
629 # optimizer
630 f1, f2 = lambda x: x in {0}, lambda x: x in {0}
631 self.assertIs(f1.__code__, f2.__code__)
632 self.check_constant(f1, frozenset({0}))
633 self.assertTrue(f1(0))
634
Inada Naokibdb941b2021-02-10 09:20:42 +0900635 # Merging equal co_linetable and co_code is not a strict requirement
636 # for the Python semantics, it's a more an implementation detail.
637 @support.cpython_only
638 def test_merge_code_attrs(self):
639 # See https://bugs.python.org/issue42217
640 f1 = lambda x: x.y.z
641 f2 = lambda a: a.b.c
642
643 self.assertIs(f1.__code__.co_linetable, f2.__code__.co_linetable)
644 self.assertIs(f1.__code__.co_code, f2.__code__.co_code)
645
Gregory P. Smith49fa4a92018-11-08 17:55:07 -0800646 # This is a regression test for a CPython specific peephole optimizer
647 # implementation bug present in a few releases. It's assertion verifies
648 # that peephole optimization was actually done though that isn't an
649 # indication of the bugs presence or not (crashing is).
650 @support.cpython_only
651 def test_peephole_opt_unreachable_code_array_access_in_bounds(self):
652 """Regression test for issue35193 when run under clang msan."""
653 def unused_code_at_end():
654 return 3
655 raise RuntimeError("unreachable")
656 # The above function definition will trigger the out of bounds
657 # bug in the peephole optimizer as it scans opcodes past the
658 # RETURN_VALUE opcode. This does not always crash an interpreter.
659 # When you build with the clang memory sanitizer it reliably aborts.
660 self.assertEqual(
661 'RETURN_VALUE',
662 list(dis.get_instructions(unused_code_at_end))[-1].opname)
663
Victor Stinner3cdd5fb2016-01-22 12:33:12 +0100664 def test_dont_merge_constants(self):
665 # Issue #25843: compile() must not merge constants which are equal
666 # but have a different type.
667
668 def check_different_constants(const1, const2):
669 ns = {}
670 exec("f1, f2 = lambda: %r, lambda: %r" % (const1, const2), ns)
671 f1 = ns['f1']
672 f2 = ns['f2']
673 self.assertIsNot(f1.__code__, f2.__code__)
Serhiy Storchaka713640c2017-01-24 20:49:26 +0200674 self.assertNotEqual(f1.__code__, f2.__code__)
Victor Stinner3cdd5fb2016-01-22 12:33:12 +0100675 self.check_constant(f1, const1)
676 self.check_constant(f2, const2)
677 self.assertEqual(repr(f1()), repr(const1))
678 self.assertEqual(repr(f2()), repr(const2))
679
680 check_different_constants(0, 0.0)
681 check_different_constants(+0.0, -0.0)
682 check_different_constants((0,), (0.0,))
Serhiy Storchaka713640c2017-01-24 20:49:26 +0200683 check_different_constants('a', b'a')
684 check_different_constants(('a',), (b'a',))
Victor Stinner3cdd5fb2016-01-22 12:33:12 +0100685
686 # check_different_constants() cannot be used because repr(-0j) is
687 # '(-0-0j)', but when '(-0-0j)' is evaluated to 0j: we loose the sign.
688 f1, f2 = lambda: +0.0j, lambda: -0.0j
689 self.assertIsNot(f1.__code__, f2.__code__)
690 self.check_constant(f1, +0.0j)
691 self.check_constant(f2, -0.0j)
692 self.assertEqual(repr(f1()), repr(+0.0j))
693 self.assertEqual(repr(f2()), repr(-0.0j))
694
695 # {0} is converted to a constant frozenset({0}) by the peephole
696 # optimizer
697 f1, f2 = lambda x: x in {0}, lambda x: x in {0.0}
698 self.assertIsNot(f1.__code__, f2.__code__)
699 self.check_constant(f1, frozenset({0}))
700 self.check_constant(f2, frozenset({0.0}))
701 self.assertTrue(f1(0))
702 self.assertTrue(f2(0.0))
703
Brett Cannona5711202016-09-06 19:36:01 -0700704 def test_path_like_objects(self):
705 # An implicit test for PyUnicode_FSDecoder().
Serhiy Storchakab21d1552018-03-02 11:53:51 +0200706 compile("42", FakePath("test_compile_pathlike"), "single")
Brett Cannona5711202016-09-06 19:36:01 -0700707
Serhiy Storchaka782d6fe2018-01-11 20:20:13 +0200708 def test_stack_overflow(self):
709 # bpo-31113: Stack overflow when compile a long sequence of
710 # complex statements.
711 compile("if a: b\n" * 200000, "<dummy>", "exec")
712
Pablo Galindo18c5f9d2019-07-15 10:15:01 +0100713 # Multiple users rely on the fact that CPython does not generate
714 # bytecode for dead code blocks. See bpo-37500 for more context.
715 @support.cpython_only
716 def test_dead_blocks_do_not_generate_bytecode(self):
717 def unused_block_if():
718 if 0:
719 return 42
720
721 def unused_block_while():
722 while 0:
723 return 42
724
725 def unused_block_if_else():
726 if 1:
727 return None
728 else:
729 return 42
730
731 def unused_block_while_else():
732 while 1:
733 return None
734 else:
735 return 42
736
737 funcs = [unused_block_if, unused_block_while,
738 unused_block_if_else, unused_block_while_else]
739
740 for func in funcs:
741 opcodes = list(dis.get_instructions(func))
Mark Shannon8473cf82020-12-15 11:07:50 +0000742 self.assertLessEqual(len(opcodes), 3)
743 self.assertEqual('LOAD_CONST', opcodes[-2].opname)
744 self.assertEqual(None, opcodes[-2].argval)
745 self.assertEqual('RETURN_VALUE', opcodes[-1].opname)
Pablo Galindo18c5f9d2019-07-15 10:15:01 +0100746
Pablo Galindo6c3e66a2019-10-30 11:53:26 +0000747 def test_false_while_loop(self):
748 def break_in_while():
749 while False:
750 break
751
752 def continue_in_while():
753 while False:
754 continue
755
756 funcs = [break_in_while, continue_in_while]
757
758 # Check that we did not raise but we also don't generate bytecode
759 for func in funcs:
760 opcodes = list(dis.get_instructions(func))
761 self.assertEqual(2, len(opcodes))
762 self.assertEqual('LOAD_CONST', opcodes[0].opname)
763 self.assertEqual(None, opcodes[0].argval)
764 self.assertEqual('RETURN_VALUE', opcodes[1].opname)
Nick Coghlanaab9c2b2012-11-04 23:14:34 +1000765
Mark Shannon266b4622020-11-17 19:30:14 +0000766 def test_consts_in_conditionals(self):
767 def and_true(x):
768 return True and x
769
770 def and_false(x):
771 return False and x
772
773 def or_true(x):
774 return True or x
775
776 def or_false(x):
777 return False or x
778
779 funcs = [and_true, and_false, or_true, or_false]
780
781 # Check that condition is removed.
782 for func in funcs:
783 with self.subTest(func=func):
784 opcodes = list(dis.get_instructions(func))
785 self.assertEqual(2, len(opcodes))
786 self.assertIn('LOAD_', opcodes[0].opname)
787 self.assertEqual('RETURN_VALUE', opcodes[1].opname)
788
Mark Shannonc5440932021-03-15 14:24:25 +0000789 def test_lineno_procedure_call(self):
790 def call():
791 (
792 print()
793 )
794 line1 = call.__code__.co_firstlineno + 1
795 assert line1 not in [line for (_, _, line) in call.__code__.co_lines()]
796
Mark Shannon5977a792020-12-02 13:31:40 +0000797 def test_lineno_after_implicit_return(self):
798 TRUE = True
799 # Don't use constant True or False, as compiler will remove test
800 def if1(x):
801 x()
802 if TRUE:
803 pass
804 def if2(x):
805 x()
806 if TRUE:
807 pass
808 else:
809 pass
810 def if3(x):
811 x()
812 if TRUE:
813 pass
814 else:
815 return None
816 def if4(x):
817 x()
818 if not TRUE:
819 pass
820 funcs = [ if1, if2, if3, if4]
821 lastlines = [ 3, 3, 3, 2]
822 frame = None
823 def save_caller_frame():
824 nonlocal frame
825 frame = sys._getframe(1)
826 for func, lastline in zip(funcs, lastlines, strict=True):
827 with self.subTest(func=func):
828 func(save_caller_frame)
829 self.assertEqual(frame.f_lineno-frame.f_code.co_firstlineno, lastline)
Mark Shannon266b4622020-11-17 19:30:14 +0000830
Mark Shannoneaccc122020-12-04 15:22:12 +0000831 def test_lineno_after_no_code(self):
832 def no_code1():
833 "doc string"
834
835 def no_code2():
836 a: int
837
838 for func in (no_code1, no_code2):
839 with self.subTest(func=func):
840 code = func.__code__
841 lines = list(code.co_lines())
842 self.assertEqual(len(lines), 1)
843 start, end, line = lines[0]
844 self.assertEqual(start, 0)
845 self.assertEqual(end, len(code.co_code))
846 self.assertEqual(line, code.co_firstlineno)
847
Mark Shannond48848c2021-03-14 18:01:30 +0000848 def test_lineno_attribute(self):
849 def load_attr():
850 return (
851 o.
852 a
853 )
854 load_attr_lines = [ 2, 3, 1 ]
855
856 def load_method():
857 return (
858 o.
859 m(
860 0
861 )
862 )
863 load_method_lines = [ 2, 3, 4, 3, 1 ]
864
865 def store_attr():
866 (
867 o.
868 a
869 ) = (
870 v
871 )
872 store_attr_lines = [ 5, 2, 3 ]
873
874 def aug_store_attr():
875 (
876 o.
877 a
878 ) += (
879 v
880 )
881 aug_store_attr_lines = [ 2, 3, 5, 1, 3 ]
882
883 funcs = [ load_attr, load_method, store_attr, aug_store_attr]
884 func_lines = [ load_attr_lines, load_method_lines,
885 store_attr_lines, aug_store_attr_lines]
886
887 for func, lines in zip(funcs, func_lines, strict=True):
888 with self.subTest(func=func):
889 code_lines = [ line-func.__code__.co_firstlineno
890 for (_, _, line) in func.__code__.co_lines() ]
891 self.assertEqual(lines, code_lines)
892
Mark Shannoneaccc122020-12-04 15:22:12 +0000893
Pablo Galindoc51db0e2020-08-13 09:48:41 +0100894 def test_big_dict_literal(self):
895 # The compiler has a flushing point in "compiler_dict" that calls compiles
896 # a portion of the dictionary literal when the loop that iterates over the items
897 # reaches 0xFFFF elements but the code was not including the boundary element,
898 # dropping the key at position 0xFFFF. See bpo-41531 for more information
899
900 dict_size = 0xFFFF + 1
901 the_dict = "{" + ",".join(f"{x}:{x}" for x in range(dict_size)) + "}"
902 self.assertEqual(len(eval(the_dict)), dict_size)
903
Om Gc71581c2020-12-16 17:48:05 +0530904 def test_redundant_jump_in_if_else_break(self):
905 # Check if bytecode containing jumps that simply point to the next line
906 # is generated around if-else-break style structures. See bpo-42615.
907
908 def if_else_break():
909 val = 1
910 while True:
911 if val > 0:
912 val -= 1
913 else:
914 break
915 val = -1
916
917 INSTR_SIZE = 2
918 HANDLED_JUMPS = (
919 'POP_JUMP_IF_FALSE',
920 'POP_JUMP_IF_TRUE',
921 'JUMP_ABSOLUTE',
922 'JUMP_FORWARD',
923 )
924
925 for line, instr in enumerate(dis.Bytecode(if_else_break)):
926 if instr.opname == 'JUMP_FORWARD':
927 self.assertNotEqual(instr.arg, 0)
928 elif instr.opname in HANDLED_JUMPS:
929 self.assertNotEqual(instr.arg, (line + 1)*INSTR_SIZE)
930
931
Serhiy Storchakad4864c62018-01-09 21:54:52 +0200932class TestExpressionStackSize(unittest.TestCase):
Antoine Pitrou99614052014-05-23 11:46:03 +0200933 # These tests check that the computed stack size for a code object
934 # stays within reasonable bounds (see issue #21523 for an example
935 # dysfunction).
936 N = 100
937
938 def check_stack_size(self, code):
939 # To assert that the alleged stack size is not O(N), we
940 # check that it is smaller than log(N).
941 if isinstance(code, str):
942 code = compile(code, "<foo>", "single")
943 max_size = math.ceil(math.log(len(code.co_code)))
944 self.assertLessEqual(code.co_stacksize, max_size)
945
946 def test_and(self):
947 self.check_stack_size("x and " * self.N + "x")
948
949 def test_or(self):
950 self.check_stack_size("x or " * self.N + "x")
951
952 def test_and_or(self):
953 self.check_stack_size("x and x or " * self.N + "x")
954
955 def test_chained_comparison(self):
956 self.check_stack_size("x < " * self.N + "x")
957
958 def test_if_else(self):
959 self.check_stack_size("x if x else " * self.N + "x")
960
961 def test_binop(self):
962 self.check_stack_size("x + " * self.N + "x")
963
Mark Shannon11e0b292021-04-15 14:28:56 +0100964 def test_list(self):
965 self.check_stack_size("[" + "x, " * self.N + "x]")
966
967 def test_tuple(self):
968 self.check_stack_size("(" + "x, " * self.N + "x)")
969
970 def test_set(self):
971 self.check_stack_size("{" + "x, " * self.N + "x}")
972
973 def test_dict(self):
974 self.check_stack_size("{" + "x:x, " * self.N + "x:x}")
975
976 def test_func_args(self):
977 self.check_stack_size("f(" + "x, " * self.N + ")")
978
979 def test_func_kwargs(self):
980 kwargs = (f'a{i}=x' for i in range(self.N))
981 self.check_stack_size("f(" + ", ".join(kwargs) + ")")
982
983 def test_func_args(self):
984 self.check_stack_size("o.m(" + "x, " * self.N + ")")
985
986 def test_meth_kwargs(self):
987 kwargs = (f'a{i}=x' for i in range(self.N))
988 self.check_stack_size("o.m(" + ", ".join(kwargs) + ")")
989
Antoine Pitrou99614052014-05-23 11:46:03 +0200990 def test_func_and(self):
991 code = "def f(x):\n"
992 code += " x and x\n" * self.N
993 self.check_stack_size(code)
994
Tim Petersd507dab2001-08-30 20:51:59 +0000995
Serhiy Storchakad4864c62018-01-09 21:54:52 +0200996class TestStackSizeStability(unittest.TestCase):
997 # Check that repeating certain snippets doesn't increase the stack size
998 # beyond what a single snippet requires.
999
1000 def check_stack_size(self, snippet, async_=False):
1001 def compile_snippet(i):
1002 ns = {}
1003 script = """def func():\n""" + i * snippet
1004 if async_:
1005 script = "async " + script
1006 code = compile(script, "<script>", "exec")
1007 exec(code, ns, ns)
1008 return ns['func'].__code__
1009
1010 sizes = [compile_snippet(i).co_stacksize for i in range(2, 5)]
1011 if len(set(sizes)) != 1:
1012 import dis, io
1013 out = io.StringIO()
1014 dis.dis(compile_snippet(1), file=out)
1015 self.fail("stack sizes diverge with # of consecutive snippets: "
1016 "%s\n%s\n%s" % (sizes, snippet, out.getvalue()))
1017
1018 def test_if(self):
1019 snippet = """
1020 if x:
1021 a
1022 """
1023 self.check_stack_size(snippet)
1024
1025 def test_if_else(self):
1026 snippet = """
1027 if x:
1028 a
1029 elif y:
1030 b
1031 else:
1032 c
1033 """
1034 self.check_stack_size(snippet)
1035
1036 def test_try_except_bare(self):
1037 snippet = """
1038 try:
1039 a
1040 except:
1041 b
1042 """
1043 self.check_stack_size(snippet)
1044
1045 def test_try_except_qualified(self):
1046 snippet = """
1047 try:
1048 a
1049 except ImportError:
1050 b
1051 except:
1052 c
1053 else:
1054 d
1055 """
1056 self.check_stack_size(snippet)
1057
1058 def test_try_except_as(self):
1059 snippet = """
1060 try:
1061 a
1062 except ImportError as e:
1063 b
1064 except:
1065 c
1066 else:
1067 d
1068 """
1069 self.check_stack_size(snippet)
1070
1071 def test_try_finally(self):
1072 snippet = """
1073 try:
1074 a
1075 finally:
1076 b
1077 """
1078 self.check_stack_size(snippet)
1079
1080 def test_with(self):
1081 snippet = """
1082 with x as y:
1083 a
1084 """
1085 self.check_stack_size(snippet)
1086
1087 def test_while_else(self):
1088 snippet = """
1089 while x:
1090 a
1091 else:
1092 b
1093 """
1094 self.check_stack_size(snippet)
1095
1096 def test_for(self):
1097 snippet = """
1098 for x in y:
1099 a
1100 """
1101 self.check_stack_size(snippet)
1102
1103 def test_for_else(self):
1104 snippet = """
1105 for x in y:
1106 a
1107 else:
1108 b
1109 """
1110 self.check_stack_size(snippet)
1111
1112 def test_for_break_continue(self):
1113 snippet = """
1114 for x in y:
1115 if z:
1116 break
1117 elif u:
1118 continue
1119 else:
1120 a
1121 else:
1122 b
1123 """
1124 self.check_stack_size(snippet)
1125
1126 def test_for_break_continue_inside_try_finally_block(self):
1127 snippet = """
1128 for x in y:
1129 try:
1130 if z:
1131 break
1132 elif u:
1133 continue
1134 else:
1135 a
1136 finally:
1137 f
1138 else:
1139 b
1140 """
1141 self.check_stack_size(snippet)
1142
Serhiy Storchakafe2bbb12018-03-18 09:56:52 +02001143 def test_for_break_continue_inside_finally_block(self):
Serhiy Storchakad4864c62018-01-09 21:54:52 +02001144 snippet = """
1145 for x in y:
1146 try:
1147 t
1148 finally:
1149 if z:
1150 break
Serhiy Storchakafe2bbb12018-03-18 09:56:52 +02001151 elif u:
1152 continue
Serhiy Storchakad4864c62018-01-09 21:54:52 +02001153 else:
1154 a
1155 else:
1156 b
1157 """
1158 self.check_stack_size(snippet)
1159
1160 def test_for_break_continue_inside_except_block(self):
1161 snippet = """
1162 for x in y:
1163 try:
1164 t
1165 except:
1166 if z:
1167 break
1168 elif u:
1169 continue
1170 else:
1171 a
1172 else:
1173 b
1174 """
1175 self.check_stack_size(snippet)
1176
1177 def test_for_break_continue_inside_with_block(self):
1178 snippet = """
1179 for x in y:
1180 with c:
1181 if z:
1182 break
1183 elif u:
1184 continue
1185 else:
1186 a
1187 else:
1188 b
1189 """
1190 self.check_stack_size(snippet)
1191
1192 def test_return_inside_try_finally_block(self):
1193 snippet = """
1194 try:
1195 if z:
1196 return
1197 else:
1198 a
1199 finally:
1200 f
1201 """
1202 self.check_stack_size(snippet)
1203
1204 def test_return_inside_finally_block(self):
1205 snippet = """
1206 try:
1207 t
1208 finally:
1209 if z:
1210 return
1211 else:
1212 a
1213 """
1214 self.check_stack_size(snippet)
1215
1216 def test_return_inside_except_block(self):
1217 snippet = """
1218 try:
1219 t
1220 except:
1221 if z:
1222 return
1223 else:
1224 a
1225 """
1226 self.check_stack_size(snippet)
1227
1228 def test_return_inside_with_block(self):
1229 snippet = """
1230 with c:
1231 if z:
1232 return
1233 else:
1234 a
1235 """
1236 self.check_stack_size(snippet)
1237
1238 def test_async_with(self):
1239 snippet = """
1240 async with x as y:
1241 a
1242 """
1243 self.check_stack_size(snippet, async_=True)
1244
1245 def test_async_for(self):
1246 snippet = """
1247 async for x in y:
1248 a
1249 """
1250 self.check_stack_size(snippet, async_=True)
1251
1252 def test_async_for_else(self):
1253 snippet = """
1254 async for x in y:
1255 a
1256 else:
1257 b
1258 """
1259 self.check_stack_size(snippet, async_=True)
1260
1261 def test_for_break_continue_inside_async_with_block(self):
1262 snippet = """
1263 for x in y:
1264 async with c:
1265 if z:
1266 break
1267 elif u:
1268 continue
1269 else:
1270 a
1271 else:
1272 b
1273 """
1274 self.check_stack_size(snippet, async_=True)
1275
1276 def test_return_inside_async_with_block(self):
1277 snippet = """
1278 async with c:
1279 if z:
1280 return
1281 else:
1282 a
1283 """
1284 self.check_stack_size(snippet, async_=True)
1285
1286
Raymond Hettinger8a99b502003-06-23 13:36:57 +00001287if __name__ == "__main__":
Antoine Pitrou99614052014-05-23 11:46:03 +02001288 unittest.main()