-
-
Notifications
You must be signed in to change notification settings - Fork 32.2k
gh-111874: Call __set_name__
on objects that define the method insid
8000
e a typing.NamedTuple
class dictionary as part of the creation of that class
#111876
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e3b703d
f053310
7ccff63
0d13e83
e4e968a
e0c88f0
d8102fd
f2a57b2
1909fd5
ed53fcb
c2c65c6
e79ea37
9fd8b6b
fdab495
3932d48
3359ff6
ef628da
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2743,11 +2743,26 @@ def __new__(cls, typename, bases, ns): | |
class_getitem = _generic_class_getitem | ||
nm_tpl.__class_getitem__ = classmethod(class_getitem) | ||
# update from user namespace without overriding special namedtuple attributes | ||
for key in ns: | ||
for key, val in ns.items(): | ||
if key in _prohibited: | ||
raise AttributeError("Cannot overwrite NamedTuple attribute " + key) | ||
elif key not in _special and key not in nm_tpl._fields: | ||
setattr(nm_tpl, key, ns[key]) | ||
elif key not in _special: | ||
if key not in nm_tpl._fields: | ||
setattr(nm_tpl, key, val) | ||
try: | ||
set_name = type(val).__set_name__ | ||
except AttributeError: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it worth adding a test for the case where this yields some other exception (e.g. due to a weird metaclass)? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch. Seems like for normal classes, if any strange exception is raised when trying to lookup >>> class Meta(type):
... def __getattribute__(self, attr):
... if attr == "__set_name__":
... raise BaseException("NO")
...
>>> class VeryAnnoying(metaclass=Meta): pass
...
>>> class Foo:
... attr = VeryAnnoying()
...
>>> We should do the same here (though I don't want to swallow There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Addressed in 1909fd5 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It looks like a bug. I do not think it should be reproduced here. It is better to fix it for normal classes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, I opened #112453, and will revert the changes made here that reproduce the bug |
||
pass | ||
else: | ||
try: | ||
set_name(val, nm_tpl, key) | ||
except BaseException as e: | ||
e.add_note( | ||
f"Error calling __set_name__ on {type(val).__name__!r} " | ||
f"instance {key!r} in {typename!r}" | ||
) | ||
raise | ||
|
||
if Generic in bases: | ||
nm_tpl.__init_subclass__() | ||
return nm_tpl | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
When creating a :class:`typing.NamedTuple` class, ensure | ||
:func:`~object.__set_name__` is called on all objects that define | ||
``__set_name__`` and exist in the values of the ``NamedTuple`` class's class | ||
dictionary. Patch by Alex Waygood. |
Uh oh!
There was an error while loading. Please reload this page.