Author: Armin Rigo <[email protected]>
Branch:
Changeset: r91976:e71aec0042dd
Date: 2017-07-27 15:48 +0200
http://bitbucket.org/pypy/pypy/changeset/e71aec0042dd/
Log: Issue #2619
Experimental: remove the special case for the identity of *bound*
method objects. This depends on CPython, where it seems that no
strange internal type exists where the equivalent of ``x.method is
x.method`` would return True. (This is unlike unbound methods, where
e.g. ``list.append is list.append`` returns True; this is why the
special case remains for *unbound* method objects.)
diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -330,7 +330,7 @@
- ``frozenset`` (empty frozenset only)
- - unbound and bound method objects
+ - unbound method objects
This change requires some changes to ``id`` as well. ``id`` fulfills the
following condition: ``x is y <=> id(x) == id(y)``. Therefore ``id`` of the
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -559,21 +559,29 @@
return space.newbool(space.eq_w(self.w_function, w_other.w_function))
def is_w(self, space, other):
+ if self.w_instance is not None:
+ return W_Root.is_w(self, space, other)
+ # The following special-case is only for *unbound* method objects.
+ # Motivation: in CPython, it seems that no strange internal type
+ # exists where the equivalent of ``x.method is x.method`` would
+ # return True. This is unlike unbound methods, where e.g.
+ # ``list.append is list.append`` returns True. The following code
+ # is here to emulate that behaviour. Unlike CPython, we return
+ # True for all equal unbound methods, not just for built-in types.
if not isinstance(other, Method):
return False
- return (self.w_instance is other.w_instance and
+ return (other.w_instance is None 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
+ if self.w_instance is not None:
+ return W_Root.immutable_unique_id(self, space)
+ # the special-case is only for *unbound* method objects
+ #
+ from pypy.objspace.std.util import IDTAG_UNBOUND_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 = id.lshift(LONG_BIT)
- else:
- id = rbigint.fromint(0)
- id = id.or_(space.bigint_w(space.id(self.w_function)))
+ id = 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)
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
@@ -1,4 +1,4 @@
-import pytest
+import pytest, sys
from pypy.interpreter import eval
from pypy.interpreter.function import Function, Method, descr_function_get
from pypy.interpreter.pycode import PyCode
@@ -342,6 +342,11 @@
raises(ValueError, type(f).__setstate__, f, (1, 2, 3))
class AppTestMethod:
+ def setup_class(cls):
+ cls.w_runappdirect_on_cpython = cls.space.wrap(
+ cls.runappdirect and
+ '__pypy__' not in sys.builtin_module_names)
+
def test_simple_call(self):
class A(object):
def func(self, arg2):
@@ -572,7 +577,6 @@
assert meth == meth
assert meth == MethodType(func, object)
- @pytest.mark.skipif("config.option.runappdirect")
def test_method_identity(self):
class A(object):
def m(self):
@@ -589,19 +593,24 @@
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)
+ x = a.m; y = a.m
+ assert x is not y
+ assert id(x) != id(y)
+ assert x == y
+ assert x is not a.n
+ assert id(x) != id(a.n)
+ assert x is not a2.m
+ assert id(x) != 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)
+ if not self.runappdirect_on_cpython:
+ assert A.m is A.m
+ assert id(A.m) == id(A.m)
+ assert A.m == A.m
+ x = A.m
+ assert x is not A.n
+ assert id(x) != id(A.n)
+ assert x is not B.m
+ assert id(x) != id(B.m)
class TestMethod:
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
@@ -8,7 +8,7 @@
IDTAG_LONG = 3
IDTAG_FLOAT = 5
IDTAG_COMPLEX = 7
-IDTAG_METHOD = 9
+IDTAG_UNBOUND_METHOD = 9
IDTAG_SPECIAL = 11 # -1 - (-maxunicode-1): unichar
# 0 - 255: char
# 256: empty string
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit