Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for @dataclass_transform on Generic's method #16031

Open
lukaspiatkowski opened this issue Sep 3, 2023 · 0 comments
Open

Support for @dataclass_transform on Generic's method #16031

lukaspiatkowski opened this issue Sep 3, 2023 · 0 comments
Labels

Comments

@lukaspiatkowski
Copy link

lukaspiatkowski commented Sep 3, 2023

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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant