You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
ModuleType.__annotations__ and type.__annotations__ result in AttributeError #123242
If you call dir() on ModuleType or type, it shows __annotations__ as one of the attributes. However, when you attempt to access that attribute, for ModuleType you get AttributeError: type object 'module' has no attribute '__annotations__' and for type you get AttributeError: type object 'type' has no attribute '__annotations__'.
I found this bug because I have a method that iterates over the attributes returned from dir and gets each attribute. After upgrading from Python 3.8 to 3.11, this caused an interesting failure. I would expect that attributes returned by dir() would be accessible and not result in an AttributeError.
>>> type.__annotations__
Traceback (most recent call last):
File "<python-input-62>", line 1, in <module>
type.__annotations__
AttributeError: type object 'type' has no attribute '__annotations__'. Did you mean: '__annotate__'?
>>> type.__annotate__
Traceback (most recent call last):
File "<python-input-63>", line 1, in <module>
type.__annotate__
AttributeError: type object 'type' has no attribute '__annotate__'. Did you mean: '__annotations__'?
staticPyObject*type_get_annotations(PyTypeObject*type, void*context)
{
if (!(type->tp_flags&Py_TPFLAGS_HEAPTYPE)) {
PyErr_Format(PyExc_AttributeError, "type object '%s' has no attribute '__annotations__'", type->tp_name);
returnNULL;
}
...
}
So the attribute does exist. It's just that it immediately raises an error. The reason why it's being listed in __dir__ is that it's actually set in the __dict__. So the question is: is it really a bug or not? it results in an AttributeError, yes, but maybe we could return an empty dict in the case of type? or maybe change the error message? (and for non-heap types, we would just return empty dicts everytime, but still disallow to set __annotations__).
We could outright filter the output of type___dir___impl by rejecting __annotations__ and __annotate__ if we are dealing with a heap type, but only if a parent does not already have __annotations__.
Well.. maybe amend the docs a little? or at least the error message? (though I don't have an better error message for that). Otherwise, we should close the issue. For beginners and for introspection tools, it could be undesirable (in Sphinx, I think we do getattr(obj, name, sentinel) even if we iterate over the names returned by dir but I should check that's indeed the case, otherwise we could have surprises).
Activity
sobolevn commentedon Aug 23, 2024
Docs say:
So, this seems like a bug to me.
__annotations__is not a valid attribute for this object. It should not be returned.I can see
__abstractmethods__there as well, which also raises:And
__annotate__for 3.14+picnixz commentedon Aug 23, 2024
Fun fact:
picnixz commentedon Aug 23, 2024
@sobolevn Do you want to work on it? or can I take it perhaps?
sobolevn commentedon Aug 23, 2024
@picnixz sure, go ahead!
picnixz commentedon Aug 23, 2024
Ok, I see what happens:
So the attribute does exist. It's just that it immediately raises an error. The reason why it's being listed in
__dir__is that it's actually set in the__dict__. So the question is: is it really a bug or not? it results in an AttributeError, yes, but maybe we could return an empty dict in the case oftype? or maybe change the error message? (and for non-heap types, we would just return empty dicts everytime, but still disallow to set__annotations__).We could outright filter the output of
type___dir___implby rejecting__annotations__and__annotate__if we are dealing with a heap type, but only if a parent does not already have__annotations__.cc @JelleZijlstra
JelleZijlstra commentedon Aug 23, 2024
I don't think the issue reported here is severe enough to justify changing this behavior. As Nikita noted,
type.__abstractmethods__behaves similarly.picnixz commentedon Aug 24, 2024
Well.. maybe amend the docs a little? or at least the error message? (though I don't have an better error message for that). Otherwise, we should close the issue. For beginners and for introspection tools, it could be undesirable (in Sphinx, I think we do
getattr(obj, name, sentinel)even if we iterate over the names returned bydirbut I should check that's indeed the case, otherwise we could have surprises).pythongh-123242: Note that type.__annotations__ may not exist
pythongh-123242: Note that type.__annotations__ may not exist (python…
[3.12] pythongh-123242: Note that type.__annotations__ may not exist (p…
[3.12] gh-123242: Note that type.__annotations__ may not exist (GH-12…
Merge branch 'main' into fix-help-double-prompt
[3.13] pythongh-123242: Note that type.__annotations__ may not exist (p…
[3.13] gh-123242: Note that type.__annotations__ may not exist (GH-12…