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
Generic Alias attributes nor in dir() #85946
Comments
The implementation of PEP-585 in 3.9 adds some new attributes, but they aren't listed with dir() (then, not list in autocomplete and IntelliSense). Python 3.9.0rc1+ (heads/3.9:d7cd1164c1, Aug 25 2020, 17:27:09) >>> li = list[int]
>>> li.__origin__
<class 'list'>
>>> getattr(li, '__origin__')
<class 'list'>
>>> '__origin__' in dir(li)
False That applies to: __origin__ It seems to be not the expected behaviour, so this bug report. If this is not the case, some piece of documentation could be interesting. Also, I couldn't find anything about Generic Alias in the documentation, only in the source code. Should this be addressed too? |
I actually have no idea where dir() gets its information. IIRC the implementation was a collaboration with Batuhan -- @batuhan, do you want to look into this? Presumably some metadata needs to be added to genericaliasobject.c. |
Sure, will check it out! |
I will share what I find out already, so it may hopefully be helpful. The dir function used is the general object.__dir__ function, defined in Objects/typeobject.c:type___dir___impl(), that just takes everything from __dict__ of the class and its bases. But the GenericAlias is trying hard pretending to be the origin class, so when you ask for the __dict__, it gives the original class, not the GenericAlias: >>> list[int].__dict__ == list.__dict__
True There are also some other things that seems a bit strange, but it may just be right: >>> list.__class__
<class 'type'>
>>> list[int].__class__
<class 'type'>
>>> type(list)
<class 'type'>
>>> type(list[int])
<class 'types.GenericAlias'> This happens because of the tp_getattro function genericaliasobject.c:ga_getattro(), that takes the attributes from the origin except for the following names, that are taken from the GenericAlias itself: So, when the dir() is getting the __dict__, it gets list.__dict__ and base (object) instead of GenericAlias. Looking the ga_getattro() calls when dir() is fired, it also gets the __class__ attribute after getting the __dict__. Adding one or another makes the dir() showing up the GenericAlias attributes, but others went missing. An idea to solve this spefic issue could be overriding the __dir__ method, def __dir__(self):
r = super().__dir__()
return r + attribute_names_list + method_names_list But I wonder what else should not be forwarded to origin. |
Okay, so IIRC if we stop forwarding __class__ (add it as an exception to attr_exceptions) it would return us the original dir(), and also solve the inconsistency of the example you gave;
but the problem is that, it is not 'exactly' complying with the specs at PEP-585. I am aware that we already added some extras to this list (https://www.python.org/dev/peps/pep-0585/#parameters-to-generics-are-available-at-runtime) like __mro_entries__ etc, but __class__ looks like a tricky problem. @gvanrossum any comments? |
The forwarding of I think overriding |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: