Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(2)

Side by Side Diff: Lib/test/test_compile.py

Issue 25843: lambdas on the same line may incorrectly share code objects
Patch Set: Created 4 years ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Include/code.h ('k') | Objects/codeobject.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 import math 1 import math
2 import os 2 import os
3 import unittest 3 import unittest
4 import sys 4 import sys
5 import _ast 5 import _ast
6 import tempfile 6 import tempfile
7 import types 7 import types
8 from test import support 8 from test import support
9 from test.support import script_helper 9 from test.support import script_helper
10 10
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 code = compile(memoryview(b"1234")[1:-1], "<dummy>", "eval") 564 code = compile(memoryview(b"1234")[1:-1], "<dummy>", "eval")
565 self.assertEqual(eval(code), 23) 565 self.assertEqual(eval(code), 23)
566 code = compile(memoryview(b"$23$")[1:-1], "<dummy>", "eval") 566 code = compile(memoryview(b"$23$")[1:-1], "<dummy>", "eval")
567 self.assertEqual(eval(code), 23) 567 self.assertEqual(eval(code), 23)
568 568
569 # Also test when eval() and exec() do the compilation step 569 # Also test when eval() and exec() do the compilation step
570 self.assertEqual(eval(memoryview(b"1234")[1:-1]), 23) 570 self.assertEqual(eval(memoryview(b"1234")[1:-1]), 23)
571 namespace = dict() 571 namespace = dict()
572 exec(memoryview(b"ax = 123")[1:-1], namespace) 572 exec(memoryview(b"ax = 123")[1:-1], namespace)
573 self.assertEqual(namespace['x'], 12) 573 self.assertEqual(namespace['x'], 12)
574
575 def check_constant(self, func, expected):
576 for const in func.__code__.co_consts:
577 if repr(const) == repr(expected):
578 break
579 else:
580 self.fail("unable to find constant %r in %r"
581 % (expected, func.__code__.co_consts))
582
583 # Merging equal constants is not a strict requirements for the Python
584 # semantics, it's a more an implementation detail.
585 @support.cpython_only
586 def test_merge_constants(self):
587 # Issue #25843: compile() must merge constants which are equal
588 # and have the same type.
589
590 def check_same_constant(const):
591 ns = {}
592 code = "f1, f2 = lambda: %r, lambda: %r" % (const, const)
593 exec(code, ns)
594 f1 = ns['f1']
595 f2 = ns['f2']
596 self.assertIs(f1.__code__, f2.__code__)
597 self.check_constant(f1, const)
598 self.assertEqual(repr(f1()), repr(const))
599
600 check_same_constant(None)
601 check_same_constant(0)
602 check_same_constant(0.0)
603 check_same_constant(b'abc')
604 check_same_constant('abc')
605
606 # Note: "lambda: ..." emits "LOAD_CONST Ellipsis",
607 # whereas "lambda: Ellipsis" emits "LOAD_GLOBAL Ellipsis"
608 f1, f2 = lambda: ..., lambda: ...
609 self.assertIs(f1.__code__, f2.__code__)
610 self.check_constant(f1, Ellipsis)
611 self.assertEqual(repr(f1()), repr(Ellipsis))
612
613 # {0} is converted to a constant frozenset({0}) by the peephole
614 # optimizer
615 f1, f2 = lambda x: x in {0}, lambda x: x in {0}
616 self.assertIs(f1.__code__, f2.__code__)
617 self.check_constant(f1, frozenset({0}))
618 self.assertTrue(f1(0))
619
620 def test_dont_merge_constants(self):
621 # Issue #25843: compile() must not merge constants which are equal
622 # but have a different type.
623
624 def check_different_constants(const1, const2):
625 ns = {}
626 exec("f1, f2 = lambda: %r, lambda: %r" % (const1, const2), ns)
627 f1 = ns['f1']
628 f2 = ns['f2']
629 self.assertIsNot(f1.__code__, f2.__code__)
630 self.check_constant(f1, const1)
631 self.check_constant(f2, const2)
632 self.assertEqual(repr(f1()), repr(const1))
633 self.assertEqual(repr(f2()), repr(const2))
634
635 check_different_constants(0, 0.0)
636 check_different_constants(+0.0, -0.0)
637 check_different_constants((0,), (0.0,))
638
639 # check_different_constants() cannot be used because repr(-0j) is
640 # '(-0-0j)', but when '(-0-0j)' is evaluated to 0j: we loose the sign.
641 f1, f2 = lambda: +0.0j, lambda: -0.0j
642 self.assertIsNot(f1.__code__, f2.__code__)
643 self.check_constant(f1, +0.0j)
644 self.check_constant(f2, -0.0j)
645 self.assertEqual(repr(f1()), repr(+0.0j))
646 self.assertEqual(repr(f2()), repr(-0.0j))
647
648 # {0} is converted to a constant frozenset({0}) by the peephole
649 # optimizer
650 f1, f2 = lambda x: x in {0}, lambda x: x in {0.0}
651 self.assertIsNot(f1.__code__, f2.__code__)
652 self.check_constant(f1, frozenset({0}))
653 self.check_constant(f2, frozenset({0.0}))
654 self.assertTrue(f1(0))
655 self.assertTrue(f2(0.0))
574 656
575 657
576 class TestStackSize(unittest.TestCase): 658 class TestStackSize(unittest.TestCase):
577 # These tests check that the computed stack size for a code object 659 # These tests check that the computed stack size for a code object
578 # stays within reasonable bounds (see issue #21523 for an example 660 # stays within reasonable bounds (see issue #21523 for an example
579 # dysfunction). 661 # dysfunction).
580 N = 100 662 N = 100
581 663
582 def check_stack_size(self, code): 664 def check_stack_size(self, code):
583 # To assert that the alleged stack size is not O(N), we 665 # To assert that the alleged stack size is not O(N), we
(...skipping 22 matching lines...) Expand all
606 self.check_stack_size("x + " * self.N + "x") 688 self.check_stack_size("x + " * self.N + "x")
607 689
608 def test_func_and(self): 690 def test_func_and(self):
609 code = "def f(x):\n" 691 code = "def f(x):\n"
610 code += " x and x\n" * self.N 692 code += " x and x\n" * self.N
611 self.check_stack_size(code) 693 self.check_stack_size(code)
612 694
613 695
614 if __name__ == "__main__": 696 if __name__ == "__main__":
615 unittest.main() 697 unittest.main()
OLDNEW
« no previous file with comments | « Include/code.h ('k') | Objects/codeobject.c » ('j') | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+