Improve the signature of typing.NamedTuple.__init__#10292
Improve the signature of typing.NamedTuple.__init__#10292srittau merged 1 commit intopython:mainfrom
typing.NamedTuple.__init__#10292Conversation
|
Diff from mypy_primer, showing the effect of this PR on open source code: pydantic (https://github.com/samuelcolvin/pydantic)
+ pydantic/v1/validators.py:614: error: No overload variant of "NamedTuple" matches argument type "Dict[str, Any]" [call-overload]
+ pydantic/v1/validators.py:614: note: Possible overload variants:
+ pydantic/v1/validators.py:614: note: def __init__(self, str, Iterable[Tuple[str, Any]], /) -> NamedTupleT
+ pydantic/v1/validators.py:614: note: def __init__(self, str, None = ..., /, **kwargs: Any) -> NamedTupleT
koda-validate (https://github.com/keithasaurus/koda-validate)
+ koda_validate/namedtuple.py:207: error: No overload variant of "NamedTuple" matches argument type "Dict[Any, Any]" [call-overload]
+ koda_validate/namedtuple.py:207: note: Possible overload variants:
+ koda_validate/namedtuple.py:207: note: def __init__(self, str, Iterable[Tuple[str, Any]], /) -> _NTT
+ koda_validate/namedtuple.py:207: note: def __init__(self, str, None = ..., /, **kwargs: Any) -> _NTT
+ koda_validate/namedtuple.py:258: error: No overload variant of "NamedTuple" matches argument type "Dict[Any, Any]" [call-overload]
+ koda_validate/namedtuple.py:258: note: Possible overload variants:
+ koda_validate/namedtuple.py:258: note: def __init__(self, str, Iterable[Tuple[str, Any]], /) -> _NTT
+ koda_validate/namedtuple.py:258: note: def __init__(self, str, None = ..., /, **kwargs: Any) -> _NTT
|
|
Well, the reason why I originally wrote this PR is that pyright currently allows this, and interprets it (incorrectly) as creating a Point = NamedTuple("Point", fields=[("x", int), ("y", int)])According to our current stubs, pyright is correct to allow that, which is why I wanted to change the stubs. Mypy doesn't allow it, but that's just because of how heavily mypy special-cases However, mypy has a strange feature where you can use bare I feel like mypy is in the wrong here, though -- |
|
Pydantic and koda-validate are also just doing very dynamic things with named tuples, which I don't think they should reasonably expect to type check honestly. |
There was a problem hiding this comment.
They are also marked as positional-only in the implementation:
https://github.com/python/cpython/blob/d4fa52934a282df51cff800eee5caeb94a229547/Lib/typing.py#L2756
Both
typenameandfieldsshould be positional-only. Here's what happens if you try to specify both as keyword arguments at runtime:If you specify just
fieldsas a keyword argument, there's no error at runtime. However, it probably doesn't do what you wanted it to do: the user gets aNamedTupleclass that has a single field namedfields:Additionally, the first overload shouldn't have a default for the
fieldsargument. It's only okay to not specifyfieldsif you specify keyword arguments. (Though we'll probably be deprecating that as well.)