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