ยปCore Development>Code coverage>Lib/test/test_compile.py

Python code coverage for Lib/test/test_compile.py

#countcontent
1n/aimport math
2n/aimport os
3n/aimport unittest
4n/aimport sys
5n/aimport _ast
6n/aimport tempfile
7n/aimport types
8n/afrom test import support
9n/afrom test.support import script_helper
10n/a
11n/aclass TestSpecifics(unittest.TestCase):
12n/a
13n/a def compile_single(self, source):
14n/a compile(source, "<single>", "single")
15n/a
16n/a def assertInvalidSingle(self, source):
17n/a self.assertRaises(SyntaxError, self.compile_single, source)
18n/a
19n/a def test_no_ending_newline(self):
20n/a compile("hi", "<test>", "exec")
21n/a compile("hi\r", "<test>", "exec")
22n/a
23n/a def test_empty(self):
24n/a compile("", "<test>", "exec")
25n/a
26n/a def test_other_newlines(self):
27n/a compile("\r\n", "<test>", "exec")
28n/a compile("\r", "<test>", "exec")
29n/a compile("hi\r\nstuff\r\ndef f():\n pass\r", "<test>", "exec")
30n/a compile("this_is\rreally_old_mac\rdef f():\n pass", "<test>", "exec")
31n/a
32n/a def test_debug_assignment(self):
33n/a # catch assignments to __debug__
34n/a self.assertRaises(SyntaxError, compile, '__debug__ = 1', '?', 'single')
35n/a import builtins
36n/a prev = builtins.__debug__
37n/a setattr(builtins, '__debug__', 'sure')
38n/a setattr(builtins, '__debug__', prev)
39n/a
40n/a def test_argument_handling(self):
41n/a # detect duplicate positional and keyword arguments
42n/a self.assertRaises(SyntaxError, eval, 'lambda a,a:0')
43n/a self.assertRaises(SyntaxError, eval, 'lambda a,a=1:0')
44n/a self.assertRaises(SyntaxError, eval, 'lambda a=1,a=1:0')
45n/a self.assertRaises(SyntaxError, exec, 'def f(a, a): pass')
46n/a self.assertRaises(SyntaxError, exec, 'def f(a = 0, a = 1): pass')
47n/a self.assertRaises(SyntaxError, exec, 'def f(a): global a; a = 1')
48n/a
49n/a def test_syntax_error(self):
50n/a self.assertRaises(SyntaxError, compile, "1+*3", "filename", "exec")
51n/a
52n/a def test_none_keyword_arg(self):
53n/a self.assertRaises(SyntaxError, compile, "f(None=1)", "<string>", "exec")
54n/a
55n/a def test_duplicate_global_local(self):
56n/a self.assertRaises(SyntaxError, exec, 'def f(a): global a; a = 1')
57n/a
58n/a def test_exec_with_general_mapping_for_locals(self):
59n/a
60n/a class M:
61n/a "Test mapping interface versus possible calls from eval()."
62n/a def __getitem__(self, key):
63n/a if key == 'a':
64n/a return 12
65n/a raise KeyError
66n/a def __setitem__(self, key, value):
67n/a self.results = (key, value)
68n/a def keys(self):
69n/a return list('xyz')
70n/a
71n/a m = M()
72n/a g = globals()
73n/a exec('z = a', g, m)
74n/a self.assertEqual(m.results, ('z', 12))
75n/a try:
76n/a exec('z = b', g, m)
77n/a except NameError:
78n/a pass
79n/a else:
80n/a self.fail('Did not detect a KeyError')
81n/a exec('z = dir()', g, m)
82n/a self.assertEqual(m.results, ('z', list('xyz')))
83n/a exec('z = globals()', g, m)
84n/a self.assertEqual(m.results, ('z', g))
85n/a exec('z = locals()', g, m)
86n/a self.assertEqual(m.results, ('z', m))
87n/a self.assertRaises(TypeError, exec, 'z = b', m)
88n/a
89n/a class A:
90n/a "Non-mapping"
91n/a pass
92n/a m = A()
93n/a self.assertRaises(TypeError, exec, 'z = a', g, m)
94n/a
95n/a # Verify that dict subclasses work as well
96n/a class D(dict):
97n/a def __getitem__(self, key):
98n/a if key == 'a':
99n/a return 12
100n/a return dict.__getitem__(self, key)
101n/a d = D()
102n/a exec('z = a', g, d)
103n/a self.assertEqual(d['z'], 12)
104n/a
105n/a def test_extended_arg(self):
106n/a longexpr = 'x = x or ' + '-x' * 2500
107n/a g = {}
108n/a code = '''
109n/adef f(x):
110n/a %s
111n/a %s
112n/a %s
113n/a %s
114n/a %s
115n/a %s
116n/a %s
117n/a %s
118n/a %s
119n/a %s
120n/a # the expressions above have no effect, x == argument
121n/a while x:
122n/a x -= 1
123n/a # EXTENDED_ARG/JUMP_ABSOLUTE here
124n/a return x
125n/a''' % ((longexpr,)*10)
126n/a exec(code, g)
127n/a self.assertEqual(g['f'](5), 0)
128n/a
129n/a def test_argument_order(self):
130n/a self.assertRaises(SyntaxError, exec, 'def f(a=1, b): pass')
131n/a
132n/a def test_float_literals(self):
133n/a # testing bad float literals
134n/a self.assertRaises(SyntaxError, eval, "2e")
135n/a self.assertRaises(SyntaxError, eval, "2.0e+")
136n/a self.assertRaises(SyntaxError, eval, "1e-")
137n/a self.assertRaises(SyntaxError, eval, "3-4e/21")
138n/a
139n/a def test_indentation(self):
140n/a # testing compile() of indented block w/o trailing newline"
141n/a s = """
142n/aif 1:
143n/a if 2:
144n/a pass"""
145n/a compile(s, "<string>", "exec")
146n/a
147n/a # This test is probably specific to CPython and may not generalize
148n/a # to other implementations. We are trying to ensure that when
149n/a # the first line of code starts after 256, correct line numbers
150n/a # in tracebacks are still produced.
151n/a def test_leading_newlines(self):
152n/a s256 = "".join(["\n"] * 256 + ["spam"])
153n/a co = compile(s256, 'fn', 'exec')
154n/a self.assertEqual(co.co_firstlineno, 257)
155n/a self.assertEqual(co.co_lnotab, bytes())
156n/a
157n/a def test_literals_with_leading_zeroes(self):
158n/a for arg in ["077787", "0xj", "0x.", "0e", "090000000000000",
159n/a "080000000000000", "000000000000009", "000000000000008",
160n/a "0b42", "0BADCAFE", "0o123456789", "0b1.1", "0o4.2",
161n/a "0b101j2", "0o153j2", "0b100e1", "0o777e1", "0777",
162n/a "000777", "000000000000007"]:
163n/a self.assertRaises(SyntaxError, eval, arg)
164n/a
165n/a self.assertEqual(eval("0xff"), 255)
166n/a self.assertEqual(eval("0777."), 777)
167n/a self.assertEqual(eval("0777.0"), 777)
168n/a self.assertEqual(eval("000000000000000000000000000000000000000000000000000777e0"), 777)
169n/a self.assertEqual(eval("0777e1"), 7770)
170n/a self.assertEqual(eval("0e0"), 0)
171n/a self.assertEqual(eval("0000e-012"), 0)
172n/a self.assertEqual(eval("09.5"), 9.5)
173n/a self.assertEqual(eval("0777j"), 777j)
174n/a self.assertEqual(eval("000"), 0)
175n/a self.assertEqual(eval("00j"), 0j)
176n/a self.assertEqual(eval("00.0"), 0)
177n/a self.assertEqual(eval("0e3"), 0)
178n/a self.assertEqual(eval("090000000000000."), 90000000000000.)
179n/a self.assertEqual(eval("090000000000000.0000000000000000000000"), 90000000000000.)
180n/a self.assertEqual(eval("090000000000000e0"), 90000000000000.)
181n/a self.assertEqual(eval("090000000000000e-0"), 90000000000000.)
182n/a self.assertEqual(eval("090000000000000j"), 90000000000000j)
183n/a self.assertEqual(eval("000000000000008."), 8.)
184n/a self.assertEqual(eval("000000000000009."), 9.)
185n/a self.assertEqual(eval("0b101010"), 42)
186n/a self.assertEqual(eval("-0b000000000010"), -2)
187n/a self.assertEqual(eval("0o777"), 511)
188n/a self.assertEqual(eval("-0o0000010"), -8)
189n/a
190n/a def test_unary_minus(self):
191n/a # Verify treatment of unary minus on negative numbers SF bug #660455
192n/a if sys.maxsize == 2147483647:
193n/a # 32-bit machine
194n/a all_one_bits = '0xffffffff'
195n/a self.assertEqual(eval(all_one_bits), 4294967295)
196n/a self.assertEqual(eval("-" + all_one_bits), -4294967295)
197n/a elif sys.maxsize == 9223372036854775807:
198n/a # 64-bit machine
199n/a all_one_bits = '0xffffffffffffffff'
200n/a self.assertEqual(eval(all_one_bits), 18446744073709551615)
201n/a self.assertEqual(eval("-" + all_one_bits), -18446744073709551615)
202n/a else:
203n/a self.fail("How many bits *does* this machine have???")
204n/a # Verify treatment of constant folding on -(sys.maxsize+1)
205n/a # i.e. -2147483648 on 32 bit platforms. Should return int.
206n/a self.assertIsInstance(eval("%s" % (-sys.maxsize - 1)), int)
207n/a self.assertIsInstance(eval("%s" % (-sys.maxsize - 2)), int)
208n/a
209n/a if sys.maxsize == 9223372036854775807:
210n/a def test_32_63_bit_values(self):
211n/a a = +4294967296 # 1 << 32
212n/a b = -4294967296 # 1 << 32
213n/a c = +281474976710656 # 1 << 48
214n/a d = -281474976710656 # 1 << 48
215n/a e = +4611686018427387904 # 1 << 62
216n/a f = -4611686018427387904 # 1 << 62
217n/a g = +9223372036854775807 # 1 << 63 - 1
218n/a h = -9223372036854775807 # 1 << 63 - 1
219n/a
220n/a for variable in self.test_32_63_bit_values.__code__.co_consts:
221n/a if variable is not None:
222n/a self.assertIsInstance(variable, int)
223n/a
224n/a def test_sequence_unpacking_error(self):
225n/a # Verify sequence packing/unpacking with "or". SF bug #757818
226n/a i,j = (1, -1) or (-1, 1)
227n/a self.assertEqual(i, 1)
228n/a self.assertEqual(j, -1)
229n/a
230n/a def test_none_assignment(self):
231n/a stmts = [
232n/a 'None = 0',
233n/a 'None += 0',
234n/a '__builtins__.None = 0',
235n/a 'def None(): pass',
236n/a 'class None: pass',
237n/a '(a, None) = 0, 0',
238n/a 'for None in range(10): pass',
239n/a 'def f(None): pass',
240n/a 'import None',
241n/a 'import x as None',
242n/a 'from x import None',
243n/a 'from x import y as None'
244n/a ]
245n/a for stmt in stmts:
246n/a stmt += "\n"
247n/a self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'single')
248n/a self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec')
249n/a
250n/a def test_import(self):
251n/a succeed = [
252n/a 'import sys',
253n/a 'import os, sys',
254n/a 'import os as bar',
255n/a 'import os.path as bar',
256n/a 'from __future__ import nested_scopes, generators',
257n/a 'from __future__ import (nested_scopes,\ngenerators)',
258n/a 'from __future__ import (nested_scopes,\ngenerators,)',
259n/a 'from sys import stdin, stderr, stdout',
260n/a 'from sys import (stdin, stderr,\nstdout)',
261n/a 'from sys import (stdin, stderr,\nstdout,)',
262n/a 'from sys import (stdin\n, stderr, stdout)',
263n/a 'from sys import (stdin\n, stderr, stdout,)',
264n/a 'from sys import stdin as si, stdout as so, stderr as se',
265n/a 'from sys import (stdin as si, stdout as so, stderr as se)',
266n/a 'from sys import (stdin as si, stdout as so, stderr as se,)',
267n/a ]
268n/a fail = [
269n/a 'import (os, sys)',
270n/a 'import (os), (sys)',
271n/a 'import ((os), (sys))',
272n/a 'import (sys',
273n/a 'import sys)',
274n/a 'import (os,)',
275n/a 'import os As bar',
276n/a 'import os.path a bar',
277n/a 'from sys import stdin As stdout',
278n/a 'from sys import stdin a stdout',
279n/a 'from (sys) import stdin',
280n/a 'from __future__ import (nested_scopes',
281n/a 'from __future__ import nested_scopes)',
282n/a 'from __future__ import nested_scopes,\ngenerators',
283n/a 'from sys import (stdin',
284n/a 'from sys import stdin)',
285n/a 'from sys import stdin, stdout,\nstderr',
286n/a 'from sys import stdin si',
287n/a 'from sys import stdin,'
288n/a 'from sys import (*)',
289n/a 'from sys import (stdin,, stdout, stderr)',
290n/a 'from sys import (stdin, stdout),',
291n/a ]
292n/a for stmt in succeed:
293n/a compile(stmt, 'tmp', 'exec')
294n/a for stmt in fail:
295n/a self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec')
296n/a
297n/a def test_for_distinct_code_objects(self):
298n/a # SF bug 1048870
299n/a def f():
300n/a f1 = lambda x=1: x
301n/a f2 = lambda x=2: x
302n/a return f1, f2
303n/a f1, f2 = f()
304n/a self.assertNotEqual(id(f1.__code__), id(f2.__code__))
305n/a
306n/a def test_lambda_doc(self):
307n/a l = lambda: "foo"
308n/a self.assertIsNone(l.__doc__)
309n/a
310n/a def test_encoding(self):
311n/a code = b'# -*- coding: badencoding -*-\npass\n'
312n/a self.assertRaises(SyntaxError, compile, code, 'tmp', 'exec')
313n/a code = '# -*- coding: badencoding -*-\n"\xc2\xa4"\n'
314n/a compile(code, 'tmp', 'exec')
315n/a self.assertEqual(eval(code), '\xc2\xa4')
316n/a code = '"\xc2\xa4"\n'
317n/a self.assertEqual(eval(code), '\xc2\xa4')
318n/a code = b'"\xc2\xa4"\n'
319n/a self.assertEqual(eval(code), '\xa4')
320n/a code = b'# -*- coding: latin1 -*-\n"\xc2\xa4"\n'
321n/a self.assertEqual(eval(code), '\xc2\xa4')
322n/a code = b'# -*- coding: utf-8 -*-\n"\xc2\xa4"\n'
323n/a self.assertEqual(eval(code), '\xa4')
324n/a code = b'# -*- coding: iso8859-15 -*-\n"\xc2\xa4"\n'
325n/a self.assertEqual(eval(code), '\xc2\u20ac')
326n/a code = '"""\\\n# -*- coding: iso8859-15 -*-\n\xc2\xa4"""\n'
327n/a self.assertEqual(eval(code), '# -*- coding: iso8859-15 -*-\n\xc2\xa4')
328n/a code = b'"""\\\n# -*- coding: iso8859-15 -*-\n\xc2\xa4"""\n'
329n/a self.assertEqual(eval(code), '# -*- coding: iso8859-15 -*-\n\xa4')
330n/a
331n/a def test_subscripts(self):
332n/a # SF bug 1448804
333n/a # Class to make testing subscript results easy
334n/a class str_map(object):
335n/a def __init__(self):
336n/a self.data = {}
337n/a def __getitem__(self, key):
338n/a return self.data[str(key)]
339n/a def __setitem__(self, key, value):
340n/a self.data[str(key)] = value
341n/a def __delitem__(self, key):
342n/a del self.data[str(key)]
343n/a def __contains__(self, key):
344n/a return str(key) in self.data
345n/a d = str_map()
346n/a # Index
347n/a d[1] = 1
348n/a self.assertEqual(d[1], 1)
349n/a d[1] += 1
350n/a self.assertEqual(d[1], 2)
351n/a del d[1]
352n/a self.assertNotIn(1, d)
353n/a # Tuple of indices
354n/a d[1, 1] = 1
355n/a self.assertEqual(d[1, 1], 1)
356n/a d[1, 1] += 1
357n/a self.assertEqual(d[1, 1], 2)
358n/a del d[1, 1]
359n/a self.assertNotIn((1, 1), d)
360n/a # Simple slice
361n/a d[1:2] = 1
362n/a self.assertEqual(d[1:2], 1)
363n/a d[1:2] += 1
364n/a self.assertEqual(d[1:2], 2)
365n/a del d[1:2]
366n/a self.assertNotIn(slice(1, 2), d)
367n/a # Tuple of simple slices
368n/a d[1:2, 1:2] = 1
369n/a self.assertEqual(d[1:2, 1:2], 1)
370n/a d[1:2, 1:2] += 1
371n/a self.assertEqual(d[1:2, 1:2], 2)
372n/a del d[1:2, 1:2]
373n/a self.assertNotIn((slice(1, 2), slice(1, 2)), d)
374n/a # Extended slice
375n/a d[1:2:3] = 1
376n/a self.assertEqual(d[1:2:3], 1)
377n/a d[1:2:3] += 1
378n/a self.assertEqual(d[1:2:3], 2)
379n/a del d[1:2:3]
380n/a self.assertNotIn(slice(1, 2, 3), d)
381n/a # Tuple of extended slices
382n/a d[1:2:3, 1:2:3] = 1
383n/a self.assertEqual(d[1:2:3, 1:2:3], 1)
384n/a d[1:2:3, 1:2:3] += 1
385n/a self.assertEqual(d[1:2:3, 1:2:3], 2)
386n/a del d[1:2:3, 1:2:3]
387n/a self.assertNotIn((slice(1, 2, 3), slice(1, 2, 3)), d)
388n/a # Ellipsis
389n/a d[...] = 1
390n/a self.assertEqual(d[...], 1)
391n/a d[...] += 1
392n/a self.assertEqual(d[...], 2)
393n/a del d[...]
394n/a self.assertNotIn(Ellipsis, d)
395n/a # Tuple of Ellipses
396n/a d[..., ...] = 1
397n/a self.assertEqual(d[..., ...], 1)
398n/a d[..., ...] += 1
399n/a self.assertEqual(d[..., ...], 2)
400n/a del d[..., ...]
401n/a self.assertNotIn((Ellipsis, Ellipsis), d)
402n/a
403n/a def test_annotation_limit(self):
404n/a # more than 255 annotations, should compile ok
405n/a s = "def f(%s): pass"
406n/a s %= ', '.join('a%d:%d' % (i,i) for i in range(300))
407n/a compile(s, '?', 'exec')
408n/a
409n/a def test_mangling(self):
410n/a class A:
411n/a def f():
412n/a __mangled = 1
413n/a __not_mangled__ = 2
414n/a import __mangled_mod
415n/a import __package__.module
416n/a
417n/a self.assertIn("_A__mangled", A.f.__code__.co_varnames)
418n/a self.assertIn("__not_mangled__", A.f.__code__.co_varnames)
419n/a self.assertIn("_A__mangled_mod", A.f.__code__.co_varnames)
420n/a self.assertIn("__package__", A.f.__code__.co_varnames)
421n/a
422n/a def test_compile_ast(self):
423n/a fname = __file__
424n/a if fname.lower().endswith('pyc'):
425n/a fname = fname[:-1]
426n/a with open(fname, 'r') as f:
427n/a fcontents = f.read()
428n/a sample_code = [
429n/a ['<assign>', 'x = 5'],
430n/a ['<ifblock>', """if True:\n pass\n"""],
431n/a ['<forblock>', """for n in [1, 2, 3]:\n print(n)\n"""],
432n/a ['<deffunc>', """def foo():\n pass\nfoo()\n"""],
433n/a [fname, fcontents],
434n/a ]
435n/a
436n/a for fname, code in sample_code:
437n/a co1 = compile(code, '%s1' % fname, 'exec')
438n/a ast = compile(code, '%s2' % fname, 'exec', _ast.PyCF_ONLY_AST)
439n/a self.assertTrue(type(ast) == _ast.Module)
440n/a co2 = compile(ast, '%s3' % fname, 'exec')
441n/a self.assertEqual(co1, co2)
442n/a # the code object's filename comes from the second compilation step
443n/a self.assertEqual(co2.co_filename, '%s3' % fname)
444n/a
445n/a # raise exception when node type doesn't match with compile mode
446n/a co1 = compile('print(1)', '<string>', 'exec', _ast.PyCF_ONLY_AST)
447n/a self.assertRaises(TypeError, compile, co1, '<ast>', 'eval')
448n/a
449n/a # raise exception when node type is no start node
450n/a self.assertRaises(TypeError, compile, _ast.If(), '<ast>', 'exec')
451n/a
452n/a # raise exception when node has invalid children
453n/a ast = _ast.Module()
454n/a ast.body = [_ast.BoolOp()]
455n/a self.assertRaises(TypeError, compile, ast, '<ast>', 'exec')
456n/a
457n/a def test_dict_evaluation_order(self):
458n/a i = 0
459n/a
460n/a def f():
461n/a nonlocal i
462n/a i += 1
463n/a return i
464n/a
465n/a d = {f(): f(), f(): f()}
466n/a self.assertEqual(d, {1: 2, 3: 4})
467n/a
468n/a def test_compile_filename(self):
469n/a for filename in 'file.py', b'file.py':
470n/a code = compile('pass', filename, 'exec')
471n/a self.assertEqual(code.co_filename, 'file.py')
472n/a for filename in bytearray(b'file.py'), memoryview(b'file.py'):
473n/a with self.assertWarns(DeprecationWarning):
474n/a code = compile('pass', filename, 'exec')
475n/a self.assertEqual(code.co_filename, 'file.py')
476n/a self.assertRaises(TypeError, compile, 'pass', list(b'file.py'), 'exec')
477n/a
478n/a @support.cpython_only
479n/a def test_same_filename_used(self):
480n/a s = """def f(): pass\ndef g(): pass"""
481n/a c = compile(s, "myfile", "exec")
482n/a for obj in c.co_consts:
483n/a if isinstance(obj, types.CodeType):
484n/a self.assertIs(obj.co_filename, c.co_filename)
485n/a
486n/a def test_single_statement(self):
487n/a self.compile_single("1 + 2")
488n/a self.compile_single("\n1 + 2")
489n/a self.compile_single("1 + 2\n")
490n/a self.compile_single("1 + 2\n\n")
491n/a self.compile_single("1 + 2\t\t\n")
492n/a self.compile_single("1 + 2\t\t\n ")
493n/a self.compile_single("1 + 2 # one plus two")
494n/a self.compile_single("1; 2")
495n/a self.compile_single("import sys; sys")
496n/a self.compile_single("def f():\n pass")
497n/a self.compile_single("while False:\n pass")
498n/a self.compile_single("if x:\n f(x)")
499n/a self.compile_single("if x:\n f(x)\nelse:\n g(x)")
500n/a self.compile_single("class T:\n pass")
501n/a
502n/a def test_bad_single_statement(self):
503n/a self.assertInvalidSingle('1\n2')
504n/a self.assertInvalidSingle('def f(): pass')
505n/a self.assertInvalidSingle('a = 13\nb = 187')
506n/a self.assertInvalidSingle('del x\ndel y')
507n/a self.assertInvalidSingle('f()\ng()')
508n/a self.assertInvalidSingle('f()\n# blah\nblah()')
509n/a self.assertInvalidSingle('f()\nxy # blah\nblah()')
510n/a self.assertInvalidSingle('x = 5 # comment\nx = 6\n')
511n/a
512n/a def test_particularly_evil_undecodable(self):
513n/a # Issue 24022
514n/a src = b'0000\x00\n00000000000\n\x00\n\x9e\n'
515n/a with tempfile.TemporaryDirectory() as tmpd:
516n/a fn = os.path.join(tmpd, "bad.py")
517n/a with open(fn, "wb") as fp:
518n/a fp.write(src)
519n/a res = script_helper.run_python_until_end(fn)[0]
520n/a self.assertIn(b"Non-UTF-8", res.err)
521n/a
522n/a def test_yet_more_evil_still_undecodable(self):
523n/a # Issue #25388
524n/a src = b"#\x00\n#\xfd\n"
525n/a with tempfile.TemporaryDirectory() as tmpd:
526n/a fn = os.path.join(tmpd, "bad.py")
527n/a with open(fn, "wb") as fp:
528n/a fp.write(src)
529n/a res = script_helper.run_python_until_end(fn)[0]
530n/a self.assertIn(b"Non-UTF-8", res.err)
531n/a
532n/a @support.cpython_only
533n/a def test_compiler_recursion_limit(self):
534n/a # Expected limit is sys.getrecursionlimit() * the scaling factor
535n/a # in symtable.c (currently 3)
536n/a # We expect to fail *at* that limit, because we use up some of
537n/a # the stack depth limit in the test suite code
538n/a # So we check the expected limit and 75% of that
539n/a # XXX (ncoghlan): duplicating the scaling factor here is a little
540n/a # ugly. Perhaps it should be exposed somewhere...
541n/a fail_depth = sys.getrecursionlimit() * 3
542n/a success_depth = int(fail_depth * 0.75)
543n/a
544n/a def check_limit(prefix, repeated):
545n/a expect_ok = prefix + repeated * success_depth
546n/a self.compile_single(expect_ok)
547n/a broken = prefix + repeated * fail_depth
548n/a details = "Compiling ({!r} + {!r} * {})".format(
549n/a prefix, repeated, fail_depth)
550n/a with self.assertRaises(RecursionError, msg=details):
551n/a self.compile_single(broken)
552n/a
553n/a check_limit("a", "()")
554n/a check_limit("a", ".b")
555n/a check_limit("a", "[0]")
556n/a check_limit("a", "*a")
557n/a
558n/a def test_null_terminated(self):
559n/a # The source code is null-terminated internally, but bytes-like
560n/a # objects are accepted, which could be not terminated.
561n/a with self.assertRaisesRegex(ValueError, "cannot contain null"):
562n/a compile("123\x00", "<dummy>", "eval")
563n/a with self.assertRaisesRegex(ValueError, "cannot contain null"):
564n/a compile(memoryview(b"123\x00"), "<dummy>", "eval")
565n/a code = compile(memoryview(b"123\x00")[1:-1], "<dummy>", "eval")
566n/a self.assertEqual(eval(code), 23)
567n/a code = compile(memoryview(b"1234")[1:-1], "<dummy>", "eval")
568n/a self.assertEqual(eval(code), 23)
569n/a code = compile(memoryview(b"$23$")[1:-1], "<dummy>", "eval")
570n/a self.assertEqual(eval(code), 23)
571n/a
572n/a # Also test when eval() and exec() do the compilation step
573n/a self.assertEqual(eval(memoryview(b"1234")[1:-1]), 23)
574n/a namespace = dict()
575n/a exec(memoryview(b"ax = 123")[1:-1], namespace)
576n/a self.assertEqual(namespace['x'], 12)
577n/a
578n/a def check_constant(self, func, expected):
579n/a for const in func.__code__.co_consts:
580n/a if repr(const) == repr(expected):
581n/a break
582n/a else:
583n/a self.fail("unable to find constant %r in %r"
584n/a % (expected, func.__code__.co_consts))
585n/a
586n/a # Merging equal constants is not a strict requirement for the Python
587n/a # semantics, it's a more an implementation detail.
588n/a @support.cpython_only
589n/a def test_merge_constants(self):
590n/a # Issue #25843: compile() must merge constants which are equal
591n/a # and have the same type.
592n/a
593n/a def check_same_constant(const):
594n/a ns = {}
595n/a code = "f1, f2 = lambda: %r, lambda: %r" % (const, const)
596n/a exec(code, ns)
597n/a f1 = ns['f1']
598n/a f2 = ns['f2']
599n/a self.assertIs(f1.__code__, f2.__code__)
600n/a self.check_constant(f1, const)
601n/a self.assertEqual(repr(f1()), repr(const))
602n/a
603n/a check_same_constant(None)
604n/a check_same_constant(0)
605n/a check_same_constant(0.0)
606n/a check_same_constant(b'abc')
607n/a check_same_constant('abc')
608n/a
609n/a # Note: "lambda: ..." emits "LOAD_CONST Ellipsis",
610n/a # whereas "lambda: Ellipsis" emits "LOAD_GLOBAL Ellipsis"
611n/a f1, f2 = lambda: ..., lambda: ...
612n/a self.assertIs(f1.__code__, f2.__code__)
613n/a self.check_constant(f1, Ellipsis)
614n/a self.assertEqual(repr(f1()), repr(Ellipsis))
615n/a
616n/a # {0} is converted to a constant frozenset({0}) by the peephole
617n/a # optimizer
618n/a f1, f2 = lambda x: x in {0}, lambda x: x in {0}
619n/a self.assertIs(f1.__code__, f2.__code__)
620n/a self.check_constant(f1, frozenset({0}))
621n/a self.assertTrue(f1(0))
622n/a
623n/a def test_dont_merge_constants(self):
624n/a # Issue #25843: compile() must not merge constants which are equal
625n/a # but have a different type.
626n/a
627n/a def check_different_constants(const1, const2):
628n/a ns = {}
629n/a exec("f1, f2 = lambda: %r, lambda: %r" % (const1, const2), ns)
630n/a f1 = ns['f1']
631n/a f2 = ns['f2']
632n/a self.assertIsNot(f1.__code__, f2.__code__)
633n/a self.assertNotEqual(f1.__code__, f2.__code__)
634n/a self.check_constant(f1, const1)
635n/a self.check_constant(f2, const2)
636n/a self.assertEqual(repr(f1()), repr(const1))
637n/a self.assertEqual(repr(f2()), repr(const2))
638n/a
639n/a check_different_constants(0, 0.0)
640n/a check_different_constants(+0.0, -0.0)
641n/a check_different_constants((0,), (0.0,))
642n/a check_different_constants('a', b'a')
643n/a check_different_constants(('a',), (b'a',))
644n/a
645n/a # check_different_constants() cannot be used because repr(-0j) is
646n/a # '(-0-0j)', but when '(-0-0j)' is evaluated to 0j: we loose the sign.
647n/a f1, f2 = lambda: +0.0j, lambda: -0.0j
648n/a self.assertIsNot(f1.__code__, f2.__code__)
649n/a self.check_constant(f1, +0.0j)
650n/a self.check_constant(f2, -0.0j)
651n/a self.assertEqual(repr(f1()), repr(+0.0j))
652n/a self.assertEqual(repr(f2()), repr(-0.0j))
653n/a
654n/a # {0} is converted to a constant frozenset({0}) by the peephole
655n/a # optimizer
656n/a f1, f2 = lambda x: x in {0}, lambda x: x in {0.0}
657n/a self.assertIsNot(f1.__code__, f2.__code__)
658n/a self.check_constant(f1, frozenset({0}))
659n/a self.check_constant(f2, frozenset({0.0}))
660n/a self.assertTrue(f1(0))
661n/a self.assertTrue(f2(0.0))
662n/a
663n/a def test_path_like_objects(self):
664n/a # An implicit test for PyUnicode_FSDecoder().
665n/a class PathLike:
666n/a def __init__(self, path):
667n/a self._path = path
668n/a def __fspath__(self):
669n/a return self._path
670n/a
671n/a compile("42", PathLike("test_compile_pathlike"), "single")
672n/a
673n/a
674n/aclass TestStackSize(unittest.TestCase):
675n/a # These tests check that the computed stack size for a code object
676n/a # stays within reasonable bounds (see issue #21523 for an example
677n/a # dysfunction).
678n/a N = 100
679n/a
680n/a def check_stack_size(self, code):
681n/a # To assert that the alleged stack size is not O(N), we
682n/a # check that it is smaller than log(N).
683n/a if isinstance(code, str):
684n/a code = compile(code, "<foo>", "single")
685n/a max_size = math.ceil(math.log(len(code.co_code)))
686n/a self.assertLessEqual(code.co_stacksize, max_size)
687n/a
688n/a def test_and(self):
689n/a self.check_stack_size("x and " * self.N + "x")
690n/a
691n/a def test_or(self):
692n/a self.check_stack_size("x or " * self.N + "x")
693n/a
694n/a def test_and_or(self):
695n/a self.check_stack_size("x and x or " * self.N + "x")
696n/a
697n/a def test_chained_comparison(self):
698n/a self.check_stack_size("x < " * self.N + "x")
699n/a
700n/a def test_if_else(self):
701n/a self.check_stack_size("x if x else " * self.N + "x")
702n/a
703n/a def test_binop(self):
704n/a self.check_stack_size("x + " * self.N + "x")
705n/a
706n/a def test_func_and(self):
707n/a code = "def f(x):\n"
708n/a code += " x and x\n" * self.N
709n/a self.check_stack_size(code)
710n/a
711n/a
712n/aif __name__ == "__main__":
713n/a unittest.main()