Closed ndjensen closed 1 month ago
Docs say:
With an argument, attempt to return a list of valid attributes for that object. https://docs.python.org/3/library/functions.html#dir
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:
>>> type.__abstractmethods__
Traceback (most recent call last):
File "<python-input-1>", line 1, in <module>
type.__abstractmethods__
AttributeError: __abstractmethods__
And __annotate__
for 3.14+
Fun fact:
>>> 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__'?
@sobolevn Do you want to work on it? or can I take it perhaps?
@picnixz sure, go ahead!
Ok, I see what happens:
static PyObject *
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);
return NULL;
}
...
}
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__
.
cc @JelleZijlstra
I don't think the issue reported here is severe enough to justify changing this behavior. As Nikita noted, type.__abstractmethods__
behaves similarly.
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).
Bug report
Bug description:
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 getAttributeError: type object 'module' has no attribute '__annotations__'
and for type you getAttributeError: 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.
CPython versions tested on:
3.11, 3.13
Operating systems tested on:
Linux
Linked PRs