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

mypy thinks that instance variables that implement the descriptor protocol are invoked when accessing them #15822

Open
glyph opened this issue Aug 5, 2023 · 3 comments
Labels
bug mypy got something wrong topic-descriptors Properties, class vs. instance attributes

Comments

@glyph
Copy link

glyph commented Aug 5, 2023

Bug Report

__get__ should only be understood to be invoked on descriptors stored in a type's dictionary. But mypy type-checks as if there is a default present. This makes any infrastructure that wraps a decorator impossible to type correctly.

To Reproduce

https://mypy-play.net/?mypy=latest&python=3.11&flags=strict&gist=9483880764b49d2ce31d4156c9f4190a

from dataclasses import dataclass

class A:
    pass

class B:
    def __get__(self, instance: A, owner: None=None) -> int:
        return 3

    def __set__(self, instance: A, value: int) -> None:
        print("set:", value)


@dataclass
class W:
    b: B

    def set_b(self, b: B) -> None:
        self.b = b

w = W(B())
w.set_b(B())
print(w.b)

Expected Behavior

It should type-check without errors, as Python runs it fine.

Actual Behavior

main.py:19: error: Argument 1 to "__get__" of "B" has incompatible type "W"; expected "A"  [arg-type]
main.py:19: error: Argument 2 to "__get__" of "B" has incompatible type "type[W]"; expected "None"  [arg-type]
main.py:19: error: Argument 1 to "__set__" of "B" has incompatible type "W"; expected "A"  [arg-type]
main.py:19: error: Incompatible types in assignment (expression has type "B", variable has type "int")  [assignment]
Found 4 errors in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: 1.4.1
  • Mypy command-line flags: --strict
  • Python version used: 3.11
@glyph glyph added the bug mypy got something wrong label Aug 5, 2023
@glyph
Copy link
Author

glyph commented Aug 5, 2023

Apologies if this is a dup; I did look through the descriptors topic and there's lots of stuff adjacent to this, but I didn't see it reported as such.

@glyph
Copy link
Author

glyph commented Aug 5, 2023

(Also worth noting that the @dataclass seems to be irrelevant; this happens with regular type annotations too with a manual __init__.)

@JelleZijlstra JelleZijlstra added the topic-descriptors Properties, class vs. instance attributes label Aug 6, 2023
@jace
Copy link

jace commented Dec 5, 2023

I've run into the same issue trying to use a Protocol to declare a function's namespace (as is usually set by decorators):

https://mypy-play.net/?mypy=latest&python=3.11&gist=3dc9a75bf220a34c461fe2ed2523f61b

IMO, Mypy should invoke the descriptor protocol only when the variable is a ClassVar (implicit or explicit):

class Foo:
    a: ClassVar[Descriptor]  # Variable type is the return type of Descriptor.__get__
    b = Descriptor()  # Implicit ClassVar descriptor
    c: Descriptor  # The type is just `Descriptor`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong topic-descriptors Properties, class vs. instance attributes
Projects
None yet
Development

No branches or pull requests

3 participants