Antonio Cuni avatar Antonio Cuni committed 6a28c75

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

Comments (0)

Files changed (4)

pypy/objspace/std/objecttype.py

     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'",

pypy/objspace/std/objspace.py

     """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):
         # 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()
         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()

pypy/objspace/std/test/test_typeobject.py

         # 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

pypy/objspace/std/typeobject.py

                                             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
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.