Author: Carl Friedrich Bolz <cfb...@gmx.de>
Branch: 
Changeset: r82793:666871b885d9
Date: 2016-03-05 17:58 +0100
http://bitbucket.org/pypy/pypy/changeset/666871b885d9/

Log:    make method identity the same as equality (since people seem to do
        stuff like cls.__repr__ is object.__repr__, see issue #2253)

diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -13,6 +13,9 @@
 from pypy.interpreter.argument import Arguments
 from rpython.rlib import jit
 
+from rpython.rlib.rarithmetic import LONG_BIT
+from rpython.rlib.rbigint import rbigint
+
 
 funccallunrolling = unrolling_iterable(range(4))
 
@@ -557,6 +560,26 @@
                 return space.w_False
         return space.eq(self.w_function, w_other.w_function)
 
+    def is_w(self, space, other):
+        if not isinstance(other, Method):
+            return False
+        return (self.w_instance is other.w_instance and
+                self.w_function is other.w_function and
+                self.w_class is other.w_class)
+
+    def immutable_unique_id(self, space):
+        from pypy.objspace.std.util import IDTAG_METHOD as tag
+        from pypy.objspace.std.util import IDTAG_SHIFT
+        if self.w_instance is not None:
+            id = space.bigint_w(space.id(self.w_instance))
+            id.lshift(LONG_BIT)
+        else:
+            id = rbigint.fromint(0)
+        id = id.or_(space.bigint_w(space.id(self.w_function)))
+        id = id.lshift(LONG_BIT).or_(space.bigint_w(space.id(self.w_class)))
+        id = id.lshift(IDTAG_SHIFT).int_or_(tag)
+        return space.newlong_from_rbigint(id)
+
     def descr_method_hash(self):
         space = self.space
         w_result = space.hash(self.w_function)
diff --git a/pypy/interpreter/test/test_function.py 
b/pypy/interpreter/test/test_function.py
--- a/pypy/interpreter/test/test_function.py
+++ b/pypy/interpreter/test/test_function.py
@@ -552,6 +552,37 @@
         assert A().m == X()
         assert X() == A().m
 
+    @pytest.mark.skipif("config.option.runappdirect")
+    def test_method_identity(self):
+        class A(object):
+            def m(self):
+                pass
+            def n(self):
+                pass
+
+        class B(A):
+            pass
+
+        class X(object):
+            def __eq__(self, other):
+                return True
+
+        a = A()
+        a2 = A()
+        assert a.m is a.m
+        assert id(a.m) == id(a.m)
+        assert a.m is not a.n
+        assert id(a.m) != id(a.n)
+        assert a.m is not a2.m
+        assert id(a.m) != id(a2.m)
+
+        assert A.m is A.m
+        assert id(A.m) == id(A.m)
+        assert A.m is not A.n
+        assert id(A.m) != id(A.n)
+        assert A.m is not B.m
+        assert id(A.m) != id(B.m)
+
 
 class TestMethod:
     def setup_method(self, method):
diff --git a/pypy/objspace/std/util.py b/pypy/objspace/std/util.py
--- a/pypy/objspace/std/util.py
+++ b/pypy/objspace/std/util.py
@@ -2,12 +2,13 @@
 
 from pypy.interpreter.error import OperationError, oefmt
 
-IDTAG_SHIFT   = 3
+IDTAG_SHIFT   = 4
 
 IDTAG_INT     = 1
 IDTAG_LONG    = 3
 IDTAG_FLOAT   = 5
 IDTAG_COMPLEX = 7
+IDTAG_METHOD  = 9
 
 CMP_OPS = dict(lt='<', le='<=', eq='==', ne='!=', gt='>', ge='>=')
 BINARY_BITWISE_OPS = {'and': '&', 'lshift': '<<', 'or': '|', 'rshift': '>>',
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to