Search code examples
python-3.xtypesabstract-classmypy

How do you annotate the type of an abstract class with mypy?


I'm writing a library where I need a method that takes a (potentially) abstract type, and returns an instance of a concrete subtype of that type:

# script.py
from typing import Type
from abc import ABC, abstractmethod


class AbstractClass(ABC):
    @abstractmethod
    def abstract_method(self):
        pass

T = TypeVar('T', bound=AbstractClass)

def f(c: Type[T]) -> T:
    # find concrete implementation of c based on
    # environment configuration
    ...


f(AbstractClass)  # doesn't type check

Running mypy script.py yields:

error: Only concrete class can be given where "Type[AbstractClass]" is expected

I don't understand this error message and am having a hard time finding any documentation for it. Is there any way to annotate the function so that mypy will type check this?

As a side note, PyCharm's type checker, which is what I use the most, type checks f with no errors.


Solution

  • There exists a github issue about this misbehaviour (IMHO) in mypy. Basically, Type[_T] with _T being a TypeVar will never accept an abstract class.

    The only sane solution I have seen is disabling this error, for example by including this in the mypy.ini file:

    [mypy]
    # Allows Type[T] to refer to abstract classes, which is not otherwise supported.
    # See https://github.com/python/mypy/issues/4717
    disable_error_code = type-abstract
    

    Quoting from the discussion:

    Now that #14619 was merged, would disabling the type-abstract error code by default address all the main issues, or is there something else that would need to be done?

    I'll add my 2¢ to the ticket later and hope, they will iron this out.