New submission from Christian Heimes:
Here is a first patch to remove unbound method objects.
6 tests failed:
test_descr test_inspect test_pyclbr test_typechecks test_unittest
test_weakref
----------
assignee: gvanrossum
components: Interpreter Core
files: py3k_remove_unbound.patch
keywords: patch, py3k
messages: 57798
nosy: gvanrossum, tiran
priority: high
severity: normal
status: open
title: Patch to remove unbound methods
type: rfe
versions: Python 3.0
Added file: http://bugs.python.org/file8799/py3k_remove_unbound.patch
__________________________________
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1493>
__________________________________
Index: Objects/funcobject.c
===================================================================
--- Objects/funcobject.c (Revision 59163)
+++ Objects/funcobject.c (Arbeitskopie)
@@ -643,8 +643,10 @@
static PyObject *
func_descr_get(PyObject *func, PyObject *obj, PyObject *type)
{
- if (obj == Py_None)
- obj = NULL;
+ if (obj == Py_None || obj == NULL) {
+ Py_INCREF(func);
+ return func;
+ }
return PyMethod_New(func, obj, type);
}
Index: Lib/DocXMLRPCServer.py
===================================================================
--- Lib/DocXMLRPCServer.py (Revision 59163)
+++ Lib/DocXMLRPCServer.py (Arbeitskopie)
@@ -74,7 +74,7 @@
title = '<a name="%s"><strong>%s</strong></a>' % (anchor, name)
if inspect.ismethod(object):
- args, varargs, varkw, defaults = inspect.getargspec(object.im_func)
+ args, varargs, varkw, defaults = inspect.getargspec(object)
# exclude the argument bound to the instance, it will be
# confusing to the non-Python user
argspec = inspect.formatargspec (
Index: Lib/test/test_extcall.py
===================================================================
--- Lib/test/test_extcall.py (Revision 59163)
+++ Lib/test/test_extcall.py (Arbeitskopie)
@@ -231,18 +231,8 @@
x = Foo()
print(Foo.method(*(x, 1, 2)))
print(Foo.method(x, *(1, 2)))
-try:
- print(Foo.method(*(1, 2, 3)))
-except TypeError as err:
- pass
-else:
- print('expected a TypeError for unbound method call')
-try:
- print(Foo.method(1, *(2, 3)))
-except TypeError as err:
- pass
-else:
- print('expected a TypeError for unbound method call')
+print(Foo.method(*(1, 2, 3)))
+print(Foo.method(1, *(2, 3)))
# A PyCFunction that takes only positional parameters should allow an
# empty keyword dictionary to pass without a complaint, but raise a
Index: Lib/test/test_repr.py
===================================================================
--- Lib/test/test_repr.py (Revision 59163)
+++ Lib/test/test_repr.py (Arbeitskopie)
@@ -280,8 +280,8 @@
''')
from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import qux
# Unbound methods first
- eq(repr(qux.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod),
- '<unbound method aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod>')
+ self.failUnless(repr(qux.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod).startswith(
+ '<function amethod'))
# Bound method next
iqux = qux.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()
self.failUnless(repr(iqux.amethod).startswith(
Index: Lib/test/test_descrtut.py
===================================================================
--- Lib/test/test_descrtut.py (Revision 59163)
+++ Lib/test/test_descrtut.py (Arbeitskopie)
@@ -444,9 +444,7 @@
... B.foo(self)
>>> C().foo()
-Traceback (most recent call last):
- ...
-TypeError: unbound method foo() must be called with B instance as first argument (got C instance instead)
+called A.foo()
>>> class C(A):
... def foo(self):
Index: Lib/test/test_descr.py
===================================================================
--- Lib/test/test_descr.py (Revision 59163)
+++ Lib/test/test_descr.py (Arbeitskopie)
@@ -280,12 +280,12 @@
c = C()
vereq(interesting(dir(c)), cstuff)
- verify('im_self' in dir(C.Cmethod))
+ #verify('im_self' in dir(C.Cmethod))
c.cdata = 2
c.cmethod = lambda self: 0
vereq(interesting(dir(c)), cstuff + ['cdata', 'cmethod'])
- verify('im_self' in dir(c.Cmethod))
+ #verify('im_self' in dir(c.Cmethod))
class A(C):
Adata = 1
@@ -293,13 +293,13 @@
astuff = ['Adata', 'Amethod'] + cstuff
vereq(interesting(dir(A)), astuff)
- verify('im_self' in dir(A.Amethod))
+ #verify('im_self' in dir(A.Amethod))
a = A()
vereq(interesting(dir(a)), astuff)
a.adata = 42
a.amethod = lambda self: 3
vereq(interesting(dir(a)), astuff + ['adata', 'amethod'])
- verify('im_self' in dir(a.Amethod))
+ #verify('im_self' in dir(a.Amethod))
# Try a module subclass.
import sys
@@ -1504,8 +1504,11 @@
vereq(D.foo(d, 1), (d, 1))
class E: # *not* subclassing from C
foo = C.foo
- vereq(E().foo, C.foo) # i.e., unbound
- verify(repr(C.foo.__get__(C())).startswith("<bound method "))
+ r = repr(E().foo)
+ verify(r.startswith("<bound method E.foo "), r)
+ r = repr(C.foo.__get__(C()))
+ # XXX <bound method ?.foo of <__main__.C object at ...>>
+ verify(r.startswith("<bound method C.foo "), r)
def compattr():
if verbose: print("Testing computed attributes...")
@@ -1685,8 +1688,10 @@
vereq(d2.goo(), 1)
class E(object):
foo = C.foo
- vereq(E().foo, C.foo) # i.e., unbound
- verify(repr(C.foo.__get__(C(1))).startswith("<bound method "))
+ vereq(E().foo.im_func, C.foo) # i.e., unbound
+ r = repr(C.foo.__get__(C(1)))
+ # XXX <bound method ?.foo of <__main__.C object at ...c>>
+ verify(r.startswith("<bound method C.foo "), r)
def specials():
# Test operators like __hash__ for which a built-in default exists
Index: Lib/test/test_inspect.py
===================================================================
--- Lib/test/test_inspect.py (Revision 59163)
+++ Lib/test/test_inspect.py (Arbeitskopie)
@@ -395,7 +395,8 @@
self.assert_(('s', 'static method', A) in attrs, 'missing static method')
self.assert_(('c', 'class method', A) in attrs, 'missing class method')
self.assert_(('p', 'property', A) in attrs, 'missing property')
- self.assert_(('m', 'method', A) in attrs, 'missing plain method')
+ self.assert_(('m', 'method', A) in attrs,
+ 'missing plain method: %r' % attrs)
self.assert_(('m1', 'method', A) in attrs, 'missing plain method')
self.assert_(('datablob', 'data', A) in attrs, 'missing data')
Index: Lib/test/output/test_extcall
===================================================================
--- Lib/test/output/test_extcall (Revision 59163)
+++ Lib/test/output/test_extcall (Arbeitskopie)
@@ -38,6 +38,8 @@
3 512 True
3
3
+5
+5
za () {} -> za() takes exactly 1 positional argument (0 given)
za () {'a': 'aa'} -> ok za aa B D E V a
za () {'d': 'dd'} -> za() got an unexpected keyword argument 'd'
Index: Lib/test/inspect_fodder2.py
===================================================================
--- Lib/test/inspect_fodder2.py (Revision 59163)
+++ Lib/test/inspect_fodder2.py (Arbeitskopie)
@@ -96,7 +96,7 @@
"doc"
return 42
return X
-method_in_dynamic_class = f().g.im_func
+method_in_dynamic_class = f().g
#line 101
def keyworded(*arg1, arg2=1):
Index: Lib/test/test_class.py
===================================================================
--- Lib/test/test_class.py (Revision 59163)
+++ Lib/test/test_class.py (Arbeitskopie)
@@ -552,7 +552,7 @@
self.assertEquals(hash(B.f), hash(A.f))
# the following triggers a SystemError in 2.4
- a = A(hash(A.f.im_func)^(-1))
+ a = A(hash(A.f)^(-1))
hash(a.f)
def test_main():
Index: Lib/test/test_funcattrs.py
===================================================================
--- Lib/test/test_funcattrs.py (Revision 59163)
+++ Lib/test/test_funcattrs.py (Arbeitskopie)
@@ -67,14 +67,9 @@
# In Python 2.1 beta 1, we disallowed setting attributes on unbound methods
# (it was already disallowed on bound methods). See the PEP for details.
-try:
- F.a.publish = 1
-except (AttributeError, TypeError): pass
-else: raise TestFailed('expected AttributeError or TypeError')
+# In Python 3.0 unbound methods are gone.
+F.a.publish = 1
-# But setting it explicitly on the underlying function object is okay.
-F.a.im_func.publish = 1
-
if F.a.publish != 1:
raise TestFailed('unbound method attribute not set to expected value')
@@ -92,31 +87,9 @@
except (AttributeError, TypeError): pass
else: raise TestFailed('expected AttributeError or TypeError')
-# See the comment above about the change in semantics for Python 2.1b1
-try:
- F.a.myclass = F
-except (AttributeError, TypeError): pass
-else: raise TestFailed('expected AttributeError or TypeError')
-
-F.a.im_func.myclass = F
-
-f1.a.myclass
-f2.a.myclass
-f1.a.myclass
-F.a.myclass
-
-if f1.a.myclass is not f2.a.myclass or \
- f1.a.myclass is not F.a.myclass:
- raise TestFailed('attributes were not the same')
-
# try setting __dict__
-try:
- F.a.__dict__ = (1, 2, 3)
-except (AttributeError, TypeError): pass
-else: raise TestFailed('expected TypeError or AttributeError')
+F.a.__dict__ = {'one': 11, 'two': 22, 'three': 33}
-F.a.im_func.__dict__ = {'one': 11, 'two': 22, 'three': 33}
-
if f1.a.two != 22:
raise TestFailed('setting __dict__')
@@ -315,9 +288,9 @@
def test_im_class():
class C:
def foo(self): pass
- verify(C.foo.im_class is C)
+ #verify(C.foo.im_class is C)
verify(C().foo.im_class is C)
- cantset(C.foo, "im_class", C)
+ #cantset(C.foo, "im_class", C)
cantset(C().foo, "im_class", C)
def test_im_func():
@@ -325,19 +298,19 @@
class C:
pass
C.foo = foo
- verify(C.foo.im_func is foo)
+ #verify(C.foo.im_func is foo)
verify(C().foo.im_func is foo)
- cantset(C.foo, "im_func", foo)
+ #cantset(C.foo, "im_func", foo)
cantset(C().foo, "im_func", foo)
def test_im_self():
class C:
def foo(self): pass
- verify(C.foo.im_self is None)
+ #verify(C.foo.im_self is None)
c = C()
- verify(c.foo.im_self is c)
- cantset(C.foo, "im_self", None)
- cantset(c.foo, "im_self", c)
+ #verify(c.foo.im_self is c)
+ #cantset(C.foo, "im_self", None)
+ #cantset(c.foo, "im_self", c)
def test_im_dict():
class C:
@@ -345,24 +318,24 @@
foo.bar = 42
verify(C.foo.__dict__ == {'bar': 42})
verify(C().foo.__dict__ == {'bar': 42})
- cantset(C.foo, "__dict__", C.foo.__dict__)
- cantset(C().foo, "__dict__", C.foo.__dict__)
+ #cantset(C.foo, "__dict__", C.foo.__dict__)
+ #cantset(C().foo, "__dict__", C.foo.__dict__)
def test_im_doc():
class C:
def foo(self): "hello"
verify(C.foo.__doc__ == "hello")
verify(C().foo.__doc__ == "hello")
- cantset(C.foo, "__doc__", "hello")
- cantset(C().foo, "__doc__", "hello")
+ #cantset(C.foo, "__doc__", "hello")
+ #cantset(C().foo, "__doc__", "hello")
def test_im_name():
class C:
def foo(self): pass
verify(C.foo.__name__ == "foo")
verify(C().foo.__name__ == "foo")
- cantset(C.foo, "__name__", "foo")
- cantset(C().foo, "__name__", "foo")
+ #cantset(C.foo, "__name__", "foo")
+ #cantset(C().foo, "__name__", "foo")
def testmore():
test_func_closure()
Index: Lib/test/test_sys.py
===================================================================
--- Lib/test/test_sys.py (Revision 59163)
+++ Lib/test/test_sys.py (Arbeitskopie)
@@ -183,7 +183,7 @@
self.assertRaises(TypeError, sys._getframe, 42, 42)
self.assertRaises(ValueError, sys._getframe, 2000000000)
self.assert_(
- SysModuleTest.test_getframe.im_func.__code__ \
+ SysModuleTest.test_getframe.__code__ \
is sys._getframe().f_code
)
Index: Lib/xml/dom/minicompat.py
===================================================================
--- Lib/xml/dom/minicompat.py (Revision 59163)
+++ Lib/xml/dom/minicompat.py (Arbeitskopie)
@@ -95,7 +95,7 @@
def defproperty(klass, name, doc):
- get = getattr(klass, ("_get_" + name)).im_func
+ get = getattr(klass, ("_get_" + name))
def set(self, value, name=name):
raise xml.dom.NoModificationAllowedErr(
"attempt to modify read-only attribute " + repr(name))
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com