-
-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
gh-111874: Call __set_name__
on objects that define the method inside a typing.NamedTuple
class dictionary as part of the creation of that class
#111876
Conversation
…d inside a `typing.NamedTuple` class dictionary as part of the creation of that class
This reverts commit 7ccff63.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but I have few minor suggestions.
Thanks @serhiy-storchaka! I applied your suggestions; would you mind taking another look? I discovered another interesting thing in the process: Python 3.13.0a1+ (heads/main:e5dfcc2b6e, Nov 15 2023, 17:23:51) [MSC v.1932 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from dataclasses import dataclass
>>> class Vanilla:
... def __set_name__(self, owner, name):
... self.name = name
...
>>> @dataclass
... class Foo:
... v: Vanilla = Vanilla()
...
>>> f = Foo()
>>> f.v.name
'v' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure that __set_name__
should be called for annotated fields.
Yes, I could be persuaded either way there. |
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 comment
The 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 comment
The 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 __set_name__
, the interpreter just swallows it and moves on:
>>> 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 BaseException
s, since that would catch KeyboardInterrupt
, SystemExit
, etc. -- I think I'll just use except Exception
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The 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 comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like for normal classes, if any strange exception is raised when trying to lookup
__set_name__
, the interpreter just swallows it and moves on:
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 comment
The 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
Co-authored-by: Jelle Zijlstra <[email protected]>
0c9f2b9
to
3932d48
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
Few minor suggestions which you can ignore.
Thanks for the reviews! |
# Release 4.9.0 (December 9, 2023) This feature release adds `typing_extensions.ReadOnly`, as specified by PEP 705, and makes various other improvements, especially to `@typing_extensions.deprecated()`. There are no changes since 4.9.0rc1. # Release 4.9.0rc1 (November 29, 2023) - Add support for PEP 705, adding `typing_extensions.ReadOnly`. Patch by Jelle Zijlstra. - All parameters on `NewType.__call__` are now positional-only. This means that the signature of `typing_extensions.NewType.__call__` now exactly matches the signature of `typing.NewType.__call__`. Patch by Alex Waygood. - Fix bug with using `@deprecated` on a mixin class. Inheriting from a deprecated class now raises a `DeprecationWarning`. Patch by Jelle Zijlstra. - `@deprecated` now gives a better error message if you pass a non-`str` argument to the `msg` parameter. Patch by Alex Waygood. - `@deprecated` is now implemented as a class for better introspectability. Patch by Jelle Zijlstra. - Exclude `__match_args__` from `Protocol` members. Backport of python/cpython#110683 by Nikita Sobolev. - When creating a `typing_extensions.NamedTuple` class, ensure `__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, backporting python/cpython#111876. - Improve the error message when trying to call `issubclass()` against a `Protocol` that has non-method members. Patch by Alex Waygood (backporting python/cpython#112344, by Randolph Scholz).
…d inside a `typing.NamedTuple` class dictionary as part of the creation of that class (python#111876) Co-authored-by: Jelle Zijlstra <[email protected]>
Closes #111874
NamedTuple
class namespaces don't have__set_name__
called on them #111874