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

Custom property/descriptor and base classes #5803

Open
mm-matthias opened this issue Oct 19, 2018 · 2 comments
Open

Custom property/descriptor and base classes #5803

mm-matthias opened this issue Oct 19, 2018 · 2 comments
Labels
bug mypy got something wrong false-positive mypy gave an error on correct code priority-1-normal topic-descriptors Properties, class vs. instance attributes topic-inheritance Inheritance and incompatible overrides

Comments

@mm-matthias
Copy link

I am trying to get this code working:

from abc import ABC, abstractmethod
from typing import Any


class DataProperty:
    def __get__(self, instance: Any, owner: Any) -> str:
        return "X"


class BadBase1(ABC):
    @property
    @abstractmethod
    def id(self) -> str:
        raise NotImplementedError()


class BadBase2(ABC):
    id: str


class GoodBase(ABC):
    pass


class BadDerived1(BadBase1):
    id = DataProperty()   # Incompatible types in assignment (expression has type "DataProperty", base class "BadBase1" defined the type as "str")


class BadDerived2(BadBase2):
    id = DataProperty()   # Incompatible types in assignment (expression has type "DataProperty", base class "BadBase2" defined the type as "str")


class GoodDerived(GoodBase):
    id = DataProperty()


reveal_type(BadDerived1().id)  # Revealed type is 'Any'
reveal_type(BadDerived2().id)  # Revealed type is 'Any'
reveal_type(GoodDerived().id)  # Revealed type is 'builtins.str'

I run mypy without any flags, i.e. "mypy test.py". The mypy version is 0.641, using Python 3.6.5.

Basically I want to have some kind of base class that says "any subclasses will have a member called id and the type of this member is str.

The two cases labelled with "Bad" result in the errors shown in the comments ("incompatible types in assignment" and "revealed type is 'Any'".

The only case that works is the "Good" one, but it only works because the base class does not define anything.

Am I doing something wrong or is this a bug/limitation in mypy?

@gvanrossum gvanrossum added bug mypy got something wrong priority-1-normal labels Oct 19, 2018
@gvanrossum
Copy link
Member

Looks like a bug in the inheritance checking to me. This is a special case, overriding a property with a descriptor.

@kedder
Copy link

kedder commented Jan 20, 2019

Here's a simpler example:

from typing import Any

class D:
    def __get__(self, inst: Any, own: Any) -> int: return 0

class A:
    x = 1

class SuperA(A):
    x = D()

reveal_type(A.x)
reveal_type(SuperA.x)

mypy-0.660 produces this output:

tmp/descr.py:10: error: Incompatible types in assignment (expression has type "D", base class "A" defined the type as "int")
tmp/descr.py:12: error: Revealed type is 'builtins.int'
tmp/descr.py:13: error: Revealed type is 'Any'
tmp/descr.py:13: error: Cannot determine type of 'x'

I'd expect SuperA.x would be inferred as int, compatible with superclass A.x.

@JukkaL JukkaL added the false-positive mypy gave an error on correct code label Jan 21, 2019
@JelleZijlstra JelleZijlstra added topic-inheritance Inheritance and incompatible overrides topic-descriptors Properties, class vs. instance attributes labels Mar 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong false-positive mypy gave an error on correct code priority-1-normal topic-descriptors Properties, class vs. instance attributes topic-inheritance Inheritance and incompatible overrides
Projects
None yet
Development

No branches or pull requests

5 participants