(original) (raw)



On Thu, Jul 19, 2012 at 12:53 PM, M Stefan <mstefanro@gmail.com> wrote:

Hey,



As part of pickle4, I found it interesting to add the possibility

of pickling bound functions (instance methods). This is done by

pickling f.__self__ and f.__func__ separately, and then adding

a BIND opcode to tie them together.



While this appears to work fine for python methods (non-builtin), some

issues arise with builtins. These are partly caused because

not all builtin function types support __func__, partly because

not all of them fill __module__ when they should and partly

because there are many (7) types a function can actually have:



ClassMethodDescriptorType = type(??)

BuiltinFunctionType = type(len)

FunctionType = type(f)

MethodType = type(A().f())

MethodDescriptorType = type(list.append)

WrapperDescriptorType = type(list.__add__)

MethodWrapperType = type([].__add__)



AllFunctionTypes = (ClassMethodDescriptorType, BuiltinFunctionType,

FunctionType, MethodType, MethodDescriptorType,

WrapperDescriptorType, MethodWrapperType)

repr(AllFunctionTypes) = (

<class 'classmethod_descriptor'>,

<class 'builtin_function_or_method'>, <class 'function'>,

<class 'method'>, <class 'method_descriptor'>,

<class 'wrapper_descriptor'>, <class 'method-wrapper'>)



I have created a patch at [1], which adds __func__ to some other

function types, as well as:

  1. adds AllFunctionTypes etc. to Lib/types.py
  2. inspect.isanyfunction(), inspect.isanyboundfunction(),

    inspect.isanyunboundfunction()
  3. functools.unbind

    Note that I am not knowledgeable of cpython internals and therefore

    the patch needs to be carefully reviewed.

    Possible issues: Should classmethods be considered bound or unbound?
    If cm is a classmethod, then should
    cm.\_\_func\_\_.\_\_self\_\_ = cm.\_\_self\_\_ or cm.\_\_func\_\_.\_\_self\_\_ = None?
    Currently does the latter:
    >>> cm.\_\_self\_\_, hasattr(cm,'\_\_self\_\_'), hasattr(cm.\_\_func\_\_, '\_\_self\_\_')
    (<class '\_\_main\_\_.A'>, True, False)
    This requires treating classmethods separately when pickling,
    so I'm not sure if this is ideal.

    Let me know if I should have opened an issue instead. I look
    forward to hearing your opinions/suggestions on this matter.

Yes, open an issue for your patch and reply here with the issue #.