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

Only concrete class can be given where "Type[Abstract]" is expected when creating a list comprehension of an ABC's concrete subclasses #16442

Closed
CalebMDMI opened this issue Nov 9, 2023 · 3 comments
Labels
bug mypy got something wrong topic-join-v-union Using join vs. using unions

Comments

@CalebMDMI
Copy link

CalebMDMI commented Nov 9, 2023

I'm getting an error when creating a list of classes using a comprehension. The classes are concrete subclasses of an abstract base class.

from abc import ABC, abstractmethod
from typing import Type

class Abstract(ABC):
    @abstractmethod
    def method(self):
        ...

class Concrete1(Abstract):
    def method(self):
        pass

class Concrete2(Abstract):
    def method(self):
        pass

literal_registry: list[Type[Abstract]] = [Concrete1, Concrete2]  # no error

generated_registry: list[Type[Abstract]] = [
    cls for cls in (Concrete1, Concrete2)  # error: Only concrete class can be given where "Type[Abstract]" is expected  [type-abstract]
]

This error disappears if I remove the @abstractmethod decorator.

There is also no error if I only iterate over a tuple with only one element, like so:

generated_registry: list[Type[Abstract]] = [cls for cls in (Concrete1,)]  # no error

 

  • Mypy version used: 1.3.0
  • Python version used: 3.10.5
@CalebMDMI CalebMDMI added the bug mypy got something wrong label Nov 9, 2023
@AlexWaygood AlexWaygood added the topic-join-v-union Using join vs. using unions label Nov 9, 2023
@AlexWaygood
Copy link
Member

Duplicate of #3115, I think

@AlexWaygood AlexWaygood closed this as not planned Won't fix, can't repro, duplicate, stale Nov 9, 2023
@CalebMDMI
Copy link
Author

Yep, looks like it. Sorry about that. Searched around but couldn't find anything.

@joooeey
Copy link

joooeey commented Aug 12, 2024

The code above raises no errors now. I just checked a similar case, where the newest version of MyPy is not great at inferring the correct type:

from abc import ABC, abstractmethod
from typing import Type

class Abstract(ABC):
    @abstractmethod
    def method(self):
        ...

class Concrete1(Abstract):
    def method(self):
        pass

class Concrete2(Abstract):
    def method(self):
        pass

list_of_concrete_classes: list[Type[Abstract]] = [Concrete1, Concrete2]  # mandatory type hint

index: int = 1

one_concrete_class = list_of_concrete_classes[index]

def function(cls: type[Abstract]):
    ...

function(Concrete1)  # no error
function(one_concrete_class)  # error [type-abstract] if the mandatory type hint is missing

The annotation for list_of_concrete_classes is necessary here to silence MyPy.

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-join-v-union Using join vs. using unions
Projects
None yet
Development

No branches or pull requests

3 participants