Issue1605019

classification
Title: assigning a bound method to a class rebinds to instances
Type: Severity: normal
Components: Core Versions:
Milestone:
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: cgroves Nosy List: cgroves, kzuberi, leouserz, pedronis
Priority: normal Keywords:

Created on 2006-11-29.05:47:23 by cgroves, last changed 2007-01-31.04:44:16 by cgroves.

Messages
msg1336 (view) Author: Charlie Groves (cgroves) Date: 2006-11-29.05:47:23
Assigning a method bound to an instance of a class C to a class D rebinds the method to instances of D instead of using the already bound instance C.  This causes methods in test_descr to fail.
msg1337 (view) Author: Deleted User leouserz (leouserz) Date: 2006-12-20.19:12:56
Im trying to understand the bug here.  Ive got a test case together:
class x:
    def zoom1(self):
        print self

class z:
    pass

a = x()
a.zoom1()

t = z()
z.zoom1 = a.zoom1
t.zoom1()

and they do the same thing for me in Python as in Jython.

leouser
msg1338 (view) Author: Khalid Zuberi (kzuberi) Date: 2006-12-20.19:25:35

Leo, if you haven't already, try running the test 'methods()' from test_descr.py (which currently fails for me) and see if you can find the cause of the failure.

- kz
msg1339 (view) Author: Deleted User leouserz (leouserz) Date: 2006-12-20.20:05:36
Ahh, I see the bug.  This is odd, since I would expect a PyMethod to be there, which would be bound to C.  Ill have to see what's up.

leouser
msg1340 (view) Author: Deleted User leouserz (leouserz) Date: 2006-12-20.20:41:55
Well, the method is created in PyMethod _doget.

From altering this line in _doget:
if (__builtin__.issubclass(container.fastGetClass(), im_class))

To:
if (__builtin__.issubclass(container.fastGetClass(), im_class) && im_self == null){

the code moves further along in the test, but bombs here:
verify(repr(C.foo.__get__(C(1))).startswith("<bound method "))

at the last line in methods.  Ill see what the deal is here.


Im trying to think if the == null makes sense as a test.  It guards against the problem, but what else can go wrong. 

leouser
msg1341 (view) Author: Deleted User leouserz (leouserz) Date: 2006-12-20.20:56:56
Ahh, I see the bug.  This is odd, since I would expect a PyMethod to be there, which would be bound to C.  Ill have to see what's up.

leouser
msg1342 (view) Author: Deleted User leouserz (leouserz) Date: 2006-12-20.21:33:43
The final bomb can be navigated through by giving the PyMethod a dictionary with a __get__ function.  This in turn requires _doget to be further enhanced to create a new PyMethod if the container is null but wherefrom is not null.  wherefrom is used as the "self" argument.  Also the toString needs to return a "bound method" instead of a "method" string.

Im trying to locate the spec for a unbound methods + __get__ invocations to see if there is clear behavior as what to do with it.

leouser
msg1343 (view) Author: Deleted User leouserz (leouserz) Date: 2006-12-20.21:51:35
oh yeah,

there are worlds of differences between CPython and Jythons bound and unbound methods:
Jython:
>>> class x:
...    def zoo(self):
...       print "Zoo"
>>> a = x.zoo
>>> dir(a)
['__dict__', '__doc__', '__name__', 'im_class', 'im_func', 'im_self']

Python:
>>> class z:
...    def mork(self):
...      print "mork"
...
>>> x = z.mork
['__call__', '__class__', '__cmp__', '__delattr__', '__doc__', '__get__', '__get attribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'im_class', 'im_func', 'im_self']

leouser
msg1344 (view) Author: Deleted User leouserz (leouserz) Date: 2006-12-21.00:15:57
This article is instructive about descriptors:
http://users.rcn.com/python/download/Descriptor.htm

It appears that unbound methods are descriptors and if passed in an Object it they need to create a bound method to the Object.

leouser
msg1345 (view) Author: Samuele Pedroni (pedronis) Date: 2006-12-21.05:55:52
the problem is very simple

a) further calls on the __get__ behavior of a bound method should simply return the bound method untouched
   (see 
    http://svn.python.org/view/python/trunk/Objects/classobject.c  instancemethod_descr_get
    or https://codespeak.net/viewvc/pypy/dist/pypy/interpreter/function.py  def descr_method_get)

b) PyMethod is still 2.1 code, it needs to be converted to new-style conventions
msg1346 (view) Author: Charlie Groves (cgroves) Date: 2007-01-31.04:44:16
Fixed in r3067.  
History
Date User Action Args
2006-11-29 05:47:23cgrovescreate