python / python/mypy

Support for @dataclass_transform on Generic's method

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

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

feature
主要言語
Python
スター
20.6k
フォーク
3.3k
PR マージ指標
PR 指標を取得中

説明

Feature

@dataclass_transform is a PEP-681 feature that is now mostly supported according to #14293. My proposition is to make sure that it can be used inside of a Generic class. What is more, it should handle passing Genaric methods in field_specifiers, like so:

class F(Generic[T]):
    @staticmethod
    def field(factory: Callable[[T], V]) -> V: ...

class G(Generic[T]):
    @staticmethod
    @dataclass_transform(field_specifiers=(F[T].field, ))
    def foo(c): ...

@G[int].foo
class A:
    x: int = F[int].field(factory=lambda x: x+2))

reveal_type(A.__init__)  # Type of "A.__init__" is "(self: A, x: int = lambda x: x + 2) -> None"

Pitch

The current behavior is that if you annotate a static method (let alone a method inside a Generic class) with @dataclass_transform mypy won't treat it as dataclass-making decorator (see mypy playground). In this regard pyright does a better job as it allows you to do it (see pyright playground).

If the type checker would allow for the aforementioned feature, then this pattern would be possible to implement (using the above defined code):

class UserModel:
	id: str
	name: str

class ItemModel:
	id: str
	price: int

@G[UserModel].foo
class User:
	id: str = F[UserModel].field(factory = lamda user: user.id)
	name: str = F[UserModel].field(factory = lamda user: user.name)
	more_data: str

@G[ItemModel].foo
class User:
	id: str = F[ItemModel].field(factory = lamda item: item.id)
	price: int = F[ItemModel].field(factory = lamda item: item.price)
	more_data: str

The type checker should be able to catch type mismatches between the decorator and field, like so:

@G[UserModel].foo
class User:
    # Error: F[ItemModel].field found where F[UserModel].field expected
	id: str = F[ItemModel].field(factory = lamda item: item.id)
	# Error: no field "price" found for user: UserModel
	name: str = F[UserModel].field(factory = lamda user: user.price)

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

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

はじめの一歩

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

調査の方向性

まず、issue #14293 で参照されている mypy の既存の PEP 681 サポートを確認し、リンク先の mypy playground の例を再現してください。次に、この issue の例を受け入れ条件として使用し、dataclass_transform が static methods、Generic methods、field_specifiers をどのように扱うかを調査してください。decorator と field type mismatches が説明どおりに診断されれば完了です。

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

評価

技術スタック
python
領域
devtools
issue の種類
機能追加
難易度
5/5
見積もり時間
1週間以上
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
35/100

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

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