[pypy-commit] pypy identity-dict-strategy: update the global version counter if we change the class of an object whose old class was tracked as compares_by_identity

antocuni noreply at buildbot.pypy.org
Tue Jul 19 18:44:22 CEST 2011


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: identity-dict-strategy
Changeset: r45744:6a28c75d117e
Date: 2011-07-19 18:30 +0200
http://bitbucket.org/pypy/pypy/changeset/6a28c75d117e/

Log:	update the global version counter if we change the class of an
	object whose old class was tracked as compares_by_identity

diff --git a/pypy/objspace/std/objecttype.py b/pypy/objspace/std/objecttype.py
--- a/pypy/objspace/std/objecttype.py
+++ b/pypy/objspace/std/objecttype.py
@@ -43,6 +43,9 @@
     assert isinstance(w_oldcls, W_TypeObject)
     if w_oldcls.get_full_instance_layout() == w_newcls.get_full_instance_layout():
         w_obj.setclass(space, w_newcls)
+        if space.config.objspace.std.trackcomparebyidentity:
+            if not w_oldcls.overrides_hash_eq_or_cmp and not w_newcls.compares_by_identity():
+                space.bump_compares_by_identity_version()
     else:
         raise operationerrfmt(space.w_TypeError,
                               "__class__ assignment: '%s' object layout differs from '%s'",
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -43,6 +43,13 @@
     """The standard object space, implementing a general-purpose object
     library in Restricted Python."""
 
+    # a global version counter to track live instances which "compare by
+    # identity" (i.e., whose __eq__, __cmp__ and __hash__ are the default
+    # ones).  The idea is to track only classes for which we checked the
+    # compares_by_identity() status at least once: we increment the version if
+    # its status might change, e.g. because we set one of those attributes.
+    # The actual work is done by W_TypeObject.mutated() and
+    # objecttype:descr_setclass
     compares_by_identity_version = None
 
     def initialize(self):
@@ -81,14 +88,8 @@
         # the type of old-style classes
         self.w_classobj = self.builtin.get('__metaclass__')
 
-        # a global version counter to track live instances which "compare by
-        # identity" (i.e., whose __eq__, __cmp__ and __hash__ are the default
-        # ones).  The idea is to track only classes for which we checked the
-        # compares_by_identity() status at least once: we increment the
-        # version if its status might change, e.g. because we set one of those
-        # attributes.  The actual work is done by W_TypeObject.mutated()
         if self.config.objspace.std.trackcomparebyidentity:
-            self.compares_by_identity_version = VersionTag()
+            self.bump_compares_by_identity_version()
 
         # final setup
         self.setup_builtin_modules()
@@ -579,3 +580,6 @@
         if isinstance(w_sub, W_TypeObject) and isinstance(w_type, W_TypeObject):
             return self.wrap(w_sub.issubtype(w_type))
         raise OperationError(self.w_TypeError, self.wrap("need type objects"))
+
+    def bump_compares_by_identity_version(self):
+        self.compares_by_identity_version = VersionTag()
diff --git a/pypy/objspace/std/test/test_typeobject.py b/pypy/objspace/std/test/test_typeobject.py
--- a/pypy/objspace/std/test/test_typeobject.py
+++ b/pypy/objspace/std/test/test_typeobject.py
@@ -1279,3 +1279,22 @@
         # version
         Y.__eq__ = lambda x: None
         assert self.get_version() == 2
+
+    def test_change___class__(self):
+        class X(object):
+            pass
+
+        class Y(object):
+            pass
+
+        class Z(object):
+            def __eq__(self, other):
+                pass
+
+        x = X()
+        assert self.compares_by_identity(X)
+        assert self.get_version() == 0
+        x.__class__ = Y
+        assert self.get_version() == 0
+        x.__class__ = Z
+        assert self.get_version() == 1
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -175,7 +175,7 @@
                                             key == '__cmp__' or
                                             key == '__hash__'):
                 w_self.overrides_hash_eq_or_cmp = True
-                w_self.space.compares_by_identity_version = VersionTag()
+                w_self.space.bump_compares_by_identity_version()
                 
         if space.config.objspace.std.newshortcut:
             w_self.w_bltin_new = None


More information about the pypy-commit mailing list