Open AJMansfield opened 2 months ago
__set_name__()
is only called for values set in the class body. Direct setting the class attribute does not trigger calling __set_name__()
. If you need to call it, do it explicitly.
@serhiy-storchaka The documentation says that __set_name__
is "Automatically called at the time the owning class owner is created", and says nothing about the attribute having to be set in the class body. And from a user's perspective the attribute han_solo
is set while Cloud_City
is still being created, so it may be reasonable for the OP to expect owner.han_solo.__set_name__
to be called.
I guess we may have to either clarify the existing behavior in the documentation, or implement type_new_set_names
with a while loop that looks for any new names in __dict__
after calls to __set_name__
s, perhaps by just comparing the size of __dict__
before and after the calls.
I think we should clarify the documentation. Cc @ncoghlan
perhaps by just comparing the size of
__dict__
before and after the calls.
I don't think the size of __dict__
is specific enough, since a __set_name__
also has the potential to delete members from a class. But, type_new_set_names
could set some sort of "class creation set-names phase" flag, and then rely on type_new_set_attrs
to append newly added names to a list or even invoke __set_name__
directly. (Invoking it directly would also have the benefit of appropriately failing on code that reaches a recursion depth limit, instead of needing explicit code to fail out on an infinite loop in the list version.)
I think we should clarify the documentation. Cc @ncoghlan
Documenting and adding tests that that it's specifically not called on members inserted this would be a perfectly acceptable resolution for me -- to be honest, my main interest here is just to determining what the official correct behavior is, so I can implement this feature in Micropython with the same semantics as CPython.
Bug report
Bug description:
When inserting a class member during some other class member's
__set_name__
call, the__set_name__
method of the newly-inserted member doesn't get called as expected.As an example, take this snippet:
I would expect both
__set_name__
functions to be called, resulting in the output:But what is actually output, is:
Discovered while testing a PEP-487 implementation for Micropython: micropython/micropython#15503.
Maybe be related to #72983.
CPython versions tested on:
3.8, 3.10, 3.12
Operating systems tested on:
Linux