New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

__qualname__ inconsistent on Python 2, returns a descriptor on the class instead of class name #2562

Open
jamadden opened this Issue Aug 17, 2018 · 0 comments

Comments

Projects
None yet
1 participant
@jamadden
Contributor

jamadden commented Aug 17, 2018

Over in zopefoundation/zope.app.apidoc#25 we noticed an issue with the __qualname__ of functions (at least) on Python 2. Because it's implemented as a PyGetSetDef, when accessed on the class, it returns a getset_descriptor object instead of the class name.

Python 2.7.15 (default, May  2 2018, 00:53:27)
[GCC 4.2.1 Compatible Apple LLVM 9.1.0 (clang-902.0.39.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from Cython.Compiler.Visitor import recursively_replace_node
>>> recursively_replace_node
<cyfunction recursively_replace_node at 0x10cd04950>
>>> recursively_replace_node.__class__
<type 'cython_function_or_method'>
>>> recursively_replace_node.__qualname__
'recursively_replace_node'
>>> recursively_replace_node.__class__.__qualname__
<attribute '__qualname__' of 'cython_function_or_method' objects>

That breaks code expecting a string.

Python 3 (at least 3.6, the only version I checked) doesn't seem to have this problem; presumably the built-in meaning of __qualname__ is taking over? The results are consistent with other built-in functions by returning a string.

Python 3.6.6 (default, Jun 28 2018, 05:43:53)
[GCC 4.2.1 Compatible Apple LLVM 9.1.0 (clang-902.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from Cython.Compiler.Visitor import recursively_replace_node
>>> recursively_replace_node
<cyfunction recursively_replace_node at 0x10e9a66c0>
>>> recursively_replace_node.__class__
<class 'cython_function_or_method'>
>>> recursively_replace_node.__qualname__
'recursively_replace_node'
>>> recursively_replace_node.__class__.__qualname__
'cython_function_or_method'
>>> import os
>>> os.chmod.__class__.__qualname__
'builtin_function_or_method'

It seems like it would be a lot of work to transform the PyGetSetDef for __qualname__ into a custom descriptor that does in the __dict__ (the only way I know how to fix it, but I am no CPython API expert!). Python 2 functions don't generally have __qualname__, perhaps the easiest thing to do would just be to #ifdef the __qualname__ out of the __pyx_CyFunction_getsets?

(I understand if that's not appealing either; this isn't a big deal, we plan to workaround it on that project.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment