1 import unittest 2 import sys 3 import _ast 4 from test import test_support 5 import textwrap 6 7 class TestSpecifics(unittest.TestCase): 8 9 def test_no_ending_newline(self): 10 compile("hi", "<test>", "exec") 11 compile("hi\r", "<test>", "exec") 12 13 def test_empty(self): 14 compile("", "<test>", "exec") 15 16 def test_other_newlines(self): 17 compile("\r\n", "<test>", "exec") 18 compile("\r", "<test>", "exec") 19 compile("hi\r\nstuff\r\ndef f():\n pass\r", "<test>", "exec") 20 compile("this_is\rreally_old_mac\rdef f():\n pass", "<test>", "exec") 21 22 def test_debug_assignment(self): 23 # catch assignments to __debug__ 24 self.assertRaises(SyntaxError, compile, '__debug__ = 1', '?', 'single') 25 import __builtin__ 26 prev = __builtin__.__debug__ 27 setattr(__builtin__, '__debug__', 'sure') 28 setattr(__builtin__, '__debug__', prev) 29 30 def test_argument_handling(self): 31 # detect duplicate positional and keyword arguments 32 self.assertRaises(SyntaxError, eval, 'lambda a,a:0') 33 self.assertRaises(SyntaxError, eval, 'lambda a,a=1:0') 34 self.assertRaises(SyntaxError, eval, 'lambda a=1,a=1:0') 35 try: 36 exec 'def f(a, a): pass' 37 self.fail("duplicate arguments") 38 except SyntaxError: 39 pass 40 try: 41 exec 'def f(a = 0, a = 1): pass' 42 self.fail("duplicate keyword arguments") 43 except SyntaxError: 44 pass 45 try: 46 exec 'def f(a): global a; a = 1' 47 self.fail("variable is global and local") 48 except SyntaxError: 49 pass 50 51 def test_syntax_error(self): 52 self.assertRaises(SyntaxError, compile, "1+*3", "filename", "exec") 53 54 def test_none_keyword_arg(self): 55 self.assertRaises(SyntaxError, compile, "f(None=1)", "<string>", "exec") 56 57 def test_duplicate_global_local(self): 58 try: 59 exec 'def f(a): global a; a = 1' 60 self.fail("variable is global and local") 61 except SyntaxError: 62 pass 63 64 def test_exec_functional_style(self): 65 # Exec'ing a tuple of length 2 works. 66 g = {'b': 2} 67 exec("a = b + 1", g) 68 self.assertEqual(g['a'], 3) 69 70 # As does exec'ing a tuple of length 3. 71 l = {'b': 3} 72 g = {'b': 5, 'c': 7} 73 exec("a = b + c", g, l) 74 self.assertNotIn('a', g) 75 self.assertEqual(l['a'], 10) 76 77 # Tuples not of length 2 or 3 are invalid. 78 with self.assertRaises(TypeError): 79 exec("a = b + 1",) 80 81 with self.assertRaises(TypeError): 82 exec("a = b + 1", {}, {}, {}) 83 84 # Can't mix and match the two calling forms. 85 g = {'a': 3, 'b': 4} 86 l = {} 87 with self.assertRaises(TypeError): 88 exec("a = b + 1", g) in g 89 with self.assertRaises(TypeError): 90 exec("a = b + 1", g, l) in g, l 91 92 def test_exec_with_general_mapping_for_locals(self): 93 94 class M: 95 "Test mapping interface versus possible calls from eval()." 96 def __getitem__(self, key): 97 if key == 'a': 98 return 12 99 raise KeyError 100 def __setitem__(self, key, value): 101 self.results = (key, value) 102 def keys(self): 103 return list('xyz') 104 105 m = M() 106 g = globals() 107 exec 'z = a' in g, m 108 self.assertEqual(m.results, ('z', 12)) 109 try: 110 exec 'z = b' in g, m 111 except NameError: 112 pass 113 else: 114 self.fail('Did not detect a KeyError') 115 exec 'z = dir()' in g, m 116 self.assertEqual(m.results, ('z', list('xyz'))) 117 exec 'z = globals()' in g, m 118 self.assertEqual(m.results, ('z', g)) 119 exec 'z = locals()' in g, m 120 self.assertEqual(m.results, ('z', m)) 121 try: 122 exec 'z = b' in m 123 except TypeError: 124 pass 125 else: 126 self.fail('Did not validate globals as a real dict') 127 128 class A: 129 "Non-mapping" 130 pass 131 m = A() 132 try: 133 exec 'z = a' in g, m 134 except TypeError: 135 pass 136 else: 137 self.fail('Did not validate locals as a mapping') 138 139 # Verify that dict subclasses work as well 140 class D(dict): 141 def __getitem__(self, key): 142 if key == 'a': 143 return 12 144 return dict.__getitem__(self, key) 145 d = D() 146 exec 'z = a' in g, d 147 self.assertEqual(d['z'], 12) 148 149 def test_extended_arg(self): 150 longexpr = 'x = x or ' + '-x' * 2500 151 code = ''' 152 def f(x): 153 %s 154 %s 155 %s 156 %s 157 %s 158 %s 159 %s 160 %s 161 %s 162 %s 163 # the expressions above have no effect, x == argument 164 while x: 165 x -= 1 166 # EXTENDED_ARG/JUMP_ABSOLUTE here 167 return x 168 ''' % ((longexpr,)*10) 169 exec code 170 self.assertEqual(f(5), 0) 171 172 def test_complex_args(self): 173 174 with test_support.check_py3k_warnings( 175 ("tuple parameter unpacking has been removed", SyntaxWarning)): 176 exec textwrap.dedent(''' 177 def comp_args((a, b)): 178 return a,b 179 self.assertEqual(comp_args((1, 2)), (1, 2)) 180 181 def comp_args((a, b)=(3, 4)): 182 return a, b 183 self.assertEqual(comp_args((1, 2)), (1, 2)) 184 self.assertEqual(comp_args(), (3, 4)) 185 186 def comp_args(a, (b, c)): 187 return a, b, c 188 self.assertEqual(comp_args(1, (2, 3)), (1, 2, 3)) 189 190 def comp_args(a=2, (b, c)=(3, 4)): 191 return a, b, c 192 self.assertEqual(comp_args(1, (2, 3)), (1, 2, 3)) 193 self.assertEqual(comp_args(), (2, 3, 4)) 194 ''') 195 196 def test_argument_order(self): 197 try: 198 exec 'def f(a=1, (b, c)): pass' 199 self.fail("non-default args after default") 200 except SyntaxError: 201 pass 202 203 def test_float_literals(self): 204 # testing bad float literals 205 self.assertRaises(SyntaxError, eval, "2e") 206 self.assertRaises(SyntaxError, eval, "2.0e+") 207 self.assertRaises(SyntaxError, eval, "1e-") 208 self.assertRaises(SyntaxError, eval, "3-4e/21") 209 210 def test_indentation(self): 211 # testing compile() of indented block w/o trailing newline" 212 s = """ 213 if 1: 214 if 2: 215 pass""" 216 compile(s, "<string>", "exec") 217 218 # This test is probably specific to CPython and may not generalize 219 # to other implementations. We are trying to ensure that when 220 # the first line of code starts after 256, correct line numbers 221 # in tracebacks are still produced. 222 def test_leading_newlines(self): 223 s256 = "".join(["\n"] * 256 + ["spam"]) 224 co = compile(s256, 'fn', 'exec') 225 self.assertEqual(co.co_firstlineno, 257) 226 self.assertEqual(co.co_lnotab, '') 227 228 def test_literals_with_leading_zeroes(self): 229 for arg in ["077787", "0xj", "0x.", "0e", "090000000000000", 230 "080000000000000", "000000000000009", "000000000000008", 231 "0b42", "0BADCAFE", "0o123456789", "0b1.1", "0o4.2", 232 "0b101j2", "0o153j2", "0b100e1", "0o777e1", "0o8", "0o78"]: 233 self.assertRaises(SyntaxError, eval, arg) 234 235 self.assertEqual(eval("0777"), 511) 236 self.assertEqual(eval("0777L"), 511) 237 self.assertEqual(eval("000777"), 511) 238 self.assertEqual(eval("0xff"), 255) 239 self.assertEqual(eval("0xffL"), 255) 240 self.assertEqual(eval("0XfF"), 255) 241 self.assertEqual(eval("0777."), 777) 242 self.assertEqual(eval("0777.0"), 777) 243 self.assertEqual(eval("000000000000000000000000000000000000000000000000000777e0"), 777) 244 self.assertEqual(eval("0777e1"), 7770) 245 self.assertEqual(eval("0e0"), 0) 246 self.assertEqual(eval("0000E-012"), 0) 247 self.assertEqual(eval("09.5"), 9.5) 248 self.assertEqual(eval("0777j"), 777j) 249 self.assertEqual(eval("00j"), 0j) 250 self.assertEqual(eval("00.0"), 0) 251 self.assertEqual(eval("0e3"), 0) 252 self.assertEqual(eval("090000000000000."), 90000000000000.) 253 self.assertEqual(eval("090000000000000.0000000000000000000000"), 90000000000000.) 254 self.assertEqual(eval("090000000000000e0"), 90000000000000.) 255 self.assertEqual(eval("090000000000000e-0"), 90000000000000.) 256 self.assertEqual(eval("090000000000000j"), 90000000000000j) 257 self.assertEqual(eval("000000000000007"), 7) 258 self.assertEqual(eval("000000000000008."), 8.) 259 self.assertEqual(eval("000000000000009."), 9.) 260 self.assertEqual(eval("0b101010"), 42) 261 self.assertEqual(eval("-0b000000000010"), -2) 262 self.assertEqual(eval("0o777"), 511) 263 self.assertEqual(eval("-0o0000010"), -8) 264 self.assertEqual(eval("020000000000.0"), 20000000000.0) 265 self.assertEqual(eval("037777777777e0"), 37777777777.0) 266 self.assertEqual(eval("01000000000000000000000.0"), 267 1000000000000000000000.0) 268 269 def test_unary_minus(self): 270 # Verify treatment of unary minus on negative numbers SF bug #660455 271 if sys.maxint == 2147483647: 272 # 32-bit machine 273 all_one_bits = '0xffffffff' 274 self.assertEqual(eval(all_one_bits), 4294967295L) 275 self.assertEqual(eval("-" + all_one_bits), -4294967295L) 276 elif sys.maxint == 9223372036854775807: 277 # 64-bit machine 278 all_one_bits = '0xffffffffffffffff' 279 self.assertEqual(eval(all_one_bits), 18446744073709551615L) 280 self.assertEqual(eval("-" + all_one_bits), -18446744073709551615L) 281 else: 282 self.fail("How many bits *does* this machine have???") 283 # Verify treatment of constant folding on -(sys.maxint+1) 284 # i.e. -2147483648 on 32 bit platforms. Should return int, not long. 285 self.assertIsInstance(eval("%s" % (-sys.maxint - 1)), int) 286 self.assertIsInstance(eval("%s" % (-sys.maxint - 2)), long) 287 288 if sys.maxint == 9223372036854775807: 289 def test_32_63_bit_values(self): 290 a = +4294967296 # 1 << 32 291 b = -4294967296 # 1 << 32 292 c = +281474976710656 # 1 << 48 293 d = -281474976710656 # 1 << 48 294 e = +4611686018427387904 # 1 << 62 295 f = -4611686018427387904 # 1 << 62 296 g = +9223372036854775807 # 1 << 63 - 1 297 h = -9223372036854775807 # 1 << 63 - 1 298 299 for variable in self.test_32_63_bit_values.func_code.co_consts: 300 if variable is not None: 301 self.assertIsInstance(variable, int) 302 303 def test_sequence_unpacking_error(self): 304 # Verify sequence packing/unpacking with "or". SF bug #757818 305 i,j = (1, -1) or (-1, 1) 306 self.assertEqual(i, 1) 307 self.assertEqual(j, -1) 308 309 def test_none_assignment(self): 310 stmts = [ 311 'None = 0', 312 'None += 0', 313 '__builtins__.None = 0', 314 'def None(): pass', 315 'class None: pass', 316 '(a, None) = 0, 0', 317 'for None in range(10): pass', 318 'def f(None): pass', 319 'import None', 320 'import x as None', 321 'from x import None', 322 'from x import y as None' 323 ] 324 for stmt in stmts: 325 stmt += "\n" 326 self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'single') 327 self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec') 328 # This is ok. 329 compile("from None import x", "tmp", "exec") 330 compile("from x import None as y", "tmp", "exec") 331 compile("import None as x", "tmp", "exec") 332 333 def test_import(self): 334 succeed = [ 335 'import sys', 336 'import os, sys', 337 'import os as bar', 338 'import os.path as bar', 339 'from __future__ import nested_scopes, generators', 340 'from __future__ import (nested_scopes,\ngenerators)', 341 'from __future__ import (nested_scopes,\ngenerators,)', 342 'from sys import stdin, stderr, stdout', 343 'from sys import (stdin, stderr,\nstdout)', 344 'from sys import (stdin, stderr,\nstdout,)', 345 'from sys import (stdin\n, stderr, stdout)', 346 'from sys import (stdin\n, stderr, stdout,)', 347 'from sys import stdin as si, stdout as so, stderr as se', 348 'from sys import (stdin as si, stdout as so, stderr as se)', 349 'from sys import (stdin as si, stdout as so, stderr as se,)', 350 ] 351 fail = [ 352 'import (os, sys)', 353 'import (os), (sys)', 354 'import ((os), (sys))', 355 'import (sys', 356 'import sys)', 357 'import (os,)', 358 'import os As bar', 359 'import os.path a bar', 360 'from sys import stdin As stdout', 361 'from sys import stdin a stdout', 362 'from (sys) import stdin', 363 'from __future__ import (nested_scopes', 364 'from __future__ import nested_scopes)', 365 'from __future__ import nested_scopes,\ngenerators', 366 'from sys import (stdin', 367 'from sys import stdin)', 368 'from sys import stdin, stdout,\nstderr', 369 'from sys import stdin si', 370 'from sys import stdin,' 371 'from sys import (*)', 372 'from sys import (stdin,, stdout, stderr)', 373 'from sys import (stdin, stdout),', 374 ] 375 for stmt in succeed: 376 compile(stmt, 'tmp', 'exec') 377 for stmt in fail: 378 self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec') 379 380 def test_for_distinct_code_objects(self): 381 # SF bug 1048870 382 def f(): 383 f1 = lambda x=1: x 384 f2 = lambda x=2: x 385 return f1, f2 386 f1, f2 = f() 387 self.assertNotEqual(id(f1.func_code), id(f2.func_code)) 388 389 def test_lambda_doc(self): 390 l = lambda: "foo" 391 self.assertIsNone(l.__doc__) 392 393 def test_unicode_encoding(self): 394 code = u"# -*- coding: utf-8 -*-\npass\n" 395 self.assertRaises(SyntaxError, compile, code, "tmp", "exec") 396 397 def test_subscripts(self): 398 # SF bug 1448804 399 # Class to make testing subscript results easy 400 class str_map(object): 401 def __init__(self): 402 self.data = {} 403 def __getitem__(self, key): 404 return self.data[str(key)] 405 def __setitem__(self, key, value): 406 self.data[str(key)] = value 407 def __delitem__(self, key): 408 del self.data[str(key)] 409 def __contains__(self, key): 410 return str(key) in self.data 411 d = str_map() 412 # Index 413 d[1] = 1 414 self.assertEqual(d[1], 1) 415 d[1] += 1 416 self.assertEqual(d[1], 2) 417 del d[1] 418 self.assertNotIn(1, d) 419 # Tuple of indices 420 d[1, 1] = 1 421 self.assertEqual(d[1, 1], 1) 422 d[1, 1] += 1 423 self.assertEqual(d[1, 1], 2) 424 del d[1, 1] 425 self.assertNotIn((1, 1), d) 426 # Simple slice 427 d[1:2] = 1 428 self.assertEqual(d[1:2], 1) 429 d[1:2] += 1 430 self.assertEqual(d[1:2], 2) 431 del d[1:2] 432 self.assertNotIn(slice(1, 2), d) 433 # Tuple of simple slices 434 d[1:2, 1:2] = 1 435 self.assertEqual(d[1:2, 1:2], 1) 436 d[1:2, 1:2] += 1 437 self.assertEqual(d[1:2, 1:2], 2) 438 del d[1:2, 1:2] 439 self.assertNotIn((slice(1, 2), slice(1, 2)), d) 440 # Extended slice 441 d[1:2:3] = 1 442 self.assertEqual(d[1:2:3], 1) 443 d[1:2:3] += 1 444 self.assertEqual(d[1:2:3], 2) 445 del d[1:2:3] 446 self.assertNotIn(slice(1, 2, 3), d) 447 # Tuple of extended slices 448 d[1:2:3, 1:2:3] = 1 449 self.assertEqual(d[1:2:3, 1:2:3], 1) 450 d[1:2:3, 1:2:3] += 1 451 self.assertEqual(d[1:2:3, 1:2:3], 2) 452 del d[1:2:3, 1:2:3] 453 self.assertNotIn((slice(1, 2, 3), slice(1, 2, 3)), d) 454 # Ellipsis 455 d[...] = 1 456 self.assertEqual(d[...], 1) 457 d[...] += 1 458 self.assertEqual(d[...], 2) 459 del d[...] 460 self.assertNotIn(Ellipsis, d) 461 # Tuple of Ellipses 462 d[..., ...] = 1 463 self.assertEqual(d[..., ...], 1) 464 d[..., ...] += 1 465 self.assertEqual(d[..., ...], 2) 466 del d[..., ...] 467 self.assertNotIn((Ellipsis, Ellipsis), d) 468 469 def test_mangling(self): 470 class A: 471 def f(): 472 __mangled = 1 473 __not_mangled__ = 2 474 import __mangled_mod 475 import __package__.module 476 477 self.assertIn("_A__mangled", A.f.func_code.co_varnames) 478 self.assertIn("__not_mangled__", A.f.func_code.co_varnames) 479 self.assertIn("_A__mangled_mod", A.f.func_code.co_varnames) 480 self.assertIn("__package__", A.f.func_code.co_varnames) 481 482 def test_compile_ast(self): 483 fname = __file__ 484 if fname.lower().endswith(('pyc', 'pyo')): 485 fname = fname[:-1] 486 with open(fname, 'r') as f: 487 fcontents = f.read() 488 sample_code = [ 489 ['<assign>', 'x = 5'], 490 ['<print1>', 'print 1'], 491 ['<printv>', 'print v'], 492 ['<printTrue>', 'print True'], 493 ['<printList>', 'print []'], 494 ['<ifblock>', """if True:\n pass\n"""], 495 ['<forblock>', """for n in [1, 2, 3]:\n print n\n"""], 496 ['<deffunc>', """def foo():\n pass\nfoo()\n"""], 497 [fname, fcontents], 498 ] 499 500 for fname, code in sample_code: 501 co1 = compile(code, '%s1' % fname, 'exec') 502 ast = compile(code, '%s2' % fname, 'exec', _ast.PyCF_ONLY_AST) 503 self.assertTrue(type(ast) == _ast.Module) 504 co2 = compile(ast, '%s3' % fname, 'exec') 505 self.assertEqual(co1, co2) 506 # the code object's filename comes from the second compilation step 507 self.assertEqual(co2.co_filename, '%s3' % fname) 508 509 # raise exception when node type doesn't match with compile mode 510 co1 = compile('print 1', '<string>', 'exec', _ast.PyCF_ONLY_AST) 511 self.assertRaises(TypeError, compile, co1, '<ast>', 'eval') 512 513 # raise exception when node type is no start node 514 self.assertRaises(TypeError, compile, _ast.If(), '<ast>', 'exec') 515 516 # raise exception when node has invalid children 517 ast = _ast.Module() 518 ast.body = [_ast.BoolOp()] 519 self.assertRaises(TypeError, compile, ast, '<ast>', 'exec') 520 521 522 def test_main(): 523 test_support.run_unittest(TestSpecifics) 524 525 if __name__ == "__main__": 526 test_main() 527