[pypy-commit] pypy default: (Alex_Gaynor, antocuni): special-case type.__eq__ so that type (and subclasses) are marked as compares_by_identity()

antocuni noreply at buildbot.pypy.org
Wed Jul 27 14:38:50 CEST 2011


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: 
Changeset: r46015:bb9c6a2bd529
Date: 2011-07-27 14:39 +0200
http://bitbucket.org/pypy/pypy/changeset/bb9c6a2bd529/

Log:	(Alex_Gaynor, antocuni): special-case type.__eq__ so that type (and
	subclasses) are marked as compares_by_identity()

diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -35,6 +35,13 @@
     return w_hash
 object_hash._annspecialcase_ = 'specialize:memo'
 
+def type_eq(space):
+    "Utility that returns the app-level descriptor type.__eq__."
+    w_src, w_eq = space.lookup_in_type_where(space.w_type,
+                                             '__eq__')
+    return w_eq
+type_eq._annspecialcase_ = 'specialize:memo'
+
 def raiseattrerror(space, w_obj, name, w_descr=None):
     w_type = space.type(w_obj)
     typename = w_type.getname(space)
diff --git a/pypy/objspace/std/test/test_identitydict.py b/pypy/objspace/std/test/test_identitydict.py
--- a/pypy/objspace/std/test/test_identitydict.py
+++ b/pypy/objspace/std/test/test_identitydict.py
@@ -32,10 +32,20 @@
             def __hash__(self):
                 return 0
 
+        class TypeSubclass(type):
+            pass
+
+        class TypeSubclassCustomCmp(type):
+            def __cmp__(self, other):
+                return 0
+
         assert self.compares_by_identity(Plain)
         assert not self.compares_by_identity(CustomEq)
         assert not self.compares_by_identity(CustomCmp)
         assert not self.compares_by_identity(CustomHash)
+        assert self.compares_by_identity(type)
+        assert self.compares_by_identity(TypeSubclass)
+        assert not self.compares_by_identity(TypeSubclassCustomCmp)
 
     def test_modify_class(self):
         class X(object):
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
@@ -173,8 +173,6 @@
             # ^^^ conservative default, fixed during real usage
 
         if space.config.objspace.std.withidentitydict:
-            did_compare_by_identity = (
-                w_self.compares_by_identity_status == COMPARES_BY_IDENTITY)
             if (key is None or key == '__eq__' or
                 key == '__cmp__' or key == '__hash__'):
                 w_self.compares_by_identity_status = UNKNOWN
@@ -229,7 +227,7 @@
         return w_self.getattribute_if_not_from_object() is None
 
     def compares_by_identity(w_self):
-        from pypy.objspace.descroperation import object_hash
+        from pypy.objspace.descroperation import object_hash, type_eq
         if not w_self.space.config.objspace.std.withidentitydict:
             return False # conservative
         #
@@ -238,7 +236,9 @@
             return w_self.compares_by_identity_status == COMPARES_BY_IDENTITY
         #
         default_hash = object_hash(w_self.space)
-        overrides_eq_cmp_or_hash = (w_self.lookup('__eq__') or
+        my_eq = w_self.lookup('__eq__')
+        overrides_eq = (my_eq and my_eq is not type_eq(w_self.space))
+        overrides_eq_cmp_or_hash = (overrides_eq or
                                     w_self.lookup('__cmp__') or
                                     w_self.lookup('__hash__') is not default_hash)
         if overrides_eq_cmp_or_hash:


More information about the pypy-commit mailing list