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

Fail to handle property and init-only field with same name #3750

Closed
Henkhogan opened this issue Dec 11, 2022 · 6 comments
Closed

Fail to handle property and init-only field with same name #3750

Henkhogan opened this issue Dec 11, 2022 · 6 comments

Comments

@Henkhogan
Copy link

Henkhogan commented Dec 11, 2022

Environment data

  • Language Server version: v2022.12.20
  • OS and version: Ubuntu 22.10
  • Python version (& distribution if applicable, e.g. Anaconda): 3.11.0

Code Snippet

from dataclasses import dataclass, field, InitVar

@dataclass(slots=True)
class MyClass:
    foo: InitVar[str]  # type: ignore
    _foo: str = field(init = False)

    def __post_init__(self, foo):
        self.foo = foo

    @property
    def foo(self) -> str:
        return self._foo

    @foo.setter
    def foo(self, value: str):
        if not isinstance(value, str):
            raise TypeError(f'foo attribute must be of type: {str} but received: {value}')
        self._foo = value


c = MyClass(foo = 'foostring')





_ = c.foo

image

@erictraut
Copy link
Contributor

This behavior is correct. You are attempting to redefine the symbol foo in an incompatible manner. Not surprisingly, mypy generates the same error here.

You should use different names for the init variable and the property if you want this to work with a static type checker.

@Henkhogan
Copy link
Author

Well I think it should not be too difficult to handle that since it's already detected that we have an init-only field, which could be completely ignored for each access against instance attributes.

However if that's an issue that should rather be fixed in mypy than in pylance, I'll address it there

@erictraut
Copy link
Contributor

This violates the Python type system, so there's nothing to "fix" in mypy. A symbol is not allowed to have two conflicting declarations. In your example, you've declared foo as being both an init variable and a property. The job of a type checker is to detect type violations — including conflicting type declarations. Both pylance and mypy are correct in flagging this as a violation. You'll need to choose non-conflicting names for the init variable and the property if you want this to work with a static type checker.

@erictraut
Copy link
Contributor

If you're not interested in static type checking, you can set python.analysis.typeCheckingMode to "off", and these errors will not be reported by pylance.

@rchiodo rchiodo closed this as completed Dec 12, 2022
@Henkhogan
Copy link
Author

This violates the Python type system, so there's nothing to "fix" in mypy. A symbol is not allowed to have two conflicting declarations. In your example, you've declared foo as being both an init variable and a property. The job of a type checker is to detect type violations — including conflicting type declarations. Both pylance and mypy are correct in flagging this as a violation. You'll need to choose non-conflicting names for the init variable and the property if you want this to work with a static type checker.

@erictraut I am aware, but I don't see a real conflict here. What I see is a pseudo-conflict that will not be present at runtime. In my opinion the special characteristic of the init-only field is not sufficiently considered. Quoting the dataclass docs

If a field is an InitVar, it is considered a pseudo-field called an init-only field. As it is not a true field, it is not returned by the module-level fields() function. Init-only fields are added as parameters to the generated init() method, and are passed to the optional post_init() method. They are not otherwise used by dataclasses.

@Henkhogan
Copy link
Author

Duplicates #python/mypy#12046

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

No branches or pull requests

3 participants