Home | History | Annotate | Download | only in test
      1 import dis
      2 import math
      3 import os
      4 import unittest
      5 import sys
      6 import _ast
      7 import tempfile
      8 import types
      9 from test import support
     10 from test.support import script_helper, FakePath
     11 
     12 class 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 = '''
    111 def 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 = """
    144 if 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         # {0} is converted to a constant frozenset({0}) by the peephole
    619         # optimizer
    620         f1, f2 = lambda x: x in {0}, lambda x: x in {0}
    621         self.assertIs(f1.__code__, f2.__code__)
    622         self.check_constant(f1, frozenset({0}))
    623         self.assertTrue(f1(0))
    624 
    625     # This is a regression test for a CPython specific peephole optimizer
    626     # implementation bug present in a few releases.  It's assertion verifies
    627     # that peephole optimization was actually done though that isn't an
    628     # indication of the bugs presence or not (crashing is).
    629     @support.cpython_only
    630     def test_peephole_opt_unreachable_code_array_access_in_bounds(self):
    631         """Regression test for issue35193 when run under clang msan."""
    632         def unused_code_at_end():
    633             return 3
    634             raise RuntimeError("unreachable")
    635         # The above function definition will trigger the out of bounds
    636         # bug in the peephole optimizer as it scans opcodes past the
    637         # RETURN_VALUE opcode.  This does not always crash an interpreter.
    638         # When you build with the clang memory sanitizer it reliably aborts.
    639         self.assertEqual(
    640             'RETURN_VALUE',
    641             list(dis.get_instructions(unused_code_at_end))[-1].opname)
    642 
    643     def test_dont_merge_constants(self):
    644         # Issue #25843: compile() must not merge constants which are equal
    645         # but have a different type.
    646 
    647         def check_different_constants(const1, const2):
    648             ns = {}
    649             exec("f1, f2 = lambda: %r, lambda: %r" % (const1, const2), ns)
    650             f1 = ns['f1']
    651             f2 = ns['f2']
    652             self.assertIsNot(f1.__code__, f2.__code__)
    653             self.assertNotEqual(f1.__code__, f2.__code__)
    654             self.check_constant(f1, const1)
    655             self.check_constant(f2, const2)
    656             self.assertEqual(repr(f1()), repr(const1))
    657             self.assertEqual(repr(f2()), repr(const2))
    658 
    659         check_different_constants(0, 0.0)
    660         check_different_constants(+0.0, -0.0)
    661         check_different_constants((0,), (0.0,))
    662         check_different_constants('a', b'a')
    663         check_different_constants(('a',), (b'a',))
    664 
    665         # check_different_constants() cannot be used because repr(-0j) is
    666         # '(-0-0j)', but when '(-0-0j)' is evaluated to 0j: we loose the sign.
    667         f1, f2 = lambda: +0.0j, lambda: -0.0j
    668         self.assertIsNot(f1.__code__, f2.__code__)
    669         self.check_constant(f1, +0.0j)
    670         self.check_constant(f2, -0.0j)
    671         self.assertEqual(repr(f1()), repr(+0.0j))
    672         self.assertEqual(repr(f2()), repr(-0.0j))
    673 
    674         # {0} is converted to a constant frozenset({0}) by the peephole
    675         # optimizer
    676         f1, f2 = lambda x: x in {0}, lambda x: x in {0.0}
    677         self.assertIsNot(f1.__code__, f2.__code__)
    678         self.check_constant(f1, frozenset({0}))
    679         self.check_constant(f2, frozenset({0.0}))
    680         self.assertTrue(f1(0))
    681         self.assertTrue(f2(0.0))
    682 
    683     def test_path_like_objects(self):
    684         # An implicit test for PyUnicode_FSDecoder().
    685         compile("42", FakePath("test_compile_pathlike"), "single")
    686 
    687     def test_stack_overflow(self):
    688         # bpo-31113: Stack overflow when compile a long sequence of
    689         # complex statements.
    690         compile("if a: b\n" * 200000, "<dummy>", "exec")
    691 
    692 
    693 class TestExpressionStackSize(unittest.TestCase):
    694     # These tests check that the computed stack size for a code object
    695     # stays within reasonable bounds (see issue #21523 for an example
    696     # dysfunction).
    697     N = 100
    698 
    699     def check_stack_size(self, code):
    700         # To assert that the alleged stack size is not O(N), we
    701         # check that it is smaller than log(N).
    702         if isinstance(code, str):
    703             code = compile(code, "<foo>", "single")
    704         max_size = math.ceil(math.log(len(code.co_code)))
    705         self.assertLessEqual(code.co_stacksize, max_size)
    706 
    707     def test_and(self):
    708         self.check_stack_size("x and " * self.N + "x")
    709 
    710     def test_or(self):
    711         self.check_stack_size("x or " * self.N + "x")
    712 
    713     def test_and_or(self):
    714         self.check_stack_size("x and x or " * self.N + "x")
    715 
    716     def test_chained_comparison(self):
    717         self.check_stack_size("x < " * self.N + "x")
    718 
    719     def test_if_else(self):
    720         self.check_stack_size("x if x else " * self.N + "x")
    721 
    722     def test_binop(self):
    723         self.check_stack_size("x + " * self.N + "x")
    724 
    725     def test_func_and(self):
    726         code = "def f(x):\n"
    727         code += "   x and x\n" * self.N
    728         self.check_stack_size(code)
    729 
    730 
    731 class TestStackSizeStability(unittest.TestCase):
    732     # Check that repeating certain snippets doesn't increase the stack size
    733     # beyond what a single snippet requires.
    734 
    735     def check_stack_size(self, snippet, async_=False):
    736         def compile_snippet(i):
    737             ns = {}
    738             script = """def func():\n""" + i * snippet
    739             if async_:
    740                 script = "async " + script
    741             code = compile(script, "<script>", "exec")
    742             exec(code, ns, ns)
    743             return ns['func'].__code__
    744 
    745         sizes = [compile_snippet(i).co_stacksize for i in range(2, 5)]
    746         if len(set(sizes)) != 1:
    747             import dis, io
    748             out = io.StringIO()
    749             dis.dis(compile_snippet(1), file=out)
    750             self.fail("stack sizes diverge with # of consecutive snippets: "
    751                       "%s\n%s\n%s" % (sizes, snippet, out.getvalue()))
    752 
    753     def test_if(self):
    754         snippet = """
    755             if x:
    756                 a
    757             """
    758         self.check_stack_size(snippet)
    759 
    760     def test_if_else(self):
    761         snippet = """
    762             if x:
    763                 a
    764             elif y:
    765                 b
    766             else:
    767                 c
    768             """
    769         self.check_stack_size(snippet)
    770 
    771     def test_try_except_bare(self):
    772         snippet = """
    773             try:
    774                 a
    775             except:
    776                 b
    777             """
    778         self.check_stack_size(snippet)
    779 
    780     def test_try_except_qualified(self):
    781         snippet = """
    782             try:
    783                 a
    784             except ImportError:
    785                 b
    786             except:
    787                 c
    788             else:
    789                 d
    790             """
    791         self.check_stack_size(snippet)
    792 
    793     def test_try_except_as(self):
    794         snippet = """
    795             try:
    796                 a
    797             except ImportError as e:
    798                 b
    799             except:
    800                 c
    801             else:
    802                 d
    803             """
    804         self.check_stack_size(snippet)
    805 
    806     def test_try_finally(self):
    807         snippet = """
    808                 try:
    809                     a
    810                 finally:
    811                     b
    812             """
    813         self.check_stack_size(snippet)
    814 
    815     def test_with(self):
    816         snippet = """
    817             with x as y:
    818                 a
    819             """
    820         self.check_stack_size(snippet)
    821 
    822     def test_while_else(self):
    823         snippet = """
    824             while x:
    825                 a
    826             else:
    827                 b
    828             """
    829         self.check_stack_size(snippet)
    830 
    831     def test_for(self):
    832         snippet = """
    833             for x in y:
    834                 a
    835             """
    836         self.check_stack_size(snippet)
    837 
    838     def test_for_else(self):
    839         snippet = """
    840             for x in y:
    841                 a
    842             else:
    843                 b
    844             """
    845         self.check_stack_size(snippet)
    846 
    847     def test_for_break_continue(self):
    848         snippet = """
    849             for x in y:
    850                 if z:
    851                     break
    852                 elif u:
    853                     continue
    854                 else:
    855                     a
    856             else:
    857                 b
    858             """
    859         self.check_stack_size(snippet)
    860 
    861     def test_for_break_continue_inside_try_finally_block(self):
    862         snippet = """
    863             for x in y:
    864                 try:
    865                     if z:
    866                         break
    867                     elif u:
    868                         continue
    869                     else:
    870                         a
    871                 finally:
    872                     f
    873             else:
    874                 b
    875             """
    876         self.check_stack_size(snippet)
    877 
    878     def test_for_break_inside_finally_block(self):
    879         snippet = """
    880             for x in y:
    881                 try:
    882                     t
    883                 finally:
    884                     if z:
    885                         break
    886                     else:
    887                         a
    888             else:
    889                 b
    890             """
    891         self.check_stack_size(snippet)
    892 
    893     def test_for_break_continue_inside_except_block(self):
    894         snippet = """
    895             for x in y:
    896                 try:
    897                     t
    898                 except:
    899                     if z:
    900                         break
    901                     elif u:
    902                         continue
    903                     else:
    904                         a
    905             else:
    906                 b
    907             """
    908         self.check_stack_size(snippet)
    909 
    910     def test_for_break_continue_inside_with_block(self):
    911         snippet = """
    912             for x in y:
    913                 with c:
    914                     if z:
    915                         break
    916                     elif u:
    917                         continue
    918                     else:
    919                         a
    920             else:
    921                 b
    922             """
    923         self.check_stack_size(snippet)
    924 
    925     def test_return_inside_try_finally_block(self):
    926         snippet = """
    927             try:
    928                 if z:
    929                     return
    930                 else:
    931                     a
    932             finally:
    933                 f
    934             """
    935         self.check_stack_size(snippet)
    936 
    937     def test_return_inside_finally_block(self):
    938         snippet = """
    939             try:
    940                 t
    941             finally:
    942                 if z:
    943                     return
    944                 else:
    945                     a
    946             """
    947         self.check_stack_size(snippet)
    948 
    949     def test_return_inside_except_block(self):
    950         snippet = """
    951             try:
    952                 t
    953             except:
    954                 if z:
    955                     return
    956                 else:
    957                     a
    958             """
    959         self.check_stack_size(snippet)
    960 
    961     def test_return_inside_with_block(self):
    962         snippet = """
    963             with c:
    964                 if z:
    965                     return
    966                 else:
    967                     a
    968             """
    969         self.check_stack_size(snippet)
    970 
    971     def test_async_with(self):
    972         snippet = """
    973             async with x as y:
    974                 a
    975             """
    976         self.check_stack_size(snippet, async_=True)
    977 
    978     def test_async_for(self):
    979         snippet = """
    980             async for x in y:
    981                 a
    982             """
    983         self.check_stack_size(snippet, async_=True)
    984 
    985     def test_async_for_else(self):
    986         snippet = """
    987             async for x in y:
    988                 a
    989             else:
    990                 b
    991             """
    992         self.check_stack_size(snippet, async_=True)
    993 
    994     def test_for_break_continue_inside_async_with_block(self):
    995         snippet = """
    996             for x in y:
    997                 async with c:
    998                     if z:
    999                         break
   1000                     elif u:
   1001                         continue
   1002                     else:
   1003                         a
   1004             else:
   1005                 b
   1006             """
   1007         self.check_stack_size(snippet, async_=True)
   1008 
   1009     def test_return_inside_async_with_block(self):
   1010         snippet = """
   1011             async with c:
   1012                 if z:
   1013                     return
   1014                 else:
   1015                     a
   1016             """
   1017         self.check_stack_size(snippet, async_=True)
   1018 
   1019 
   1020 if __name__ == "__main__":
   1021     unittest.main()
   1022