<br><br><div class="gmail_quote">On Thu, Jul 19, 2012 at 12:53 PM, M Stefan <span dir="ltr">&lt;<a href="mailto:mstefanro@gmail.com" target="_blank">mstefanro@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

Hey,<br>
<br>
As part of pickle4, I found it interesting to add the possibility<br>
of pickling bound functions (instance methods). This is done by<br>
pickling f.__self__ and f.__func__ separately, and then adding<br>
a BIND opcode to tie them together.<br>
<br>
While this appears to work fine for python methods (non-builtin), some<br>
issues arise with builtins. These are partly caused because<br>
not all builtin function types support __func__, partly because<br>
not all of them fill __module__ when they should and partly<br>
because there are many (7) types a function can actually have:<br>
<br>
ClassMethodDescriptorType = type(??)<br>
BuiltinFunctionType = type(len)<br>
FunctionType = type(f)<br>
MethodType = type(A().f())<br>
MethodDescriptorType = type(list.append)<br>
WrapperDescriptorType = type(list.__add__)<br>
MethodWrapperType = type([].__add__)<br>
<br>
AllFunctionTypes = (ClassMethodDescriptorType, BuiltinFunctionType,<br>
                    FunctionType, MethodType, MethodDescriptorType,<br>
                    WrapperDescriptorType, MethodWrapperType)<br>
repr(AllFunctionTypes) = (<br>
    &lt;class &#39;classmethod_descriptor&#39;&gt;,<br>
    &lt;class &#39;builtin_function_or_method&#39;&gt;, &lt;class &#39;function&#39;&gt;,<br>
    &lt;class &#39;method&#39;&gt;, &lt;class &#39;method_descriptor&#39;&gt;,<br>
    &lt;class &#39;wrapper_descriptor&#39;&gt;, &lt;class &#39;method-wrapper&#39;&gt;)<br>
<br>
I have created a patch at [1], which adds __func__ to some other<br>
function types, as well as:<br>
 1) adds AllFunctionTypes etc. to Lib/types.py<br>
 2) inspect.isanyfunction(), inspect.isanyboundfunction(),<br>
    inspect.isanyunboundfunction()<br>
 3) functools.unbind<br>
Note that I am not knowledgeable of cpython internals and therefore<br>
the patch needs to be carefully reviewed.<br>
<br>
Possible issues: Should classmethods be considered bound or unbound?<br>
If cm is a classmethod, then should<br>
cm.__func__.__self__ = cm.__self__ or cm.__func__.__self__ = None?<br>
Currently does the latter:<br>
    &gt;&gt;&gt; cm.__self__, hasattr(cm,&#39;__self__&#39;), hasattr(cm.__func__, &#39;__self__&#39;)<br>
    (&lt;class &#39;__main__.A&#39;&gt;, True, False)<br>
This requires treating classmethods separately when pickling,<br>
so I&#39;m not sure if this is ideal.<br>
<br>
Let me know if I should have opened an issue instead. I look<br>
forward to hearing your opinions/suggestions on this matter.<br></blockquote><div><br></div><div>Yes, open an issue for your patch and reply here with the issue #. </div></div>