17db96d56Sopenharmony_ciimport dis
27db96d56Sopenharmony_ciimport math
37db96d56Sopenharmony_ciimport os
47db96d56Sopenharmony_ciimport unittest
57db96d56Sopenharmony_ciimport sys
67db96d56Sopenharmony_ciimport ast
77db96d56Sopenharmony_ciimport _ast
87db96d56Sopenharmony_ciimport tempfile
97db96d56Sopenharmony_ciimport types
107db96d56Sopenharmony_ciimport textwrap
117db96d56Sopenharmony_cifrom test import support
127db96d56Sopenharmony_cifrom test.support import script_helper, requires_debug_ranges
137db96d56Sopenharmony_cifrom test.support.os_helper import FakePath
147db96d56Sopenharmony_ci
157db96d56Sopenharmony_ci
167db96d56Sopenharmony_ciclass TestSpecifics(unittest.TestCase):
177db96d56Sopenharmony_ci
187db96d56Sopenharmony_ci    def compile_single(self, source):
197db96d56Sopenharmony_ci        compile(source, "<single>", "single")
207db96d56Sopenharmony_ci
217db96d56Sopenharmony_ci    def assertInvalidSingle(self, source):
227db96d56Sopenharmony_ci        self.assertRaises(SyntaxError, self.compile_single, source)
237db96d56Sopenharmony_ci
247db96d56Sopenharmony_ci    def test_no_ending_newline(self):
257db96d56Sopenharmony_ci        compile("hi", "<test>", "exec")
267db96d56Sopenharmony_ci        compile("hi\r", "<test>", "exec")
277db96d56Sopenharmony_ci
287db96d56Sopenharmony_ci    def test_empty(self):
297db96d56Sopenharmony_ci        compile("", "<test>", "exec")
307db96d56Sopenharmony_ci
317db96d56Sopenharmony_ci    def test_other_newlines(self):
327db96d56Sopenharmony_ci        compile("\r\n", "<test>", "exec")
337db96d56Sopenharmony_ci        compile("\r", "<test>", "exec")
347db96d56Sopenharmony_ci        compile("hi\r\nstuff\r\ndef f():\n    pass\r", "<test>", "exec")
357db96d56Sopenharmony_ci        compile("this_is\rreally_old_mac\rdef f():\n    pass", "<test>", "exec")
367db96d56Sopenharmony_ci
377db96d56Sopenharmony_ci    def test_debug_assignment(self):
387db96d56Sopenharmony_ci        # catch assignments to __debug__
397db96d56Sopenharmony_ci        self.assertRaises(SyntaxError, compile, '__debug__ = 1', '?', 'single')
407db96d56Sopenharmony_ci        import builtins
417db96d56Sopenharmony_ci        prev = builtins.__debug__
427db96d56Sopenharmony_ci        setattr(builtins, '__debug__', 'sure')
437db96d56Sopenharmony_ci        self.assertEqual(__debug__, prev)
447db96d56Sopenharmony_ci        setattr(builtins, '__debug__', prev)
457db96d56Sopenharmony_ci
467db96d56Sopenharmony_ci    def test_argument_handling(self):
477db96d56Sopenharmony_ci        # detect duplicate positional and keyword arguments
487db96d56Sopenharmony_ci        self.assertRaises(SyntaxError, eval, 'lambda a,a:0')
497db96d56Sopenharmony_ci        self.assertRaises(SyntaxError, eval, 'lambda a,a=1:0')
507db96d56Sopenharmony_ci        self.assertRaises(SyntaxError, eval, 'lambda a=1,a=1:0')
517db96d56Sopenharmony_ci        self.assertRaises(SyntaxError, exec, 'def f(a, a): pass')
527db96d56Sopenharmony_ci        self.assertRaises(SyntaxError, exec, 'def f(a = 0, a = 1): pass')
537db96d56Sopenharmony_ci        self.assertRaises(SyntaxError, exec, 'def f(a): global a; a = 1')
547db96d56Sopenharmony_ci
557db96d56Sopenharmony_ci    def test_syntax_error(self):
567db96d56Sopenharmony_ci        self.assertRaises(SyntaxError, compile, "1+*3", "filename", "exec")
577db96d56Sopenharmony_ci
587db96d56Sopenharmony_ci    def test_none_keyword_arg(self):
597db96d56Sopenharmony_ci        self.assertRaises(SyntaxError, compile, "f(None=1)", "<string>", "exec")
607db96d56Sopenharmony_ci
617db96d56Sopenharmony_ci    def test_duplicate_global_local(self):
627db96d56Sopenharmony_ci        self.assertRaises(SyntaxError, exec, 'def f(a): global a; a = 1')
637db96d56Sopenharmony_ci
647db96d56Sopenharmony_ci    def test_exec_with_general_mapping_for_locals(self):
657db96d56Sopenharmony_ci
667db96d56Sopenharmony_ci        class M:
677db96d56Sopenharmony_ci            "Test mapping interface versus possible calls from eval()."
687db96d56Sopenharmony_ci            def __getitem__(self, key):
697db96d56Sopenharmony_ci                if key == 'a':
707db96d56Sopenharmony_ci                    return 12
717db96d56Sopenharmony_ci                raise KeyError
727db96d56Sopenharmony_ci            def __setitem__(self, key, value):
737db96d56Sopenharmony_ci                self.results = (key, value)
747db96d56Sopenharmony_ci            def keys(self):
757db96d56Sopenharmony_ci                return list('xyz')
767db96d56Sopenharmony_ci
777db96d56Sopenharmony_ci        m = M()
787db96d56Sopenharmony_ci        g = globals()
797db96d56Sopenharmony_ci        exec('z = a', g, m)
807db96d56Sopenharmony_ci        self.assertEqual(m.results, ('z', 12))
817db96d56Sopenharmony_ci        try:
827db96d56Sopenharmony_ci            exec('z = b', g, m)
837db96d56Sopenharmony_ci        except NameError:
847db96d56Sopenharmony_ci            pass
857db96d56Sopenharmony_ci        else:
867db96d56Sopenharmony_ci            self.fail('Did not detect a KeyError')
877db96d56Sopenharmony_ci        exec('z = dir()', g, m)
887db96d56Sopenharmony_ci        self.assertEqual(m.results, ('z', list('xyz')))
897db96d56Sopenharmony_ci        exec('z = globals()', g, m)
907db96d56Sopenharmony_ci        self.assertEqual(m.results, ('z', g))
917db96d56Sopenharmony_ci        exec('z = locals()', g, m)
927db96d56Sopenharmony_ci        self.assertEqual(m.results, ('z', m))
937db96d56Sopenharmony_ci        self.assertRaises(TypeError, exec, 'z = b', m)
947db96d56Sopenharmony_ci
957db96d56Sopenharmony_ci        class A:
967db96d56Sopenharmony_ci            "Non-mapping"
977db96d56Sopenharmony_ci            pass
987db96d56Sopenharmony_ci        m = A()
997db96d56Sopenharmony_ci        self.assertRaises(TypeError, exec, 'z = a', g, m)
1007db96d56Sopenharmony_ci
1017db96d56Sopenharmony_ci        # Verify that dict subclasses work as well
1027db96d56Sopenharmony_ci        class D(dict):
1037db96d56Sopenharmony_ci            def __getitem__(self, key):
1047db96d56Sopenharmony_ci                if key == 'a':
1057db96d56Sopenharmony_ci                    return 12
1067db96d56Sopenharmony_ci                return dict.__getitem__(self, key)
1077db96d56Sopenharmony_ci        d = D()
1087db96d56Sopenharmony_ci        exec('z = a', g, d)
1097db96d56Sopenharmony_ci        self.assertEqual(d['z'], 12)
1107db96d56Sopenharmony_ci
1117db96d56Sopenharmony_ci    def test_extended_arg(self):
1127db96d56Sopenharmony_ci        # default: 1000 * 2.5 = 2500 repetitions
1137db96d56Sopenharmony_ci        repeat = int(sys.getrecursionlimit() * 2.5)
1147db96d56Sopenharmony_ci        longexpr = 'x = x or ' + '-x' * repeat
1157db96d56Sopenharmony_ci        g = {}
1167db96d56Sopenharmony_ci        code = '''
1177db96d56Sopenharmony_cidef f(x):
1187db96d56Sopenharmony_ci    %s
1197db96d56Sopenharmony_ci    %s
1207db96d56Sopenharmony_ci    %s
1217db96d56Sopenharmony_ci    %s
1227db96d56Sopenharmony_ci    %s
1237db96d56Sopenharmony_ci    %s
1247db96d56Sopenharmony_ci    %s
1257db96d56Sopenharmony_ci    %s
1267db96d56Sopenharmony_ci    %s
1277db96d56Sopenharmony_ci    %s
1287db96d56Sopenharmony_ci    # the expressions above have no effect, x == argument
1297db96d56Sopenharmony_ci    while x:
1307db96d56Sopenharmony_ci        x -= 1
1317db96d56Sopenharmony_ci        # EXTENDED_ARG/JUMP_ABSOLUTE here
1327db96d56Sopenharmony_ci    return x
1337db96d56Sopenharmony_ci''' % ((longexpr,)*10)
1347db96d56Sopenharmony_ci        exec(code, g)
1357db96d56Sopenharmony_ci        self.assertEqual(g['f'](5), 0)
1367db96d56Sopenharmony_ci
1377db96d56Sopenharmony_ci    def test_argument_order(self):
1387db96d56Sopenharmony_ci        self.assertRaises(SyntaxError, exec, 'def f(a=1, b): pass')
1397db96d56Sopenharmony_ci
1407db96d56Sopenharmony_ci    def test_float_literals(self):
1417db96d56Sopenharmony_ci        # testing bad float literals
1427db96d56Sopenharmony_ci        self.assertRaises(SyntaxError, eval, "2e")
1437db96d56Sopenharmony_ci        self.assertRaises(SyntaxError, eval, "2.0e+")
1447db96d56Sopenharmony_ci        self.assertRaises(SyntaxError, eval, "1e-")
1457db96d56Sopenharmony_ci        self.assertRaises(SyntaxError, eval, "3-4e/21")
1467db96d56Sopenharmony_ci
1477db96d56Sopenharmony_ci    def test_indentation(self):
1487db96d56Sopenharmony_ci        # testing compile() of indented block w/o trailing newline"
1497db96d56Sopenharmony_ci        s = """
1507db96d56Sopenharmony_ciif 1:
1517db96d56Sopenharmony_ci    if 2:
1527db96d56Sopenharmony_ci        pass"""
1537db96d56Sopenharmony_ci        compile(s, "<string>", "exec")
1547db96d56Sopenharmony_ci
1557db96d56Sopenharmony_ci    # This test is probably specific to CPython and may not generalize
1567db96d56Sopenharmony_ci    # to other implementations.  We are trying to ensure that when
1577db96d56Sopenharmony_ci    # the first line of code starts after 256, correct line numbers
1587db96d56Sopenharmony_ci    # in tracebacks are still produced.
1597db96d56Sopenharmony_ci    def test_leading_newlines(self):
1607db96d56Sopenharmony_ci        s256 = "".join(["\n"] * 256 + ["spam"])
1617db96d56Sopenharmony_ci        co = compile(s256, 'fn', 'exec')
1627db96d56Sopenharmony_ci        self.assertEqual(co.co_firstlineno, 1)
1637db96d56Sopenharmony_ci        lines = list(co.co_lines())
1647db96d56Sopenharmony_ci        self.assertEqual(lines[0][2], 0)
1657db96d56Sopenharmony_ci        self.assertEqual(lines[1][2], 257)
1667db96d56Sopenharmony_ci
1677db96d56Sopenharmony_ci    def test_literals_with_leading_zeroes(self):
1687db96d56Sopenharmony_ci        for arg in ["077787", "0xj", "0x.", "0e",  "090000000000000",
1697db96d56Sopenharmony_ci                    "080000000000000", "000000000000009", "000000000000008",
1707db96d56Sopenharmony_ci                    "0b42", "0BADCAFE", "0o123456789", "0b1.1", "0o4.2",
1717db96d56Sopenharmony_ci                    "0b101j", "0o153j", "0b100e1", "0o777e1", "0777",
1727db96d56Sopenharmony_ci                    "000777", "000000000000007"]:
1737db96d56Sopenharmony_ci            self.assertRaises(SyntaxError, eval, arg)
1747db96d56Sopenharmony_ci
1757db96d56Sopenharmony_ci        self.assertEqual(eval("0xff"), 255)
1767db96d56Sopenharmony_ci        self.assertEqual(eval("0777."), 777)
1777db96d56Sopenharmony_ci        self.assertEqual(eval("0777.0"), 777)
1787db96d56Sopenharmony_ci        self.assertEqual(eval("000000000000000000000000000000000000000000000000000777e0"), 777)
1797db96d56Sopenharmony_ci        self.assertEqual(eval("0777e1"), 7770)
1807db96d56Sopenharmony_ci        self.assertEqual(eval("0e0"), 0)
1817db96d56Sopenharmony_ci        self.assertEqual(eval("0000e-012"), 0)
1827db96d56Sopenharmony_ci        self.assertEqual(eval("09.5"), 9.5)
1837db96d56Sopenharmony_ci        self.assertEqual(eval("0777j"), 777j)
1847db96d56Sopenharmony_ci        self.assertEqual(eval("000"), 0)
1857db96d56Sopenharmony_ci        self.assertEqual(eval("00j"), 0j)
1867db96d56Sopenharmony_ci        self.assertEqual(eval("00.0"), 0)
1877db96d56Sopenharmony_ci        self.assertEqual(eval("0e3"), 0)
1887db96d56Sopenharmony_ci        self.assertEqual(eval("090000000000000."), 90000000000000.)
1897db96d56Sopenharmony_ci        self.assertEqual(eval("090000000000000.0000000000000000000000"), 90000000000000.)
1907db96d56Sopenharmony_ci        self.assertEqual(eval("090000000000000e0"), 90000000000000.)
1917db96d56Sopenharmony_ci        self.assertEqual(eval("090000000000000e-0"), 90000000000000.)
1927db96d56Sopenharmony_ci        self.assertEqual(eval("090000000000000j"), 90000000000000j)
1937db96d56Sopenharmony_ci        self.assertEqual(eval("000000000000008."), 8.)
1947db96d56Sopenharmony_ci        self.assertEqual(eval("000000000000009."), 9.)
1957db96d56Sopenharmony_ci        self.assertEqual(eval("0b101010"), 42)
1967db96d56Sopenharmony_ci        self.assertEqual(eval("-0b000000000010"), -2)
1977db96d56Sopenharmony_ci        self.assertEqual(eval("0o777"), 511)
1987db96d56Sopenharmony_ci        self.assertEqual(eval("-0o0000010"), -8)
1997db96d56Sopenharmony_ci
2007db96d56Sopenharmony_ci    def test_int_literals_too_long(self):
2017db96d56Sopenharmony_ci        n = 3000
2027db96d56Sopenharmony_ci        source = f"a = 1\nb = 2\nc = {'3'*n}\nd = 4"
2037db96d56Sopenharmony_ci        with support.adjust_int_max_str_digits(n):
2047db96d56Sopenharmony_ci            compile(source, "<long_int_pass>", "exec")  # no errors.
2057db96d56Sopenharmony_ci        with support.adjust_int_max_str_digits(n-1):
2067db96d56Sopenharmony_ci            with self.assertRaises(SyntaxError) as err_ctx:
2077db96d56Sopenharmony_ci                compile(source, "<long_int_fail>", "exec")
2087db96d56Sopenharmony_ci            exc = err_ctx.exception
2097db96d56Sopenharmony_ci            self.assertEqual(exc.lineno, 3)
2107db96d56Sopenharmony_ci            self.assertIn('Exceeds the limit ', str(exc))
2117db96d56Sopenharmony_ci            self.assertIn(' Consider hexadecimal ', str(exc))
2127db96d56Sopenharmony_ci
2137db96d56Sopenharmony_ci    def test_unary_minus(self):
2147db96d56Sopenharmony_ci        # Verify treatment of unary minus on negative numbers SF bug #660455
2157db96d56Sopenharmony_ci        if sys.maxsize == 2147483647:
2167db96d56Sopenharmony_ci            # 32-bit machine
2177db96d56Sopenharmony_ci            all_one_bits = '0xffffffff'
2187db96d56Sopenharmony_ci            self.assertEqual(eval(all_one_bits), 4294967295)
2197db96d56Sopenharmony_ci            self.assertEqual(eval("-" + all_one_bits), -4294967295)
2207db96d56Sopenharmony_ci        elif sys.maxsize == 9223372036854775807:
2217db96d56Sopenharmony_ci            # 64-bit machine
2227db96d56Sopenharmony_ci            all_one_bits = '0xffffffffffffffff'
2237db96d56Sopenharmony_ci            self.assertEqual(eval(all_one_bits), 18446744073709551615)
2247db96d56Sopenharmony_ci            self.assertEqual(eval("-" + all_one_bits), -18446744073709551615)
2257db96d56Sopenharmony_ci        else:
2267db96d56Sopenharmony_ci            self.fail("How many bits *does* this machine have???")
2277db96d56Sopenharmony_ci        # Verify treatment of constant folding on -(sys.maxsize+1)
2287db96d56Sopenharmony_ci        # i.e. -2147483648 on 32 bit platforms.  Should return int.
2297db96d56Sopenharmony_ci        self.assertIsInstance(eval("%s" % (-sys.maxsize - 1)), int)
2307db96d56Sopenharmony_ci        self.assertIsInstance(eval("%s" % (-sys.maxsize - 2)), int)
2317db96d56Sopenharmony_ci
2327db96d56Sopenharmony_ci    if sys.maxsize == 9223372036854775807:
2337db96d56Sopenharmony_ci        def test_32_63_bit_values(self):
2347db96d56Sopenharmony_ci            a = +4294967296  # 1 << 32
2357db96d56Sopenharmony_ci            b = -4294967296  # 1 << 32
2367db96d56Sopenharmony_ci            c = +281474976710656  # 1 << 48
2377db96d56Sopenharmony_ci            d = -281474976710656  # 1 << 48
2387db96d56Sopenharmony_ci            e = +4611686018427387904  # 1 << 62
2397db96d56Sopenharmony_ci            f = -4611686018427387904  # 1 << 62
2407db96d56Sopenharmony_ci            g = +9223372036854775807  # 1 << 63 - 1
2417db96d56Sopenharmony_ci            h = -9223372036854775807  # 1 << 63 - 1
2427db96d56Sopenharmony_ci
2437db96d56Sopenharmony_ci            for variable in self.test_32_63_bit_values.__code__.co_consts:
2447db96d56Sopenharmony_ci                if variable is not None:
2457db96d56Sopenharmony_ci                    self.assertIsInstance(variable, int)
2467db96d56Sopenharmony_ci
2477db96d56Sopenharmony_ci    def test_sequence_unpacking_error(self):
2487db96d56Sopenharmony_ci        # Verify sequence packing/unpacking with "or".  SF bug #757818
2497db96d56Sopenharmony_ci        i,j = (1, -1) or (-1, 1)
2507db96d56Sopenharmony_ci        self.assertEqual(i, 1)
2517db96d56Sopenharmony_ci        self.assertEqual(j, -1)
2527db96d56Sopenharmony_ci
2537db96d56Sopenharmony_ci    def test_none_assignment(self):
2547db96d56Sopenharmony_ci        stmts = [
2557db96d56Sopenharmony_ci            'None = 0',
2567db96d56Sopenharmony_ci            'None += 0',
2577db96d56Sopenharmony_ci            '__builtins__.None = 0',
2587db96d56Sopenharmony_ci            'def None(): pass',
2597db96d56Sopenharmony_ci            'class None: pass',
2607db96d56Sopenharmony_ci            '(a, None) = 0, 0',
2617db96d56Sopenharmony_ci            'for None in range(10): pass',
2627db96d56Sopenharmony_ci            'def f(None): pass',
2637db96d56Sopenharmony_ci            'import None',
2647db96d56Sopenharmony_ci            'import x as None',
2657db96d56Sopenharmony_ci            'from x import None',
2667db96d56Sopenharmony_ci            'from x import y as None'
2677db96d56Sopenharmony_ci        ]
2687db96d56Sopenharmony_ci        for stmt in stmts:
2697db96d56Sopenharmony_ci            stmt += "\n"
2707db96d56Sopenharmony_ci            self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'single')
2717db96d56Sopenharmony_ci            self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec')
2727db96d56Sopenharmony_ci
2737db96d56Sopenharmony_ci    def test_import(self):
2747db96d56Sopenharmony_ci        succeed = [
2757db96d56Sopenharmony_ci            'import sys',
2767db96d56Sopenharmony_ci            'import os, sys',
2777db96d56Sopenharmony_ci            'import os as bar',
2787db96d56Sopenharmony_ci            'import os.path as bar',
2797db96d56Sopenharmony_ci            'from __future__ import nested_scopes, generators',
2807db96d56Sopenharmony_ci            'from __future__ import (nested_scopes,\ngenerators)',
2817db96d56Sopenharmony_ci            'from __future__ import (nested_scopes,\ngenerators,)',
2827db96d56Sopenharmony_ci            'from sys import stdin, stderr, stdout',
2837db96d56Sopenharmony_ci            'from sys import (stdin, stderr,\nstdout)',
2847db96d56Sopenharmony_ci            'from sys import (stdin, stderr,\nstdout,)',
2857db96d56Sopenharmony_ci            'from sys import (stdin\n, stderr, stdout)',
2867db96d56Sopenharmony_ci            'from sys import (stdin\n, stderr, stdout,)',
2877db96d56Sopenharmony_ci            'from sys import stdin as si, stdout as so, stderr as se',
2887db96d56Sopenharmony_ci            'from sys import (stdin as si, stdout as so, stderr as se)',
2897db96d56Sopenharmony_ci            'from sys import (stdin as si, stdout as so, stderr as se,)',
2907db96d56Sopenharmony_ci            ]
2917db96d56Sopenharmony_ci        fail = [
2927db96d56Sopenharmony_ci            'import (os, sys)',
2937db96d56Sopenharmony_ci            'import (os), (sys)',
2947db96d56Sopenharmony_ci            'import ((os), (sys))',
2957db96d56Sopenharmony_ci            'import (sys',
2967db96d56Sopenharmony_ci            'import sys)',
2977db96d56Sopenharmony_ci            'import (os,)',
2987db96d56Sopenharmony_ci            'import os As bar',
2997db96d56Sopenharmony_ci            'import os.path a bar',
3007db96d56Sopenharmony_ci            'from sys import stdin As stdout',
3017db96d56Sopenharmony_ci            'from sys import stdin a stdout',
3027db96d56Sopenharmony_ci            'from (sys) import stdin',
3037db96d56Sopenharmony_ci            'from __future__ import (nested_scopes',
3047db96d56Sopenharmony_ci            'from __future__ import nested_scopes)',
3057db96d56Sopenharmony_ci            'from __future__ import nested_scopes,\ngenerators',
3067db96d56Sopenharmony_ci            'from sys import (stdin',
3077db96d56Sopenharmony_ci            'from sys import stdin)',
3087db96d56Sopenharmony_ci            'from sys import stdin, stdout,\nstderr',
3097db96d56Sopenharmony_ci            'from sys import stdin si',
3107db96d56Sopenharmony_ci            'from sys import stdin,',
3117db96d56Sopenharmony_ci            'from sys import (*)',
3127db96d56Sopenharmony_ci            'from sys import (stdin,, stdout, stderr)',
3137db96d56Sopenharmony_ci            'from sys import (stdin, stdout),',
3147db96d56Sopenharmony_ci            ]
3157db96d56Sopenharmony_ci        for stmt in succeed:
3167db96d56Sopenharmony_ci            compile(stmt, 'tmp', 'exec')
3177db96d56Sopenharmony_ci        for stmt in fail:
3187db96d56Sopenharmony_ci            self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec')
3197db96d56Sopenharmony_ci
3207db96d56Sopenharmony_ci    def test_for_distinct_code_objects(self):
3217db96d56Sopenharmony_ci        # SF bug 1048870
3227db96d56Sopenharmony_ci        def f():
3237db96d56Sopenharmony_ci            f1 = lambda x=1: x
3247db96d56Sopenharmony_ci            f2 = lambda x=2: x
3257db96d56Sopenharmony_ci            return f1, f2
3267db96d56Sopenharmony_ci        f1, f2 = f()
3277db96d56Sopenharmony_ci        self.assertNotEqual(id(f1.__code__), id(f2.__code__))
3287db96d56Sopenharmony_ci
3297db96d56Sopenharmony_ci    def test_lambda_doc(self):
3307db96d56Sopenharmony_ci        l = lambda: "foo"
3317db96d56Sopenharmony_ci        self.assertIsNone(l.__doc__)
3327db96d56Sopenharmony_ci
3337db96d56Sopenharmony_ci    def test_encoding(self):
3347db96d56Sopenharmony_ci        code = b'# -*- coding: badencoding -*-\npass\n'
3357db96d56Sopenharmony_ci        self.assertRaises(SyntaxError, compile, code, 'tmp', 'exec')
3367db96d56Sopenharmony_ci        code = '# -*- coding: badencoding -*-\n"\xc2\xa4"\n'
3377db96d56Sopenharmony_ci        compile(code, 'tmp', 'exec')
3387db96d56Sopenharmony_ci        self.assertEqual(eval(code), '\xc2\xa4')
3397db96d56Sopenharmony_ci        code = '"\xc2\xa4"\n'
3407db96d56Sopenharmony_ci        self.assertEqual(eval(code), '\xc2\xa4')
3417db96d56Sopenharmony_ci        code = b'"\xc2\xa4"\n'
3427db96d56Sopenharmony_ci        self.assertEqual(eval(code), '\xa4')
3437db96d56Sopenharmony_ci        code = b'# -*- coding: latin1 -*-\n"\xc2\xa4"\n'
3447db96d56Sopenharmony_ci        self.assertEqual(eval(code), '\xc2\xa4')
3457db96d56Sopenharmony_ci        code = b'# -*- coding: utf-8 -*-\n"\xc2\xa4"\n'
3467db96d56Sopenharmony_ci        self.assertEqual(eval(code), '\xa4')
3477db96d56Sopenharmony_ci        code = b'# -*- coding: iso8859-15 -*-\n"\xc2\xa4"\n'
3487db96d56Sopenharmony_ci        self.assertEqual(eval(code), '\xc2\u20ac')
3497db96d56Sopenharmony_ci        code = '"""\\\n# -*- coding: iso8859-15 -*-\n\xc2\xa4"""\n'
3507db96d56Sopenharmony_ci        self.assertEqual(eval(code), '# -*- coding: iso8859-15 -*-\n\xc2\xa4')
3517db96d56Sopenharmony_ci        code = b'"""\\\n# -*- coding: iso8859-15 -*-\n\xc2\xa4"""\n'
3527db96d56Sopenharmony_ci        self.assertEqual(eval(code), '# -*- coding: iso8859-15 -*-\n\xa4')
3537db96d56Sopenharmony_ci
3547db96d56Sopenharmony_ci    def test_subscripts(self):
3557db96d56Sopenharmony_ci        # SF bug 1448804
3567db96d56Sopenharmony_ci        # Class to make testing subscript results easy
3577db96d56Sopenharmony_ci        class str_map(object):
3587db96d56Sopenharmony_ci            def __init__(self):
3597db96d56Sopenharmony_ci                self.data = {}
3607db96d56Sopenharmony_ci            def __getitem__(self, key):
3617db96d56Sopenharmony_ci                return self.data[str(key)]
3627db96d56Sopenharmony_ci            def __setitem__(self, key, value):
3637db96d56Sopenharmony_ci                self.data[str(key)] = value
3647db96d56Sopenharmony_ci            def __delitem__(self, key):
3657db96d56Sopenharmony_ci                del self.data[str(key)]
3667db96d56Sopenharmony_ci            def __contains__(self, key):
3677db96d56Sopenharmony_ci                return str(key) in self.data
3687db96d56Sopenharmony_ci        d = str_map()
3697db96d56Sopenharmony_ci        # Index
3707db96d56Sopenharmony_ci        d[1] = 1
3717db96d56Sopenharmony_ci        self.assertEqual(d[1], 1)
3727db96d56Sopenharmony_ci        d[1] += 1
3737db96d56Sopenharmony_ci        self.assertEqual(d[1], 2)
3747db96d56Sopenharmony_ci        del d[1]
3757db96d56Sopenharmony_ci        self.assertNotIn(1, d)
3767db96d56Sopenharmony_ci        # Tuple of indices
3777db96d56Sopenharmony_ci        d[1, 1] = 1
3787db96d56Sopenharmony_ci        self.assertEqual(d[1, 1], 1)
3797db96d56Sopenharmony_ci        d[1, 1] += 1
3807db96d56Sopenharmony_ci        self.assertEqual(d[1, 1], 2)
3817db96d56Sopenharmony_ci        del d[1, 1]
3827db96d56Sopenharmony_ci        self.assertNotIn((1, 1), d)
3837db96d56Sopenharmony_ci        # Simple slice
3847db96d56Sopenharmony_ci        d[1:2] = 1
3857db96d56Sopenharmony_ci        self.assertEqual(d[1:2], 1)
3867db96d56Sopenharmony_ci        d[1:2] += 1
3877db96d56Sopenharmony_ci        self.assertEqual(d[1:2], 2)
3887db96d56Sopenharmony_ci        del d[1:2]
3897db96d56Sopenharmony_ci        self.assertNotIn(slice(1, 2), d)
3907db96d56Sopenharmony_ci        # Tuple of simple slices
3917db96d56Sopenharmony_ci        d[1:2, 1:2] = 1
3927db96d56Sopenharmony_ci        self.assertEqual(d[1:2, 1:2], 1)
3937db96d56Sopenharmony_ci        d[1:2, 1:2] += 1
3947db96d56Sopenharmony_ci        self.assertEqual(d[1:2, 1:2], 2)
3957db96d56Sopenharmony_ci        del d[1:2, 1:2]
3967db96d56Sopenharmony_ci        self.assertNotIn((slice(1, 2), slice(1, 2)), d)
3977db96d56Sopenharmony_ci        # Extended slice
3987db96d56Sopenharmony_ci        d[1:2:3] = 1
3997db96d56Sopenharmony_ci        self.assertEqual(d[1:2:3], 1)
4007db96d56Sopenharmony_ci        d[1:2:3] += 1
4017db96d56Sopenharmony_ci        self.assertEqual(d[1:2:3], 2)
4027db96d56Sopenharmony_ci        del d[1:2:3]
4037db96d56Sopenharmony_ci        self.assertNotIn(slice(1, 2, 3), d)
4047db96d56Sopenharmony_ci        # Tuple of extended slices
4057db96d56Sopenharmony_ci        d[1:2:3, 1:2:3] = 1
4067db96d56Sopenharmony_ci        self.assertEqual(d[1:2:3, 1:2:3], 1)
4077db96d56Sopenharmony_ci        d[1:2:3, 1:2:3] += 1
4087db96d56Sopenharmony_ci        self.assertEqual(d[1:2:3, 1:2:3], 2)
4097db96d56Sopenharmony_ci        del d[1:2:3, 1:2:3]
4107db96d56Sopenharmony_ci        self.assertNotIn((slice(1, 2, 3), slice(1, 2, 3)), d)
4117db96d56Sopenharmony_ci        # Ellipsis
4127db96d56Sopenharmony_ci        d[...] = 1
4137db96d56Sopenharmony_ci        self.assertEqual(d[...], 1)
4147db96d56Sopenharmony_ci        d[...] += 1
4157db96d56Sopenharmony_ci        self.assertEqual(d[...], 2)
4167db96d56Sopenharmony_ci        del d[...]
4177db96d56Sopenharmony_ci        self.assertNotIn(Ellipsis, d)
4187db96d56Sopenharmony_ci        # Tuple of Ellipses
4197db96d56Sopenharmony_ci        d[..., ...] = 1
4207db96d56Sopenharmony_ci        self.assertEqual(d[..., ...], 1)
4217db96d56Sopenharmony_ci        d[..., ...] += 1
4227db96d56Sopenharmony_ci        self.assertEqual(d[..., ...], 2)
4237db96d56Sopenharmony_ci        del d[..., ...]
4247db96d56Sopenharmony_ci        self.assertNotIn((Ellipsis, Ellipsis), d)
4257db96d56Sopenharmony_ci
4267db96d56Sopenharmony_ci    def test_annotation_limit(self):
4277db96d56Sopenharmony_ci        # more than 255 annotations, should compile ok
4287db96d56Sopenharmony_ci        s = "def f(%s): pass"
4297db96d56Sopenharmony_ci        s %= ', '.join('a%d:%d' % (i,i) for i in range(300))
4307db96d56Sopenharmony_ci        compile(s, '?', 'exec')
4317db96d56Sopenharmony_ci
4327db96d56Sopenharmony_ci    def test_mangling(self):
4337db96d56Sopenharmony_ci        class A:
4347db96d56Sopenharmony_ci            def f():
4357db96d56Sopenharmony_ci                __mangled = 1
4367db96d56Sopenharmony_ci                __not_mangled__ = 2
4377db96d56Sopenharmony_ci                import __mangled_mod
4387db96d56Sopenharmony_ci                import __package__.module
4397db96d56Sopenharmony_ci
4407db96d56Sopenharmony_ci        self.assertIn("_A__mangled", A.f.__code__.co_varnames)
4417db96d56Sopenharmony_ci        self.assertIn("__not_mangled__", A.f.__code__.co_varnames)
4427db96d56Sopenharmony_ci        self.assertIn("_A__mangled_mod", A.f.__code__.co_varnames)
4437db96d56Sopenharmony_ci        self.assertIn("__package__", A.f.__code__.co_varnames)
4447db96d56Sopenharmony_ci
4457db96d56Sopenharmony_ci    def test_compile_ast(self):
4467db96d56Sopenharmony_ci        fname = __file__
4477db96d56Sopenharmony_ci        if fname.lower().endswith('pyc'):
4487db96d56Sopenharmony_ci            fname = fname[:-1]
4497db96d56Sopenharmony_ci        with open(fname, encoding='utf-8') as f:
4507db96d56Sopenharmony_ci            fcontents = f.read()
4517db96d56Sopenharmony_ci        sample_code = [
4527db96d56Sopenharmony_ci            ['<assign>', 'x = 5'],
4537db96d56Sopenharmony_ci            ['<ifblock>', """if True:\n    pass\n"""],
4547db96d56Sopenharmony_ci            ['<forblock>', """for n in [1, 2, 3]:\n    print(n)\n"""],
4557db96d56Sopenharmony_ci            ['<deffunc>', """def foo():\n    pass\nfoo()\n"""],
4567db96d56Sopenharmony_ci            [fname, fcontents],
4577db96d56Sopenharmony_ci        ]
4587db96d56Sopenharmony_ci
4597db96d56Sopenharmony_ci        for fname, code in sample_code:
4607db96d56Sopenharmony_ci            co1 = compile(code, '%s1' % fname, 'exec')
4617db96d56Sopenharmony_ci            ast = compile(code, '%s2' % fname, 'exec', _ast.PyCF_ONLY_AST)
4627db96d56Sopenharmony_ci            self.assertTrue(type(ast) == _ast.Module)
4637db96d56Sopenharmony_ci            co2 = compile(ast, '%s3' % fname, 'exec')
4647db96d56Sopenharmony_ci            self.assertEqual(co1, co2)
4657db96d56Sopenharmony_ci            # the code object's filename comes from the second compilation step
4667db96d56Sopenharmony_ci            self.assertEqual(co2.co_filename, '%s3' % fname)
4677db96d56Sopenharmony_ci
4687db96d56Sopenharmony_ci        # raise exception when node type doesn't match with compile mode
4697db96d56Sopenharmony_ci        co1 = compile('print(1)', '<string>', 'exec', _ast.PyCF_ONLY_AST)
4707db96d56Sopenharmony_ci        self.assertRaises(TypeError, compile, co1, '<ast>', 'eval')
4717db96d56Sopenharmony_ci
4727db96d56Sopenharmony_ci        # raise exception when node type is no start node
4737db96d56Sopenharmony_ci        self.assertRaises(TypeError, compile, _ast.If(), '<ast>', 'exec')
4747db96d56Sopenharmony_ci
4757db96d56Sopenharmony_ci        # raise exception when node has invalid children
4767db96d56Sopenharmony_ci        ast = _ast.Module()
4777db96d56Sopenharmony_ci        ast.body = [_ast.BoolOp()]
4787db96d56Sopenharmony_ci        self.assertRaises(TypeError, compile, ast, '<ast>', 'exec')
4797db96d56Sopenharmony_ci
4807db96d56Sopenharmony_ci    def test_dict_evaluation_order(self):
4817db96d56Sopenharmony_ci        i = 0
4827db96d56Sopenharmony_ci
4837db96d56Sopenharmony_ci        def f():
4847db96d56Sopenharmony_ci            nonlocal i
4857db96d56Sopenharmony_ci            i += 1
4867db96d56Sopenharmony_ci            return i
4877db96d56Sopenharmony_ci
4887db96d56Sopenharmony_ci        d = {f(): f(), f(): f()}
4897db96d56Sopenharmony_ci        self.assertEqual(d, {1: 2, 3: 4})
4907db96d56Sopenharmony_ci
4917db96d56Sopenharmony_ci    def test_compile_filename(self):
4927db96d56Sopenharmony_ci        for filename in 'file.py', b'file.py':
4937db96d56Sopenharmony_ci            code = compile('pass', filename, 'exec')
4947db96d56Sopenharmony_ci            self.assertEqual(code.co_filename, 'file.py')
4957db96d56Sopenharmony_ci        for filename in bytearray(b'file.py'), memoryview(b'file.py'):
4967db96d56Sopenharmony_ci            with self.assertWarns(DeprecationWarning):
4977db96d56Sopenharmony_ci                code = compile('pass', filename, 'exec')
4987db96d56Sopenharmony_ci            self.assertEqual(code.co_filename, 'file.py')
4997db96d56Sopenharmony_ci        self.assertRaises(TypeError, compile, 'pass', list(b'file.py'), 'exec')
5007db96d56Sopenharmony_ci
5017db96d56Sopenharmony_ci    @support.cpython_only
5027db96d56Sopenharmony_ci    def test_same_filename_used(self):
5037db96d56Sopenharmony_ci        s = """def f(): pass\ndef g(): pass"""
5047db96d56Sopenharmony_ci        c = compile(s, "myfile", "exec")
5057db96d56Sopenharmony_ci        for obj in c.co_consts:
5067db96d56Sopenharmony_ci            if isinstance(obj, types.CodeType):
5077db96d56Sopenharmony_ci                self.assertIs(obj.co_filename, c.co_filename)
5087db96d56Sopenharmony_ci
5097db96d56Sopenharmony_ci    def test_single_statement(self):
5107db96d56Sopenharmony_ci        self.compile_single("1 + 2")
5117db96d56Sopenharmony_ci        self.compile_single("\n1 + 2")
5127db96d56Sopenharmony_ci        self.compile_single("1 + 2\n")
5137db96d56Sopenharmony_ci        self.compile_single("1 + 2\n\n")
5147db96d56Sopenharmony_ci        self.compile_single("1 + 2\t\t\n")
5157db96d56Sopenharmony_ci        self.compile_single("1 + 2\t\t\n        ")
5167db96d56Sopenharmony_ci        self.compile_single("1 + 2 # one plus two")
5177db96d56Sopenharmony_ci        self.compile_single("1; 2")
5187db96d56Sopenharmony_ci        self.compile_single("import sys; sys")
5197db96d56Sopenharmony_ci        self.compile_single("def f():\n   pass")
5207db96d56Sopenharmony_ci        self.compile_single("while False:\n   pass")
5217db96d56Sopenharmony_ci        self.compile_single("if x:\n   f(x)")
5227db96d56Sopenharmony_ci        self.compile_single("if x:\n   f(x)\nelse:\n   g(x)")
5237db96d56Sopenharmony_ci        self.compile_single("class T:\n   pass")
5247db96d56Sopenharmony_ci        self.compile_single("c = '''\na=1\nb=2\nc=3\n'''")
5257db96d56Sopenharmony_ci
5267db96d56Sopenharmony_ci    def test_bad_single_statement(self):
5277db96d56Sopenharmony_ci        self.assertInvalidSingle('1\n2')
5287db96d56Sopenharmony_ci        self.assertInvalidSingle('def f(): pass')
5297db96d56Sopenharmony_ci        self.assertInvalidSingle('a = 13\nb = 187')
5307db96d56Sopenharmony_ci        self.assertInvalidSingle('del x\ndel y')
5317db96d56Sopenharmony_ci        self.assertInvalidSingle('f()\ng()')
5327db96d56Sopenharmony_ci        self.assertInvalidSingle('f()\n# blah\nblah()')
5337db96d56Sopenharmony_ci        self.assertInvalidSingle('f()\nxy # blah\nblah()')
5347db96d56Sopenharmony_ci        self.assertInvalidSingle('x = 5 # comment\nx = 6\n')
5357db96d56Sopenharmony_ci        self.assertInvalidSingle("c = '''\nd=1\n'''\na = 1\n\nb = 2\n")
5367db96d56Sopenharmony_ci
5377db96d56Sopenharmony_ci    def test_particularly_evil_undecodable(self):
5387db96d56Sopenharmony_ci        # Issue 24022
5397db96d56Sopenharmony_ci        src = b'0000\x00\n00000000000\n\x00\n\x9e\n'
5407db96d56Sopenharmony_ci        with tempfile.TemporaryDirectory() as tmpd:
5417db96d56Sopenharmony_ci            fn = os.path.join(tmpd, "bad.py")
5427db96d56Sopenharmony_ci            with open(fn, "wb") as fp:
5437db96d56Sopenharmony_ci                fp.write(src)
5447db96d56Sopenharmony_ci            res = script_helper.run_python_until_end(fn)[0]
5457db96d56Sopenharmony_ci        self.assertIn(b"source code cannot contain null bytes", res.err)
5467db96d56Sopenharmony_ci
5477db96d56Sopenharmony_ci    def test_yet_more_evil_still_undecodable(self):
5487db96d56Sopenharmony_ci        # Issue #25388
5497db96d56Sopenharmony_ci        src = b"#\x00\n#\xfd\n"
5507db96d56Sopenharmony_ci        with tempfile.TemporaryDirectory() as tmpd:
5517db96d56Sopenharmony_ci            fn = os.path.join(tmpd, "bad.py")
5527db96d56Sopenharmony_ci            with open(fn, "wb") as fp:
5537db96d56Sopenharmony_ci                fp.write(src)
5547db96d56Sopenharmony_ci            res = script_helper.run_python_until_end(fn)[0]
5557db96d56Sopenharmony_ci        self.assertIn(b"source code cannot contain null bytes", res.err)
5567db96d56Sopenharmony_ci
5577db96d56Sopenharmony_ci    @support.cpython_only
5587db96d56Sopenharmony_ci    def test_compiler_recursion_limit(self):
5597db96d56Sopenharmony_ci        # Expected limit is sys.getrecursionlimit() * the scaling factor
5607db96d56Sopenharmony_ci        # in symtable.c (currently 3)
5617db96d56Sopenharmony_ci        # We expect to fail *at* that limit, because we use up some of
5627db96d56Sopenharmony_ci        # the stack depth limit in the test suite code
5637db96d56Sopenharmony_ci        # So we check the expected limit and 75% of that
5647db96d56Sopenharmony_ci        # XXX (ncoghlan): duplicating the scaling factor here is a little
5657db96d56Sopenharmony_ci        # ugly. Perhaps it should be exposed somewhere...
5667db96d56Sopenharmony_ci        fail_depth = sys.getrecursionlimit() * 3
5677db96d56Sopenharmony_ci        crash_depth = sys.getrecursionlimit() * 300
5687db96d56Sopenharmony_ci        success_depth = int(fail_depth * 0.75)
5697db96d56Sopenharmony_ci
5707db96d56Sopenharmony_ci        def check_limit(prefix, repeated, mode="single"):
5717db96d56Sopenharmony_ci            expect_ok = prefix + repeated * success_depth
5727db96d56Sopenharmony_ci            compile(expect_ok, '<test>', mode)
5737db96d56Sopenharmony_ci            for depth in (fail_depth, crash_depth):
5747db96d56Sopenharmony_ci                broken = prefix + repeated * depth
5757db96d56Sopenharmony_ci                details = "Compiling ({!r} + {!r} * {})".format(
5767db96d56Sopenharmony_ci                            prefix, repeated, depth)
5777db96d56Sopenharmony_ci                with self.assertRaises(RecursionError, msg=details):
5787db96d56Sopenharmony_ci                    compile(broken, '<test>', mode)
5797db96d56Sopenharmony_ci
5807db96d56Sopenharmony_ci        check_limit("a", "()")
5817db96d56Sopenharmony_ci        check_limit("a", ".b")
5827db96d56Sopenharmony_ci        check_limit("a", "[0]")
5837db96d56Sopenharmony_ci        check_limit("a", "*a")
5847db96d56Sopenharmony_ci        # XXX Crashes in the parser.
5857db96d56Sopenharmony_ci        # check_limit("a", " if a else a")
5867db96d56Sopenharmony_ci        # check_limit("if a: pass", "\nelif a: pass", mode="exec")
5877db96d56Sopenharmony_ci
5887db96d56Sopenharmony_ci    def test_null_terminated(self):
5897db96d56Sopenharmony_ci        # The source code is null-terminated internally, but bytes-like
5907db96d56Sopenharmony_ci        # objects are accepted, which could be not terminated.
5917db96d56Sopenharmony_ci        with self.assertRaisesRegex(SyntaxError, "cannot contain null"):
5927db96d56Sopenharmony_ci            compile("123\x00", "<dummy>", "eval")
5937db96d56Sopenharmony_ci        with self.assertRaisesRegex(SyntaxError, "cannot contain null"):
5947db96d56Sopenharmony_ci            compile(memoryview(b"123\x00"), "<dummy>", "eval")
5957db96d56Sopenharmony_ci        code = compile(memoryview(b"123\x00")[1:-1], "<dummy>", "eval")
5967db96d56Sopenharmony_ci        self.assertEqual(eval(code), 23)
5977db96d56Sopenharmony_ci        code = compile(memoryview(b"1234")[1:-1], "<dummy>", "eval")
5987db96d56Sopenharmony_ci        self.assertEqual(eval(code), 23)
5997db96d56Sopenharmony_ci        code = compile(memoryview(b"$23$")[1:-1], "<dummy>", "eval")
6007db96d56Sopenharmony_ci        self.assertEqual(eval(code), 23)
6017db96d56Sopenharmony_ci
6027db96d56Sopenharmony_ci        # Also test when eval() and exec() do the compilation step
6037db96d56Sopenharmony_ci        self.assertEqual(eval(memoryview(b"1234")[1:-1]), 23)
6047db96d56Sopenharmony_ci        namespace = dict()
6057db96d56Sopenharmony_ci        exec(memoryview(b"ax = 123")[1:-1], namespace)
6067db96d56Sopenharmony_ci        self.assertEqual(namespace['x'], 12)
6077db96d56Sopenharmony_ci
6087db96d56Sopenharmony_ci    def check_constant(self, func, expected):
6097db96d56Sopenharmony_ci        for const in func.__code__.co_consts:
6107db96d56Sopenharmony_ci            if repr(const) == repr(expected):
6117db96d56Sopenharmony_ci                break
6127db96d56Sopenharmony_ci        else:
6137db96d56Sopenharmony_ci            self.fail("unable to find constant %r in %r"
6147db96d56Sopenharmony_ci                      % (expected, func.__code__.co_consts))
6157db96d56Sopenharmony_ci
6167db96d56Sopenharmony_ci    # Merging equal constants is not a strict requirement for the Python
6177db96d56Sopenharmony_ci    # semantics, it's a more an implementation detail.
6187db96d56Sopenharmony_ci    @support.cpython_only
6197db96d56Sopenharmony_ci    def test_merge_constants(self):
6207db96d56Sopenharmony_ci        # Issue #25843: compile() must merge constants which are equal
6217db96d56Sopenharmony_ci        # and have the same type.
6227db96d56Sopenharmony_ci
6237db96d56Sopenharmony_ci        def check_same_constant(const):
6247db96d56Sopenharmony_ci            ns = {}
6257db96d56Sopenharmony_ci            code = "f1, f2 = lambda: %r, lambda: %r" % (const, const)
6267db96d56Sopenharmony_ci            exec(code, ns)
6277db96d56Sopenharmony_ci            f1 = ns['f1']
6287db96d56Sopenharmony_ci            f2 = ns['f2']
6297db96d56Sopenharmony_ci            self.assertIs(f1.__code__.co_consts, f2.__code__.co_consts)
6307db96d56Sopenharmony_ci            self.check_constant(f1, const)
6317db96d56Sopenharmony_ci            self.assertEqual(repr(f1()), repr(const))
6327db96d56Sopenharmony_ci
6337db96d56Sopenharmony_ci        check_same_constant(None)
6347db96d56Sopenharmony_ci        check_same_constant(0)
6357db96d56Sopenharmony_ci        check_same_constant(0.0)
6367db96d56Sopenharmony_ci        check_same_constant(b'abc')
6377db96d56Sopenharmony_ci        check_same_constant('abc')
6387db96d56Sopenharmony_ci
6397db96d56Sopenharmony_ci        # Note: "lambda: ..." emits "LOAD_CONST Ellipsis",
6407db96d56Sopenharmony_ci        # whereas "lambda: Ellipsis" emits "LOAD_GLOBAL Ellipsis"
6417db96d56Sopenharmony_ci        f1, f2 = lambda: ..., lambda: ...
6427db96d56Sopenharmony_ci        self.assertIs(f1.__code__.co_consts, f2.__code__.co_consts)
6437db96d56Sopenharmony_ci        self.check_constant(f1, Ellipsis)
6447db96d56Sopenharmony_ci        self.assertEqual(repr(f1()), repr(Ellipsis))
6457db96d56Sopenharmony_ci
6467db96d56Sopenharmony_ci        # Merge constants in tuple or frozenset
6477db96d56Sopenharmony_ci        f1, f2 = lambda: "not a name", lambda: ("not a name",)
6487db96d56Sopenharmony_ci        f3 = lambda x: x in {("not a name",)}
6497db96d56Sopenharmony_ci        self.assertIs(f1.__code__.co_consts[1],
6507db96d56Sopenharmony_ci                      f2.__code__.co_consts[1][0])
6517db96d56Sopenharmony_ci        self.assertIs(next(iter(f3.__code__.co_consts[1])),
6527db96d56Sopenharmony_ci                      f2.__code__.co_consts[1])
6537db96d56Sopenharmony_ci
6547db96d56Sopenharmony_ci        # {0} is converted to a constant frozenset({0}) by the peephole
6557db96d56Sopenharmony_ci        # optimizer
6567db96d56Sopenharmony_ci        f1, f2 = lambda x: x in {0}, lambda x: x in {0}
6577db96d56Sopenharmony_ci        self.assertIs(f1.__code__.co_consts, f2.__code__.co_consts)
6587db96d56Sopenharmony_ci        self.check_constant(f1, frozenset({0}))
6597db96d56Sopenharmony_ci        self.assertTrue(f1(0))
6607db96d56Sopenharmony_ci
6617db96d56Sopenharmony_ci    # Merging equal co_linetable is not a strict requirement
6627db96d56Sopenharmony_ci    # for the Python semantics, it's a more an implementation detail.
6637db96d56Sopenharmony_ci    @support.cpython_only
6647db96d56Sopenharmony_ci    def test_merge_code_attrs(self):
6657db96d56Sopenharmony_ci        # See https://bugs.python.org/issue42217
6667db96d56Sopenharmony_ci        f1 = lambda x: x.y.z
6677db96d56Sopenharmony_ci        f2 = lambda a: a.b.c
6687db96d56Sopenharmony_ci
6697db96d56Sopenharmony_ci        self.assertIs(f1.__code__.co_linetable, f2.__code__.co_linetable)
6707db96d56Sopenharmony_ci
6717db96d56Sopenharmony_ci    # Stripping unused constants is not a strict requirement for the
6727db96d56Sopenharmony_ci    # Python semantics, it's a more an implementation detail.
6737db96d56Sopenharmony_ci    @support.cpython_only
6747db96d56Sopenharmony_ci    def test_strip_unused_consts(self):
6757db96d56Sopenharmony_ci        # Python 3.10rc1 appended None to co_consts when None is not used
6767db96d56Sopenharmony_ci        # at all. See bpo-45056.
6777db96d56Sopenharmony_ci        def f1():
6787db96d56Sopenharmony_ci            "docstring"
6797db96d56Sopenharmony_ci            return 42
6807db96d56Sopenharmony_ci        self.assertEqual(f1.__code__.co_consts, ("docstring", 42))
6817db96d56Sopenharmony_ci
6827db96d56Sopenharmony_ci    # This is a regression test for a CPython specific peephole optimizer
6837db96d56Sopenharmony_ci    # implementation bug present in a few releases.  It's assertion verifies
6847db96d56Sopenharmony_ci    # that peephole optimization was actually done though that isn't an
6857db96d56Sopenharmony_ci    # indication of the bugs presence or not (crashing is).
6867db96d56Sopenharmony_ci    @support.cpython_only
6877db96d56Sopenharmony_ci    def test_peephole_opt_unreachable_code_array_access_in_bounds(self):
6887db96d56Sopenharmony_ci        """Regression test for issue35193 when run under clang msan."""
6897db96d56Sopenharmony_ci        def unused_code_at_end():
6907db96d56Sopenharmony_ci            return 3
6917db96d56Sopenharmony_ci            raise RuntimeError("unreachable")
6927db96d56Sopenharmony_ci        # The above function definition will trigger the out of bounds
6937db96d56Sopenharmony_ci        # bug in the peephole optimizer as it scans opcodes past the
6947db96d56Sopenharmony_ci        # RETURN_VALUE opcode.  This does not always crash an interpreter.
6957db96d56Sopenharmony_ci        # When you build with the clang memory sanitizer it reliably aborts.
6967db96d56Sopenharmony_ci        self.assertEqual(
6977db96d56Sopenharmony_ci            'RETURN_VALUE',
6987db96d56Sopenharmony_ci            list(dis.get_instructions(unused_code_at_end))[-1].opname)
6997db96d56Sopenharmony_ci
7007db96d56Sopenharmony_ci    def test_dont_merge_constants(self):
7017db96d56Sopenharmony_ci        # Issue #25843: compile() must not merge constants which are equal
7027db96d56Sopenharmony_ci        # but have a different type.
7037db96d56Sopenharmony_ci
7047db96d56Sopenharmony_ci        def check_different_constants(const1, const2):
7057db96d56Sopenharmony_ci            ns = {}
7067db96d56Sopenharmony_ci            exec("f1, f2 = lambda: %r, lambda: %r" % (const1, const2), ns)
7077db96d56Sopenharmony_ci            f1 = ns['f1']
7087db96d56Sopenharmony_ci            f2 = ns['f2']
7097db96d56Sopenharmony_ci            self.assertIsNot(f1.__code__, f2.__code__)
7107db96d56Sopenharmony_ci            self.assertNotEqual(f1.__code__, f2.__code__)
7117db96d56Sopenharmony_ci            self.check_constant(f1, const1)
7127db96d56Sopenharmony_ci            self.check_constant(f2, const2)
7137db96d56Sopenharmony_ci            self.assertEqual(repr(f1()), repr(const1))
7147db96d56Sopenharmony_ci            self.assertEqual(repr(f2()), repr(const2))
7157db96d56Sopenharmony_ci
7167db96d56Sopenharmony_ci        check_different_constants(0, 0.0)
7177db96d56Sopenharmony_ci        check_different_constants(+0.0, -0.0)
7187db96d56Sopenharmony_ci        check_different_constants((0,), (0.0,))
7197db96d56Sopenharmony_ci        check_different_constants('a', b'a')
7207db96d56Sopenharmony_ci        check_different_constants(('a',), (b'a',))
7217db96d56Sopenharmony_ci
7227db96d56Sopenharmony_ci        # check_different_constants() cannot be used because repr(-0j) is
7237db96d56Sopenharmony_ci        # '(-0-0j)', but when '(-0-0j)' is evaluated to 0j: we loose the sign.
7247db96d56Sopenharmony_ci        f1, f2 = lambda: +0.0j, lambda: -0.0j
7257db96d56Sopenharmony_ci        self.assertIsNot(f1.__code__, f2.__code__)
7267db96d56Sopenharmony_ci        self.check_constant(f1, +0.0j)
7277db96d56Sopenharmony_ci        self.check_constant(f2, -0.0j)
7287db96d56Sopenharmony_ci        self.assertEqual(repr(f1()), repr(+0.0j))
7297db96d56Sopenharmony_ci        self.assertEqual(repr(f2()), repr(-0.0j))
7307db96d56Sopenharmony_ci
7317db96d56Sopenharmony_ci        # {0} is converted to a constant frozenset({0}) by the peephole
7327db96d56Sopenharmony_ci        # optimizer
7337db96d56Sopenharmony_ci        f1, f2 = lambda x: x in {0}, lambda x: x in {0.0}
7347db96d56Sopenharmony_ci        self.assertIsNot(f1.__code__, f2.__code__)
7357db96d56Sopenharmony_ci        self.check_constant(f1, frozenset({0}))
7367db96d56Sopenharmony_ci        self.check_constant(f2, frozenset({0.0}))
7377db96d56Sopenharmony_ci        self.assertTrue(f1(0))
7387db96d56Sopenharmony_ci        self.assertTrue(f2(0.0))
7397db96d56Sopenharmony_ci
7407db96d56Sopenharmony_ci    def test_path_like_objects(self):
7417db96d56Sopenharmony_ci        # An implicit test for PyUnicode_FSDecoder().
7427db96d56Sopenharmony_ci        compile("42", FakePath("test_compile_pathlike"), "single")
7437db96d56Sopenharmony_ci
7447db96d56Sopenharmony_ci    def test_stack_overflow(self):
7457db96d56Sopenharmony_ci        # bpo-31113: Stack overflow when compile a long sequence of
7467db96d56Sopenharmony_ci        # complex statements.
7477db96d56Sopenharmony_ci        compile("if a: b\n" * 200000, "<dummy>", "exec")
7487db96d56Sopenharmony_ci
7497db96d56Sopenharmony_ci    # Multiple users rely on the fact that CPython does not generate
7507db96d56Sopenharmony_ci    # bytecode for dead code blocks. See bpo-37500 for more context.
7517db96d56Sopenharmony_ci    @support.cpython_only
7527db96d56Sopenharmony_ci    def test_dead_blocks_do_not_generate_bytecode(self):
7537db96d56Sopenharmony_ci        def unused_block_if():
7547db96d56Sopenharmony_ci            if 0:
7557db96d56Sopenharmony_ci                return 42
7567db96d56Sopenharmony_ci
7577db96d56Sopenharmony_ci        def unused_block_while():
7587db96d56Sopenharmony_ci            while 0:
7597db96d56Sopenharmony_ci                return 42
7607db96d56Sopenharmony_ci
7617db96d56Sopenharmony_ci        def unused_block_if_else():
7627db96d56Sopenharmony_ci            if 1:
7637db96d56Sopenharmony_ci                return None
7647db96d56Sopenharmony_ci            else:
7657db96d56Sopenharmony_ci                return 42
7667db96d56Sopenharmony_ci
7677db96d56Sopenharmony_ci        def unused_block_while_else():
7687db96d56Sopenharmony_ci            while 1:
7697db96d56Sopenharmony_ci                return None
7707db96d56Sopenharmony_ci            else:
7717db96d56Sopenharmony_ci                return 42
7727db96d56Sopenharmony_ci
7737db96d56Sopenharmony_ci        funcs = [unused_block_if, unused_block_while,
7747db96d56Sopenharmony_ci                 unused_block_if_else, unused_block_while_else]
7757db96d56Sopenharmony_ci
7767db96d56Sopenharmony_ci        for func in funcs:
7777db96d56Sopenharmony_ci            opcodes = list(dis.get_instructions(func))
7787db96d56Sopenharmony_ci            self.assertLessEqual(len(opcodes), 4)
7797db96d56Sopenharmony_ci            self.assertEqual('LOAD_CONST', opcodes[-2].opname)
7807db96d56Sopenharmony_ci            self.assertEqual(None, opcodes[-2].argval)
7817db96d56Sopenharmony_ci            self.assertEqual('RETURN_VALUE', opcodes[-1].opname)
7827db96d56Sopenharmony_ci
7837db96d56Sopenharmony_ci    def test_false_while_loop(self):
7847db96d56Sopenharmony_ci        def break_in_while():
7857db96d56Sopenharmony_ci            while False:
7867db96d56Sopenharmony_ci                break
7877db96d56Sopenharmony_ci
7887db96d56Sopenharmony_ci        def continue_in_while():
7897db96d56Sopenharmony_ci            while False:
7907db96d56Sopenharmony_ci                continue
7917db96d56Sopenharmony_ci
7927db96d56Sopenharmony_ci        funcs = [break_in_while, continue_in_while]
7937db96d56Sopenharmony_ci
7947db96d56Sopenharmony_ci        # Check that we did not raise but we also don't generate bytecode
7957db96d56Sopenharmony_ci        for func in funcs:
7967db96d56Sopenharmony_ci            opcodes = list(dis.get_instructions(func))
7977db96d56Sopenharmony_ci            self.assertEqual(3, len(opcodes))
7987db96d56Sopenharmony_ci            self.assertEqual('LOAD_CONST', opcodes[1].opname)
7997db96d56Sopenharmony_ci            self.assertEqual(None, opcodes[1].argval)
8007db96d56Sopenharmony_ci            self.assertEqual('RETURN_VALUE', opcodes[2].opname)
8017db96d56Sopenharmony_ci
8027db96d56Sopenharmony_ci    def test_consts_in_conditionals(self):
8037db96d56Sopenharmony_ci        def and_true(x):
8047db96d56Sopenharmony_ci            return True and x
8057db96d56Sopenharmony_ci
8067db96d56Sopenharmony_ci        def and_false(x):
8077db96d56Sopenharmony_ci            return False and x
8087db96d56Sopenharmony_ci
8097db96d56Sopenharmony_ci        def or_true(x):
8107db96d56Sopenharmony_ci            return True or x
8117db96d56Sopenharmony_ci
8127db96d56Sopenharmony_ci        def or_false(x):
8137db96d56Sopenharmony_ci            return False or x
8147db96d56Sopenharmony_ci
8157db96d56Sopenharmony_ci        funcs = [and_true, and_false, or_true, or_false]
8167db96d56Sopenharmony_ci
8177db96d56Sopenharmony_ci        # Check that condition is removed.
8187db96d56Sopenharmony_ci        for func in funcs:
8197db96d56Sopenharmony_ci            with self.subTest(func=func):
8207db96d56Sopenharmony_ci                opcodes = list(dis.get_instructions(func))
8217db96d56Sopenharmony_ci                self.assertLessEqual(len(opcodes), 3)
8227db96d56Sopenharmony_ci                self.assertIn('LOAD_', opcodes[-2].opname)
8237db96d56Sopenharmony_ci                self.assertEqual('RETURN_VALUE', opcodes[-1].opname)
8247db96d56Sopenharmony_ci
8257db96d56Sopenharmony_ci    def test_imported_load_method(self):
8267db96d56Sopenharmony_ci        sources = [
8277db96d56Sopenharmony_ci            """\
8287db96d56Sopenharmony_ci            import os
8297db96d56Sopenharmony_ci            def foo():
8307db96d56Sopenharmony_ci                return os.uname()
8317db96d56Sopenharmony_ci            """,
8327db96d56Sopenharmony_ci            """\
8337db96d56Sopenharmony_ci            import os as operating_system
8347db96d56Sopenharmony_ci            def foo():
8357db96d56Sopenharmony_ci                return operating_system.uname()
8367db96d56Sopenharmony_ci            """,
8377db96d56Sopenharmony_ci            """\
8387db96d56Sopenharmony_ci            from os import path
8397db96d56Sopenharmony_ci            def foo(x):
8407db96d56Sopenharmony_ci                return path.join(x)
8417db96d56Sopenharmony_ci            """,
8427db96d56Sopenharmony_ci            """\
8437db96d56Sopenharmony_ci            from os import path as os_path
8447db96d56Sopenharmony_ci            def foo(x):
8457db96d56Sopenharmony_ci                return os_path.join(x)
8467db96d56Sopenharmony_ci            """
8477db96d56Sopenharmony_ci        ]
8487db96d56Sopenharmony_ci        for source in sources:
8497db96d56Sopenharmony_ci            namespace = {}
8507db96d56Sopenharmony_ci            exec(textwrap.dedent(source), namespace)
8517db96d56Sopenharmony_ci            func = namespace['foo']
8527db96d56Sopenharmony_ci            with self.subTest(func=func.__name__):
8537db96d56Sopenharmony_ci                opcodes = list(dis.get_instructions(func))
8547db96d56Sopenharmony_ci                instructions = [opcode.opname for opcode in opcodes]
8557db96d56Sopenharmony_ci                self.assertNotIn('LOAD_METHOD', instructions)
8567db96d56Sopenharmony_ci                self.assertIn('LOAD_ATTR', instructions)
8577db96d56Sopenharmony_ci                self.assertIn('PRECALL', instructions)
8587db96d56Sopenharmony_ci
8597db96d56Sopenharmony_ci    def test_lineno_procedure_call(self):
8607db96d56Sopenharmony_ci        def call():
8617db96d56Sopenharmony_ci            (
8627db96d56Sopenharmony_ci                print()
8637db96d56Sopenharmony_ci            )
8647db96d56Sopenharmony_ci        line1 = call.__code__.co_firstlineno + 1
8657db96d56Sopenharmony_ci        assert line1 not in [line for (_, _, line) in call.__code__.co_lines()]
8667db96d56Sopenharmony_ci
8677db96d56Sopenharmony_ci    def test_lineno_after_implicit_return(self):
8687db96d56Sopenharmony_ci        TRUE = True
8697db96d56Sopenharmony_ci        # Don't use constant True or False, as compiler will remove test
8707db96d56Sopenharmony_ci        def if1(x):
8717db96d56Sopenharmony_ci            x()
8727db96d56Sopenharmony_ci            if TRUE:
8737db96d56Sopenharmony_ci                pass
8747db96d56Sopenharmony_ci        def if2(x):
8757db96d56Sopenharmony_ci            x()
8767db96d56Sopenharmony_ci            if TRUE:
8777db96d56Sopenharmony_ci                pass
8787db96d56Sopenharmony_ci            else:
8797db96d56Sopenharmony_ci                pass
8807db96d56Sopenharmony_ci        def if3(x):
8817db96d56Sopenharmony_ci            x()
8827db96d56Sopenharmony_ci            if TRUE:
8837db96d56Sopenharmony_ci                pass
8847db96d56Sopenharmony_ci            else:
8857db96d56Sopenharmony_ci                return None
8867db96d56Sopenharmony_ci        def if4(x):
8877db96d56Sopenharmony_ci            x()
8887db96d56Sopenharmony_ci            if not TRUE:
8897db96d56Sopenharmony_ci                pass
8907db96d56Sopenharmony_ci        funcs = [ if1, if2, if3, if4]
8917db96d56Sopenharmony_ci        lastlines = [ 3, 3, 3, 2]
8927db96d56Sopenharmony_ci        frame = None
8937db96d56Sopenharmony_ci        def save_caller_frame():
8947db96d56Sopenharmony_ci            nonlocal frame
8957db96d56Sopenharmony_ci            frame = sys._getframe(1)
8967db96d56Sopenharmony_ci        for func, lastline in zip(funcs, lastlines, strict=True):
8977db96d56Sopenharmony_ci            with self.subTest(func=func):
8987db96d56Sopenharmony_ci                func(save_caller_frame)
8997db96d56Sopenharmony_ci                self.assertEqual(frame.f_lineno-frame.f_code.co_firstlineno, lastline)
9007db96d56Sopenharmony_ci
9017db96d56Sopenharmony_ci    def test_lineno_after_no_code(self):
9027db96d56Sopenharmony_ci        def no_code1():
9037db96d56Sopenharmony_ci            "doc string"
9047db96d56Sopenharmony_ci
9057db96d56Sopenharmony_ci        def no_code2():
9067db96d56Sopenharmony_ci            a: int
9077db96d56Sopenharmony_ci
9087db96d56Sopenharmony_ci        for func in (no_code1, no_code2):
9097db96d56Sopenharmony_ci            with self.subTest(func=func):
9107db96d56Sopenharmony_ci                code = func.__code__
9117db96d56Sopenharmony_ci                lines = list(code.co_lines())
9127db96d56Sopenharmony_ci                start, end, line = lines[0]
9137db96d56Sopenharmony_ci                self.assertEqual(start, 0)
9147db96d56Sopenharmony_ci                self.assertEqual(line, code.co_firstlineno)
9157db96d56Sopenharmony_ci
9167db96d56Sopenharmony_ci    def get_code_lines(self, code):
9177db96d56Sopenharmony_ci        last_line = -2
9187db96d56Sopenharmony_ci        res = []
9197db96d56Sopenharmony_ci        for _, _, line in code.co_lines():
9207db96d56Sopenharmony_ci            if line is not None and line != last_line:
9217db96d56Sopenharmony_ci                res.append(line - code.co_firstlineno)
9227db96d56Sopenharmony_ci                last_line = line
9237db96d56Sopenharmony_ci        return res
9247db96d56Sopenharmony_ci
9257db96d56Sopenharmony_ci    def test_lineno_attribute(self):
9267db96d56Sopenharmony_ci        def load_attr():
9277db96d56Sopenharmony_ci            return (
9287db96d56Sopenharmony_ci                o.
9297db96d56Sopenharmony_ci                a
9307db96d56Sopenharmony_ci            )
9317db96d56Sopenharmony_ci        load_attr_lines = [ 0, 2, 3, 1 ]
9327db96d56Sopenharmony_ci
9337db96d56Sopenharmony_ci        def load_method():
9347db96d56Sopenharmony_ci            return (
9357db96d56Sopenharmony_ci                o.
9367db96d56Sopenharmony_ci                m(
9377db96d56Sopenharmony_ci                    0
9387db96d56Sopenharmony_ci                )
9397db96d56Sopenharmony_ci            )
9407db96d56Sopenharmony_ci        load_method_lines = [ 0, 2, 3, 4, 3, 1 ]
9417db96d56Sopenharmony_ci
9427db96d56Sopenharmony_ci        def store_attr():
9437db96d56Sopenharmony_ci            (
9447db96d56Sopenharmony_ci                o.
9457db96d56Sopenharmony_ci                a
9467db96d56Sopenharmony_ci            ) = (
9477db96d56Sopenharmony_ci                v
9487db96d56Sopenharmony_ci            )
9497db96d56Sopenharmony_ci        store_attr_lines = [ 0, 5, 2, 3 ]
9507db96d56Sopenharmony_ci
9517db96d56Sopenharmony_ci        def aug_store_attr():
9527db96d56Sopenharmony_ci            (
9537db96d56Sopenharmony_ci                o.
9547db96d56Sopenharmony_ci                a
9557db96d56Sopenharmony_ci            ) += (
9567db96d56Sopenharmony_ci                v
9577db96d56Sopenharmony_ci            )
9587db96d56Sopenharmony_ci        aug_store_attr_lines = [ 0, 2, 3, 5, 1, 3 ]
9597db96d56Sopenharmony_ci
9607db96d56Sopenharmony_ci        funcs = [ load_attr, load_method, store_attr, aug_store_attr]
9617db96d56Sopenharmony_ci        func_lines = [ load_attr_lines, load_method_lines,
9627db96d56Sopenharmony_ci                 store_attr_lines, aug_store_attr_lines]
9637db96d56Sopenharmony_ci
9647db96d56Sopenharmony_ci        for func, lines in zip(funcs, func_lines, strict=True):
9657db96d56Sopenharmony_ci            with self.subTest(func=func):
9667db96d56Sopenharmony_ci                code_lines = self.get_code_lines(func.__code__)
9677db96d56Sopenharmony_ci                self.assertEqual(lines, code_lines)
9687db96d56Sopenharmony_ci
9697db96d56Sopenharmony_ci    def test_line_number_genexp(self):
9707db96d56Sopenharmony_ci
9717db96d56Sopenharmony_ci        def return_genexp():
9727db96d56Sopenharmony_ci            return (1
9737db96d56Sopenharmony_ci                    for
9747db96d56Sopenharmony_ci                    x
9757db96d56Sopenharmony_ci                    in
9767db96d56Sopenharmony_ci                    y)
9777db96d56Sopenharmony_ci        genexp_lines = [0, 2, 0]
9787db96d56Sopenharmony_ci
9797db96d56Sopenharmony_ci        genexp_code = return_genexp.__code__.co_consts[1]
9807db96d56Sopenharmony_ci        code_lines = self.get_code_lines(genexp_code)
9817db96d56Sopenharmony_ci        self.assertEqual(genexp_lines, code_lines)
9827db96d56Sopenharmony_ci
9837db96d56Sopenharmony_ci    def test_line_number_implicit_return_after_async_for(self):
9847db96d56Sopenharmony_ci
9857db96d56Sopenharmony_ci        async def test(aseq):
9867db96d56Sopenharmony_ci            async for i in aseq:
9877db96d56Sopenharmony_ci                body
9887db96d56Sopenharmony_ci
9897db96d56Sopenharmony_ci        expected_lines = [0, 1, 2, 1]
9907db96d56Sopenharmony_ci        code_lines = self.get_code_lines(test.__code__)
9917db96d56Sopenharmony_ci        self.assertEqual(expected_lines, code_lines)
9927db96d56Sopenharmony_ci
9937db96d56Sopenharmony_ci    def test_big_dict_literal(self):
9947db96d56Sopenharmony_ci        # The compiler has a flushing point in "compiler_dict" that calls compiles
9957db96d56Sopenharmony_ci        # a portion of the dictionary literal when the loop that iterates over the items
9967db96d56Sopenharmony_ci        # reaches 0xFFFF elements but the code was not including the boundary element,
9977db96d56Sopenharmony_ci        # dropping the key at position 0xFFFF. See bpo-41531 for more information
9987db96d56Sopenharmony_ci
9997db96d56Sopenharmony_ci        dict_size = 0xFFFF + 1
10007db96d56Sopenharmony_ci        the_dict = "{" + ",".join(f"{x}:{x}" for x in range(dict_size)) + "}"
10017db96d56Sopenharmony_ci        self.assertEqual(len(eval(the_dict)), dict_size)
10027db96d56Sopenharmony_ci
10037db96d56Sopenharmony_ci    def test_redundant_jump_in_if_else_break(self):
10047db96d56Sopenharmony_ci        # Check if bytecode containing jumps that simply point to the next line
10057db96d56Sopenharmony_ci        # is generated around if-else-break style structures. See bpo-42615.
10067db96d56Sopenharmony_ci
10077db96d56Sopenharmony_ci        def if_else_break():
10087db96d56Sopenharmony_ci            val = 1
10097db96d56Sopenharmony_ci            while True:
10107db96d56Sopenharmony_ci                if val > 0:
10117db96d56Sopenharmony_ci                    val -= 1
10127db96d56Sopenharmony_ci                else:
10137db96d56Sopenharmony_ci                    break
10147db96d56Sopenharmony_ci                val = -1
10157db96d56Sopenharmony_ci
10167db96d56Sopenharmony_ci        INSTR_SIZE = 2
10177db96d56Sopenharmony_ci        HANDLED_JUMPS = (
10187db96d56Sopenharmony_ci            'POP_JUMP_IF_FALSE',
10197db96d56Sopenharmony_ci            'POP_JUMP_IF_TRUE',
10207db96d56Sopenharmony_ci            'JUMP_ABSOLUTE',
10217db96d56Sopenharmony_ci            'JUMP_FORWARD',
10227db96d56Sopenharmony_ci        )
10237db96d56Sopenharmony_ci
10247db96d56Sopenharmony_ci        for line, instr in enumerate(
10257db96d56Sopenharmony_ci            dis.Bytecode(if_else_break, show_caches=True)
10267db96d56Sopenharmony_ci        ):
10277db96d56Sopenharmony_ci            if instr.opname == 'JUMP_FORWARD':
10287db96d56Sopenharmony_ci                self.assertNotEqual(instr.arg, 0)
10297db96d56Sopenharmony_ci            elif instr.opname in HANDLED_JUMPS:
10307db96d56Sopenharmony_ci                self.assertNotEqual(instr.arg, (line + 1)*INSTR_SIZE)
10317db96d56Sopenharmony_ci
10327db96d56Sopenharmony_ci    def test_no_wraparound_jump(self):
10337db96d56Sopenharmony_ci        # See https://bugs.python.org/issue46724
10347db96d56Sopenharmony_ci
10357db96d56Sopenharmony_ci        def while_not_chained(a, b, c):
10367db96d56Sopenharmony_ci            while not (a < b < c):
10377db96d56Sopenharmony_ci                pass
10387db96d56Sopenharmony_ci
10397db96d56Sopenharmony_ci        for instr in dis.Bytecode(while_not_chained):
10407db96d56Sopenharmony_ci            self.assertNotEqual(instr.opname, "EXTENDED_ARG")
10417db96d56Sopenharmony_ci
10427db96d56Sopenharmony_ci    def test_compare_positions(self):
10437db96d56Sopenharmony_ci        for opname, op in [
10447db96d56Sopenharmony_ci            ("COMPARE_OP", "<"),
10457db96d56Sopenharmony_ci            ("COMPARE_OP", "<="),
10467db96d56Sopenharmony_ci            ("COMPARE_OP", ">"),
10477db96d56Sopenharmony_ci            ("COMPARE_OP", ">="),
10487db96d56Sopenharmony_ci            ("CONTAINS_OP", "in"),
10497db96d56Sopenharmony_ci            ("CONTAINS_OP", "not in"),
10507db96d56Sopenharmony_ci            ("IS_OP", "is"),
10517db96d56Sopenharmony_ci            ("IS_OP", "is not"),
10527db96d56Sopenharmony_ci        ]:
10537db96d56Sopenharmony_ci            expr = f'a {op} b {op} c'
10547db96d56Sopenharmony_ci            expected_positions = 2 * [(2, 2, 0, len(expr))]
10557db96d56Sopenharmony_ci            for source in [
10567db96d56Sopenharmony_ci                f"\\\n{expr}", f'if \\\n{expr}: x', f"x if \\\n{expr} else y"
10577db96d56Sopenharmony_ci            ]:
10587db96d56Sopenharmony_ci                code = compile(source, "<test>", "exec")
10597db96d56Sopenharmony_ci                actual_positions = [
10607db96d56Sopenharmony_ci                    instruction.positions
10617db96d56Sopenharmony_ci                    for instruction in dis.get_instructions(code)
10627db96d56Sopenharmony_ci                    if instruction.opname == opname
10637db96d56Sopenharmony_ci                ]
10647db96d56Sopenharmony_ci                with self.subTest(source):
10657db96d56Sopenharmony_ci                    self.assertEqual(actual_positions, expected_positions)
10667db96d56Sopenharmony_ci
10677db96d56Sopenharmony_ci    def test_apply_static_swaps(self):
10687db96d56Sopenharmony_ci        def f(x, y):
10697db96d56Sopenharmony_ci            a, a = x, y
10707db96d56Sopenharmony_ci            return a
10717db96d56Sopenharmony_ci        self.assertEqual(f("x", "y"), "y")
10727db96d56Sopenharmony_ci
10737db96d56Sopenharmony_ci    def test_apply_static_swaps_2(self):
10747db96d56Sopenharmony_ci        def f(x, y, z):
10757db96d56Sopenharmony_ci            a, b, a = x, y, z
10767db96d56Sopenharmony_ci            return a
10777db96d56Sopenharmony_ci        self.assertEqual(f("x", "y", "z"), "z")
10787db96d56Sopenharmony_ci
10797db96d56Sopenharmony_ci    def test_apply_static_swaps_3(self):
10807db96d56Sopenharmony_ci        def f(x, y, z):
10817db96d56Sopenharmony_ci            a, a, b = x, y, z
10827db96d56Sopenharmony_ci            return a
10837db96d56Sopenharmony_ci        self.assertEqual(f("x", "y", "z"), "y")
10847db96d56Sopenharmony_ci
10857db96d56Sopenharmony_ci
10867db96d56Sopenharmony_ci@requires_debug_ranges()
10877db96d56Sopenharmony_ciclass TestSourcePositions(unittest.TestCase):
10887db96d56Sopenharmony_ci    # Ensure that compiled code snippets have correct line and column numbers
10897db96d56Sopenharmony_ci    # in `co_positions()`.
10907db96d56Sopenharmony_ci
10917db96d56Sopenharmony_ci    def check_positions_against_ast(self, snippet):
10927db96d56Sopenharmony_ci        # Basic check that makes sure each line and column is at least present
10937db96d56Sopenharmony_ci        # in one of the AST nodes of the source code.
10947db96d56Sopenharmony_ci        code = compile(snippet, 'test_compile.py', 'exec')
10957db96d56Sopenharmony_ci        ast_tree = compile(snippet, 'test_compile.py', 'exec', _ast.PyCF_ONLY_AST)
10967db96d56Sopenharmony_ci        self.assertTrue(type(ast_tree) == _ast.Module)
10977db96d56Sopenharmony_ci
10987db96d56Sopenharmony_ci        # Use an AST visitor that notes all the offsets.
10997db96d56Sopenharmony_ci        lines, end_lines, columns, end_columns = set(), set(), set(), set()
11007db96d56Sopenharmony_ci        class SourceOffsetVisitor(ast.NodeVisitor):
11017db96d56Sopenharmony_ci            def generic_visit(self, node):
11027db96d56Sopenharmony_ci                super().generic_visit(node)
11037db96d56Sopenharmony_ci                if not isinstance(node, ast.expr) and not isinstance(node, ast.stmt):
11047db96d56Sopenharmony_ci                    return
11057db96d56Sopenharmony_ci                lines.add(node.lineno)
11067db96d56Sopenharmony_ci                end_lines.add(node.end_lineno)
11077db96d56Sopenharmony_ci                columns.add(node.col_offset)
11087db96d56Sopenharmony_ci                end_columns.add(node.end_col_offset)
11097db96d56Sopenharmony_ci
11107db96d56Sopenharmony_ci        SourceOffsetVisitor().visit(ast_tree)
11117db96d56Sopenharmony_ci
11127db96d56Sopenharmony_ci        # Check against the positions in the code object.
11137db96d56Sopenharmony_ci        for (line, end_line, col, end_col) in code.co_positions():
11147db96d56Sopenharmony_ci            if line == 0:
11157db96d56Sopenharmony_ci                continue # This is an artificial module-start line
11167db96d56Sopenharmony_ci            # If the offset is not None (indicating missing data), ensure that
11177db96d56Sopenharmony_ci            # it was part of one of the AST nodes.
11187db96d56Sopenharmony_ci            if line is not None:
11197db96d56Sopenharmony_ci                self.assertIn(line, lines)
11207db96d56Sopenharmony_ci            if end_line is not None:
11217db96d56Sopenharmony_ci                self.assertIn(end_line, end_lines)
11227db96d56Sopenharmony_ci            if col is not None:
11237db96d56Sopenharmony_ci                self.assertIn(col, columns)
11247db96d56Sopenharmony_ci            if end_col is not None:
11257db96d56Sopenharmony_ci                self.assertIn(end_col, end_columns)
11267db96d56Sopenharmony_ci
11277db96d56Sopenharmony_ci        return code, ast_tree
11287db96d56Sopenharmony_ci
11297db96d56Sopenharmony_ci    def assertOpcodeSourcePositionIs(self, code, opcode,
11307db96d56Sopenharmony_ci            line, end_line, column, end_column, occurrence=1):
11317db96d56Sopenharmony_ci
11327db96d56Sopenharmony_ci        for instr, position in zip(
11337db96d56Sopenharmony_ci            dis.Bytecode(code, show_caches=True), code.co_positions(), strict=True
11347db96d56Sopenharmony_ci        ):
11357db96d56Sopenharmony_ci            if instr.opname == opcode:
11367db96d56Sopenharmony_ci                occurrence -= 1
11377db96d56Sopenharmony_ci                if not occurrence:
11387db96d56Sopenharmony_ci                    self.assertEqual(position[0], line)
11397db96d56Sopenharmony_ci                    self.assertEqual(position[1], end_line)
11407db96d56Sopenharmony_ci                    self.assertEqual(position[2], column)
11417db96d56Sopenharmony_ci                    self.assertEqual(position[3], end_column)
11427db96d56Sopenharmony_ci                    return
11437db96d56Sopenharmony_ci
11447db96d56Sopenharmony_ci        self.fail(f"Opcode {opcode} not found in code")
11457db96d56Sopenharmony_ci
11467db96d56Sopenharmony_ci    def test_simple_assignment(self):
11477db96d56Sopenharmony_ci        snippet = "x = 1"
11487db96d56Sopenharmony_ci        self.check_positions_against_ast(snippet)
11497db96d56Sopenharmony_ci
11507db96d56Sopenharmony_ci    def test_compiles_to_extended_op_arg(self):
11517db96d56Sopenharmony_ci        # Make sure we still have valid positions when the code compiles to an
11527db96d56Sopenharmony_ci        # EXTENDED_ARG by performing a loop which needs a JUMP_ABSOLUTE after
11537db96d56Sopenharmony_ci        # a bunch of opcodes.
11547db96d56Sopenharmony_ci        snippet = "x = x\n" * 10_000
11557db96d56Sopenharmony_ci        snippet += ("while x != 0:\n"
11567db96d56Sopenharmony_ci                    "  x -= 1\n"
11577db96d56Sopenharmony_ci                    "while x != 0:\n"
11587db96d56Sopenharmony_ci                    "  x +=  1\n"
11597db96d56Sopenharmony_ci                   )
11607db96d56Sopenharmony_ci
11617db96d56Sopenharmony_ci        compiled_code, _ = self.check_positions_against_ast(snippet)
11627db96d56Sopenharmony_ci
11637db96d56Sopenharmony_ci        self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_OP',
11647db96d56Sopenharmony_ci            line=10_000 + 2, end_line=10_000 + 2,
11657db96d56Sopenharmony_ci            column=2, end_column=8, occurrence=1)
11667db96d56Sopenharmony_ci        self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_OP',
11677db96d56Sopenharmony_ci            line=10_000 + 4, end_line=10_000 + 4,
11687db96d56Sopenharmony_ci            column=2, end_column=9, occurrence=2)
11697db96d56Sopenharmony_ci
11707db96d56Sopenharmony_ci    def test_multiline_expression(self):
11717db96d56Sopenharmony_ci        snippet = """\
11727db96d56Sopenharmony_cif(
11737db96d56Sopenharmony_ci    1, 2, 3, 4
11747db96d56Sopenharmony_ci)
11757db96d56Sopenharmony_ci"""
11767db96d56Sopenharmony_ci        compiled_code, _ = self.check_positions_against_ast(snippet)
11777db96d56Sopenharmony_ci        self.assertOpcodeSourcePositionIs(compiled_code, 'CALL',
11787db96d56Sopenharmony_ci            line=1, end_line=3, column=0, end_column=1)
11797db96d56Sopenharmony_ci
11807db96d56Sopenharmony_ci    def test_very_long_line_end_offset(self):
11817db96d56Sopenharmony_ci        # Make sure we get the correct column offset for offsets
11827db96d56Sopenharmony_ci        # too large to store in a byte.
11837db96d56Sopenharmony_ci        long_string = "a" * 1000
11847db96d56Sopenharmony_ci        snippet = f"g('{long_string}')"
11857db96d56Sopenharmony_ci
11867db96d56Sopenharmony_ci        compiled_code, _ = self.check_positions_against_ast(snippet)
11877db96d56Sopenharmony_ci        self.assertOpcodeSourcePositionIs(compiled_code, 'CALL',
11887db96d56Sopenharmony_ci            line=1, end_line=1, column=0, end_column=1005)
11897db96d56Sopenharmony_ci
11907db96d56Sopenharmony_ci    def test_complex_single_line_expression(self):
11917db96d56Sopenharmony_ci        snippet = "a - b @ (c * x['key'] + 23)"
11927db96d56Sopenharmony_ci
11937db96d56Sopenharmony_ci        compiled_code, _ = self.check_positions_against_ast(snippet)
11947db96d56Sopenharmony_ci        self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_SUBSCR',
11957db96d56Sopenharmony_ci            line=1, end_line=1, column=13, end_column=21)
11967db96d56Sopenharmony_ci        self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_OP',
11977db96d56Sopenharmony_ci            line=1, end_line=1, column=9, end_column=21, occurrence=1)
11987db96d56Sopenharmony_ci        self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_OP',
11997db96d56Sopenharmony_ci            line=1, end_line=1, column=9, end_column=26, occurrence=2)
12007db96d56Sopenharmony_ci        self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_OP',
12017db96d56Sopenharmony_ci            line=1, end_line=1, column=4, end_column=27, occurrence=3)
12027db96d56Sopenharmony_ci        self.assertOpcodeSourcePositionIs(compiled_code, 'BINARY_OP',
12037db96d56Sopenharmony_ci            line=1, end_line=1, column=0, end_column=27, occurrence=4)
12047db96d56Sopenharmony_ci
12057db96d56Sopenharmony_ci    def test_multiline_assert_rewritten_as_method_call(self):
12067db96d56Sopenharmony_ci        # GH-94694: Don't crash if pytest rewrites a multiline assert as a
12077db96d56Sopenharmony_ci        # method call with the same location information:
12087db96d56Sopenharmony_ci        tree = ast.parse("assert (\n42\n)")
12097db96d56Sopenharmony_ci        old_node = tree.body[0]
12107db96d56Sopenharmony_ci        new_node = ast.Expr(
12117db96d56Sopenharmony_ci            ast.Call(
12127db96d56Sopenharmony_ci                ast.Attribute(
12137db96d56Sopenharmony_ci                    ast.Name("spam", ast.Load()),
12147db96d56Sopenharmony_ci                    "eggs",
12157db96d56Sopenharmony_ci                    ast.Load(),
12167db96d56Sopenharmony_ci                ),
12177db96d56Sopenharmony_ci                [],
12187db96d56Sopenharmony_ci                [],
12197db96d56Sopenharmony_ci            )
12207db96d56Sopenharmony_ci        )
12217db96d56Sopenharmony_ci        ast.copy_location(new_node, old_node)
12227db96d56Sopenharmony_ci        ast.fix_missing_locations(new_node)
12237db96d56Sopenharmony_ci        tree.body[0] = new_node
12247db96d56Sopenharmony_ci        compile(tree, "<test>", "exec")
12257db96d56Sopenharmony_ci
12267db96d56Sopenharmony_ci    def test_push_null_load_global_positions(self):
12277db96d56Sopenharmony_ci        source_template = """
12287db96d56Sopenharmony_ci        import abc, dis
12297db96d56Sopenharmony_ci        import ast as art
12307db96d56Sopenharmony_ci
12317db96d56Sopenharmony_ci        abc = None
12327db96d56Sopenharmony_ci        dix = dis
12337db96d56Sopenharmony_ci        ast = art
12347db96d56Sopenharmony_ci
12357db96d56Sopenharmony_ci        def f():
12367db96d56Sopenharmony_ci        {}
12377db96d56Sopenharmony_ci        """
12387db96d56Sopenharmony_ci        for body in [
12397db96d56Sopenharmony_ci            "    abc.a()",
12407db96d56Sopenharmony_ci            "    art.a()",
12417db96d56Sopenharmony_ci            "    ast.a()",
12427db96d56Sopenharmony_ci            "    dis.a()",
12437db96d56Sopenharmony_ci            "    dix.a()",
12447db96d56Sopenharmony_ci            "    abc[...]()",
12457db96d56Sopenharmony_ci            "    art()()",
12467db96d56Sopenharmony_ci            "   (ast or ...)()",
12477db96d56Sopenharmony_ci            "   [dis]()",
12487db96d56Sopenharmony_ci            "   (dix + ...)()",
12497db96d56Sopenharmony_ci        ]:
12507db96d56Sopenharmony_ci            with self.subTest(body):
12517db96d56Sopenharmony_ci                namespace = {}
12527db96d56Sopenharmony_ci                source = textwrap.dedent(source_template.format(body))
12537db96d56Sopenharmony_ci                exec(source, namespace)
12547db96d56Sopenharmony_ci                code = namespace["f"].__code__
12557db96d56Sopenharmony_ci                self.assertOpcodeSourcePositionIs(
12567db96d56Sopenharmony_ci                    code,
12577db96d56Sopenharmony_ci                    "LOAD_GLOBAL",
12587db96d56Sopenharmony_ci                    line=10,
12597db96d56Sopenharmony_ci                    end_line=10,
12607db96d56Sopenharmony_ci                    column=4,
12617db96d56Sopenharmony_ci                    end_column=7,
12627db96d56Sopenharmony_ci                )
12637db96d56Sopenharmony_ci
12647db96d56Sopenharmony_ci    def test_attribute_augassign(self):
12657db96d56Sopenharmony_ci        source = "(\n lhs  \n   .    \n     rhs      \n       ) += 42"
12667db96d56Sopenharmony_ci        code = compile(source, "<test>", "exec")
12677db96d56Sopenharmony_ci        self.assertOpcodeSourcePositionIs(
12687db96d56Sopenharmony_ci            code, "LOAD_ATTR", line=4, end_line=4, column=5, end_column=8
12697db96d56Sopenharmony_ci        )
12707db96d56Sopenharmony_ci        self.assertOpcodeSourcePositionIs(
12717db96d56Sopenharmony_ci            code, "STORE_ATTR", line=4, end_line=4, column=5, end_column=8
12727db96d56Sopenharmony_ci        )
12737db96d56Sopenharmony_ci
12747db96d56Sopenharmony_ci    def test_attribute_del(self):
12757db96d56Sopenharmony_ci        source = "del (\n lhs  \n   .    \n     rhs      \n       )"
12767db96d56Sopenharmony_ci        code = compile(source, "<test>", "exec")
12777db96d56Sopenharmony_ci        self.assertOpcodeSourcePositionIs(
12787db96d56Sopenharmony_ci            code, "DELETE_ATTR", line=4, end_line=4, column=5, end_column=8
12797db96d56Sopenharmony_ci        )
12807db96d56Sopenharmony_ci
12817db96d56Sopenharmony_ci    def test_attribute_load(self):
12827db96d56Sopenharmony_ci        source = "(\n lhs  \n   .    \n     rhs      \n       )"
12837db96d56Sopenharmony_ci        code = compile(source, "<test>", "exec")
12847db96d56Sopenharmony_ci        self.assertOpcodeSourcePositionIs(
12857db96d56Sopenharmony_ci            code, "LOAD_ATTR", line=4, end_line=4, column=5, end_column=8
12867db96d56Sopenharmony_ci        )
12877db96d56Sopenharmony_ci
12887db96d56Sopenharmony_ci    def test_attribute_store(self):
12897db96d56Sopenharmony_ci        source = "(\n lhs  \n   .    \n     rhs      \n       ) = 42"
12907db96d56Sopenharmony_ci        code = compile(source, "<test>", "exec")
12917db96d56Sopenharmony_ci        self.assertOpcodeSourcePositionIs(
12927db96d56Sopenharmony_ci            code, "STORE_ATTR", line=4, end_line=4, column=5, end_column=8
12937db96d56Sopenharmony_ci        )
12947db96d56Sopenharmony_ci
12957db96d56Sopenharmony_ci    def test_method_call(self):
12967db96d56Sopenharmony_ci        source = "(\n lhs  \n   .    \n     rhs      \n       )()"
12977db96d56Sopenharmony_ci        code = compile(source, "<test>", "exec")
12987db96d56Sopenharmony_ci        self.assertOpcodeSourcePositionIs(
12997db96d56Sopenharmony_ci            code, "LOAD_METHOD", line=4, end_line=4, column=5, end_column=8
13007db96d56Sopenharmony_ci        )
13017db96d56Sopenharmony_ci        self.assertOpcodeSourcePositionIs(
13027db96d56Sopenharmony_ci            code, "CALL", line=4, end_line=5, column=5, end_column=10
13037db96d56Sopenharmony_ci        )
13047db96d56Sopenharmony_ci
13057db96d56Sopenharmony_ci    def test_weird_attribute_position_regressions(self):
13067db96d56Sopenharmony_ci        def f():
13077db96d56Sopenharmony_ci            (bar.
13087db96d56Sopenharmony_ci        baz)
13097db96d56Sopenharmony_ci            (bar.
13107db96d56Sopenharmony_ci        baz(
13117db96d56Sopenharmony_ci        ))
13127db96d56Sopenharmony_ci            files().setdefault(
13137db96d56Sopenharmony_ci                0
13147db96d56Sopenharmony_ci            ).setdefault(
13157db96d56Sopenharmony_ci                0
13167db96d56Sopenharmony_ci            )
13177db96d56Sopenharmony_ci        for line, end_line, column, end_column in f.__code__.co_positions():
13187db96d56Sopenharmony_ci            self.assertIsNotNone(line)
13197db96d56Sopenharmony_ci            self.assertIsNotNone(end_line)
13207db96d56Sopenharmony_ci            self.assertIsNotNone(column)
13217db96d56Sopenharmony_ci            self.assertIsNotNone(end_column)
13227db96d56Sopenharmony_ci            self.assertLessEqual((line, column), (end_line, end_column))
13237db96d56Sopenharmony_ci
13247db96d56Sopenharmony_ci    @support.cpython_only
13257db96d56Sopenharmony_ci    def test_column_offset_deduplication(self):
13267db96d56Sopenharmony_ci        # GH-95150: Code with different column offsets shouldn't be merged!
13277db96d56Sopenharmony_ci        for source in [
13287db96d56Sopenharmony_ci            "lambda: a",
13297db96d56Sopenharmony_ci            "(a for b in c)",
13307db96d56Sopenharmony_ci            "[a for b in c]",
13317db96d56Sopenharmony_ci            "{a for b in c}",
13327db96d56Sopenharmony_ci            "{a: b for c in d}",
13337db96d56Sopenharmony_ci        ]:
13347db96d56Sopenharmony_ci            with self.subTest(source):
13357db96d56Sopenharmony_ci                code = compile(f"{source}, {source}", "<test>", "eval")
13367db96d56Sopenharmony_ci                self.assertEqual(len(code.co_consts), 2)
13377db96d56Sopenharmony_ci                self.assertIsInstance(code.co_consts[0], types.CodeType)
13387db96d56Sopenharmony_ci                self.assertIsInstance(code.co_consts[1], types.CodeType)
13397db96d56Sopenharmony_ci                self.assertNotEqual(code.co_consts[0], code.co_consts[1])
13407db96d56Sopenharmony_ci                self.assertNotEqual(
13417db96d56Sopenharmony_ci                    list(code.co_consts[0].co_positions()),
13427db96d56Sopenharmony_ci                    list(code.co_consts[1].co_positions()),
13437db96d56Sopenharmony_ci                )
13447db96d56Sopenharmony_ci
13457db96d56Sopenharmony_ci
13467db96d56Sopenharmony_ciclass TestExpressionStackSize(unittest.TestCase):
13477db96d56Sopenharmony_ci    # These tests check that the computed stack size for a code object
13487db96d56Sopenharmony_ci    # stays within reasonable bounds (see issue #21523 for an example
13497db96d56Sopenharmony_ci    # dysfunction).
13507db96d56Sopenharmony_ci    N = 100
13517db96d56Sopenharmony_ci
13527db96d56Sopenharmony_ci    def check_stack_size(self, code):
13537db96d56Sopenharmony_ci        # To assert that the alleged stack size is not O(N), we
13547db96d56Sopenharmony_ci        # check that it is smaller than log(N).
13557db96d56Sopenharmony_ci        if isinstance(code, str):
13567db96d56Sopenharmony_ci            code = compile(code, "<foo>", "single")
13577db96d56Sopenharmony_ci        max_size = math.ceil(math.log(len(code.co_code)))
13587db96d56Sopenharmony_ci        self.assertLessEqual(code.co_stacksize, max_size)
13597db96d56Sopenharmony_ci
13607db96d56Sopenharmony_ci    def test_and(self):
13617db96d56Sopenharmony_ci        self.check_stack_size("x and " * self.N + "x")
13627db96d56Sopenharmony_ci
13637db96d56Sopenharmony_ci    def test_or(self):
13647db96d56Sopenharmony_ci        self.check_stack_size("x or " * self.N + "x")
13657db96d56Sopenharmony_ci
13667db96d56Sopenharmony_ci    def test_and_or(self):
13677db96d56Sopenharmony_ci        self.check_stack_size("x and x or " * self.N + "x")
13687db96d56Sopenharmony_ci
13697db96d56Sopenharmony_ci    def test_chained_comparison(self):
13707db96d56Sopenharmony_ci        self.check_stack_size("x < " * self.N + "x")
13717db96d56Sopenharmony_ci
13727db96d56Sopenharmony_ci    def test_if_else(self):
13737db96d56Sopenharmony_ci        self.check_stack_size("x if x else " * self.N + "x")
13747db96d56Sopenharmony_ci
13757db96d56Sopenharmony_ci    def test_binop(self):
13767db96d56Sopenharmony_ci        self.check_stack_size("x + " * self.N + "x")
13777db96d56Sopenharmony_ci
13787db96d56Sopenharmony_ci    def test_list(self):
13797db96d56Sopenharmony_ci        self.check_stack_size("[" + "x, " * self.N + "x]")
13807db96d56Sopenharmony_ci
13817db96d56Sopenharmony_ci    def test_tuple(self):
13827db96d56Sopenharmony_ci        self.check_stack_size("(" + "x, " * self.N + "x)")
13837db96d56Sopenharmony_ci
13847db96d56Sopenharmony_ci    def test_set(self):
13857db96d56Sopenharmony_ci        self.check_stack_size("{" + "x, " * self.N + "x}")
13867db96d56Sopenharmony_ci
13877db96d56Sopenharmony_ci    def test_dict(self):
13887db96d56Sopenharmony_ci        self.check_stack_size("{" + "x:x, " * self.N + "x:x}")
13897db96d56Sopenharmony_ci
13907db96d56Sopenharmony_ci    def test_func_args(self):
13917db96d56Sopenharmony_ci        self.check_stack_size("f(" + "x, " * self.N + ")")
13927db96d56Sopenharmony_ci
13937db96d56Sopenharmony_ci    def test_func_kwargs(self):
13947db96d56Sopenharmony_ci        kwargs = (f'a{i}=x' for i in range(self.N))
13957db96d56Sopenharmony_ci        self.check_stack_size("f(" +  ", ".join(kwargs) + ")")
13967db96d56Sopenharmony_ci
13977db96d56Sopenharmony_ci    def test_meth_args(self):
13987db96d56Sopenharmony_ci        self.check_stack_size("o.m(" + "x, " * self.N + ")")
13997db96d56Sopenharmony_ci
14007db96d56Sopenharmony_ci    def test_meth_kwargs(self):
14017db96d56Sopenharmony_ci        kwargs = (f'a{i}=x' for i in range(self.N))
14027db96d56Sopenharmony_ci        self.check_stack_size("o.m(" +  ", ".join(kwargs) + ")")
14037db96d56Sopenharmony_ci
14047db96d56Sopenharmony_ci    def test_func_and(self):
14057db96d56Sopenharmony_ci        code = "def f(x):\n"
14067db96d56Sopenharmony_ci        code += "   x and x\n" * self.N
14077db96d56Sopenharmony_ci        self.check_stack_size(code)
14087db96d56Sopenharmony_ci
14097db96d56Sopenharmony_ci    def test_stack_3050(self):
14107db96d56Sopenharmony_ci        M = 3050
14117db96d56Sopenharmony_ci        code = "x," * M + "=t"
14127db96d56Sopenharmony_ci        # This raised on 3.10.0 to 3.10.5
14137db96d56Sopenharmony_ci        compile(code, "<foo>", "single")
14147db96d56Sopenharmony_ci
14157db96d56Sopenharmony_ci    def test_stack_3050_2(self):
14167db96d56Sopenharmony_ci        M = 3050
14177db96d56Sopenharmony_ci        args = ", ".join(f"arg{i}:type{i}" for i in range(M))
14187db96d56Sopenharmony_ci        code = f"def f({args}):\n  pass"
14197db96d56Sopenharmony_ci        # This raised on 3.10.0 to 3.10.5
14207db96d56Sopenharmony_ci        compile(code, "<foo>", "single")
14217db96d56Sopenharmony_ci
14227db96d56Sopenharmony_ci
14237db96d56Sopenharmony_ciclass TestStackSizeStability(unittest.TestCase):
14247db96d56Sopenharmony_ci    # Check that repeating certain snippets doesn't increase the stack size
14257db96d56Sopenharmony_ci    # beyond what a single snippet requires.
14267db96d56Sopenharmony_ci
14277db96d56Sopenharmony_ci    def check_stack_size(self, snippet, async_=False):
14287db96d56Sopenharmony_ci        def compile_snippet(i):
14297db96d56Sopenharmony_ci            ns = {}
14307db96d56Sopenharmony_ci            script = """def func():\n""" + i * snippet
14317db96d56Sopenharmony_ci            if async_:
14327db96d56Sopenharmony_ci                script = "async " + script
14337db96d56Sopenharmony_ci            code = compile(script, "<script>", "exec")
14347db96d56Sopenharmony_ci            exec(code, ns, ns)
14357db96d56Sopenharmony_ci            return ns['func'].__code__
14367db96d56Sopenharmony_ci
14377db96d56Sopenharmony_ci        sizes = [compile_snippet(i).co_stacksize for i in range(2, 5)]
14387db96d56Sopenharmony_ci        if len(set(sizes)) != 1:
14397db96d56Sopenharmony_ci            import dis, io
14407db96d56Sopenharmony_ci            out = io.StringIO()
14417db96d56Sopenharmony_ci            dis.dis(compile_snippet(1), file=out)
14427db96d56Sopenharmony_ci            self.fail("stack sizes diverge with # of consecutive snippets: "
14437db96d56Sopenharmony_ci                      "%s\n%s\n%s" % (sizes, snippet, out.getvalue()))
14447db96d56Sopenharmony_ci
14457db96d56Sopenharmony_ci    def test_if(self):
14467db96d56Sopenharmony_ci        snippet = """
14477db96d56Sopenharmony_ci            if x:
14487db96d56Sopenharmony_ci                a
14497db96d56Sopenharmony_ci            """
14507db96d56Sopenharmony_ci        self.check_stack_size(snippet)
14517db96d56Sopenharmony_ci
14527db96d56Sopenharmony_ci    def test_if_else(self):
14537db96d56Sopenharmony_ci        snippet = """
14547db96d56Sopenharmony_ci            if x:
14557db96d56Sopenharmony_ci                a
14567db96d56Sopenharmony_ci            elif y:
14577db96d56Sopenharmony_ci                b
14587db96d56Sopenharmony_ci            else:
14597db96d56Sopenharmony_ci                c
14607db96d56Sopenharmony_ci            """
14617db96d56Sopenharmony_ci        self.check_stack_size(snippet)
14627db96d56Sopenharmony_ci
14637db96d56Sopenharmony_ci    def test_try_except_bare(self):
14647db96d56Sopenharmony_ci        snippet = """
14657db96d56Sopenharmony_ci            try:
14667db96d56Sopenharmony_ci                a
14677db96d56Sopenharmony_ci            except:
14687db96d56Sopenharmony_ci                b
14697db96d56Sopenharmony_ci            """
14707db96d56Sopenharmony_ci        self.check_stack_size(snippet)
14717db96d56Sopenharmony_ci
14727db96d56Sopenharmony_ci    def test_try_except_qualified(self):
14737db96d56Sopenharmony_ci        snippet = """
14747db96d56Sopenharmony_ci            try:
14757db96d56Sopenharmony_ci                a
14767db96d56Sopenharmony_ci            except ImportError:
14777db96d56Sopenharmony_ci                b
14787db96d56Sopenharmony_ci            except:
14797db96d56Sopenharmony_ci                c
14807db96d56Sopenharmony_ci            else:
14817db96d56Sopenharmony_ci                d
14827db96d56Sopenharmony_ci            """
14837db96d56Sopenharmony_ci        self.check_stack_size(snippet)
14847db96d56Sopenharmony_ci
14857db96d56Sopenharmony_ci    def test_try_except_as(self):
14867db96d56Sopenharmony_ci        snippet = """
14877db96d56Sopenharmony_ci            try:
14887db96d56Sopenharmony_ci                a
14897db96d56Sopenharmony_ci            except ImportError as e:
14907db96d56Sopenharmony_ci                b
14917db96d56Sopenharmony_ci            except:
14927db96d56Sopenharmony_ci                c
14937db96d56Sopenharmony_ci            else:
14947db96d56Sopenharmony_ci                d
14957db96d56Sopenharmony_ci            """
14967db96d56Sopenharmony_ci        self.check_stack_size(snippet)
14977db96d56Sopenharmony_ci
14987db96d56Sopenharmony_ci    def test_try_except_star_qualified(self):
14997db96d56Sopenharmony_ci        snippet = """
15007db96d56Sopenharmony_ci            try:
15017db96d56Sopenharmony_ci                a
15027db96d56Sopenharmony_ci            except* ImportError:
15037db96d56Sopenharmony_ci                b
15047db96d56Sopenharmony_ci            else:
15057db96d56Sopenharmony_ci                c
15067db96d56Sopenharmony_ci            """
15077db96d56Sopenharmony_ci        self.check_stack_size(snippet)
15087db96d56Sopenharmony_ci
15097db96d56Sopenharmony_ci    def test_try_except_star_as(self):
15107db96d56Sopenharmony_ci        snippet = """
15117db96d56Sopenharmony_ci            try:
15127db96d56Sopenharmony_ci                a
15137db96d56Sopenharmony_ci            except* ImportError as e:
15147db96d56Sopenharmony_ci                b
15157db96d56Sopenharmony_ci            else:
15167db96d56Sopenharmony_ci                c
15177db96d56Sopenharmony_ci            """
15187db96d56Sopenharmony_ci        self.check_stack_size(snippet)
15197db96d56Sopenharmony_ci
15207db96d56Sopenharmony_ci    def test_try_except_star_finally(self):
15217db96d56Sopenharmony_ci        snippet = """
15227db96d56Sopenharmony_ci                try:
15237db96d56Sopenharmony_ci                    a
15247db96d56Sopenharmony_ci                except* A:
15257db96d56Sopenharmony_ci                    b
15267db96d56Sopenharmony_ci                finally:
15277db96d56Sopenharmony_ci                    c
15287db96d56Sopenharmony_ci            """
15297db96d56Sopenharmony_ci        self.check_stack_size(snippet)
15307db96d56Sopenharmony_ci
15317db96d56Sopenharmony_ci    def test_try_finally(self):
15327db96d56Sopenharmony_ci        snippet = """
15337db96d56Sopenharmony_ci                try:
15347db96d56Sopenharmony_ci                    a
15357db96d56Sopenharmony_ci                finally:
15367db96d56Sopenharmony_ci                    b
15377db96d56Sopenharmony_ci            """
15387db96d56Sopenharmony_ci        self.check_stack_size(snippet)
15397db96d56Sopenharmony_ci
15407db96d56Sopenharmony_ci    def test_with(self):
15417db96d56Sopenharmony_ci        snippet = """
15427db96d56Sopenharmony_ci            with x as y:
15437db96d56Sopenharmony_ci                a
15447db96d56Sopenharmony_ci            """
15457db96d56Sopenharmony_ci        self.check_stack_size(snippet)
15467db96d56Sopenharmony_ci
15477db96d56Sopenharmony_ci    def test_while_else(self):
15487db96d56Sopenharmony_ci        snippet = """
15497db96d56Sopenharmony_ci            while x:
15507db96d56Sopenharmony_ci                a
15517db96d56Sopenharmony_ci            else:
15527db96d56Sopenharmony_ci                b
15537db96d56Sopenharmony_ci            """
15547db96d56Sopenharmony_ci        self.check_stack_size(snippet)
15557db96d56Sopenharmony_ci
15567db96d56Sopenharmony_ci    def test_for(self):
15577db96d56Sopenharmony_ci        snippet = """
15587db96d56Sopenharmony_ci            for x in y:
15597db96d56Sopenharmony_ci                a
15607db96d56Sopenharmony_ci            """
15617db96d56Sopenharmony_ci        self.check_stack_size(snippet)
15627db96d56Sopenharmony_ci
15637db96d56Sopenharmony_ci    def test_for_else(self):
15647db96d56Sopenharmony_ci        snippet = """
15657db96d56Sopenharmony_ci            for x in y:
15667db96d56Sopenharmony_ci                a
15677db96d56Sopenharmony_ci            else:
15687db96d56Sopenharmony_ci                b
15697db96d56Sopenharmony_ci            """
15707db96d56Sopenharmony_ci        self.check_stack_size(snippet)
15717db96d56Sopenharmony_ci
15727db96d56Sopenharmony_ci    def test_for_break_continue(self):
15737db96d56Sopenharmony_ci        snippet = """
15747db96d56Sopenharmony_ci            for x in y:
15757db96d56Sopenharmony_ci                if z:
15767db96d56Sopenharmony_ci                    break
15777db96d56Sopenharmony_ci                elif u:
15787db96d56Sopenharmony_ci                    continue
15797db96d56Sopenharmony_ci                else:
15807db96d56Sopenharmony_ci                    a
15817db96d56Sopenharmony_ci            else:
15827db96d56Sopenharmony_ci                b
15837db96d56Sopenharmony_ci            """
15847db96d56Sopenharmony_ci        self.check_stack_size(snippet)
15857db96d56Sopenharmony_ci
15867db96d56Sopenharmony_ci    def test_for_break_continue_inside_try_finally_block(self):
15877db96d56Sopenharmony_ci        snippet = """
15887db96d56Sopenharmony_ci            for x in y:
15897db96d56Sopenharmony_ci                try:
15907db96d56Sopenharmony_ci                    if z:
15917db96d56Sopenharmony_ci                        break
15927db96d56Sopenharmony_ci                    elif u:
15937db96d56Sopenharmony_ci                        continue
15947db96d56Sopenharmony_ci                    else:
15957db96d56Sopenharmony_ci                        a
15967db96d56Sopenharmony_ci                finally:
15977db96d56Sopenharmony_ci                    f
15987db96d56Sopenharmony_ci            else:
15997db96d56Sopenharmony_ci                b
16007db96d56Sopenharmony_ci            """
16017db96d56Sopenharmony_ci        self.check_stack_size(snippet)
16027db96d56Sopenharmony_ci
16037db96d56Sopenharmony_ci    def test_for_break_continue_inside_finally_block(self):
16047db96d56Sopenharmony_ci        snippet = """
16057db96d56Sopenharmony_ci            for x in y:
16067db96d56Sopenharmony_ci                try:
16077db96d56Sopenharmony_ci                    t
16087db96d56Sopenharmony_ci                finally:
16097db96d56Sopenharmony_ci                    if z:
16107db96d56Sopenharmony_ci                        break
16117db96d56Sopenharmony_ci                    elif u:
16127db96d56Sopenharmony_ci                        continue
16137db96d56Sopenharmony_ci                    else:
16147db96d56Sopenharmony_ci                        a
16157db96d56Sopenharmony_ci            else:
16167db96d56Sopenharmony_ci                b
16177db96d56Sopenharmony_ci            """
16187db96d56Sopenharmony_ci        self.check_stack_size(snippet)
16197db96d56Sopenharmony_ci
16207db96d56Sopenharmony_ci    def test_for_break_continue_inside_except_block(self):
16217db96d56Sopenharmony_ci        snippet = """
16227db96d56Sopenharmony_ci            for x in y:
16237db96d56Sopenharmony_ci                try:
16247db96d56Sopenharmony_ci                    t
16257db96d56Sopenharmony_ci                except:
16267db96d56Sopenharmony_ci                    if z:
16277db96d56Sopenharmony_ci                        break
16287db96d56Sopenharmony_ci                    elif u:
16297db96d56Sopenharmony_ci                        continue
16307db96d56Sopenharmony_ci                    else:
16317db96d56Sopenharmony_ci                        a
16327db96d56Sopenharmony_ci            else:
16337db96d56Sopenharmony_ci                b
16347db96d56Sopenharmony_ci            """
16357db96d56Sopenharmony_ci        self.check_stack_size(snippet)
16367db96d56Sopenharmony_ci
16377db96d56Sopenharmony_ci    def test_for_break_continue_inside_with_block(self):
16387db96d56Sopenharmony_ci        snippet = """
16397db96d56Sopenharmony_ci            for x in y:
16407db96d56Sopenharmony_ci                with c:
16417db96d56Sopenharmony_ci                    if z:
16427db96d56Sopenharmony_ci                        break
16437db96d56Sopenharmony_ci                    elif u:
16447db96d56Sopenharmony_ci                        continue
16457db96d56Sopenharmony_ci                    else:
16467db96d56Sopenharmony_ci                        a
16477db96d56Sopenharmony_ci            else:
16487db96d56Sopenharmony_ci                b
16497db96d56Sopenharmony_ci            """
16507db96d56Sopenharmony_ci        self.check_stack_size(snippet)
16517db96d56Sopenharmony_ci
16527db96d56Sopenharmony_ci    def test_return_inside_try_finally_block(self):
16537db96d56Sopenharmony_ci        snippet = """
16547db96d56Sopenharmony_ci            try:
16557db96d56Sopenharmony_ci                if z:
16567db96d56Sopenharmony_ci                    return
16577db96d56Sopenharmony_ci                else:
16587db96d56Sopenharmony_ci                    a
16597db96d56Sopenharmony_ci            finally:
16607db96d56Sopenharmony_ci                f
16617db96d56Sopenharmony_ci            """
16627db96d56Sopenharmony_ci        self.check_stack_size(snippet)
16637db96d56Sopenharmony_ci
16647db96d56Sopenharmony_ci    def test_return_inside_finally_block(self):
16657db96d56Sopenharmony_ci        snippet = """
16667db96d56Sopenharmony_ci            try:
16677db96d56Sopenharmony_ci                t
16687db96d56Sopenharmony_ci            finally:
16697db96d56Sopenharmony_ci                if z:
16707db96d56Sopenharmony_ci                    return
16717db96d56Sopenharmony_ci                else:
16727db96d56Sopenharmony_ci                    a
16737db96d56Sopenharmony_ci            """
16747db96d56Sopenharmony_ci        self.check_stack_size(snippet)
16757db96d56Sopenharmony_ci
16767db96d56Sopenharmony_ci    def test_return_inside_except_block(self):
16777db96d56Sopenharmony_ci        snippet = """
16787db96d56Sopenharmony_ci            try:
16797db96d56Sopenharmony_ci                t
16807db96d56Sopenharmony_ci            except:
16817db96d56Sopenharmony_ci                if z:
16827db96d56Sopenharmony_ci                    return
16837db96d56Sopenharmony_ci                else:
16847db96d56Sopenharmony_ci                    a
16857db96d56Sopenharmony_ci            """
16867db96d56Sopenharmony_ci        self.check_stack_size(snippet)
16877db96d56Sopenharmony_ci
16887db96d56Sopenharmony_ci    def test_return_inside_with_block(self):
16897db96d56Sopenharmony_ci        snippet = """
16907db96d56Sopenharmony_ci            with c:
16917db96d56Sopenharmony_ci                if z:
16927db96d56Sopenharmony_ci                    return
16937db96d56Sopenharmony_ci                else:
16947db96d56Sopenharmony_ci                    a
16957db96d56Sopenharmony_ci            """
16967db96d56Sopenharmony_ci        self.check_stack_size(snippet)
16977db96d56Sopenharmony_ci
16987db96d56Sopenharmony_ci    def test_async_with(self):
16997db96d56Sopenharmony_ci        snippet = """
17007db96d56Sopenharmony_ci            async with x as y:
17017db96d56Sopenharmony_ci                a
17027db96d56Sopenharmony_ci            """
17037db96d56Sopenharmony_ci        self.check_stack_size(snippet, async_=True)
17047db96d56Sopenharmony_ci
17057db96d56Sopenharmony_ci    def test_async_for(self):
17067db96d56Sopenharmony_ci        snippet = """
17077db96d56Sopenharmony_ci            async for x in y:
17087db96d56Sopenharmony_ci                a
17097db96d56Sopenharmony_ci            """
17107db96d56Sopenharmony_ci        self.check_stack_size(snippet, async_=True)
17117db96d56Sopenharmony_ci
17127db96d56Sopenharmony_ci    def test_async_for_else(self):
17137db96d56Sopenharmony_ci        snippet = """
17147db96d56Sopenharmony_ci            async for x in y:
17157db96d56Sopenharmony_ci                a
17167db96d56Sopenharmony_ci            else:
17177db96d56Sopenharmony_ci                b
17187db96d56Sopenharmony_ci            """
17197db96d56Sopenharmony_ci        self.check_stack_size(snippet, async_=True)
17207db96d56Sopenharmony_ci
17217db96d56Sopenharmony_ci    def test_for_break_continue_inside_async_with_block(self):
17227db96d56Sopenharmony_ci        snippet = """
17237db96d56Sopenharmony_ci            for x in y:
17247db96d56Sopenharmony_ci                async with c:
17257db96d56Sopenharmony_ci                    if z:
17267db96d56Sopenharmony_ci                        break
17277db96d56Sopenharmony_ci                    elif u:
17287db96d56Sopenharmony_ci                        continue
17297db96d56Sopenharmony_ci                    else:
17307db96d56Sopenharmony_ci                        a
17317db96d56Sopenharmony_ci            else:
17327db96d56Sopenharmony_ci                b
17337db96d56Sopenharmony_ci            """
17347db96d56Sopenharmony_ci        self.check_stack_size(snippet, async_=True)
17357db96d56Sopenharmony_ci
17367db96d56Sopenharmony_ci    def test_return_inside_async_with_block(self):
17377db96d56Sopenharmony_ci        snippet = """
17387db96d56Sopenharmony_ci            async with c:
17397db96d56Sopenharmony_ci                if z:
17407db96d56Sopenharmony_ci                    return
17417db96d56Sopenharmony_ci                else:
17427db96d56Sopenharmony_ci                    a
17437db96d56Sopenharmony_ci            """
17447db96d56Sopenharmony_ci        self.check_stack_size(snippet, async_=True)
17457db96d56Sopenharmony_ci
17467db96d56Sopenharmony_ci
17477db96d56Sopenharmony_ciif __name__ == "__main__":
17487db96d56Sopenharmony_ci    unittest.main()
1749