python / python/mypy

should mypy recognize pep-681 @dataclass_transform on a method as well as a function?

Open
#19,824 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feature needs discussion topic-dataclass-transform
Dominant language
Python
Stars
20.6k
Forks
3.3k
PR merge metrics
PR metrics pending

Description

Just noticed that trying to make an object method provide @dataclass_transform functionality is not recognized by mypy as a pep-681 use of @dataclass_transform (it does not complain either, just silently ignores it):

from typing import dataclass_transform

class SomeClassThing:
    @dataclass_transform()
    def make_a_dataclass(self, cls: type) -> type:
        return cls

sct = SomeClassThing()

@sct.make_a_dataclass
class MyClass:
    x: int
    y: str

m1 = MyClass(x=5, y="y")

mypy:

test4.py:16: error: Unexpected keyword argument "x" for "MyClass"  [call-arg]
test4.py:16: error: Unexpected keyword argument "y" for "MyClass"  [call-arg]
Found 2 errors in 1 file (checked 1 source file)

the above would need to be reorganized like this:

from typing import Callable
from typing import dataclass_transform

class SomeClassThing:
    pass

@dataclass_transform()
def make_a_dataclass(sct: SomeClassThing) -> Callable[[type], type]:
    def decorate(cls: type) -> type:
        return cls
    return decorate

sct = SomeClassThing()

@make_a_dataclass(sct)
class MyClass:
    x: int
    y: str

m1 = MyClass(x=5, y="y")

where mypy is happy:

Success: no issues found in 1 source file

SQLAlchemy has a pep-681 feature that mostly uses the superclass approach, however we also offer a decorator that looks like @mapper_registry.mapped_as_dataclass(), and I just noticed that while pyright has always accepted this, mypy does not. So I'm adding an alternative decorator of the above form @mapped_as_dataclass(mapper_registry). Took a look at pep-681 and it discusses @dataclass_transform applied to a function or a class, not a method. So I'm out of luck. but it seems ....like it should work? pyright does it....

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the method-based reproducer in the issue and read PEP 681's rules for where @dataclass_transform may be applied. Compare the behavior with the function-based example and pyright, then determine whether method support is specified; done means mypy consistently handles the decorator or clearly rejects the unsupported form.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
devtools
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.