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

dataclass initvar with the same name as attribute gives error #15423

Closed
dcbaker opened this issue Jun 12, 2023 · 2 comments
Closed

dataclass initvar with the same name as attribute gives error #15423

dcbaker opened this issue Jun 12, 2023 · 2 comments
Labels
bug mypy got something wrong

Comments

@dcbaker
Copy link

dcbaker commented Jun 12, 2023

When a dataclass InitVar has the same name as a class attribute, mypy complains that the class has no attribute.

This is possibly related to: #12046

To Reproduce

from dataclasses import dataclass, InitVar

@dataclass
class Foo:

    arg: InitVar[str | int]

    def __post_init__(self, thing: str | int) -> None:
        self.arg = str(thing)

by renaming the InitVar to arg_: InitVar it works

Expected Behavior

This would be allowed. It prevents converting some classes that would benefit from being a dataclass, since it requires changing the API, since either the attribute must be renamed or the argument must be renamed.

Actual Behavior

test.py:13:9: error: "Foo" has no attribute "arg"  [attr-defined]
Found 1 error in 1 file (checked 1 source file)

For reference, pyright also doesn't like this code, but gives a somewhat different error:

test.py:9:14 - error: Cannot assign member "arg" for type "Foo"
    Member "arg" is an init-only field (reportGeneralTypeIssues)

Environment

  • Mypy version used: 1.0.1
  • Mypy command-line flags: None
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: 3.10.11
@dcbaker dcbaker added the bug mypy got something wrong label Jun 12, 2023
@erictraut
Copy link

You are declaring the same class-scoped symbol twice with different meanings. In one case it's an InitVar and in another case it's an instance variable. I think it's reasonable for mypy to reject this. As you point out, pyright does the same. Refer to this issue if you're interested in details and workarounds.

@JelleZijlstra JelleZijlstra closed this as not planned Won't fix, can't repro, duplicate, stale Jun 12, 2023
@dcbaker
Copy link
Author

dcbaker commented Jun 12, 2023

arg is an instance variable in this case though, unlike the @property case where it's at the class scope. That means that arg isn't even present in the class, even if dataclass didn't convert it into a Field object and places it in __dataclass_fields__ dunder, removing it from the class's __dict__. In fact, many dataclass instance has a different type for instance attributes than the class attributes, since the class value might be a field anyway.

The bigger problem, is even though renaming the InitVar works in this case since my API is completely private, it requires API change, you couldn't, for example convert this class:

class Public:
   def __init__(self, arg: str | int = 5):
       self.arg = str(arg)

Without making a semantic version major change, since it would requiring either renaming the attribute or the init value, neither of which is backwards compatible

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong
Projects
None yet
Development

No branches or pull requests

3 participants