python / python/typing

Clarify the valid use locations of `typing.Concatenate`

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

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

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

説明

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

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

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

はじめの一歩

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

調査の方向性

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

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

評価

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

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

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