Skip to content
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

PEP 695 syntax doesn't work for generic NamedTuples #104616

Closed
AlexWaygood opened this issue May 18, 2023 · 5 comments
Closed

PEP 695 syntax doesn't work for generic NamedTuples #104616

AlexWaygood opened this issue May 18, 2023 · 5 comments
Assignees
Labels
3.12 bugs and security fixes topic-typing type-bug An unexpected behavior, bug, or error

Comments

@AlexWaygood
Copy link
Member

Since Python 3.11, defining generic NamedTuples has been legal, like so:

>>> from typing import *
>>> T = TypeVar("T")
>>> class Foo(NamedTuple, Generic[T]):
...     x: T
>>>

However, using the new PEP-695 syntax for generic NamedTuples fails with a slightly inexplicable error message:

>>> from typing import *
>>> class Foo[T](NamedTuple):
...     x: T
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <generic parameters of Foo>
  File "C:\Users\alexw\coding\cpython\Lib\typing.py", line 2707, in __new__
    setattr(nm_tpl, key, ns[key])
AttributeError: attribute '__type_params__' of 'type' objects is not writable

Using PEP-695 syntax for generic TypedDicts seems to work fine, but isn't tested anywhere in test_typing.py, as far as I can tell:

>>> class Bar[T](TypedDict):
...     x: T
...
>>> Bar.__type_params__
(T,)
>>> Bar.__orig_bases__
(<function TypedDict at 0x0000017E9A17D9D0>, typing.Generic[T])
>>> Bar.__mro__
(<class '__main__.Bar'>, <class 'typing.Generic'>, <class 'dict'>, <class 'object'>)

Cc. @JelleZijlstra

@AlexWaygood AlexWaygood added type-bug An unexpected behavior, bug, or error topic-typing 3.12 bugs and security fixes labels May 18, 2023
@JelleZijlstra JelleZijlstra self-assigned this May 18, 2023
@AlexWaygood
Copy link
Member Author

AlexWaygood commented May 18, 2023

I guess we need to add __type_params__ to one of these two sets here?

cpython/Lib/typing.py

Lines 2668 to 2673 in cfa517d

# attributes prohibited to set in NamedTuple class syntax
_prohibited = frozenset({'__new__', '__init__', '__slots__', '__getnewargs__',
'_fields', '_field_defaults',
'_make', '_replace', '_asdict', '_source'})
_special = frozenset({'__module__', '__name__', '__annotations__'})

@JelleZijlstra
Copy link
Member

Thanks! I'll take a look tonight (though feel free to propose a solution yourself if you can get to it earlier). Adding to _special feels like it's not enough, because that will just skip the assignment, and we still want the __type_params__ to end up on the generated class somehow.

@AlexWaygood
Copy link
Member Author

AlexWaygood commented May 18, 2023

Thanks! I'll take a look tonight (though feel free to propose a solution yourself if you can get to it earlier). Adding to _special feels like it's not enough, because that will just skip the assignment, and we still want the __type_params__ to end up on the generated class somehow.

Ah. I agree that the generated class should have the correct __type_params__ value. And, I didn't realise that it wasn't possible to set the __type_params__ field on class objects. Maybe we should allow setting it on class objects, the same as you propose for function objects in #104600? I don't see a strong reason for it to be read-only; this case would benefit from it; and in general I feel like you should be able to mutate most fields on class objects

@JelleZijlstra
Copy link
Member

Yes, it probably should be writable; I thought it already was. I can make that change.

@JelleZijlstra
Copy link
Member

Fixed in #104634

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.12 bugs and security fixes topic-typing type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

2 participants