• 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_unary_minus(self):
193        # Verify treatment of unary minus on negative numbers SF bug #660455
194        if sys.maxsize == 2147483647:
195            # 32-bit machine
196            all_one_bits = '0xffffffff'
197            self.assertEqual(eval(all_one_bits), 4294967295)
198            self.assertEqual(eval("-" + all_one_bits), -4294967295)
199        elif sys.maxsize == 9223372036854775807:
200            # 64-bit machine
201            all_one_bits = '0xffffffffffffffff'
202            self.assertEqual(eval(all_one_bits), 18446744073709551615)
203            self.assertEqual(eval("-" + all_one_bits), -18446744073709551615)
204        else:
205            self.fail("How many bits *does* this machine have???")
206        # Verify treatment of constant folding on -(sys.maxsize+1)
207        # i.e. -2147483648 on 32 bit platforms.  Should return int.
208        self.assertIsInstance(eval("%s" % (-sys.maxsize - 1)), int)
209        self.assertIsInstance(eval("%s" % (-sys.maxsize - 2)), int)
210
211    if sys.maxsize == 9223372036854775807:
212        def test_32_63_bit_values(self):
213            a = +4294967296  # 1 << 32
214            b = -4294967296  # 1 << 32
215            c = +281474976710656  # 1 << 48
216            d = -281474976710656  # 1 << 48
217            e = +4611686018427387904  # 1 << 62
218            f = -4611686018427387904  # 1 << 62
219            g = +9223372036854775807  # 1 << 63 - 1
220            h = -9223372036854775807  # 1 << 63 - 1
221
222            for variable in self.test_32_63_bit_values.__code__.co_consts:
223                if variable is not None:
224                    self.assertIsInstance(variable, int)
225
226    def test_sequence_unpacking_error(self):
227        # Verify sequence packing/unpacking with "or".  SF bug #757818
228        i,j = (1, -1) or (-1, 1)
229        self.assertEqual(i, 1)
230        self.assertEqual(j, -1)
231
232    def test_none_assignment(self):
233        stmts = [
234            'None = 0',
235            'None += 0',
236            '__builtins__.None = 0',
237            'def None(): pass',
238            'class None: pass',
239            '(a, None) = 0, 0',
240            'for None in range(10): pass',
241            'def f(None): pass',
242            'import None',
243            'import x as None',
244            'from x import None',
245            'from x import y as None'
246        ]
247        for stmt in stmts:
248            stmt += "\n"
249            self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'single')
250            self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec')
251
252    def test_import(self):
253        succeed = [
254            'import sys',
255            'import os, sys',
256            'import os as bar',
257            'import os.path as bar',
258            'from __future__ import nested_scopes, generators',
259            'from __future__ import (nested_scopes,\ngenerators)',
260            'from __future__ import (nested_scopes,\ngenerators,)',
261            'from sys import stdin, stderr, stdout',
262            'from sys import (stdin, stderr,\nstdout)',
263            'from sys import (stdin, stderr,\nstdout,)',
264            'from sys import (stdin\n, stderr, stdout)',
265            'from sys import (stdin\n, stderr, stdout,)',
266            'from sys import stdin as si, stdout as so, stderr as se',
267            'from sys import (stdin as si, stdout as so, stderr as se)',
268            'from sys import (stdin as si, stdout as so, stderr as se,)',
269            ]
270        fail = [
271            'import (os, sys)',
272            'import (os), (sys)',
273            'import ((os), (sys))',
274            'import (sys',
275            'import sys)',
276            'import (os,)',
277            'import os As bar',
278            'import os.path a bar',
279            'from sys import stdin As stdout',
280            'from sys import stdin a stdout',
281            'from (sys) import stdin',
282            'from __future__ import (nested_scopes',
283            'from __future__ import nested_scopes)',
284            'from __future__ import nested_scopes,\ngenerators',
285            'from sys import (stdin',
286            'from sys import stdin)',
287            'from sys import stdin, stdout,\nstderr',
288            'from sys import stdin si',
289            'from sys import stdin,',
290            'from sys import (*)',
291            'from sys import (stdin,, stdout, stderr)',
292            'from sys import (stdin, stdout),',
293            ]
294        for stmt in succeed:
295            compile(stmt, 'tmp', 'exec')
296        for stmt in fail:
297            self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec')
298
299    def test_for_distinct_code_objects(self):
300        # SF bug 1048870
301        def f():
302            f1 = lambda x=1: x
303            f2 = lambda x=2: x
304            return f1, f2
305        f1, f2 = f()
306        self.assertNotEqual(id(f1.__code__), id(f2.__code__))
307
308    def test_lambda_doc(self):
309        l = lambda: "foo"
310        self.assertIsNone(l.__doc__)
311
312    def test_encoding(self):
313        code = b'# -*- coding: badencoding -*-\npass\n'
314        self.assertRaises(SyntaxError, compile, code, 'tmp', 'exec')
315        code = '# -*- coding: badencoding -*-\n"\xc2\xa4"\n'
316        compile(code, 'tmp', 'exec')
317        self.assertEqual(eval(code), '\xc2\xa4')
318        code = '"\xc2\xa4"\n'
319        self.assertEqual(eval(code), '\xc2\xa4')
320        code = b'"\xc2\xa4"\n'
321        self.assertEqual(eval(code), '\xa4')
322        code = b'# -*- coding: latin1 -*-\n"\xc2\xa4"\n'
323        self.assertEqual(eval(code), '\xc2\xa4')
324        code = b'# -*- coding: utf-8 -*-\n"\xc2\xa4"\n'
325        self.assertEqual(eval(code), '\xa4')
326        code = b'# -*- coding: iso8859-15 -*-\n"\xc2\xa4"\n'
327        self.assertEqual(eval(code), '\xc2\u20ac')
328        code = '"""\\\n# -*- coding: iso8859-15 -*-\n\xc2\xa4"""\n'
329        self.assertEqual(eval(code), '# -*- coding: iso8859-15 -*-\n\xc2\xa4')
330        code = b'"""\\\n# -*- coding: iso8859-15 -*-\n\xc2\xa4"""\n'
331        self.assertEqual(eval(code), '# -*- coding: iso8859-15 -*-\n\xa4')
332
333    def test_subscripts(self):
334        # SF bug 1448804
335        # Class to make testing subscript results easy
336        class str_map(object):
337            def __init__(self):
338                self.data = {}
339            def __getitem__(self, key):
340                return self.data[str(key)]
341            def __setitem__(self, key, value):
342                self.data[str(key)] = value
343            def __delitem__(self, key):
344                del self.data[str(key)]
345            def __contains__(self, key):
346                return str(key) in self.data
347        d = str_map()
348        # Index
349        d[1] = 1
350        self.assertEqual(d[1], 1)
351        d[1] += 1
352        self.assertEqual(d[1], 2)
353        del d[1]
354        self.assertNotIn(1, d)
355        # Tuple of indices
356        d[1, 1] = 1
357        self.assertEqual(d[1, 1], 1)
358        d[1, 1] += 1
359        self.assertEqual(d[1, 1], 2)
360        del d[1, 1]
361        self.assertNotIn((1, 1), d)
362        # Simple slice
363        d[1:2] = 1
364        self.assertEqual(d[1:2], 1)
365        d[1:2] += 1
366        self.assertEqual(d[1:2], 2)
367        del d[1:2]
368        self.assertNotIn(slice(1, 2), d)
369        # Tuple of simple slices
370        d[1:2, 1:2] = 1
371        self.assertEqual(d[1:2, 1:2], 1)
372        d[1:2, 1:2] += 1
373        self.assertEqual(d[1:2, 1:2], 2)
374        del d[1:2, 1:2]
375        self.assertNotIn((slice(1, 2), slice(1, 2)), d)
376        # Extended slice
377        d[1:2:3] = 1
378        self.assertEqual(d[1:2:3], 1)
379        d[1:2:3] += 1
380        self.assertEqual(d[1:2:3], 2)
381        del d[1:2:3]
382        self.assertNotIn(slice(1, 2, 3), d)
383        # Tuple of extended slices
384        d[1:2:3, 1:2:3] = 1
385        self.assertEqual(d[1:2:3, 1:2:3], 1)
386        d[1:2:3, 1:2:3] += 1
387        self.assertEqual(d[1:2:3, 1:2:3], 2)
388        del d[1:2:3, 1:2:3]
389        self.assertNotIn((slice(1, 2, 3), slice(1, 2, 3)), d)
390        # Ellipsis
391        d[...] = 1
392        self.assertEqual(d[...], 1)
393        d[...] += 1
394        self.assertEqual(d[...], 2)
395        del d[...]
396        self.assertNotIn(Ellipsis, d)
397        # Tuple of Ellipses
398        d[..., ...] = 1
399        self.assertEqual(d[..., ...], 1)
400        d[..., ...] += 1
401        self.assertEqual(d[..., ...], 2)
402        del d[..., ...]
403        self.assertNotIn((Ellipsis, Ellipsis), d)
404
405    def test_annotation_limit(self):
406        # more than 255 annotations, should compile ok
407        s = "def f(%s): pass"
408        s %= ', '.join('a%d:%d' % (i,i) for i in range(300))
409        compile(s, '?', 'exec')
410
411    def test_mangling(self):
412        class A:
413            def f():
414                __mangled = 1
415                __not_mangled__ = 2
416                import __mangled_mod
417                import __package__.module
418
419        self.assertIn("_A__mangled", A.f.__code__.co_varnames)
420        self.assertIn("__not_mangled__", A.f.__code__.co_varnames)
421        self.assertIn("_A__mangled_mod", A.f.__code__.co_varnames)
422        self.assertIn("__package__", A.f.__code__.co_varnames)
423
424    def test_compile_ast(self):
425        fname = __file__
426        if fname.lower().endswith('pyc'):
427            fname = fname[:-1]
428        with open(fname, 'r') as f:
429            fcontents = f.read()
430        sample_code = [
431            ['<assign>', 'x = 5'],
432            ['<ifblock>', """if True:\n    pass\n"""],
433            ['<forblock>', """for n in [1, 2, 3]:\n    print(n)\n"""],
434            ['<deffunc>', """def foo():\n    pass\nfoo()\n"""],
435            [fname, fcontents],
436        ]
437
438        for fname, code in sample_code:
439            co1 = compile(code, '%s1' % fname, 'exec')
440            ast = compile(code, '%s2' % fname, 'exec', _ast.PyCF_ONLY_AST)
441            self.assertTrue(type(ast) == _ast.Module)
442            co2 = compile(ast, '%s3' % fname, 'exec')
443            self.assertEqual(co1, co2)
444            # the code object's filename comes from the second compilation step
445            self.assertEqual(co2.co_filename, '%s3' % fname)
446
447        # raise exception when node type doesn't match with compile mode
448        co1 = compile('print(1)', '<string>', 'exec', _ast.PyCF_ONLY_AST)
449        self.assertRaises(TypeError, compile, co1, '<ast>', 'eval')
450
451        # raise exception when node type is no start node
452        self.assertRaises(TypeError, compile, _ast.If(), '<ast>', 'exec')
453
454        # raise exception when node has invalid children
455        ast = _ast.Module()
456        ast.body = [_ast.BoolOp()]
457        self.assertRaises(TypeError, compile, ast, '<ast>', 'exec')
458
459    def test_dict_evaluation_order(self):
460        i = 0
461
462        def f():
463            nonlocal i
464            i += 1
465            return i
466
467        d = {f(): f(), f(): f()}
468        self.assertEqual(d, {1: 2, 3: 4})
469
470    def test_compile_filename(self):
471        for filename in 'file.py', b'file.py':
472            code = compile('pass', filename, 'exec')
473            self.assertEqual(code.co_filename, 'file.py')
474        for filename in bytearray(b'file.py'), memoryview(b'file.py'):
475            with self.assertWarns(DeprecationWarning):
476                code = compile('pass', filename, 'exec')
477            self.assertEqual(code.co_filename, 'file.py')
478        self.assertRaises(TypeError, compile, 'pass', list(b'file.py'), 'exec')
479
480    @support.cpython_only
481    def test_same_filename_used(self):
482        s = """def f(): pass\ndef g(): pass"""
483        c = compile(s, "myfile", "exec")
484        for obj in c.co_consts:
485            if isinstance(obj, types.CodeType):
486                self.assertIs(obj.co_filename, c.co_filename)
487
488    def test_single_statement(self):
489        self.compile_single("1 + 2")
490        self.compile_single("\n1 + 2")
491        self.compile_single("1 + 2\n")
492        self.compile_single("1 + 2\n\n")
493        self.compile_single("1 + 2\t\t\n")
494        self.compile_single("1 + 2\t\t\n        ")
495        self.compile_single("1 + 2 # one plus two")
496        self.compile_single("1; 2")
497        self.compile_single("import sys; sys")
498        self.compile_single("def f():\n   pass")
499        self.compile_single("while False:\n   pass")
500        self.compile_single("if x:\n   f(x)")
501        self.compile_single("if x:\n   f(x)\nelse:\n   g(x)")
502        self.compile_single("class T:\n   pass")
503
504    def test_bad_single_statement(self):
505        self.assertInvalidSingle('1\n2')
506        self.assertInvalidSingle('def f(): pass')
507        self.assertInvalidSingle('a = 13\nb = 187')
508        self.assertInvalidSingle('del x\ndel y')
509        self.assertInvalidSingle('f()\ng()')
510        self.assertInvalidSingle('f()\n# blah\nblah()')
511        self.assertInvalidSingle('f()\nxy # blah\nblah()')
512        self.assertInvalidSingle('x = 5 # comment\nx = 6\n')
513
514    def test_particularly_evil_undecodable(self):
515        # Issue 24022
516        src = b'0000\x00\n00000000000\n\x00\n\x9e\n'
517        with tempfile.TemporaryDirectory() as tmpd:
518            fn = os.path.join(tmpd, "bad.py")
519            with open(fn, "wb") as fp:
520                fp.write(src)
521            res = script_helper.run_python_until_end(fn)[0]
522        self.assertIn(b"Non-UTF-8", res.err)
523
524    def test_yet_more_evil_still_undecodable(self):
525        # Issue #25388
526        src = b"#\x00\n#\xfd\n"
527        with tempfile.TemporaryDirectory() as tmpd:
528            fn = os.path.join(tmpd, "bad.py")
529            with open(fn, "wb") as fp:
530                fp.write(src)
531            res = script_helper.run_python_until_end(fn)[0]
532        self.assertIn(b"Non-UTF-8", res.err)
533
534    @support.cpython_only
535    def test_compiler_recursion_limit(self):
536        # Expected limit is sys.getrecursionlimit() * the scaling factor
537        # in symtable.c (currently 3)
538        # We expect to fail *at* that limit, because we use up some of
539        # the stack depth limit in the test suite code
540        # So we check the expected limit and 75% of that
541        # XXX (ncoghlan): duplicating the scaling factor here is a little
542        # ugly. Perhaps it should be exposed somewhere...
543        fail_depth = sys.getrecursionlimit() * 3
544        success_depth = int(fail_depth * 0.75)
545
546        def check_limit(prefix, repeated):
547            expect_ok = prefix + repeated * success_depth
548            self.compile_single(expect_ok)
549            broken = prefix + repeated * fail_depth
550            details = "Compiling ({!r} + {!r} * {})".format(
551                         prefix, repeated, fail_depth)
552            with self.assertRaises(RecursionError, msg=details):
553                self.compile_single(broken)
554
555        check_limit("a", "()")
556        check_limit("a", ".b")
557        check_limit("a", "[0]")
558        check_limit("a", "*a")
559
560    def test_null_terminated(self):
561        # The source code is null-terminated internally, but bytes-like
562        # objects are accepted, which could be not terminated.
563        with self.assertRaisesRegex(ValueError, "cannot contain null"):
564            compile("123\x00", "<dummy>", "eval")
565        with self.assertRaisesRegex(ValueError, "cannot contain null"):
566            compile(memoryview(b"123\x00"), "<dummy>", "eval")
567        code = compile(memoryview(b"123\x00")[1:-1], "<dummy>", "eval")
568        self.assertEqual(eval(code), 23)
569        code = compile(memoryview(b"1234")[1:-1], "<dummy>", "eval")
570        self.assertEqual(eval(code), 23)
571        code = compile(memoryview(b"$23$")[1:-1], "<dummy>", "eval")
572        self.assertEqual(eval(code), 23)
573
574        # Also test when eval() and exec() do the compilation step
575        self.assertEqual(eval(memoryview(b"1234")[1:-1]), 23)
576        namespace = dict()
577        exec(memoryview(b"ax = 123")[1:-1], namespace)
578        self.assertEqual(namespace['x'], 12)
579
580    def check_constant(self, func, expected):
581        for const in func.__code__.co_consts:
582            if repr(const) == repr(expected):
583                break
584        else:
585            self.fail("unable to find constant %r in %r"
586                      % (expected, func.__code__.co_consts))
587
588    # Merging equal constants is not a strict requirement for the Python
589    # semantics, it's a more an implementation detail.
590    @support.cpython_only
591    def test_merge_constants(self):
592        # Issue #25843: compile() must merge constants which are equal
593        # and have the same type.
594
595        def check_same_constant(const):
596            ns = {}
597            code = "f1, f2 = lambda: %r, lambda: %r" % (const, const)
598            exec(code, ns)
599            f1 = ns['f1']
600            f2 = ns['f2']
601            self.assertIs(f1.__code__, f2.__code__)
602            self.check_constant(f1, const)
603            self.assertEqual(repr(f1()), repr(const))
604
605        check_same_constant(None)
606        check_same_constant(0)
607        check_same_constant(0.0)
608        check_same_constant(b'abc')
609        check_same_constant('abc')
610
611        # Note: "lambda: ..." emits "LOAD_CONST Ellipsis",
612        # whereas "lambda: Ellipsis" emits "LOAD_GLOBAL Ellipsis"
613        f1, f2 = lambda: ..., lambda: ...
614        self.assertIs(f1.__code__, f2.__code__)
615        self.check_constant(f1, Ellipsis)
616        self.assertEqual(repr(f1()), repr(Ellipsis))
617
618        # Merge constants in tuple or frozenset
619        f1, f2 = lambda: "not a name", lambda: ("not a name",)
620        f3 = lambda x: x in {("not a name",)}
621        self.assertIs(f1.__code__.co_consts[1],
622                      f2.__code__.co_consts[1][0])
623        self.assertIs(next(iter(f3.__code__.co_consts[1])),
624                      f2.__code__.co_consts[1])
625
626        # {0} is converted to a constant frozenset({0}) by the peephole
627        # optimizer
628        f1, f2 = lambda x: x in {0}, lambda x: x in {0}
629        self.assertIs(f1.__code__, f2.__code__)
630        self.check_constant(f1, frozenset({0}))
631        self.assertTrue(f1(0))
632
633    # This is a regression test for a CPython specific peephole optimizer
634    # implementation bug present in a few releases.  It's assertion verifies
635    # that peephole optimization was actually done though that isn't an
636    # indication of the bugs presence or not (crashing is).
637    @support.cpython_only
638    def test_peephole_opt_unreachable_code_array_access_in_bounds(self):
639        """Regression test for issue35193 when run under clang msan."""
640        def unused_code_at_end():
641            return 3
642            raise RuntimeError("unreachable")
643        # The above function definition will trigger the out of bounds
644        # bug in the peephole optimizer as it scans opcodes past the
645        # RETURN_VALUE opcode.  This does not always crash an interpreter.
646        # When you build with the clang memory sanitizer it reliably aborts.
647        self.assertEqual(
648            'RETURN_VALUE',
649            list(dis.get_instructions(unused_code_at_end))[-1].opname)
650
651    def test_dont_merge_constants(self):
652        # Issue #25843: compile() must not merge constants which are equal
653        # but have a different type.
654
655        def check_different_constants(const1, const2):
656            ns = {}
657            exec("f1, f2 = lambda: %r, lambda: %r" % (const1, const2), ns)
658            f1 = ns['f1']
659            f2 = ns['f2']
660            self.assertIsNot(f1.__code__, f2.__code__)
661            self.assertNotEqual(f1.__code__, f2.__code__)
662            self.check_constant(f1, const1)
663            self.check_constant(f2, const2)
664            self.assertEqual(repr(f1()), repr(const1))
665            self.assertEqual(repr(f2()), repr(const2))
666
667        check_different_constants(0, 0.0)
668        check_different_constants(+0.0, -0.0)
669        check_different_constants((0,), (0.0,))
670        check_different_constants('a', b'a')
671        check_different_constants(('a',), (b'a',))
672
673        # check_different_constants() cannot be used because repr(-0j) is
674        # '(-0-0j)', but when '(-0-0j)' is evaluated to 0j: we loose the sign.
675        f1, f2 = lambda: +0.0j, lambda: -0.0j
676        self.assertIsNot(f1.__code__, f2.__code__)
677        self.check_constant(f1, +0.0j)
678        self.check_constant(f2, -0.0j)
679        self.assertEqual(repr(f1()), repr(+0.0j))
680        self.assertEqual(repr(f2()), repr(-0.0j))
681
682        # {0} is converted to a constant frozenset({0}) by the peephole
683        # optimizer
684        f1, f2 = lambda x: x in {0}, lambda x: x in {0.0}
685        self.assertIsNot(f1.__code__, f2.__code__)
686        self.check_constant(f1, frozenset({0}))
687        self.check_constant(f2, frozenset({0.0}))
688        self.assertTrue(f1(0))
689        self.assertTrue(f2(0.0))
690
691    def test_path_like_objects(self):
692        # An implicit test for PyUnicode_FSDecoder().
693        compile("42", FakePath("test_compile_pathlike"), "single")
694
695    def test_stack_overflow(self):
696        # bpo-31113: Stack overflow when compile a long sequence of
697        # complex statements.
698        compile("if a: b\n" * 200000, "<dummy>", "exec")
699
700    # Multiple users rely on the fact that CPython does not generate
701    # bytecode for dead code blocks. See bpo-37500 for more context.
702    @support.cpython_only
703    def test_dead_blocks_do_not_generate_bytecode(self):
704        def unused_block_if():
705            if 0:
706                return 42
707
708        def unused_block_while():
709            while 0:
710                return 42
711
712        def unused_block_if_else():
713            if 1:
714                return None
715            else:
716                return 42
717
718        def unused_block_while_else():
719            while 1:
720                return None
721            else:
722                return 42
723
724        funcs = [unused_block_if, unused_block_while,
725                 unused_block_if_else, unused_block_while_else]
726
727        for func in funcs:
728            opcodes = list(dis.get_instructions(func))
729            self.assertEqual(2, len(opcodes))
730            self.assertEqual('LOAD_CONST', opcodes[0].opname)
731            self.assertEqual(None, opcodes[0].argval)
732            self.assertEqual('RETURN_VALUE', opcodes[1].opname)
733
734    def test_false_while_loop(self):
735        def break_in_while():
736            while False:
737                break
738
739        def continue_in_while():
740            while False:
741                continue
742
743        funcs = [break_in_while, continue_in_while]
744
745        # Check that we did not raise but we also don't generate bytecode
746        for func in funcs:
747            opcodes = list(dis.get_instructions(func))
748            self.assertEqual(2, len(opcodes))
749            self.assertEqual('LOAD_CONST', opcodes[0].opname)
750            self.assertEqual(None, opcodes[0].argval)
751            self.assertEqual('RETURN_VALUE', opcodes[1].opname)
752
753class TestExpressionStackSize(unittest.TestCase):
754    # These tests check that the computed stack size for a code object
755    # stays within reasonable bounds (see issue #21523 for an example
756    # dysfunction).
757    N = 100
758
759    def check_stack_size(self, code):
760        # To assert that the alleged stack size is not O(N), we
761        # check that it is smaller than log(N).
762        if isinstance(code, str):
763            code = compile(code, "<foo>", "single")
764        max_size = math.ceil(math.log(len(code.co_code)))
765        self.assertLessEqual(code.co_stacksize, max_size)
766
767    def test_and(self):
768        self.check_stack_size("x and " * self.N + "x")
769
770    def test_or(self):
771        self.check_stack_size("x or " * self.N + "x")
772
773    def test_and_or(self):
774        self.check_stack_size("x and x or " * self.N + "x")
775
776    def test_chained_comparison(self):
777        self.check_stack_size("x < " * self.N + "x")
778
779    def test_if_else(self):
780        self.check_stack_size("x if x else " * self.N + "x")
781
782    def test_binop(self):
783        self.check_stack_size("x + " * self.N + "x")
784
785    def test_func_and(self):
786        code = "def f(x):\n"
787        code += "   x and x\n" * self.N
788        self.check_stack_size(code)
789
790
791class TestStackSizeStability(unittest.TestCase):
792    # Check that repeating certain snippets doesn't increase the stack size
793    # beyond what a single snippet requires.
794
795    def check_stack_size(self, snippet, async_=False):
796        def compile_snippet(i):
797            ns = {}
798            script = """def func():\n""" + i * snippet
799            if async_:
800                script = "async " + script
801            code = compile(script, "<script>", "exec")
802            exec(code, ns, ns)
803            return ns['func'].__code__
804
805        sizes = [compile_snippet(i).co_stacksize for i in range(2, 5)]
806        if len(set(sizes)) != 1:
807            import dis, io
808            out = io.StringIO()
809            dis.dis(compile_snippet(1), file=out)
810            self.fail("stack sizes diverge with # of consecutive snippets: "
811                      "%s\n%s\n%s" % (sizes, snippet, out.getvalue()))
812
813    def test_if(self):
814        snippet = """
815            if x:
816                a
817            """
818        self.check_stack_size(snippet)
819
820    def test_if_else(self):
821        snippet = """
822            if x:
823                a
824            elif y:
825                b
826            else:
827                c
828            """
829        self.check_stack_size(snippet)
830
831    def test_try_except_bare(self):
832        snippet = """
833            try:
834                a
835            except:
836                b
837            """
838        self.check_stack_size(snippet)
839
840    def test_try_except_qualified(self):
841        snippet = """
842            try:
843                a
844            except ImportError:
845                b
846            except:
847                c
848            else:
849                d
850            """
851        self.check_stack_size(snippet)
852
853    def test_try_except_as(self):
854        snippet = """
855            try:
856                a
857            except ImportError as e:
858                b
859            except:
860                c
861            else:
862                d
863            """
864        self.check_stack_size(snippet)
865
866    def test_try_finally(self):
867        snippet = """
868                try:
869                    a
870                finally:
871                    b
872            """
873        self.check_stack_size(snippet)
874
875    def test_with(self):
876        snippet = """
877            with x as y:
878                a
879            """
880        self.check_stack_size(snippet)
881
882    def test_while_else(self):
883        snippet = """
884            while x:
885                a
886            else:
887                b
888            """
889        self.check_stack_size(snippet)
890
891    def test_for(self):
892        snippet = """
893            for x in y:
894                a
895            """
896        self.check_stack_size(snippet)
897
898    def test_for_else(self):
899        snippet = """
900            for x in y:
901                a
902            else:
903                b
904            """
905        self.check_stack_size(snippet)
906
907    def test_for_break_continue(self):
908        snippet = """
909            for x in y:
910                if z:
911                    break
912                elif u:
913                    continue
914                else:
915                    a
916            else:
917                b
918            """
919        self.check_stack_size(snippet)
920
921    def test_for_break_continue_inside_try_finally_block(self):
922        snippet = """
923            for x in y:
924                try:
925                    if z:
926                        break
927                    elif u:
928                        continue
929                    else:
930                        a
931                finally:
932                    f
933            else:
934                b
935            """
936        self.check_stack_size(snippet)
937
938    def test_for_break_continue_inside_finally_block(self):
939        snippet = """
940            for x in y:
941                try:
942                    t
943                finally:
944                    if z:
945                        break
946                    elif u:
947                        continue
948                    else:
949                        a
950            else:
951                b
952            """
953        self.check_stack_size(snippet)
954
955    def test_for_break_continue_inside_except_block(self):
956        snippet = """
957            for x in y:
958                try:
959                    t
960                except:
961                    if z:
962                        break
963                    elif u:
964                        continue
965                    else:
966                        a
967            else:
968                b
969            """
970        self.check_stack_size(snippet)
971
972    def test_for_break_continue_inside_with_block(self):
973        snippet = """
974            for x in y:
975                with c:
976                    if z:
977                        break
978                    elif u:
979                        continue
980                    else:
981                        a
982            else:
983                b
984            """
985        self.check_stack_size(snippet)
986
987    def test_return_inside_try_finally_block(self):
988        snippet = """
989            try:
990                if z:
991                    return
992                else:
993                    a
994            finally:
995                f
996            """
997        self.check_stack_size(snippet)
998
999    def test_return_inside_finally_block(self):
1000        snippet = """
1001            try:
1002                t
1003            finally:
1004                if z:
1005                    return
1006                else:
1007                    a
1008            """
1009        self.check_stack_size(snippet)
1010
1011    def test_return_inside_except_block(self):
1012        snippet = """
1013            try:
1014                t
1015            except:
1016                if z:
1017                    return
1018                else:
1019                    a
1020            """
1021        self.check_stack_size(snippet)
1022
1023    def test_return_inside_with_block(self):
1024        snippet = """
1025            with c:
1026                if z:
1027                    return
1028                else:
1029                    a
1030            """
1031        self.check_stack_size(snippet)
1032
1033    def test_async_with(self):
1034        snippet = """
1035            async with x as y:
1036                a
1037            """
1038        self.check_stack_size(snippet, async_=True)
1039
1040    def test_async_for(self):
1041        snippet = """
1042            async for x in y:
1043                a
1044            """
1045        self.check_stack_size(snippet, async_=True)
1046
1047    def test_async_for_else(self):
1048        snippet = """
1049            async for x in y:
1050                a
1051            else:
1052                b
1053            """
1054        self.check_stack_size(snippet, async_=True)
1055
1056    def test_for_break_continue_inside_async_with_block(self):
1057        snippet = """
1058            for x in y:
1059                async with c:
1060                    if z:
1061                        break
1062                    elif u:
1063                        continue
1064                    else:
1065                        a
1066            else:
1067                b
1068            """
1069        self.check_stack_size(snippet, async_=True)
1070
1071    def test_return_inside_async_with_block(self):
1072        snippet = """
1073            async with c:
1074                if z:
1075                    return
1076                else:
1077                    a
1078            """
1079        self.check_stack_size(snippet, async_=True)
1080
1081
1082if __name__ == "__main__":
1083    unittest.main()
1084