1 import parser 2 import unittest 3 import operator 4 import struct 5 from test import support 6 from test.support.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 as 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, {}, scope) 37 self.assertIsInstance(scope["x"], str) 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(): yield from 1") 55 self.check_suite("def f(): x = yield from 1") 56 self.check_suite("def f(): f((yield from 1))") 57 self.check_suite("def f(): yield 1; return 1") 58 self.check_suite("def f():\n" 59 " for x in range(30):\n" 60 " yield x\n") 61 self.check_suite("def f():\n" 62 " if (yield):\n" 63 " yield x\n") 64 65 def test_await_statement(self): 66 self.check_suite("async def f():\n await smth()") 67 self.check_suite("async def f():\n foo = await smth()") 68 self.check_suite("async def f():\n foo, bar = await smth()") 69 self.check_suite("async def f():\n (await smth())") 70 self.check_suite("async def f():\n foo((await smth()))") 71 self.check_suite("async def f():\n await foo(); return 42") 72 73 def test_async_with_statement(self): 74 self.check_suite("async def f():\n async with 1: pass") 75 self.check_suite("async def f():\n async with a as b, c as d: pass") 76 77 def test_async_for_statement(self): 78 self.check_suite("async def f():\n async for i in (): pass") 79 self.check_suite("async def f():\n async for i, b in (): pass") 80 81 def test_nonlocal_statement(self): 82 self.check_suite("def f():\n" 83 " x = 0\n" 84 " def g():\n" 85 " nonlocal x\n") 86 self.check_suite("def f():\n" 87 " x = y = 0\n" 88 " def g():\n" 89 " nonlocal x, y\n") 90 91 def test_expressions(self): 92 self.check_expr("foo(1)") 93 self.check_expr("[1, 2, 3]") 94 self.check_expr("[x**3 for x in range(20)]") 95 self.check_expr("[x**3 for x in range(20) if x % 3]") 96 self.check_expr("[x**3 for x in range(20) if x % 2 if x % 3]") 97 self.check_expr("list(x**3 for x in range(20))") 98 self.check_expr("list(x**3 for x in range(20) if x % 3)") 99 self.check_expr("list(x**3 for x in range(20) if x % 2 if x % 3)") 100 self.check_expr("foo(*args)") 101 self.check_expr("foo(*args, **kw)") 102 self.check_expr("foo(**kw)") 103 self.check_expr("foo(key=value)") 104 self.check_expr("foo(key=value, *args)") 105 self.check_expr("foo(key=value, *args, **kw)") 106 self.check_expr("foo(key=value, **kw)") 107 self.check_expr("foo(a, b, c, *args)") 108 self.check_expr("foo(a, b, c, *args, **kw)") 109 self.check_expr("foo(a, b, c, **kw)") 110 self.check_expr("foo(a, *args, keyword=23)") 111 self.check_expr("foo + bar") 112 self.check_expr("foo - bar") 113 self.check_expr("foo * bar") 114 self.check_expr("foo / bar") 115 self.check_expr("foo // bar") 116 self.check_expr("lambda: 0") 117 self.check_expr("lambda x: 0") 118 self.check_expr("lambda *y: 0") 119 self.check_expr("lambda *y, **z: 0") 120 self.check_expr("lambda **z: 0") 121 self.check_expr("lambda x, y: 0") 122 self.check_expr("lambda foo=bar: 0") 123 self.check_expr("lambda foo=bar, spaz=nifty+spit: 0") 124 self.check_expr("lambda foo=bar, **z: 0") 125 self.check_expr("lambda foo=bar, blaz=blat+2, **z: 0") 126 self.check_expr("lambda foo=bar, blaz=blat+2, *y, **z: 0") 127 self.check_expr("lambda x, *y, **z: 0") 128 self.check_expr("(x for x in range(10))") 129 self.check_expr("foo(x for x in range(10))") 130 self.check_expr("...") 131 self.check_expr("a[...]") 132 133 def test_simple_expression(self): 134 # expr_stmt 135 self.check_suite("a") 136 137 def test_simple_assignments(self): 138 self.check_suite("a = b") 139 self.check_suite("a = b = c = d = e") 140 141 def test_var_annot(self): 142 self.check_suite("x: int = 5") 143 self.check_suite("y: List[T] = []; z: [list] = fun()") 144 self.check_suite("x: tuple = (1, 2)") 145 self.check_suite("d[f()]: int = 42") 146 self.check_suite("f(d[x]): str = 'abc'") 147 self.check_suite("x.y.z.w: complex = 42j") 148 self.check_suite("x: int") 149 self.check_suite("def f():\n" 150 " x: str\n" 151 " y: int = 5\n") 152 self.check_suite("class C:\n" 153 " x: str\n" 154 " y: int = 5\n") 155 self.check_suite("class C:\n" 156 " def __init__(self, x: int) -> None:\n" 157 " self.x: int = x\n") 158 # double check for nonsense 159 with self.assertRaises(SyntaxError): 160 exec("2+2: int", {}, {}) 161 with self.assertRaises(SyntaxError): 162 exec("[]: int = 5", {}, {}) 163 with self.assertRaises(SyntaxError): 164 exec("x, *y, z: int = range(5)", {}, {}) 165 with self.assertRaises(SyntaxError): 166 exec("t: tuple = 1, 2", {}, {}) 167 with self.assertRaises(SyntaxError): 168 exec("u = v: int", {}, {}) 169 with self.assertRaises(SyntaxError): 170 exec("False: int", {}, {}) 171 with self.assertRaises(SyntaxError): 172 exec("x.False: int", {}, {}) 173 with self.assertRaises(SyntaxError): 174 exec("x.y,: int", {}, {}) 175 with self.assertRaises(SyntaxError): 176 exec("[0]: int", {}, {}) 177 with self.assertRaises(SyntaxError): 178 exec("f(): int", {}, {}) 179 180 def test_simple_augmented_assignments(self): 181 self.check_suite("a += b") 182 self.check_suite("a -= b") 183 self.check_suite("a *= b") 184 self.check_suite("a /= b") 185 self.check_suite("a //= b") 186 self.check_suite("a %= b") 187 self.check_suite("a &= b") 188 self.check_suite("a |= b") 189 self.check_suite("a ^= b") 190 self.check_suite("a <<= b") 191 self.check_suite("a >>= b") 192 self.check_suite("a **= b") 193 194 def test_function_defs(self): 195 self.check_suite("def f(): pass") 196 self.check_suite("def f(*args): pass") 197 self.check_suite("def f(*args, **kw): pass") 198 self.check_suite("def f(**kw): pass") 199 self.check_suite("def f(foo=bar): pass") 200 self.check_suite("def f(foo=bar, *args): pass") 201 self.check_suite("def f(foo=bar, *args, **kw): pass") 202 self.check_suite("def f(foo=bar, **kw): pass") 203 204 self.check_suite("def f(a, b): pass") 205 self.check_suite("def f(a, b, *args): pass") 206 self.check_suite("def f(a, b, *args, **kw): pass") 207 self.check_suite("def f(a, b, **kw): pass") 208 self.check_suite("def f(a, b, foo=bar): pass") 209 self.check_suite("def f(a, b, foo=bar, *args): pass") 210 self.check_suite("def f(a, b, foo=bar, *args, **kw): pass") 211 self.check_suite("def f(a, b, foo=bar, **kw): pass") 212 213 self.check_suite("@staticmethod\n" 214 "def f(): pass") 215 self.check_suite("@staticmethod\n" 216 "@funcattrs(x, y)\n" 217 "def f(): pass") 218 self.check_suite("@funcattrs()\n" 219 "def f(): pass") 220 221 # keyword-only arguments 222 self.check_suite("def f(*, a): pass") 223 self.check_suite("def f(*, a = 5): pass") 224 self.check_suite("def f(*, a = 5, b): pass") 225 self.check_suite("def f(*, a, b = 5): pass") 226 self.check_suite("def f(*, a, b = 5, **kwds): pass") 227 self.check_suite("def f(*args, a): pass") 228 self.check_suite("def f(*args, a = 5): pass") 229 self.check_suite("def f(*args, a = 5, b): pass") 230 self.check_suite("def f(*args, a, b = 5): pass") 231 self.check_suite("def f(*args, a, b = 5, **kwds): pass") 232 233 # function annotations 234 self.check_suite("def f(a: int): pass") 235 self.check_suite("def f(a: int = 5): pass") 236 self.check_suite("def f(*args: list): pass") 237 self.check_suite("def f(**kwds: dict): pass") 238 self.check_suite("def f(*, a: int): pass") 239 self.check_suite("def f(*, a: int = 5): pass") 240 self.check_suite("def f() -> int: pass") 241 242 def test_class_defs(self): 243 self.check_suite("class foo():pass") 244 self.check_suite("class foo(object):pass") 245 self.check_suite("@class_decorator\n" 246 "class foo():pass") 247 self.check_suite("@class_decorator(arg)\n" 248 "class foo():pass") 249 self.check_suite("@decorator1\n" 250 "@decorator2\n" 251 "class foo():pass") 252 253 def test_import_from_statement(self): 254 self.check_suite("from sys.path import *") 255 self.check_suite("from sys.path import dirname") 256 self.check_suite("from sys.path import (dirname)") 257 self.check_suite("from sys.path import (dirname,)") 258 self.check_suite("from sys.path import dirname as my_dirname") 259 self.check_suite("from sys.path import (dirname as my_dirname)") 260 self.check_suite("from sys.path import (dirname as my_dirname,)") 261 self.check_suite("from sys.path import dirname, basename") 262 self.check_suite("from sys.path import (dirname, basename)") 263 self.check_suite("from sys.path import (dirname, basename,)") 264 self.check_suite( 265 "from sys.path import dirname as my_dirname, basename") 266 self.check_suite( 267 "from sys.path import (dirname as my_dirname, basename)") 268 self.check_suite( 269 "from sys.path import (dirname as my_dirname, basename,)") 270 self.check_suite( 271 "from sys.path import dirname, basename as my_basename") 272 self.check_suite( 273 "from sys.path import (dirname, basename as my_basename)") 274 self.check_suite( 275 "from sys.path import (dirname, basename as my_basename,)") 276 self.check_suite("from .bogus import x") 277 278 def test_basic_import_statement(self): 279 self.check_suite("import sys") 280 self.check_suite("import sys as system") 281 self.check_suite("import sys, math") 282 self.check_suite("import sys as system, math") 283 self.check_suite("import sys, math as my_math") 284 285 def test_relative_imports(self): 286 self.check_suite("from . import name") 287 self.check_suite("from .. import name") 288 # check all the way up to '....', since '...' is tokenized 289 # differently from '.' (it's an ellipsis token). 290 self.check_suite("from ... import name") 291 self.check_suite("from .... import name") 292 self.check_suite("from .pkg import name") 293 self.check_suite("from ..pkg import name") 294 self.check_suite("from ...pkg import name") 295 self.check_suite("from ....pkg import name") 296 297 def test_pep263(self): 298 self.check_suite("# -*- coding: iso-8859-1 -*-\n" 299 "pass\n") 300 301 def test_assert(self): 302 self.check_suite("assert alo < ahi and blo < bhi\n") 303 304 def test_with(self): 305 self.check_suite("with open('x'): pass\n") 306 self.check_suite("with open('x') as f: pass\n") 307 self.check_suite("with open('x') as f, open('y') as g: pass\n") 308 309 def test_try_stmt(self): 310 self.check_suite("try: pass\nexcept: pass\n") 311 self.check_suite("try: pass\nfinally: pass\n") 312 self.check_suite("try: pass\nexcept A: pass\nfinally: pass\n") 313 self.check_suite("try: pass\nexcept A: pass\nexcept: pass\n" 314 "finally: pass\n") 315 self.check_suite("try: pass\nexcept: pass\nelse: pass\n") 316 self.check_suite("try: pass\nexcept: pass\nelse: pass\n" 317 "finally: pass\n") 318 319 def test_position(self): 320 # An absolutely minimal test of position information. Better 321 # tests would be a big project. 322 code = "def f(x):\n return x + 1" 323 st1 = parser.suite(code) 324 st2 = st1.totuple(line_info=1, col_info=1) 325 326 def walk(tree): 327 node_type = tree[0] 328 next = tree[1] 329 if isinstance(next, tuple): 330 for elt in tree[1:]: 331 for x in walk(elt): 332 yield x 333 else: 334 yield tree 335 336 terminals = list(walk(st2)) 337 self.assertEqual([ 338 (1, 'def', 1, 0), 339 (1, 'f', 1, 4), 340 (7, '(', 1, 5), 341 (1, 'x', 1, 6), 342 (8, ')', 1, 7), 343 (11, ':', 1, 8), 344 (4, '', 1, 9), 345 (5, '', 2, -1), 346 (1, 'return', 2, 4), 347 (1, 'x', 2, 11), 348 (14, '+', 2, 13), 349 (2, '1', 2, 15), 350 (4, '', 2, 16), 351 (6, '', 2, -1), 352 (4, '', 2, -1), 353 (0, '', 2, -1)], 354 terminals) 355 356 def test_extended_unpacking(self): 357 self.check_suite("*a = y") 358 self.check_suite("x, *b, = m") 359 self.check_suite("[*a, *b] = y") 360 self.check_suite("for [*x, b] in x: pass") 361 362 def test_raise_statement(self): 363 self.check_suite("raise\n") 364 self.check_suite("raise e\n") 365 self.check_suite("try:\n" 366 " suite\n" 367 "except Exception as e:\n" 368 " raise ValueError from e\n") 369 370 def test_list_displays(self): 371 self.check_expr('[]') 372 self.check_expr('[*{2}, 3, *[4]]') 373 374 def test_set_displays(self): 375 self.check_expr('{*{2}, 3, *[4]}') 376 self.check_expr('{2}') 377 self.check_expr('{2,}') 378 self.check_expr('{2, 3}') 379 self.check_expr('{2, 3,}') 380 381 def test_dict_displays(self): 382 self.check_expr('{}') 383 self.check_expr('{a:b}') 384 self.check_expr('{a:b,}') 385 self.check_expr('{a:b, c:d}') 386 self.check_expr('{a:b, c:d,}') 387 self.check_expr('{**{}}') 388 self.check_expr('{**{}, 3:4, **{5:6, 7:8}}') 389 390 def test_argument_unpacking(self): 391 self.check_expr("f(*a, **b)") 392 self.check_expr('f(a, *b, *c, *d)') 393 self.check_expr('f(**a, **b)') 394 self.check_expr('f(2, *a, *b, **b, **c, **d)') 395 self.check_expr("f(*b, *() or () and (), **{} and {}, **() or {})") 396 397 def test_set_comprehensions(self): 398 self.check_expr('{x for x in seq}') 399 self.check_expr('{f(x) for x in seq}') 400 self.check_expr('{f(x) for x in seq if condition(x)}') 401 402 def test_dict_comprehensions(self): 403 self.check_expr('{x:x for x in seq}') 404 self.check_expr('{x**2:x[3] for x in seq if condition(x)}') 405 self.check_expr('{x:x for x in seq1 for y in seq2 if condition(x, y)}') 406 407 408 # 409 # Second, we take *invalid* trees and make sure we get ParserError 410 # rejections for them. 411 # 412 413 class IllegalSyntaxTestCase(unittest.TestCase): 414 415 def check_bad_tree(self, tree, label): 416 try: 417 parser.sequence2st(tree) 418 except parser.ParserError: 419 pass 420 else: 421 self.fail("did not detect invalid tree for %r" % label) 422 423 def test_junk(self): 424 # not even remotely valid: 425 self.check_bad_tree((1, 2, 3), "<junk>") 426 427 def test_illegal_yield_1(self): 428 # Illegal yield statement: def f(): return 1; yield 1 429 tree = \ 430 (257, 431 (264, 432 (285, 433 (259, 434 (1, 'def'), 435 (1, 'f'), 436 (260, (7, '('), (8, ')')), 437 (11, ':'), 438 (291, 439 (4, ''), 440 (5, ''), 441 (264, 442 (265, 443 (266, 444 (272, 445 (275, 446 (1, 'return'), 447 (313, 448 (292, 449 (293, 450 (294, 451 (295, 452 (297, 453 (298, 454 (299, 455 (300, 456 (301, 457 (302, (303, (304, (305, (2, '1')))))))))))))))))), 458 (264, 459 (265, 460 (266, 461 (272, 462 (276, 463 (1, 'yield'), 464 (313, 465 (292, 466 (293, 467 (294, 468 (295, 469 (297, 470 (298, 471 (299, 472 (300, 473 (301, 474 (302, 475 (303, (304, (305, (2, '1')))))))))))))))))), 476 (4, ''))), 477 (6, ''))))), 478 (4, ''), 479 (0, '')))) 480 self.check_bad_tree(tree, "def f():\n return 1\n yield 1") 481 482 def test_illegal_yield_2(self): 483 # Illegal return in generator: def f(): return 1; yield 1 484 tree = \ 485 (257, 486 (264, 487 (265, 488 (266, 489 (278, 490 (1, 'from'), 491 (281, (1, '__future__')), 492 (1, 'import'), 493 (279, (1, 'generators')))), 494 (4, ''))), 495 (264, 496 (285, 497 (259, 498 (1, 'def'), 499 (1, 'f'), 500 (260, (7, '('), (8, ')')), 501 (11, ':'), 502 (291, 503 (4, ''), 504 (5, ''), 505 (264, 506 (265, 507 (266, 508 (272, 509 (275, 510 (1, 'return'), 511 (313, 512 (292, 513 (293, 514 (294, 515 (295, 516 (297, 517 (298, 518 (299, 519 (300, 520 (301, 521 (302, (303, (304, (305, (2, '1')))))))))))))))))), 522 (264, 523 (265, 524 (266, 525 (272, 526 (276, 527 (1, 'yield'), 528 (313, 529 (292, 530 (293, 531 (294, 532 (295, 533 (297, 534 (298, 535 (299, 536 (300, 537 (301, 538 (302, 539 (303, (304, (305, (2, '1')))))))))))))))))), 540 (4, ''))), 541 (6, ''))))), 542 (4, ''), 543 (0, '')))) 544 self.check_bad_tree(tree, "def f():\n return 1\n yield 1") 545 546 def test_a_comma_comma_c(self): 547 # Illegal input: a,,c 548 tree = \ 549 (258, 550 (311, 551 (290, 552 (291, 553 (292, 554 (293, 555 (295, 556 (296, 557 (297, 558 (298, (299, (300, (301, (302, (303, (1, 'a')))))))))))))), 559 (12, ','), 560 (12, ','), 561 (290, 562 (291, 563 (292, 564 (293, 565 (295, 566 (296, 567 (297, 568 (298, (299, (300, (301, (302, (303, (1, 'c'))))))))))))))), 569 (4, ''), 570 (0, '')) 571 self.check_bad_tree(tree, "a,,c") 572 573 def test_illegal_operator(self): 574 # Illegal input: a $= b 575 tree = \ 576 (257, 577 (264, 578 (265, 579 (266, 580 (267, 581 (312, 582 (291, 583 (292, 584 (293, 585 (294, 586 (296, 587 (297, 588 (298, 589 (299, 590 (300, (301, (302, (303, (304, (1, 'a'))))))))))))))), 591 (268, (37, '$=')), 592 (312, 593 (291, 594 (292, 595 (293, 596 (294, 597 (296, 598 (297, 599 (298, 600 (299, 601 (300, (301, (302, (303, (304, (1, 'b'))))))))))))))))), 602 (4, ''))), 603 (0, '')) 604 self.check_bad_tree(tree, "a $= b") 605 606 def test_malformed_global(self): 607 #doesn't have global keyword in ast 608 tree = (257, 609 (264, 610 (265, 611 (266, 612 (282, (1, 'foo'))), (4, ''))), 613 (4, ''), 614 (0, '')) 615 self.check_bad_tree(tree, "malformed global ast") 616 617 def test_missing_import_source(self): 618 # from import fred 619 tree = \ 620 (257, 621 (268, 622 (269, 623 (270, 624 (282, 625 (284, (1, 'from'), (1, 'import'), 626 (287, (285, (1, 'fred')))))), 627 (4, ''))), 628 (4, ''), (0, '')) 629 self.check_bad_tree(tree, "from import fred") 630 631 632 class CompileTestCase(unittest.TestCase): 633 634 # These tests are very minimal. :-( 635 636 def test_compile_expr(self): 637 st = parser.expr('2 + 3') 638 code = parser.compilest(st) 639 self.assertEqual(eval(code), 5) 640 641 def test_compile_suite(self): 642 st = parser.suite('x = 2; y = x + 3') 643 code = parser.compilest(st) 644 globs = {} 645 exec(code, globs) 646 self.assertEqual(globs['y'], 5) 647 648 def test_compile_error(self): 649 st = parser.suite('1 = 3 + 4') 650 self.assertRaises(SyntaxError, parser.compilest, st) 651 652 def test_compile_badunicode(self): 653 st = parser.suite('a = "\\U12345678"') 654 self.assertRaises(SyntaxError, parser.compilest, st) 655 st = parser.suite('a = "\\u1"') 656 self.assertRaises(SyntaxError, parser.compilest, st) 657 658 def test_issue_9011(self): 659 # Issue 9011: compilation of an unary minus expression changed 660 # the meaning of the ST, so that a second compilation produced 661 # incorrect results. 662 st = parser.expr('-3') 663 code1 = parser.compilest(st) 664 self.assertEqual(eval(code1), -3) 665 code2 = parser.compilest(st) 666 self.assertEqual(eval(code2), -3) 667 668 def test_compile_filename(self): 669 st = parser.expr('a + 5') 670 code = parser.compilest(st) 671 self.assertEqual(code.co_filename, '<syntax-tree>') 672 code = st.compile() 673 self.assertEqual(code.co_filename, '<syntax-tree>') 674 for filename in 'file.py', b'file.py': 675 code = parser.compilest(st, filename) 676 self.assertEqual(code.co_filename, 'file.py') 677 code = st.compile(filename) 678 self.assertEqual(code.co_filename, 'file.py') 679 for filename in bytearray(b'file.py'), memoryview(b'file.py'): 680 with self.assertWarns(DeprecationWarning): 681 code = parser.compilest(st, filename) 682 self.assertEqual(code.co_filename, 'file.py') 683 with self.assertWarns(DeprecationWarning): 684 code = st.compile(filename) 685 self.assertEqual(code.co_filename, 'file.py') 686 self.assertRaises(TypeError, parser.compilest, st, list(b'file.py')) 687 self.assertRaises(TypeError, st.compile, list(b'file.py')) 688 689 690 class ParserStackLimitTestCase(unittest.TestCase): 691 """try to push the parser to/over its limits. 692 see http://bugs.python.org/issue1881 for a discussion 693 """ 694 def _nested_expression(self, level): 695 return "["*level+"]"*level 696 697 def test_deeply_nested_list(self): 698 # XXX used to be 99 levels in 2.x 699 e = self._nested_expression(93) 700 st = parser.expr(e) 701 st.compile() 702 703 def test_trigger_memory_error(self): 704 e = self._nested_expression(100) 705 rc, out, err = assert_python_failure('-c', e) 706 # parsing the expression will result in an error message 707 # followed by a MemoryError (see #11963) 708 self.assertIn(b's_push: parser stack overflow', err) 709 self.assertIn(b'MemoryError', err) 710 711 class STObjectTestCase(unittest.TestCase): 712 """Test operations on ST objects themselves""" 713 714 def test_comparisons(self): 715 # ST objects should support order and equality comparisons 716 st1 = parser.expr('2 + 3') 717 st2 = parser.suite('x = 2; y = x + 3') 718 st3 = parser.expr('list(x**3 for x in range(20))') 719 st1_copy = parser.expr('2 + 3') 720 st2_copy = parser.suite('x = 2; y = x + 3') 721 st3_copy = parser.expr('list(x**3 for x in range(20))') 722 723 # exercise fast path for object identity 724 self.assertEqual(st1 == st1, True) 725 self.assertEqual(st2 == st2, True) 726 self.assertEqual(st3 == st3, True) 727 # slow path equality 728 self.assertEqual(st1, st1_copy) 729 self.assertEqual(st2, st2_copy) 730 self.assertEqual(st3, st3_copy) 731 self.assertEqual(st1 == st2, False) 732 self.assertEqual(st1 == st3, False) 733 self.assertEqual(st2 == st3, False) 734 self.assertEqual(st1 != st1, False) 735 self.assertEqual(st2 != st2, False) 736 self.assertEqual(st3 != st3, False) 737 self.assertEqual(st1 != st1_copy, False) 738 self.assertEqual(st2 != st2_copy, False) 739 self.assertEqual(st3 != st3_copy, False) 740 self.assertEqual(st2 != st1, True) 741 self.assertEqual(st1 != st3, True) 742 self.assertEqual(st3 != st2, True) 743 # we don't particularly care what the ordering is; just that 744 # it's usable and self-consistent 745 self.assertEqual(st1 < st2, not (st2 <= st1)) 746 self.assertEqual(st1 < st3, not (st3 <= st1)) 747 self.assertEqual(st2 < st3, not (st3 <= st2)) 748 self.assertEqual(st1 < st2, st2 > st1) 749 self.assertEqual(st1 < st3, st3 > st1) 750 self.assertEqual(st2 < st3, st3 > st2) 751 self.assertEqual(st1 <= st2, st2 >= st1) 752 self.assertEqual(st3 <= st1, st1 >= st3) 753 self.assertEqual(st2 <= st3, st3 >= st2) 754 # transitivity 755 bottom = min(st1, st2, st3) 756 top = max(st1, st2, st3) 757 mid = sorted([st1, st2, st3])[1] 758 self.assertTrue(bottom < mid) 759 self.assertTrue(bottom < top) 760 self.assertTrue(mid < top) 761 self.assertTrue(bottom <= mid) 762 self.assertTrue(bottom <= top) 763 self.assertTrue(mid <= top) 764 self.assertTrue(bottom <= bottom) 765 self.assertTrue(mid <= mid) 766 self.assertTrue(top <= top) 767 # interaction with other types 768 self.assertEqual(st1 == 1588.602459, False) 769 self.assertEqual('spanish armada' != st2, True) 770 self.assertRaises(TypeError, operator.ge, st3, None) 771 self.assertRaises(TypeError, operator.le, False, st1) 772 self.assertRaises(TypeError, operator.lt, st1, 1815) 773 self.assertRaises(TypeError, operator.gt, b'waterloo', st2) 774 775 check_sizeof = support.check_sizeof 776 777 @support.cpython_only 778 def test_sizeof(self): 779 def XXXROUNDUP(n): 780 if n <= 1: 781 return n 782 if n <= 128: 783 return (n + 3) & ~3 784 return 1 << (n - 1).bit_length() 785 786 basesize = support.calcobjsize('Pii') 787 nodesize = struct.calcsize('hP3iP0h') 788 def sizeofchildren(node): 789 if node is None: 790 return 0 791 res = 0 792 hasstr = len(node) > 1 and isinstance(node[-1], str) 793 if hasstr: 794 res += len(node[-1]) + 1 795 children = node[1:-1] if hasstr else node[1:] 796 if children: 797 res += XXXROUNDUP(len(children)) * nodesize 798 for child in children: 799 res += sizeofchildren(child) 800 return res 801 802 def check_st_sizeof(st): 803 self.check_sizeof(st, basesize + nodesize + 804 sizeofchildren(st.totuple())) 805 806 check_st_sizeof(parser.expr('2 + 3')) 807 check_st_sizeof(parser.expr('2 + 3 + 4')) 808 check_st_sizeof(parser.suite('x = 2 + 3')) 809 check_st_sizeof(parser.suite('')) 810 check_st_sizeof(parser.suite('# -*- coding: utf-8 -*-')) 811 check_st_sizeof(parser.expr('[' + '2,' * 1000 + ']')) 812 813 814 # XXX tests for pickling and unpickling of ST objects should go here 815 816 class OtherParserCase(unittest.TestCase): 817 818 def test_two_args_to_expr(self): 819 # See bug #12264 820 with self.assertRaises(TypeError): 821 parser.expr("a", "b") 822 823 if __name__ == "__main__": 824 unittest.main() 825