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