python / python/mypy

Support for @dataclass_transform on Generic's method

Ouverte
#16,031 0 commentaires 1 réaction 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

feature
Langage dominant
Python
Étoiles
20.6k
Forks
3.3k
Métriques de merge des PR
Métriques de PR en attente

Description

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)

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par examiner la prise en charge existante de PEP 681 par mypy, référencée dans l’issue #14293, et reproduisez l’exemple mypy playground lié. Étudiez ensuite comment dataclass_transform gère les méthodes statiques, les méthodes Generic et field_specifiers, en utilisant les exemples de cette issue comme cas d’acceptation. La tâche est terminée lorsque les incompatibilités du décorateur et des types de champs sont diagnostiquées comme décrit.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
python
Domaine
devtools
Type d'issue
Fonctionnalité
Difficulté
5/5
Temps estimé
Plus d'une semaine
Activité
À l'abandon
Clarté
Plutôt claire
Accessibilité débutants
35/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.