Clarify the valid use locations of `typing.Concatenate`

オープン
#2,140 コメント 2 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
38/100
issue の種類
ドキュメント
明瞭さ
おおむね明確
活発さ
停滞
技術スタック
python
領域
documentation

調査の方向性

typing 仕様のユーザー定義ジェネリッククラスのセクションと、typing.Concatenate に関する CPython ドキュメントから始め、その後、mypy、pyright、ty の例と報告された動作を比較します。リンクされた Concatenate の検索ノートを確認し、どの使用箇所が有効かを判断します。typing 仕様と CPython ドキュメントで、サポートされる形式とネストされた Concatenate の制限が明確に説明されていれば完了です。

索引モデルが issue の本文から書いたものです。

説明

topic: documentation

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):

  1. Accumulate Concatenates as ParamSpecs
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
  1. Bind Concatenates to user-defined generics as ParamSpecs
class X[T, **P]:
    f: Callable[P, int]
    x: T

def accept_concatenate[**P](x: X[int, Concatenate[int, P]]) -> str: ...
  1. Use Concatenate as a type argument to tuple -- 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

主要言語
Python
スター
1.8k
フォーク
302
平均マージ
23時間
マージ済み PR(30日)
8

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

python/typing のほかの issue

python/typing の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。