Um, my brain just did a double-take. Standard Python doesn't let you do that, so you must be changing some internals. Which parts of Python are you trying to change and which parts are you trying to keep unchanged? If you were using a different metaclass you could just create a different implementation of instancemethod that does what you want, so apparently you're not going that route. (With new-style classes, instancemethod isn't that special any more -- it's just a currying construct with some extra baggage.)
No no no, I'm not fiddling around with any internals, here. I just want to use the machinary as it is, and to be able to pickle almost everything.
So, if somebody did a v=C().x, I have that variable around. In order to pickle it, I ask for its __reduce__, or in other words, I don't ask for it, I try to supply it, so the pickling engine can find it.
But how, I wonder, are you providing it? You can't subclass instancemethod -- how do you manage to add a __reduce__ method to it without fiddling with any internals?
My expectation is that C().x.__reduce__ gives me the bound __reduce__ method of the bound x method of a C instance.
Yes, unfortunately you get the __reduce__ method of the unbound function instead.
I think Martin is right: copy_reg may be your last hope. (Or subclassing pickle to special-case instancemethod.)
The pickling machinery wasn't intended to pickle bound methods or functions etc., and doesn't particularly go out of its way to allow you to add that functionality.
Try again. I don't think that C().f.__reduce__ should be a method of an instance of C. You want it to be a method of a bound method object, right?
No, __reduce__ is a method of f, which is bound to an instance of C. Calling it will give me what I need to pickle the bound f method. This is all what I want. I think this is just natural.
And it would be except for the delegation of method attributes to function attributes. It is a similar aliasing problem as you see when you try to access the __getattr__ implementation for classes as C.__getattr__ -- you get the __getattr__ for C instances instead. So you have to use type(C).__getattr__ instead. That would work for __reduce__ too I think: new.instancemethod.__reduce__(C().f).
If that's not the way to do it, which is it?
I think what I suggested above -- forget about the existing instancemethod implementation. But I really don't understand the context in which you are doing this well enough to give you advice, and in any context that I understand the whole construct doesn't make sense. :-(
Once again. What I try to achieve is complete thread pickling. That means, I need to supply pickling methods to all objects which don't have builtin support in cPickle or which don't provide __reduce__ already. I have done this for some 10 or more types, successfully. Bound PyCFunction objects are nice and don't give me a problem. Bound PyFunction objects do give me a problem, since they don't want to give me what they are bound to.
OK, so you *are* messing with internals after all (== changing C code), right? Or else how do you accomplish this?
My options are:
- Do an ugly patch that special cases for __reduce__, which I did just now, in order to seet hings working.
- get the master's voice about how to do this generally right, and do it generally right.
I would of course prefer the latter, but I also try to save as much time as I can while supporting my clients, since Stackless is almost no longer sponsored, and I have money problems.
I have a real job too, that's why I have little time to help you. :-(
--Guido van Rossum (home page: http://www.python.org/%7Eguido/)