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
All exceptions are swallowed when looking up __set_name__ on an object in a class namespace during construction of that class #112453
During construction of a class Foo, all objects in the class dictionary are checked to see if they have a __set_name__ attribute. If an object in the dictionary does have a __set_name__ attribute, it is called as part of the construction of Foo:
But what if an object in a class namespace is an instance of class that has a metaclass that raises a non-AttributeError exception if __set_name__ is looked up on the class object? In this case, the exception is silently ignored when __set_name__ is looked up:
__set_name__, like all dunders, is looked up on the Problematic class object itself, rather than the instance of Problematic found in the class dictionary of Foo, so SystemExit should be raised during the creation of the Bar class when the interpreter tries to determine whether or not the Problematic class has a __set_name__ attribute. Instead, however, the SystemExit is silently swallowed.
I think the issue lies in this section of code here:
Or is the issue with the way Python looks up special names in general? It seems like there may be lots of other possible examples of this bug:
>>> classMeta(type):
... def__getattribute__(self, attr):
... if attr in {"__complex__", "__enter__", "__iter__"}:
... raiseSystemExit()
... returnobject.__getattribute__(self, attr)
...
>>> classFoo(metaclass=Meta): pass
...
>>> with Foo(): pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
with Foo(): pass
TypeError: 'Foo' object does not support the context manager protocol
>>> complex(Foo())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
complex(Foo())
TypeError: complex() first argument must be a string or a number, not 'Foo'
>>> iter(Foo())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
iter(Foo())
TypeError: 'Foo' object is not iterable
>>> Foo.__iter__# raises SystemExit...
In addition to bypassing any instance attributes in the interest of correctness, implicit special method lookup generally also bypasses the __getattribute__() method even of the object’s metaclass:
Bypassing the __getattribute__() machinery in this fashion provides significant scope for speed optimisations within the interpreter, at the cost of some flexibility in the handling of special methods (the special method must be set on the class object itself in order to be consistently invoked by the interpreter).
There should be an existing old issue for this. I once tried to solve it (or maybe similar issue in other place of this file), but I was not able to prove that the solution was correct, so it was not applied.
If errors are ignored, it is because of technical limitations and the design flaws. It should not be reproduced in Python.
Activity
AlexWaygood commentedon Nov 27, 2023
Or is the issue with the way Python looks up special names in general? It seems like there may be lots of other possible examples of this bug:
@serhiy-storchaka, thoughts?
AlexWaygood commentedon Nov 27, 2023
In fact, it seems like this behaviour is documented in the data model: https://docs.python.org/3/reference/datamodel.html#special-method-lookup
So perhaps this is not a bug at all, @serhiy-storchaka?
serhiy-storchaka commentedon Nov 27, 2023
If it simply bypasses the
__getattribute__()machinery, it is not a bug.But there is an old bug in
_PyType_Lookup():cpython/Objects/typeobject.c
Lines 4776 to 4783 in d44ee42
There should be an existing old issue for this. I once tried to solve it (or maybe similar issue in other place of this file), but I was not able to prove that the solution was correct, so it was not applied.
If errors are ignored, it is because of technical limitations and the design flaws. It should not be reproduced in Python.
AlexWaygood commentedon Nov 27, 2023
Possibly #75646 / #3616?
I see, thanks. So this issue should be closed, correct?
serhiy-storchaka commentedon Nov 27, 2023
It looks like that.