Clarify the valid use locations of `typing.Concatenate`
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1.8k
- Forks
- 302
- Avg merge
- 23h
- Merged PRs (30d)
- 8
Description
In python/cpython#142965, it was reported that the documentation of typing.Concatenate is "incorrect" (documentation that originates back to python/cpython#24000).
@A5rocks, in your example, Concatenate[int, P_2] somewhat finally lands as a first argument to Callable, just indirectly.
This snippet previously defined:
P_2 = ParamSpec("P_2")
class X(Generic[T, P]):
f: Callable[P, int]
x: T
Similar example is included in the typing spec:
https://typing.python.org/en/latest/spec/generics.html#user-defined-generic-classes
class X[T, **P]:
f: Callable[P, int]
x: T
# (...)
def accept_concatenate[**P](x: X[int, Concatenate[int, P]]) -> str: ... # Accepted
However, it seems that the current situation (confirmed with mypy, pyright and ty) is that you can use Concatenate in all valid locations of ParamSpec except directly in a Concatenate. I.e., you can't do Concatenate[int, Concatenate[str, P]]), but you can (besides passing Concatenate form as the first argument to Callable):
- Accumulate
Concatenates asParamSpecs
from collections.abc import Callable
from typing import Concatenate
type Y[**P] = Callable[Concatenate[int, P], None]
type X[**P] = Y[Concatenate[int, P]]
def foo(f: X[str]) -> None:
reveal_type(f)
# mypy: def (builtins.int, builtins.int, builtins.str)
# pyright: (int, int, str) -> None
# ty: (...) -> None
- Bind
Concatenates to user-defined generics asParamSpecs
class X[T, **P]:
f: Callable[P, int]
x: T
def accept_concatenate[**P](x: X[int, Concatenate[int, P]]) -> str: ...
- Use
Concatenateas a type argument totuple-- is this correct?
from typing import Concatenate
def c(t: tuple[Concatenate[int, ...]]) -> None:
reveal_type(c)
# mypy: def (t: tuple[[builtins.int, *Any, **Any]])
# pyright: (t: tuple[Concatenate[int, ...]]) -> None
# ty: def c(t: tuple[@Todo]) -> None
I've found this mostly by poking around -- I haven't analyzed the actual implementations (yet).
I'll continue to investigate this from these searches.
I think that the valid use locations of Concatenate should be clarified in the typing spec and then in the CPython docs.
Is there anything else I overlooked? CC @JelleZijlstra @AlexWaygood
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the typing spec's user-defined generic classes section and the CPython documentation for typing.Concatenate, then compare the examples and the reported behavior from mypy, pyright, and ty. Review the linked Concatenate search notes and determine which use locations are valid; done means the typing spec and CPython docs clearly describe the supported forms and the nested-Concatenate restriction.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- documentation
- Issue type
- Documentation
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100