1 | import parser
|
---|
2 | import unittest
|
---|
3 | import sys
|
---|
4 | import struct
|
---|
5 | from test import test_support as support
|
---|
6 | from test.script_helper import assert_python_failure
|
---|
7 |
|
---|
8 | #
|
---|
9 | # First, we test that we can generate trees from valid source fragments,
|
---|
10 | # and that these valid trees are indeed allowed by the tree-loading side
|
---|
11 | # of the parser module.
|
---|
12 | #
|
---|
13 |
|
---|
14 | class RoundtripLegalSyntaxTestCase(unittest.TestCase):
|
---|
15 |
|
---|
16 | def roundtrip(self, f, s):
|
---|
17 | st1 = f(s)
|
---|
18 | t = st1.totuple()
|
---|
19 | try:
|
---|
20 | st2 = parser.sequence2st(t)
|
---|
21 | except parser.ParserError, why:
|
---|
22 | self.fail("could not roundtrip %r: %s" % (s, why))
|
---|
23 |
|
---|
24 | self.assertEqual(t, st2.totuple(),
|
---|
25 | "could not re-generate syntax tree")
|
---|
26 |
|
---|
27 | def check_expr(self, s):
|
---|
28 | self.roundtrip(parser.expr, s)
|
---|
29 |
|
---|
30 | def test_flags_passed(self):
|
---|
31 | # The unicode literals flags has to be passed from the paser to AST
|
---|
32 | # generation.
|
---|
33 | suite = parser.suite("from __future__ import unicode_literals; x = ''")
|
---|
34 | code = suite.compile()
|
---|
35 | scope = {}
|
---|
36 | exec code in scope
|
---|
37 | self.assertIsInstance(scope["x"], unicode)
|
---|
38 |
|
---|
39 | def check_suite(self, s):
|
---|
40 | self.roundtrip(parser.suite, s)
|
---|
41 |
|
---|
42 | def test_yield_statement(self):
|
---|
43 | self.check_suite("def f(): yield 1")
|
---|
44 | self.check_suite("def f(): yield")
|
---|
45 | self.check_suite("def f(): x += yield")
|
---|
46 | self.check_suite("def f(): x = yield 1")
|
---|
47 | self.check_suite("def f(): x = y = yield 1")
|
---|
48 | self.check_suite("def f(): x = yield")
|
---|
49 | self.check_suite("def f(): x = y = yield")
|
---|
50 | self.check_suite("def f(): 1 + (yield)*2")
|
---|
51 | self.check_suite("def f(): (yield 1)*2")
|
---|
52 | self.check_suite("def f(): return; yield 1")
|
---|
53 | self.check_suite("def f(): yield 1; return")
|
---|
54 | self.check_suite("def f():\n"
|
---|
55 | " for x in range(30):\n"
|
---|
56 | " yield x\n")
|
---|
57 | self.check_suite("def f():\n"
|
---|
58 | " if (yield):\n"
|
---|
59 | " yield x\n")
|
---|
60 |
|
---|
61 | def test_expressions(self):
|
---|
62 | self.check_expr("foo(1)")
|
---|
63 | self.check_expr("{1:1}")
|
---|
64 | self.check_expr("{1:1, 2:2, 3:3}")
|
---|
65 | self.check_expr("{1:1, 2:2, 3:3,}")
|
---|
66 | self.check_expr("{1}")
|
---|
67 | self.check_expr("{1, 2, 3}")
|
---|
68 | self.check_expr("{1, 2, 3,}")
|
---|
69 | self.check_expr("[]")
|
---|
70 | self.check_expr("[1]")
|
---|
71 | self.check_expr("[1, 2, 3]")
|
---|
72 | self.check_expr("[1, 2, 3,]")
|
---|
73 | self.check_expr("()")
|
---|
74 | self.check_expr("(1,)")
|
---|
75 | self.check_expr("(1, 2, 3)")
|
---|
76 | self.check_expr("(1, 2, 3,)")
|
---|
77 | self.check_expr("[x**3 for x in range(20)]")
|
---|
78 | self.check_expr("[x**3 for x in range(20) if x % 3]")
|
---|
79 | self.check_expr("[x**3 for x in range(20) if x % 2 if x % 3]")
|
---|
80 | self.check_expr("[x+y for x in range(30) for y in range(20) if x % 2 if y % 3]")
|
---|
81 | #self.check_expr("[x for x in lambda: True, lambda: False if x()]")
|
---|
82 | self.check_expr("list(x**3 for x in range(20))")
|
---|
83 | self.check_expr("list(x**3 for x in range(20) if x % 3)")
|
---|
84 | self.check_expr("list(x**3 for x in range(20) if x % 2 if x % 3)")
|
---|
85 | self.check_expr("list(x+y for x in range(30) for y in range(20) if x % 2 if y % 3)")
|
---|
86 | self.check_expr("{x**3 for x in range(30)}")
|
---|
87 | self.check_expr("{x**3 for x in range(30) if x % 3}")
|
---|
88 | self.check_expr("{x**3 for x in range(30) if x % 2 if x % 3}")
|
---|
89 | self.check_expr("{x+y for x in range(30) for y in range(20) if x % 2 if y % 3}")
|
---|
90 | self.check_expr("{x**3: y**2 for x, y in zip(range(30), range(30))}")
|
---|
91 | self.check_expr("{x**3: y**2 for x, y in zip(range(30), range(30)) if x % 3}")
|
---|
92 | self.check_expr("{x**3: y**2 for x, y in zip(range(30), range(30)) if x % 3 if y % 3}")
|
---|
93 | self.check_expr("{x:y for x in range(30) for y in range(20) if x % 2 if y % 3}")
|
---|
94 | self.check_expr("foo(*args)")
|
---|
95 | self.check_expr("foo(*args, **kw)")
|
---|
96 | self.check_expr("foo(**kw)")
|
---|
97 | self.check_expr("foo(key=value)")
|
---|
98 | self.check_expr("foo(key=value, *args)")
|
---|
99 | self.check_expr("foo(key=value, *args, **kw)")
|
---|
100 | self.check_expr("foo(key=value, **kw)")
|
---|
101 | self.check_expr("foo(a, b, c, *args)")
|
---|
102 | self.check_expr("foo(a, b, c, *args, **kw)")
|
---|
103 | self.check_expr("foo(a, b, c, **kw)")
|
---|
104 | self.check_expr("foo(a, *args, keyword=23)")
|
---|
105 | self.check_expr("foo + bar")
|
---|
106 | self.check_expr("foo - bar")
|
---|
107 | self.check_expr("foo * bar")
|
---|
108 | self.check_expr("foo / bar")
|
---|
109 | self.check_expr("foo // bar")
|
---|
110 | self.check_expr("lambda: 0")
|
---|
111 | self.check_expr("lambda x: 0")
|
---|
112 | self.check_expr("lambda *y: 0")
|
---|
113 | self.check_expr("lambda *y, **z: 0")
|
---|
114 | self.check_expr("lambda **z: 0")
|
---|
115 | self.check_expr("lambda x, y: 0")
|
---|
116 | self.check_expr("lambda foo=bar: 0")
|
---|
117 | self.check_expr("lambda foo=bar, spaz=nifty+spit: 0")
|
---|
118 | self.check_expr("lambda foo=bar, **z: 0")
|
---|
119 | self.check_expr("lambda foo=bar, blaz=blat+2, **z: 0")
|
---|
120 | self.check_expr("lambda foo=bar, blaz=blat+2, *y, **z: 0")
|
---|
121 | self.check_expr("lambda x, *y, **z: 0")
|
---|
122 | self.check_expr("lambda x: 5 if x else 2")
|
---|
123 | self.check_expr("(x for x in range(10))")
|
---|
124 | self.check_expr("foo(x for x in range(10))")
|
---|
125 |
|
---|
126 | def test_print(self):
|
---|
127 | self.check_suite("print")
|
---|
128 | self.check_suite("print 1")
|
---|
129 | self.check_suite("print 1,")
|
---|
130 | self.check_suite("print >>fp")
|
---|
131 | self.check_suite("print >>fp, 1")
|
---|
132 | self.check_suite("print >>fp, 1,")
|
---|
133 |
|
---|
134 | def test_simple_expression(self):
|
---|
135 | # expr_stmt
|
---|
136 | self.check_suite("a")
|
---|
137 |
|
---|
138 | def test_simple_assignments(self):
|
---|
139 | self.check_suite("a = b")
|
---|
140 | self.check_suite("a = b = c = d = e")
|
---|
141 |
|
---|
142 | def test_simple_augmented_assignments(self):
|
---|
143 | self.check_suite("a += b")
|
---|
144 | self.check_suite("a -= b")
|
---|
145 | self.check_suite("a *= b")
|
---|
146 | self.check_suite("a /= b")
|
---|
147 | self.check_suite("a //= b")
|
---|
148 | self.check_suite("a %= b")
|
---|
149 | self.check_suite("a &= b")
|
---|
150 | self.check_suite("a |= b")
|
---|
151 | self.check_suite("a ^= b")
|
---|
152 | self.check_suite("a <<= b")
|
---|
153 | self.check_suite("a >>= b")
|
---|
154 | self.check_suite("a **= b")
|
---|
155 |
|
---|
156 | def test_function_defs(self):
|
---|
157 | self.check_suite("def f(): pass")
|
---|
158 | self.check_suite("def f(*args): pass")
|
---|
159 | self.check_suite("def f(*args, **kw): pass")
|
---|
160 | self.check_suite("def f(**kw): pass")
|
---|
161 | self.check_suite("def f(foo=bar): pass")
|
---|
162 | self.check_suite("def f(foo=bar, *args): pass")
|
---|
163 | self.check_suite("def f(foo=bar, *args, **kw): pass")
|
---|
164 | self.check_suite("def f(foo=bar, **kw): pass")
|
---|
165 |
|
---|
166 | self.check_suite("def f(a, b): pass")
|
---|
167 | self.check_suite("def f(a, b, *args): pass")
|
---|
168 | self.check_suite("def f(a, b, *args, **kw): pass")
|
---|
169 | self.check_suite("def f(a, b, **kw): pass")
|
---|
170 | self.check_suite("def f(a, b, foo=bar): pass")
|
---|
171 | self.check_suite("def f(a, b, foo=bar, *args): pass")
|
---|
172 | self.check_suite("def f(a, b, foo=bar, *args, **kw): pass")
|
---|
173 | self.check_suite("def f(a, b, foo=bar, **kw): pass")
|
---|
174 |
|
---|
175 | self.check_suite("@staticmethod\n"
|
---|
176 | "def f(): pass")
|
---|
177 | self.check_suite("@staticmethod\n"
|
---|
178 | "@funcattrs(x, y)\n"
|
---|
179 | "def f(): pass")
|
---|
180 | self.check_suite("@funcattrs()\n"
|
---|
181 | "def f(): pass")
|
---|
182 |
|
---|
183 | def test_class_defs(self):
|
---|
184 | self.check_suite("class foo():pass")
|
---|
185 | self.check_suite("@class_decorator\n"
|
---|
186 | "class foo():pass")
|
---|
187 | self.check_suite("@class_decorator(arg)\n"
|
---|
188 | "class foo():pass")
|
---|
189 | self.check_suite("@decorator1\n"
|
---|
190 | "@decorator2\n"
|
---|
191 | "class foo():pass")
|
---|
192 |
|
---|
193 |
|
---|
194 | def test_import_from_statement(self):
|
---|
195 | self.check_suite("from sys.path import *")
|
---|
196 | self.check_suite("from sys.path import dirname")
|
---|
197 | self.check_suite("from sys.path import (dirname)")
|
---|
198 | self.check_suite("from sys.path import (dirname,)")
|
---|
199 | self.check_suite("from sys.path import dirname as my_dirname")
|
---|
200 | self.check_suite("from sys.path import (dirname as my_dirname)")
|
---|
201 | self.check_suite("from sys.path import (dirname as my_dirname,)")
|
---|
202 | self.check_suite("from sys.path import dirname, basename")
|
---|
203 | self.check_suite("from sys.path import (dirname, basename)")
|
---|
204 | self.check_suite("from sys.path import (dirname, basename,)")
|
---|
205 | self.check_suite(
|
---|
206 | "from sys.path import dirname as my_dirname, basename")
|
---|
207 | self.check_suite(
|
---|
208 | "from sys.path import (dirname as my_dirname, basename)")
|
---|
209 | self.check_suite(
|
---|
210 | "from sys.path import (dirname as my_dirname, basename,)")
|
---|
211 | self.check_suite(
|
---|
212 | "from sys.path import dirname, basename as my_basename")
|
---|
213 | self.check_suite(
|
---|
214 | "from sys.path import (dirname, basename as my_basename)")
|
---|
215 | self.check_suite(
|
---|
216 | "from sys.path import (dirname, basename as my_basename,)")
|
---|
217 | self.check_suite("from .bogus import x")
|
---|
218 |
|
---|
219 | def test_basic_import_statement(self):
|
---|
220 | self.check_suite("import sys")
|
---|
221 | self.check_suite("import sys as system")
|
---|
222 | self.check_suite("import sys, math")
|
---|
223 | self.check_suite("import sys as system, math")
|
---|
224 | self.check_suite("import sys, math as my_math")
|
---|
225 |
|
---|
226 | def test_relative_imports(self):
|
---|
227 | self.check_suite("from . import name")
|
---|
228 | self.check_suite("from .. import name")
|
---|
229 | self.check_suite("from .pkg import name")
|
---|
230 | self.check_suite("from ..pkg import name")
|
---|
231 |
|
---|
232 | def test_pep263(self):
|
---|
233 | self.check_suite("# -*- coding: iso-8859-1 -*-\n"
|
---|
234 | "pass\n")
|
---|
235 |
|
---|
236 | def test_assert(self):
|
---|
237 | self.check_suite("assert alo < ahi and blo < bhi\n")
|
---|
238 |
|
---|
239 | def test_with(self):
|
---|
240 | self.check_suite("with open('x'): pass\n")
|
---|
241 | self.check_suite("with open('x') as f: pass\n")
|
---|
242 | self.check_suite("with open('x') as f, open('y') as g: pass\n")
|
---|
243 |
|
---|
244 | def test_try_stmt(self):
|
---|
245 | self.check_suite("try: pass\nexcept: pass\n")
|
---|
246 | self.check_suite("try: pass\nfinally: pass\n")
|
---|
247 | self.check_suite("try: pass\nexcept A: pass\nfinally: pass\n")
|
---|
248 | self.check_suite("try: pass\nexcept A: pass\nexcept: pass\n"
|
---|
249 | "finally: pass\n")
|
---|
250 | self.check_suite("try: pass\nexcept: pass\nelse: pass\n")
|
---|
251 | self.check_suite("try: pass\nexcept: pass\nelse: pass\n"
|
---|
252 | "finally: pass\n")
|
---|
253 |
|
---|
254 | def test_except_clause(self):
|
---|
255 | self.check_suite("try: pass\nexcept: pass\n")
|
---|
256 | self.check_suite("try: pass\nexcept A: pass\n")
|
---|
257 | self.check_suite("try: pass\nexcept A, e: pass\n")
|
---|
258 | self.check_suite("try: pass\nexcept A as e: pass\n")
|
---|
259 |
|
---|
260 | def test_position(self):
|
---|
261 | # An absolutely minimal test of position information. Better
|
---|
262 | # tests would be a big project.
|
---|
263 | code = "def f(x):\n return x + 1"
|
---|
264 | st1 = parser.suite(code)
|
---|
265 | st2 = st1.totuple(line_info=1, col_info=1)
|
---|
266 |
|
---|
267 | def walk(tree):
|
---|
268 | node_type = tree[0]
|
---|
269 | next = tree[1]
|
---|
270 | if isinstance(next, tuple):
|
---|
271 | for elt in tree[1:]:
|
---|
272 | for x in walk(elt):
|
---|
273 | yield x
|
---|
274 | else:
|
---|
275 | yield tree
|
---|
276 |
|
---|
277 | terminals = list(walk(st2))
|
---|
278 | self.assertEqual([
|
---|
279 | (1, 'def', 1, 0),
|
---|
280 | (1, 'f', 1, 4),
|
---|
281 | (7, '(', 1, 5),
|
---|
282 | (1, 'x', 1, 6),
|
---|
283 | (8, ')', 1, 7),
|
---|
284 | (11, ':', 1, 8),
|
---|
285 | (4, '', 1, 9),
|
---|
286 | (5, '', 2, -1),
|
---|
287 | (1, 'return', 2, 4),
|
---|
288 | (1, 'x', 2, 11),
|
---|
289 | (14, '+', 2, 13),
|
---|
290 | (2, '1', 2, 15),
|
---|
291 | (4, '', 2, 16),
|
---|
292 | (6, '', 2, -1),
|
---|
293 | (4, '', 2, -1),
|
---|
294 | (0, '', 2, -1)],
|
---|
295 | terminals)
|
---|
296 |
|
---|
297 |
|
---|
298 | #
|
---|
299 | # Second, we take *invalid* trees and make sure we get ParserError
|
---|
300 | # rejections for them.
|
---|
301 | #
|
---|
302 |
|
---|
303 | class IllegalSyntaxTestCase(unittest.TestCase):
|
---|
304 |
|
---|
305 | def check_bad_tree(self, tree, label):
|
---|
306 | try:
|
---|
307 | parser.sequence2st(tree)
|
---|
308 | except parser.ParserError:
|
---|
309 | pass
|
---|
310 | else:
|
---|
311 | self.fail("did not detect invalid tree for %r" % label)
|
---|
312 |
|
---|
313 | def test_junk(self):
|
---|
314 | # not even remotely valid:
|
---|
315 | self.check_bad_tree((1, 2, 3), "<junk>")
|
---|
316 |
|
---|
317 | def test_illegal_yield_1(self):
|
---|
318 | # Illegal yield statement: def f(): return 1; yield 1
|
---|
319 | tree = \
|
---|
320 | (257,
|
---|
321 | (264,
|
---|
322 | (285,
|
---|
323 | (259,
|
---|
324 | (1, 'def'),
|
---|
325 | (1, 'f'),
|
---|
326 | (260, (7, '('), (8, ')')),
|
---|
327 | (11, ':'),
|
---|
328 | (291,
|
---|
329 | (4, ''),
|
---|
330 | (5, ''),
|
---|
331 | (264,
|
---|
332 | (265,
|
---|
333 | (266,
|
---|
334 | (272,
|
---|
335 | (275,
|
---|
336 | (1, 'return'),
|
---|
337 | (313,
|
---|
338 | (292,
|
---|
339 | (293,
|
---|
340 | (294,
|
---|
341 | (295,
|
---|
342 | (297,
|
---|
343 | (298,
|
---|
344 | (299,
|
---|
345 | (300,
|
---|
346 | (301,
|
---|
347 | (302, (303, (304, (305, (2, '1')))))))))))))))))),
|
---|
348 | (264,
|
---|
349 | (265,
|
---|
350 | (266,
|
---|
351 | (272,
|
---|
352 | (276,
|
---|
353 | (1, 'yield'),
|
---|
354 | (313,
|
---|
355 | (292,
|
---|
356 | (293,
|
---|
357 | (294,
|
---|
358 | (295,
|
---|
359 | (297,
|
---|
360 | (298,
|
---|
361 | (299,
|
---|
362 | (300,
|
---|
363 | (301,
|
---|
364 | (302,
|
---|
365 | (303, (304, (305, (2, '1')))))))))))))))))),
|
---|
366 | (4, ''))),
|
---|
367 | (6, ''))))),
|
---|
368 | (4, ''),
|
---|
369 | (0, ''))))
|
---|
370 | self.check_bad_tree(tree, "def f():\n return 1\n yield 1")
|
---|
371 |
|
---|
372 | def test_illegal_yield_2(self):
|
---|
373 | # Illegal return in generator: def f(): return 1; yield 1
|
---|
374 | tree = \
|
---|
375 | (257,
|
---|
376 | (264,
|
---|
377 | (265,
|
---|
378 | (266,
|
---|
379 | (278,
|
---|
380 | (1, 'from'),
|
---|
381 | (281, (1, '__future__')),
|
---|
382 | (1, 'import'),
|
---|
383 | (279, (1, 'generators')))),
|
---|
384 | (4, ''))),
|
---|
385 | (264,
|
---|
386 | (285,
|
---|
387 | (259,
|
---|
388 | (1, 'def'),
|
---|
389 | (1, 'f'),
|
---|
390 | (260, (7, '('), (8, ')')),
|
---|
391 | (11, ':'),
|
---|
392 | (291,
|
---|
393 | (4, ''),
|
---|
394 | (5, ''),
|
---|
395 | (264,
|
---|
396 | (265,
|
---|
397 | (266,
|
---|
398 | (272,
|
---|
399 | (275,
|
---|
400 | (1, 'return'),
|
---|
401 | (313,
|
---|
402 | (292,
|
---|
403 | (293,
|
---|
404 | (294,
|
---|
405 | (295,
|
---|
406 | (297,
|
---|
407 | (298,
|
---|
408 | (299,
|
---|
409 | (300,
|
---|
410 | (301,
|
---|
411 | (302, (303, (304, (305, (2, '1')))))))))))))))))),
|
---|
412 | (264,
|
---|
413 | (265,
|
---|
414 | (266,
|
---|
415 | (272,
|
---|
416 | (276,
|
---|
417 | (1, 'yield'),
|
---|
418 | (313,
|
---|
419 | (292,
|
---|
420 | (293,
|
---|
421 | (294,
|
---|
422 | (295,
|
---|
423 | (297,
|
---|
424 | (298,
|
---|
425 | (299,
|
---|
426 | (300,
|
---|
427 | (301,
|
---|
428 | (302,
|
---|
429 | (303, (304, (305, (2, '1')))))))))))))))))),
|
---|
430 | (4, ''))),
|
---|
431 | (6, ''))))),
|
---|
432 | (4, ''),
|
---|
433 | (0, ''))))
|
---|
434 | self.check_bad_tree(tree, "def f():\n return 1\n yield 1")
|
---|
435 |
|
---|
436 | def test_print_chevron_comma(self):
|
---|
437 | # Illegal input: print >>fp,
|
---|
438 | tree = \
|
---|
439 | (257,
|
---|
440 | (264,
|
---|
441 | (265,
|
---|
442 | (266,
|
---|
443 | (268,
|
---|
444 | (1, 'print'),
|
---|
445 | (35, '>>'),
|
---|
446 | (290,
|
---|
447 | (291,
|
---|
448 | (292,
|
---|
449 | (293,
|
---|
450 | (295,
|
---|
451 | (296,
|
---|
452 | (297,
|
---|
453 | (298, (299, (300, (301, (302, (303, (1, 'fp')))))))))))))),
|
---|
454 | (12, ','))),
|
---|
455 | (4, ''))),
|
---|
456 | (0, ''))
|
---|
457 | self.check_bad_tree(tree, "print >>fp,")
|
---|
458 |
|
---|
459 | def test_a_comma_comma_c(self):
|
---|
460 | # Illegal input: a,,c
|
---|
461 | tree = \
|
---|
462 | (258,
|
---|
463 | (311,
|
---|
464 | (290,
|
---|
465 | (291,
|
---|
466 | (292,
|
---|
467 | (293,
|
---|
468 | (295,
|
---|
469 | (296,
|
---|
470 | (297,
|
---|
471 | (298, (299, (300, (301, (302, (303, (1, 'a')))))))))))))),
|
---|
472 | (12, ','),
|
---|
473 | (12, ','),
|
---|
474 | (290,
|
---|
475 | (291,
|
---|
476 | (292,
|
---|
477 | (293,
|
---|
478 | (295,
|
---|
479 | (296,
|
---|
480 | (297,
|
---|
481 | (298, (299, (300, (301, (302, (303, (1, 'c'))))))))))))))),
|
---|
482 | (4, ''),
|
---|
483 | (0, ''))
|
---|
484 | self.check_bad_tree(tree, "a,,c")
|
---|
485 |
|
---|
486 | def test_illegal_operator(self):
|
---|
487 | # Illegal input: a $= b
|
---|
488 | tree = \
|
---|
489 | (257,
|
---|
490 | (264,
|
---|
491 | (265,
|
---|
492 | (266,
|
---|
493 | (267,
|
---|
494 | (312,
|
---|
495 | (291,
|
---|
496 | (292,
|
---|
497 | (293,
|
---|
498 | (294,
|
---|
499 | (296,
|
---|
500 | (297,
|
---|
501 | (298,
|
---|
502 | (299,
|
---|
503 | (300, (301, (302, (303, (304, (1, 'a'))))))))))))))),
|
---|
504 | (268, (37, '$=')),
|
---|
505 | (312,
|
---|
506 | (291,
|
---|
507 | (292,
|
---|
508 | (293,
|
---|
509 | (294,
|
---|
510 | (296,
|
---|
511 | (297,
|
---|
512 | (298,
|
---|
513 | (299,
|
---|
514 | (300, (301, (302, (303, (304, (1, 'b'))))))))))))))))),
|
---|
515 | (4, ''))),
|
---|
516 | (0, ''))
|
---|
517 | self.check_bad_tree(tree, "a $= b")
|
---|
518 |
|
---|
519 | def test_malformed_global(self):
|
---|
520 | #doesn't have global keyword in ast
|
---|
521 | tree = (257,
|
---|
522 | (264,
|
---|
523 | (265,
|
---|
524 | (266,
|
---|
525 | (282, (1, 'foo'))), (4, ''))),
|
---|
526 | (4, ''),
|
---|
527 | (0, ''))
|
---|
528 | self.check_bad_tree(tree, "malformed global ast")
|
---|
529 |
|
---|
530 | def test_missing_import_source(self):
|
---|
531 | # from import a
|
---|
532 | tree = \
|
---|
533 | (257,
|
---|
534 | (267,
|
---|
535 | (268,
|
---|
536 | (269,
|
---|
537 | (281,
|
---|
538 | (283, (1, 'from'), (1, 'import'),
|
---|
539 | (286, (284, (1, 'fred')))))),
|
---|
540 | (4, ''))),
|
---|
541 | (4, ''), (0, ''))
|
---|
542 | self.check_bad_tree(tree, "from import a")
|
---|
543 |
|
---|
544 |
|
---|
545 | class CompileTestCase(unittest.TestCase):
|
---|
546 |
|
---|
547 | # These tests are very minimal. :-(
|
---|
548 |
|
---|
549 | def test_compile_expr(self):
|
---|
550 | st = parser.expr('2 + 3')
|
---|
551 | code = parser.compilest(st)
|
---|
552 | self.assertEqual(eval(code), 5)
|
---|
553 |
|
---|
554 | def test_compile_suite(self):
|
---|
555 | st = parser.suite('x = 2; y = x + 3')
|
---|
556 | code = parser.compilest(st)
|
---|
557 | globs = {}
|
---|
558 | exec code in globs
|
---|
559 | self.assertEqual(globs['y'], 5)
|
---|
560 |
|
---|
561 | def test_compile_error(self):
|
---|
562 | st = parser.suite('1 = 3 + 4')
|
---|
563 | self.assertRaises(SyntaxError, parser.compilest, st)
|
---|
564 |
|
---|
565 | def test_compile_badunicode(self):
|
---|
566 | st = parser.suite('a = u"\U12345678"')
|
---|
567 | self.assertRaises(SyntaxError, parser.compilest, st)
|
---|
568 | st = parser.suite('a = u"\u1"')
|
---|
569 | self.assertRaises(SyntaxError, parser.compilest, st)
|
---|
570 |
|
---|
571 | def test_issue_9011(self):
|
---|
572 | # Issue 9011: compilation of an unary minus expression changed
|
---|
573 | # the meaning of the ST, so that a second compilation produced
|
---|
574 | # incorrect results.
|
---|
575 | st = parser.expr('-3')
|
---|
576 | code1 = parser.compilest(st)
|
---|
577 | self.assertEqual(eval(code1), -3)
|
---|
578 | code2 = parser.compilest(st)
|
---|
579 | self.assertEqual(eval(code2), -3)
|
---|
580 |
|
---|
581 |
|
---|
582 | class ParserStackLimitTestCase(unittest.TestCase):
|
---|
583 | """try to push the parser to/over its limits.
|
---|
584 | see http://bugs.python.org/issue1881 for a discussion
|
---|
585 | """
|
---|
586 | def _nested_expression(self, level):
|
---|
587 | return "["*level+"]"*level
|
---|
588 |
|
---|
589 | def test_deeply_nested_list(self):
|
---|
590 | e = self._nested_expression(99)
|
---|
591 | st = parser.expr(e)
|
---|
592 | st.compile()
|
---|
593 |
|
---|
594 | def test_trigger_memory_error(self):
|
---|
595 | e = self._nested_expression(100)
|
---|
596 | rc, out, err = assert_python_failure('-c', e)
|
---|
597 | # parsing the expression will result in an error message
|
---|
598 | # followed by a MemoryError (see #11963)
|
---|
599 | self.assertIn(b's_push: parser stack overflow', err)
|
---|
600 | self.assertIn(b'MemoryError', err)
|
---|
601 |
|
---|
602 | class STObjectTestCase(unittest.TestCase):
|
---|
603 | """Test operations on ST objects themselves"""
|
---|
604 |
|
---|
605 | check_sizeof = support.check_sizeof
|
---|
606 |
|
---|
607 | @support.cpython_only
|
---|
608 | def test_sizeof(self):
|
---|
609 | def XXXROUNDUP(n):
|
---|
610 | if n <= 1:
|
---|
611 | return n
|
---|
612 | if n <= 128:
|
---|
613 | return (n + 3) & ~3
|
---|
614 | return 1 << (n - 1).bit_length()
|
---|
615 |
|
---|
616 | basesize = support.calcobjsize('Pii')
|
---|
617 | nodesize = struct.calcsize('hP3iP0h')
|
---|
618 | def sizeofchildren(node):
|
---|
619 | if node is None:
|
---|
620 | return 0
|
---|
621 | res = 0
|
---|
622 | hasstr = len(node) > 1 and isinstance(node[-1], str)
|
---|
623 | if hasstr:
|
---|
624 | res += len(node[-1]) + 1
|
---|
625 | children = node[1:-1] if hasstr else node[1:]
|
---|
626 | if children:
|
---|
627 | res += XXXROUNDUP(len(children)) * nodesize
|
---|
628 | for child in children:
|
---|
629 | res += sizeofchildren(child)
|
---|
630 | return res
|
---|
631 |
|
---|
632 | def check_st_sizeof(st):
|
---|
633 | self.check_sizeof(st, basesize + nodesize +
|
---|
634 | sizeofchildren(st.totuple()))
|
---|
635 |
|
---|
636 | check_st_sizeof(parser.expr('2 + 3'))
|
---|
637 | check_st_sizeof(parser.expr('2 + 3 + 4'))
|
---|
638 | check_st_sizeof(parser.suite('x = 2 + 3'))
|
---|
639 | check_st_sizeof(parser.suite(''))
|
---|
640 | check_st_sizeof(parser.suite('# -*- coding: utf-8 -*-'))
|
---|
641 | check_st_sizeof(parser.expr('[' + '2,' * 1000 + ']'))
|
---|
642 |
|
---|
643 |
|
---|
644 | # XXX tests for pickling and unpickling of ST objects should go here
|
---|
645 |
|
---|
646 | def test_main():
|
---|
647 | support.run_unittest(
|
---|
648 | RoundtripLegalSyntaxTestCase,
|
---|
649 | IllegalSyntaxTestCase,
|
---|
650 | CompileTestCase,
|
---|
651 | ParserStackLimitTestCase,
|
---|
652 | STObjectTestCase,
|
---|
653 | )
|
---|
654 |
|
---|
655 |
|
---|
656 | if __name__ == "__main__":
|
---|
657 | test_main()
|
---|