[Cython] inspect.isbuiltin(cyfunction) and inheritance from PyCFunction

Stefan Behnel stefan_ml at behnel.de
Sun Feb 2 13:12:26 CET 2014


Stefan Behnel, 02.02.2014 11:07:
> Stefan Behnel, 01.02.2014 17:04:
>> Stefan Behnel, 31.01.2014 21:01:
>>> Yury Selivanov just committed a revised version of a patch I wrote for
>>> CPython's inspect module last year. It now accepts Cython's function type
>>> as Python function, based on the function-like attributes that it exports.
>>>
>>> http://hg.python.org/cpython/rev/32a660a52aae
>>>
>>> That means that things like inspect.signature(cyfunction) will also work
>>> now, and finally have a reason to be further improved, including parameter
>>> introspection, annotations, etc. :)
>>
>> Sorry, huge correction: inspect.isfunction(cyfunction) still returns False.
>> Only introspection and signature analysis in the inspect module were
>> changed. I got it wrong because I had code in my usersitecustomize.py that
>> monkey patches inspect.isfunction(), and had completely forgotten about it.
>>
>> Looking through this a bit more, I noticed that CyFunction inherits from
>> PyCFunction, but doesn't actually tell CPython that it does. If I add this
>> line to __Pyx_CyFunction_init(), before the PyType_Ready() call:
>>
>>     __pyx_CyFunctionType_type.tp_base = &PyCFunction_Type;
>>
>> it still works as expected, but inspect.isbuiltin() now returns True (as
>> expected). Does anyone see a reason why we should not be doing this?
> 
> Tried it, found a reason. It makes CPython inherit some slot functions from
> the base type, specifically tp_hash and tp_richompare, and those don't work
> with the cyfunction type. Meaning, we'd have to implement those explicitly
> to override the base type's implementations.

I think I figured it out. The fact that the object struct starts with
"PyCFunctionObject" is more of a convenience. There is no "real"
inheritance relation between the two, and that's the right thing to do, also.

So, the situation in Py3.4 is as follows.

   inspect.isfunction(cyfunction) -> False
   inspect.isbuiltin(cyfunction) -> False
   inspect.isroutine(cyfunction) -> True
   inspect.signature(cyfunction) -> Signature

The fact that isroutine() returns True seems like a coincidence, based on
the fact that ismethoddescriptor() returns True, which sounds kind of
wrong. It just tests for an existing "__get__" on the type without a
matching "__set__".

Anyway, I think that's pretty much as good as we can ask for, given that
Cython's function type really just quacks like a Python function.

Stefan



More information about the cython-devel mailing list