Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork33.7k
Description
Bug report
Bug description:
Generally speaking, any objects present in the namespace of a classFoo that define the special__set_name__ method will have that method called on them as part of the creation of the classFoo. (__set_name__ is generally only used for descriptors, but can be defined on any class.)
For example:
Python 3.12.0 (tags/v3.12.0:0fb18b0, Oct 2 2023, 13:03:39) [MSC v.1935 64 bit (AMD64)] on win32Type "help", "copyright", "credits" or "license" for more information.>>>classAnnoying:...def__set_name__(self,owner,name):...raiseException('no')...>>>classFoo:... attr= Annoying()...Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in __set_name__Exception: noError calling __set_name__ on 'Annoying' instance 'attr' in 'Foo'
Descriptors insidetyping.NamedTuple namespaces generally work the same way as in other class namespaces...
>>>from typingimport NamedTuple>>>classFoo(NamedTuple):... bar=property(lambdaself:42)...>>> Foo().bar42
...but with one notable exception: they don't have__set_name__ called on them!
>>>classAnnoying:...def__set_name__(self,owner,name):...raiseException('no')...>>>from typingimport NamedTuple>>>classFoo(NamedTuple):... bar= Annoying()# this should cause the creation of the `Foo` class to fail......>>># ...but it didn't!
Why does this happen?
__set_name__ would normally be called on all members of a class dictionary during the class's creation. But theNamedTuple classFoo iscreated here:
Lines 2721 to 2723 in97c4c06
| nm_tpl=_make_nmtuple(typename,types.items(), | |
| defaults=[ns[n]fornindefault_names], | |
| module=ns['__module__']) |
And thebar attribute is only monkey-patched onto theFoo classafter the class has actually been created. This happens a few lines lower down intyping.py, here:
Lines 2732 to 2733 in97c4c06
| elifkeynotin_specialandkeynotinnm_tpl._fields: | |
| setattr(nm_tpl,key,ns[key]) |
__set_name__ isn't called onFoo.bar as part of the creation of theFoo class, because theFoo class doesn'thave abar attribute at the point in time when it's actually being created.
CPython versions tested on:
3.8, 3.11, 3.12, CPython main branch
Operating systems tested on:
Windows