• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import dis
2import math
3import os
4import unittest
5import sys
6import _ast
7import tempfile
8import types
9from test import support
10from test.support import script_helper, FakePath
11
12class TestSpecifics(unittest.TestCase):
13
14    def compile_single(self, source):
15        compile(source, "<single>", "single")
16
17    def assertInvalidSingle(self, source):
18        self.assertRaises(SyntaxError, self.compile_single, source)
19
20    def test_no_ending_newline(self):
21        compile("hi", "<test>", "exec")
22        compile("hi\r", "<test>", "exec")
23
24    def test_empty(self):
25        compile("", "<test>", "exec")
26
27    def test_other_newlines(self):
28        compile("\r\n", "<test>", "exec")
29        compile("\r", "<test>", "exec")
30        compile("hi\r\nstuff\r\ndef f():\n    pass\r", "<test>", "exec")
31        compile("this_is\rreally_old_mac\rdef f():\n    pass", "<test>", "exec")
32
33    def test_debug_assignment(self):
34        # catch assignments to __debug__
35        self.assertRaises(SyntaxError, compile, '__debug__ = 1', '?', 'single')
36        import builtins
37        prev = builtins.__debug__
38        setattr(builtins, '__debug__', 'sure')
39        self.assertEqual(__debug__, prev)
40        setattr(builtins, '__debug__', prev)
41
42    def test_argument_handling(self):
43        # detect duplicate positional and keyword arguments
44        self.assertRaises(SyntaxError, eval, 'lambda a,a:0')
45        self.assertRaises(SyntaxError, eval, 'lambda a,a=1:0')
46        self.assertRaises(SyntaxError, eval, 'lambda a=1,a=1:0')
47        self.assertRaises(SyntaxError, exec, 'def f(a, a): pass')
48        self.assertRaises(SyntaxError, exec, 'def f(a = 0, a = 1): pass')
49        self.assertRaises(SyntaxError, exec, 'def f(a): global a; a = 1')
50
51    def test_syntax_error(self):
52        self.assertRaises(SyntaxError, compile, "1+*3", "filename", "exec")
53
54    def test_none_keyword_arg(self):
55        self.assertRaises(SyntaxError, compile, "f(None=1)", "<string>", "exec")
56
57    def test_duplicate_global_local(self):
58        self.assertRaises(SyntaxError, exec, 'def f(a): global a; a = 1')
59
60    def test_exec_with_general_mapping_for_locals(self):
61
62        class M:
63            "Test mapping interface versus possible calls from eval()."
64            def __getitem__(self, key):
65                if key == 'a':
66                    return 12
67                raise KeyError
68            def __setitem__(self, key, value):
69                self.results = (key, value)
70            def keys(self):
71                return list('xyz')
72
73        m = M()
74        g = globals()
75        exec('z = a', g, m)
76        self.assertEqual(m.results, ('z', 12))
77        try:
78            exec('z = b', g, m)
79        except NameError:
80            pass
81        else:
82            self.fail('Did not detect a KeyError')
83        exec('z = dir()', g, m)
84        self.assertEqual(m.results, ('z', list('xyz')))
85        exec('z = globals()', g, m)
86        self.assertEqual(m.results, ('z', g))
87        exec('z = locals()', g, m)
88        self.assertEqual(m.results, ('z', m))
89        self.assertRaises(TypeError, exec, 'z = b', m)
90
91        class A:
92            "Non-mapping"
93            pass
94        m = A()
95        self.assertRaises(TypeError, exec, 'z = a', g, m)
96
97        # Verify that dict subclasses work as well
98        class D(dict):
99            def __getitem__(self, key):
100                if key == 'a':
101                    return 12
102                return dict.__getitem__(self, key)
103        d = D()
104        exec('z = a', g, d)
105        self.assertEqual(d['z'], 12)
106
107    def test_extended_arg(self):
108        longexpr = 'x = x or ' + '-x' * 2500
109        g = {}
110        code = '''
111def f(x):
112    %s
113    %s
114    %s
115    %s
116    %s
117    %s
118    %s
119    %s
120    %s
121    %s
122    # the expressions above have no effect, x == argument
123    while x:
124        x -= 1
125        # EXTENDED_ARG/JUMP_ABSOLUTE here
126    return x
127''' % ((longexpr,)*10)
128        exec(code, g)
129        self.assertEqual(g['f'](5), 0)
130
131    def test_argument_order(self):
132        self.assertRaises(SyntaxError, exec, 'def f(a=1, b): pass')
133
134    def test_float_literals(self):
135        # testing bad float literals
136        self.assertRaises(SyntaxError, eval, "2e")
137        self.assertRaises(SyntaxError, eval, "2.0e+")
138        self.assertRaises(SyntaxError, eval, "1e-")
139        self.assertRaises(SyntaxError, eval, "3-4e/21")
140
141    def test_indentation(self):
142        # testing compile() of indented block w/o trailing newline"
143        s = """
144if 1:
145    if 2:
146        pass"""
147        compile(s, "<string>", "exec")
148
149    # This test is probably specific to CPython and may not generalize
150    # to other implementations.  We are trying to ensure that when
151    # the first line of code starts after 256, correct line numbers
152    # in tracebacks are still produced.
153    def test_leading_newlines(self):
154        s256 = "".join(["\n"] * 256 + ["spam"])
155        co = compile(s256, 'fn', 'exec')
156        self.assertEqual(co.co_firstlineno, 257)
157        self.assertEqual(co.co_lnotab, bytes())
158
159    def test_literals_with_leading_zeroes(self):
160        for arg in ["077787", "0xj", "0x.", "0e",  "090000000000000",
161                    "080000000000000", "000000000000009", "000000000000008",
162                    "0b42", "0BADCAFE", "0o123456789", "0b1.1", "0o4.2",
163                    "0b101j2", "0o153j2", "0b100e1", "0o777e1", "0777",
164                    "000777", "000000000000007"]:
165            self.assertRaises(SyntaxError, eval, arg)
166
167        self.assertEqual(eval("0xff"), 255)
168        self.assertEqual(eval("0777."), 777)
169        self.assertEqual(eval("0777.0"), 777)
170        self.assertEqual(eval("000000000000000000000000000000000000000000000000000777e0"), 777)
171        self.assertEqual(eval("0777e1"), 7770)
172        self.assertEqual(eval("0e0"), 0)
173        self.assertEqual(eval("0000e-012"), 0)
174        self.assertEqual(eval("09.5"), 9.5)
175        self.assertEqual(eval("0777j"), 777j)
176        self.assertEqual(eval("000"), 0)
177        self.assertEqual(eval("00j"), 0j)
178        self.assertEqual(eval("00.0"), 0)
179        self.assertEqual(eval("0e3"), 0)
180        self.assertEqual(eval("090000000000000."), 90000000000000.)
181        self.assertEqual(eval("090000000000000.0000000000000000000000"), 90000000000000.)
182        self.assertEqual(eval("090000000000000e0"), 90000000000000.)
183        self.assertEqual(eval("090000000000000e-0"), 90000000000000.)
184        self.assertEqual(eval("090000000000000j"), 90000000000000j)
185        self.assertEqual(eval("000000000000008."), 8.)
186        self.assertEqual(eval("000000000000009."), 9.)
187        self.assertEqual(eval("0b101010"), 42)
188        self.assertEqual(eval("-0b000000000010"), -2)
189        self.assertEqual(eval("0o777"), 511)
190        self.assertEqual(eval("-0o0000010"), -8)
191
192    def test_int_literals_too_long(self):
193        n = 3000
194        source = f"a = 1\nb = 2\nc = {'3'*n}\nd = 4"
195        with support.adjust_int_max_str_digits(n):
196            compile(source, "<long_int_pass>", "exec")  # no errors.
197        with support.adjust_int_max_str_digits(n-1):
198            with self.assertRaises(SyntaxError) as err_ctx:
199                compile(source, "<long_int_fail>", "exec")
200            exc = err_ctx.exception
201            self.assertEqual(exc.lineno, 3)
202            self.assertIn('Exceeds the limit ', str(exc))
203            self.assertIn(' Consider hexadecimal ', str(exc))
204
205    def test_unary_minus(self):
206        # Verify treatment of unary minus on negative numbers SF bug #660455
207        if sys.maxsize == 2147483647:
208            # 32-bit machine
209            all_one_bits = '0xffffffff'
210            self.assertEqual(eval(all_one_bits), 4294967295)
211            self.assertEqual(eval("-" + all_one_bits), -4294967295)
212        elif sys.maxsize == 9223372036854775807:
213            # 64-bit machine
214            all_one_bits = '0xffffffffffffffff'
215            self.assertEqual(eval(all_one_bits), 18446744073709551615)
216            self.assertEqual(eval("-" + all_one_bits), -18446744073709551615)
217        else:
218            self.fail("How many bits *does* this machine have???")
219        # Verify treatment of constant folding on -(sys.maxsize+1)
220        # i.e. -2147483648 on 32 bit platforms.  Should return int.
221        self.assertIsInstance(eval("%s" % (-sys.maxsize - 1)), int)
222        self.assertIsInstance(eval("%s" % (-sys.maxsize - 2)), int)
223
224    if sys.maxsize == 9223372036854775807:
225        def test_32_63_bit_values(self):
226            a = +4294967296  # 1 << 32
227            b = -4294967296  # 1 << 32
228            c = +281474976710656  # 1 << 48
229            d = -281474976710656  # 1 << 48
230            e = +4611686018427387904  # 1 << 62
231            f = -4611686018427387904  # 1 << 62
232            g = +9223372036854775807  # 1 << 63 - 1
233            h = -9223372036854775807  # 1 << 63 - 1
234
235            for variable in self.test_32_63_bit_values.__code__.co_consts:
236                if variable is not None:
237                    self.assertIsInstance(variable, int)
238
239    def test_sequence_unpacking_error(self):
240        # Verify sequence packing/unpacking with "or".  SF bug #757818
241        i,j = (1, -1) or (-1, 1)
242        self.assertEqual(i, 1)
243        self.assertEqual(j, -1)
244
245    def test_none_assignment(self):
246        stmts = [
247            'None = 0',
248            'None += 0',
249            '__builtins__.None = 0',
250            'def None(): pass',
251            'class None: pass',
252            '(a, None) = 0, 0',
253            'for None in range(10): pass',
254            'def f(None): pass',
255            'import None',
256            'import x as None',
257            'from x import None',
258            'from x import y as None'
259        ]
260        for stmt in stmts:
261            stmt += "\n"
262            self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'single')
263            self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec')
264
265    def test_import(self):
266        succeed = [
267            'import sys',
268            'import os, sys',
269            'import os as bar',
270            'import os.path as bar',
271            'from __future__ import nested_scopes, generators',
272            'from __future__ import (nested_scopes,\ngenerators)',
273            'from __future__ import (nested_scopes,\ngenerators,)',
274            'from sys import stdin, stderr, stdout',
275            'from sys import (stdin, stderr,\nstdout)',
276            'from sys import (stdin, stderr,\nstdout,)',
277            'from sys import (stdin\n, stderr, stdout)',
278            'from sys import (stdin\n, stderr, stdout,)',
279            'from sys import stdin as si, stdout as so, stderr as se',
280            'from sys import (stdin as si, stdout as so, stderr as se)',
281            'from sys import (stdin as si, stdout as so, stderr as se,)',
282            ]
283        fail = [
284            'import (os, sys)',
285            'import (os), (sys)',
286            'import ((os), (sys))',
287            'import (sys',
288            'import sys)',
289            'import (os,)',
290            'import os As bar',
291            'import os.path a bar',
292            'from sys import stdin As stdout',
293            'from sys import stdin a stdout',
294            'from (sys) import stdin',
295            'from __future__ import (nested_scopes',
296            'from __future__ import nested_scopes)',
297            'from __future__ import nested_scopes,\ngenerators',
298            'from sys import (stdin',
299            'from sys import stdin)',
300            'from sys import stdin, stdout,\nstderr',
301            'from sys import stdin si',
302            'from sys import stdin,',
303            'from sys import (*)',
304            'from sys import (stdin,, stdout, stderr)',
305            'from sys import (stdin, stdout),',
306            ]
307        for stmt in succeed:
308            compile(stmt, 'tmp', 'exec')
309        for stmt in fail:
310            self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec')
311
312    def test_for_distinct_code_objects(self):
313        # SF bug 1048870
314        def f():
315            f1 = lambda x=1: x
316            f2 = lambda x=2: x
317            return f1, f2
318        f1, f2 = f()
319        self.assertNotEqual(id(f1.__code__), id(f2.__code__))
320
321    def test_lambda_doc(self):
322        l = lambda: "foo"
323        self.assertIsNone(l.__doc__)
324
325    def test_encoding(self):
326        code = b'# -*- coding: badencoding -*-\npass\n'
327        self.assertRaises(SyntaxError, compile, code, 'tmp', 'exec')
328        code = '# -*- coding: badencoding -*-\n"\xc2\xa4"\n'
329        compile(code, 'tmp', 'exec')
330        self.assertEqual(eval(code), '\xc2\xa4')
331        code = '"\xc2\xa4"\n'
332        self.assertEqual(eval(code), '\xc2\xa4')
333        code = b'"\xc2\xa4"\n'
334        self.assertEqual(eval(code), '\xa4')
335        code = b'# -*- coding: latin1 -*-\n"\xc2\xa4"\n'
336        self.assertEqual(eval(code), '\xc2\xa4')
337        code = b'# -*- coding: utf-8 -*-\n"\xc2\xa4"\n'
338        self.assertEqual(eval(code), '\xa4')
339        code = b'# -*- coding: iso8859-15 -*-\n"\xc2\xa4"\n'
340        self.assertEqual(eval(code), '\xc2\u20ac')
341        code = '"""\\\n# -*- coding: iso8859-15 -*-\n\xc2\xa4"""\n'
342        self.assertEqual(eval(code), '# -*- coding: iso8859-15 -*-\n\xc2\xa4')
343        code = b'"""\\\n# -*- coding: iso8859-15 -*-\n\xc2\xa4"""\n'
344        self.assertEqual(eval(code), '# -*- coding: iso8859-15 -*-\n\xa4')
345
346    def test_subscripts(self):
347        # SF bug 1448804
348        # Class to make testing subscript results easy
349        class str_map(object):
350            def __init__(self):
351                self.data = {}
352            def __getitem__(self, key):
353                return self.data[str(key)]
354            def __setitem__(self, key, value):
355                self.data[str(key)] = value
356            def __delitem__(self, key):
357                del self.data[str(key)]
358            def __contains__(self, key):
359                return str(key) in self.data
360        d = str_map()
361        # Index
362        d[1] = 1
363        self.assertEqual(d[1], 1)
364        d[1] += 1
365        self.assertEqual(d[1], 2)
366        del d[1]
367        self.assertNotIn(1, d)
368        # Tuple of indices
369        d[1, 1] = 1
370        self.assertEqual(d[1, 1], 1)
371        d[1, 1] += 1
372        self.assertEqual(d[1, 1], 2)
373        del d[1, 1]
374        self.assertNotIn((1, 1), d)
375        # Simple slice
376        d[1:2] = 1
377        self.assertEqual(d[1:2], 1)
378        d[1:2] += 1
379        self.assertEqual(d[1:2], 2)
380        del d[1:2]
381        self.assertNotIn(slice(1, 2), d)
382        # Tuple of simple slices
383        d[1:2, 1:2] = 1
384        self.assertEqual(d[1:2, 1:2], 1)
385        d[1:2, 1:2] += 1
386        self.assertEqual(d[1:2, 1:2], 2)
387        del d[1:2, 1:2]
388        self.assertNotIn((slice(1, 2), slice(1, 2)), d)
389        # Extended slice
390        d[1:2:3] = 1
391        self.assertEqual(d[1:2:3], 1)
392        d[1:2:3] += 1
393        self.assertEqual(d[1:2:3], 2)
394        del d[1:2:3]
395        self.assertNotIn(slice(1, 2, 3), d)
396        # Tuple of extended slices
397        d[1:2:3, 1:2:3] = 1
398        self.assertEqual(d[1:2:3, 1:2:3], 1)
399        d[1:2:3, 1:2:3] += 1
400        self.assertEqual(d[1:2:3, 1:2:3], 2)
401        del d[1:2:3, 1:2:3]
402        self.assertNotIn((slice(1, 2, 3), slice(1, 2, 3)), d)
403        # Ellipsis
404        d[...] = 1
405        self.assertEqual(d[...], 1)
406        d[...] += 1
407        self.assertEqual(d[...], 2)
408        del d[...]
409        self.assertNotIn(Ellipsis, d)
410        # Tuple of Ellipses
411        d[..., ...] = 1
412        self.assertEqual(d[..., ...], 1)
413        d[..., ...] += 1
414        self.assertEqual(d[..., ...], 2)
415        del d[..., ...]
416        self.assertNotIn((Ellipsis, Ellipsis), d)
417
418    def test_annotation_limit(self):
419        # more than 255 annotations, should compile ok
420        s = "def f(%s): pass"
421        s %= ', '.join('a%d:%d' % (i,i) for i in range(300))
422        compile(s, '?', 'exec')
423
424    def test_mangling(self):
425        class A:
426            def f():
427                __mangled = 1
428                __not_mangled__ = 2
429                import __mangled_mod
430                import __package__.module
431
432        self.assertIn("_A__mangled", A.f.__code__.co_varnames)
433        self.assertIn("__not_mangled__", A.f.__code__.co_varnames)
434        self.assertIn("_A__mangled_mod", A.f.__code__.co_varnames)
435        self.assertIn("__package__", A.f.__code__.co_varnames)
436
437    def test_compile_ast(self):
438        fname = __file__
439        if fname.lower().endswith('pyc'):
440            fname = fname[:-1]
441        with open(fname, 'r') as f:
442            fcontents = f.read()
443        sample_code = [
444            ['<assign>', 'x = 5'],
445            ['<ifblock>', """if True:\n    pass\n"""],
446            ['<forblock>', """for n in [1, 2, 3]:\n    print(n)\n"""],
447            ['<deffunc>', """def foo():\n    pass\nfoo()\n"""],
448            [fname, fcontents],
449        ]
450
451        for fname, code in sample_code:
452            co1 = compile(code, '%s1' % fname, 'exec')
453            ast = compile(code, '%s2' % fname, 'exec', _ast.PyCF_ONLY_AST)
454            self.assertTrue(type(ast) == _ast.Module)
455            co2 = compile(ast, '%s3' % fname, 'exec')
456            self.assertEqual(co1, co2)
457            # the code object's filename comes from the second compilation step
458            self.assertEqual(co2.co_filename, '%s3' % fname)
459
460        # raise exception when node type doesn't match with compile mode
461        co1 = compile('print(1)', '<string>', 'exec', _ast.PyCF_ONLY_AST)
462        self.assertRaises(TypeError, compile, co1, '<ast>', 'eval')
463
464        # raise exception when node type is no start node
465        self.assertRaises(TypeError, compile, _ast.If(), '<ast>', 'exec')
466
467        # raise exception when node has invalid children
468        ast = _ast.Module()
469        ast.body = [_ast.BoolOp()]
470        self.assertRaises(TypeError, compile, ast, '<ast>', 'exec')
471
472    def test_dict_evaluation_order(self):
473        i = 0
474
475        def f():
476            nonlocal i
477            i += 1
478            return i
479
480        d = {f(): f(), f(): f()}
481        self.assertEqual(d, {1: 2, 3: 4})
482
483    def test_compile_filename(self):
484        for filename in 'file.py', b'file.py':
485            code = compile('pass', filename, 'exec')
486            self.assertEqual(code.co_filename, 'file.py')
487        for filename in bytearray(b'file.py'), memoryview(b'file.py'):
488            with self.assertWarns(DeprecationWarning):
489                code = compile('pass', filename, 'exec')
490            self.assertEqual(code.co_filename, 'file.py')
491        self.assertRaises(TypeError, compile, 'pass', list(b'file.py'), 'exec')
492
493    @support.cpython_only
494    def test_same_filename_used(self):
495        s = """def f(): pass\ndef g(): pass"""
496        c = compile(s, "myfile", "exec")
497        for obj in c.co_consts:
498            if isinstance(obj, types.CodeType):
499                self.assertIs(obj.co_filename, c.co_filename)
500
501    def test_single_statement(self):
502        self.compile_single("1 + 2")
503        self.compile_single("\n1 + 2")
504        self.compile_single("1 + 2\n")
505        self.compile_single("1 + 2\n\n")
506        self.compile_single("1 + 2\t\t\n")
507        self.compile_single("1 + 2\t\t\n        ")
508        self.compile_single("1 + 2 # one plus two")
509        self.compile_single("1; 2")
510        self.compile_single("import sys; sys")
511        self.compile_single("def f():\n   pass")
512        self.compile_single("while False:\n   pass")
513        self.compile_single("if x:\n   f(x)")
514        self.compile_single("if x:\n   f(x)\nelse:\n   g(x)")
515        self.compile_single("class T:\n   pass")
516
517    def test_bad_single_statement(self):
518        self.assertInvalidSingle('1\n2')
519        self.assertInvalidSingle('def f(): pass')
520        self.assertInvalidSingle('a = 13\nb = 187')
521        self.assertInvalidSingle('del x\ndel y')
522        self.assertInvalidSingle('f()\ng()')
523        self.assertInvalidSingle('f()\n# blah\nblah()')
524        self.assertInvalidSingle('f()\nxy # blah\nblah()')
525        self.assertInvalidSingle('x = 5 # comment\nx = 6\n')
526
527    def test_particularly_evil_undecodable(self):
528        # Issue 24022
529        src = b'0000\x00\n00000000000\n\x00\n\x9e\n'
530        with tempfile.TemporaryDirectory() as tmpd:
531            fn = os.path.join(tmpd, "bad.py")
532            with open(fn, "wb") as fp:
533                fp.write(src)
534            res = script_helper.run_python_until_end(fn)[0]
535        self.assertIn(b"Non-UTF-8", res.err)
536
537    def test_yet_more_evil_still_undecodable(self):
538        # Issue #25388
539        src = b"#\x00\n#\xfd\n"
540        with tempfile.TemporaryDirectory() as tmpd:
541            fn = os.path.join(tmpd, "bad.py")
542            with open(fn, "wb") as fp:
543                fp.write(src)
544            res = script_helper.run_python_until_end(fn)[0]
545        self.assertIn(b"Non-UTF-8", res.err)
546
547    @support.cpython_only
548    def test_compiler_recursion_limit(self):
549        # Expected limit is sys.getrecursionlimit() * the scaling factor
550        # in symtable.c (currently 3)
551        # We expect to fail *at* that limit, because we use up some of
552        # the stack depth limit in the test suite code
553        # So we check the expected limit and 75% of that
554        # XXX (ncoghlan): duplicating the scaling factor here is a little
555        # ugly. Perhaps it should be exposed somewhere...
556        fail_depth = sys.getrecursionlimit() * 3
557        success_depth = int(fail_depth * 0.75)
558
559        def check_limit(prefix, repeated):
560            expect_ok = prefix + repeated * success_depth
561            self.compile_single(expect_ok)
562            broken = prefix + repeated * fail_depth
563            details = "Compiling ({!r} + {!r} * {})".format(
564                         prefix, repeated, fail_depth)
565            with self.assertRaises(RecursionError, msg=details):
566                self.compile_single(broken)
567
568        check_limit("a", "()")
569        check_limit("a", ".b")
570        check_limit("a", "[0]")
571        check_limit("a", "*a")
572
573    def test_null_terminated(self):
574        # The source code is null-terminated internally, but bytes-like
575        # objects are accepted, which could be not terminated.
576        with self.assertRaisesRegex(ValueError, "cannot contain null"):
577            compile("123\x00", "<dummy>", "eval")
578        with self.assertRaisesRegex(ValueError, "cannot contain null"):
579            compile(memoryview(b"123\x00"), "<dummy>", "eval")
580        code = compile(memoryview(b"123\x00")[1:-1], "<dummy>", "eval")
581        self.assertEqual(eval(code), 23)
582        code = compile(memoryview(b"1234")[1:-1], "<dummy>", "eval")
583        self.assertEqual(eval(code), 23)
584        code = compile(memoryview(b"$23$")[1:-1], "<dummy>", "eval")
585        self.assertEqual(eval(code), 23)
586
587        # Also test when eval() and exec() do the compilation step
588        self.assertEqual(eval(memoryview(b"1234")[1:-1]), 23)
589        namespace = dict()
590        exec(memoryview(b"ax = 123")[1:-1], namespace)
591        self.assertEqual(namespace['x'], 12)
592
593    def check_constant(self, func, expected):
594        for const in func.__code__.co_consts:
595            if repr(const) == repr(expected):
596                break
597        else:
598            self.fail("unable to find constant %r in %r"
599                      % (expected, func.__code__.co_consts))
600
601    # Merging equal constants is not a strict requirement for the Python
602    # semantics, it's a more an implementation detail.
603    @support.cpython_only
604    def test_merge_constants(self):
605        # Issue #25843: compile() must merge constants which are equal
606        # and have the same type.
607
608        def check_same_constant(const):
609            ns = {}
610            code = "f1, f2 = lambda: %r, lambda: %r" % (const, const)
611            exec(code, ns)
612            f1 = ns['f1']
613            f2 = ns['f2']
614            self.assertIs(f1.__code__, f2.__code__)
615            self.check_constant(f1, const)
616            self.assertEqual(repr(f1()), repr(const))
617
618        check_same_constant(None)
619        check_same_constant(0)
620        check_same_constant(0.0)
621        check_same_constant(b'abc')
622        check_same_constant('abc')
623
624        # Note: "lambda: ..." emits "LOAD_CONST Ellipsis",
625        # whereas "lambda: Ellipsis" emits "LOAD_GLOBAL Ellipsis"
626        f1, f2 = lambda: ..., lambda: ...
627        self.assertIs(f1.__code__, f2.__code__)
628        self.check_constant(f1, Ellipsis)
629        self.assertEqual(repr(f1()), repr(Ellipsis))
630
631        # Merge constants in tuple or frozenset
632        f1, f2 = lambda: "not a name", lambda: ("not a name",)
633        f3 = lambda x: x in {("not a name",)}
634        self.assertIs(f1.__code__.co_consts[1],
635                      f2.__code__.co_consts[1][0])
636        self.assertIs(next(iter(f3.__code__.co_consts[1])),
637                      f2.__code__.co_consts[1])
638
639        # {0} is converted to a constant frozenset({0}) by the peephole
640        # optimizer
641        f1, f2 = lambda x: x in {0}, lambda x: x in {0}
642        self.assertIs(f1.__code__, f2.__code__)
643        self.check_constant(f1, frozenset({0}))
644        self.assertTrue(f1(0))
645
646    # 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
664    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__)
674            self.assertNotEqual(f1.__code__, f2.__code__)
675            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,))
683        check_different_constants('a', b'a')
684        check_different_constants(('a',), (b'a',))
685
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
704    def test_path_like_objects(self):
705        # An implicit test for PyUnicode_FSDecoder().
706        compile("42", FakePath("test_compile_pathlike"), "single")
707
708    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
713    # 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))
742            self.assertEqual(2, len(opcodes))
743            self.assertEqual('LOAD_CONST', opcodes[0].opname)
744            self.assertEqual(None, opcodes[0].argval)
745            self.assertEqual('RETURN_VALUE', opcodes[1].opname)
746
747    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)
765
766    def test_big_dict_literal(self):
767        # The compiler has a flushing point in "compiler_dict" that calls compiles
768        # a portion of the dictionary literal when the loop that iterates over the items
769        # reaches 0xFFFF elements but the code was not including the boundary element,
770        # dropping the key at position 0xFFFF. See bpo-41531 for more information
771
772        dict_size = 0xFFFF + 1
773        the_dict = "{" + ",".join(f"{x}:{x}" for x in range(dict_size)) + "}"
774        self.assertEqual(len(eval(the_dict)), dict_size)
775
776class TestExpressionStackSize(unittest.TestCase):
777    # These tests check that the computed stack size for a code object
778    # stays within reasonable bounds (see issue #21523 for an example
779    # dysfunction).
780    N = 100
781
782    def check_stack_size(self, code):
783        # To assert that the alleged stack size is not O(N), we
784        # check that it is smaller than log(N).
785        if isinstance(code, str):
786            code = compile(code, "<foo>", "single")
787        max_size = math.ceil(math.log(len(code.co_code)))
788        self.assertLessEqual(code.co_stacksize, max_size)
789
790    def test_and(self):
791        self.check_stack_size("x and " * self.N + "x")
792
793    def test_or(self):
794        self.check_stack_size("x or " * self.N + "x")
795
796    def test_and_or(self):
797        self.check_stack_size("x and x or " * self.N + "x")
798
799    def test_chained_comparison(self):
800        self.check_stack_size("x < " * self.N + "x")
801
802    def test_if_else(self):
803        self.check_stack_size("x if x else " * self.N + "x")
804
805    def test_binop(self):
806        self.check_stack_size("x + " * self.N + "x")
807
808    def test_func_and(self):
809        code = "def f(x):\n"
810        code += "   x and x\n" * self.N
811        self.check_stack_size(code)
812
813
814class TestStackSizeStability(unittest.TestCase):
815    # Check that repeating certain snippets doesn't increase the stack size
816    # beyond what a single snippet requires.
817
818    def check_stack_size(self, snippet, async_=False):
819        def compile_snippet(i):
820            ns = {}
821            script = """def func():\n""" + i * snippet
822            if async_:
823                script = "async " + script
824            code = compile(script, "<script>", "exec")
825            exec(code, ns, ns)
826            return ns['func'].__code__
827
828        sizes = [compile_snippet(i).co_stacksize for i in range(2, 5)]
829        if len(set(sizes)) != 1:
830            import dis, io
831            out = io.StringIO()
832            dis.dis(compile_snippet(1), file=out)
833            self.fail("stack sizes diverge with # of consecutive snippets: "
834                      "%s\n%s\n%s" % (sizes, snippet, out.getvalue()))
835
836    def test_if(self):
837        snippet = """
838            if x:
839                a
840            """
841        self.check_stack_size(snippet)
842
843    def test_if_else(self):
844        snippet = """
845            if x:
846                a
847            elif y:
848                b
849            else:
850                c
851            """
852        self.check_stack_size(snippet)
853
854    def test_try_except_bare(self):
855        snippet = """
856            try:
857                a
858            except:
859                b
860            """
861        self.check_stack_size(snippet)
862
863    def test_try_except_qualified(self):
864        snippet = """
865            try:
866                a
867            except ImportError:
868                b
869            except:
870                c
871            else:
872                d
873            """
874        self.check_stack_size(snippet)
875
876    def test_try_except_as(self):
877        snippet = """
878            try:
879                a
880            except ImportError as e:
881                b
882            except:
883                c
884            else:
885                d
886            """
887        self.check_stack_size(snippet)
888
889    def test_try_finally(self):
890        snippet = """
891                try:
892                    a
893                finally:
894                    b
895            """
896        self.check_stack_size(snippet)
897
898    def test_with(self):
899        snippet = """
900            with x as y:
901                a
902            """
903        self.check_stack_size(snippet)
904
905    def test_while_else(self):
906        snippet = """
907            while x:
908                a
909            else:
910                b
911            """
912        self.check_stack_size(snippet)
913
914    def test_for(self):
915        snippet = """
916            for x in y:
917                a
918            """
919        self.check_stack_size(snippet)
920
921    def test_for_else(self):
922        snippet = """
923            for x in y:
924                a
925            else:
926                b
927            """
928        self.check_stack_size(snippet)
929
930    def test_for_break_continue(self):
931        snippet = """
932            for x in y:
933                if z:
934                    break
935                elif u:
936                    continue
937                else:
938                    a
939            else:
940                b
941            """
942        self.check_stack_size(snippet)
943
944    def test_for_break_continue_inside_try_finally_block(self):
945        snippet = """
946            for x in y:
947                try:
948                    if z:
949                        break
950                    elif u:
951                        continue
952                    else:
953                        a
954                finally:
955                    f
956            else:
957                b
958            """
959        self.check_stack_size(snippet)
960
961    def test_for_break_continue_inside_finally_block(self):
962        snippet = """
963            for x in y:
964                try:
965                    t
966                finally:
967                    if z:
968                        break
969                    elif u:
970                        continue
971                    else:
972                        a
973            else:
974                b
975            """
976        self.check_stack_size(snippet)
977
978    def test_for_break_continue_inside_except_block(self):
979        snippet = """
980            for x in y:
981                try:
982                    t
983                except:
984                    if z:
985                        break
986                    elif u:
987                        continue
988                    else:
989                        a
990            else:
991                b
992            """
993        self.check_stack_size(snippet)
994
995    def test_for_break_continue_inside_with_block(self):
996        snippet = """
997            for x in y:
998                with c:
999                    if z:
1000                        break
1001                    elif u:
1002                        continue
1003                    else:
1004                        a
1005            else:
1006                b
1007            """
1008        self.check_stack_size(snippet)
1009
1010    def test_return_inside_try_finally_block(self):
1011        snippet = """
1012            try:
1013                if z:
1014                    return
1015                else:
1016                    a
1017            finally:
1018                f
1019            """
1020        self.check_stack_size(snippet)
1021
1022    def test_return_inside_finally_block(self):
1023        snippet = """
1024            try:
1025                t
1026            finally:
1027                if z:
1028                    return
1029                else:
1030                    a
1031            """
1032        self.check_stack_size(snippet)
1033
1034    def test_return_inside_except_block(self):
1035        snippet = """
1036            try:
1037                t
1038            except:
1039                if z:
1040                    return
1041                else:
1042                    a
1043            """
1044        self.check_stack_size(snippet)
1045
1046    def test_return_inside_with_block(self):
1047        snippet = """
1048            with c:
1049                if z:
1050                    return
1051                else:
1052                    a
1053            """
1054        self.check_stack_size(snippet)
1055
1056    def test_async_with(self):
1057        snippet = """
1058            async with x as y:
1059                a
1060            """
1061        self.check_stack_size(snippet, async_=True)
1062
1063    def test_async_for(self):
1064        snippet = """
1065            async for x in y:
1066                a
1067            """
1068        self.check_stack_size(snippet, async_=True)
1069
1070    def test_async_for_else(self):
1071        snippet = """
1072            async for x in y:
1073                a
1074            else:
1075                b
1076            """
1077        self.check_stack_size(snippet, async_=True)
1078
1079    def test_for_break_continue_inside_async_with_block(self):
1080        snippet = """
1081            for x in y:
1082                async with c:
1083                    if z:
1084                        break
1085                    elif u:
1086                        continue
1087                    else:
1088                        a
1089            else:
1090                b
1091            """
1092        self.check_stack_size(snippet, async_=True)
1093
1094    def test_return_inside_async_with_block(self):
1095        snippet = """
1096            async with c:
1097                if z:
1098                    return
1099                else:
1100                    a
1101            """
1102        self.check_stack_size(snippet, async_=True)
1103
1104
1105if __name__ == "__main__":
1106    unittest.main()
1107