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

Reply via email to