Skip to content

The implementation of the abstract class is judged by mypy to be unconstructableΒ #18830

@dnomd343

Description

@dnomd343

Bug Report

Consider the following code:

#!/usr/bin/env python3

from abc import ABC, abstractmethod
from typing import override


class Base(ABC):
    def __init__(self, val: int):
        self.__val = val

    def show(self) -> None:
        print(f'hello: {self.__val}')

    @abstractmethod
    def impl(self) -> None:
        pass


class Derive1(Base):
    def __init__(self):
        super().__init__(1)

    @override
    def impl(self) -> None:
        pass


class Derive2(Base):
    def __init__(self):
        super().__init__(2)

    @override
    def impl(self) -> None:
        pass


def demo(index: int) -> Base:
    classes = [Derive1, Derive2]
    return classes[index]()


if __name__ == '__main__':
    demo(0).show()

It implements Derive1 and Derive2 on the Base abstract class, which implement the impl interface. When checking it with mypy, everything looks fine:

> mypy demo.py
Success: no issues found in 1 source file

At this time, if you try to add Derive3, the code is as follows:

#!/usr/bin/env python3

from abc import ABC, abstractmethod
from typing import override


class Base(ABC):
    def __init__(self, val: int):
        self.__val = val

    def show(self) -> None:
        print(f'hello: {self.__val}')

    @abstractmethod
    def impl(self) -> None:
        pass


class Derive1(Base):
    def __init__(self):
        super().__init__(1)

    @override
    def impl(self) -> None:
        pass


class Derive2(Base):
    def __init__(self):
        super().__init__(2)

    @override
    def impl(self) -> None:
        pass


class Derive3(Base):  # add Derive3 just like the previous two
    def __init__(self):
        super().__init__(3)

    @override
    def impl(self) -> None:
        pass


def demo(index: int) -> Base:
    classes = [Derive1, Derive2, Derive3]  # add Derive3 item
    return classes[index]()


if __name__ == '__main__':
    demo(0).show()

At this time, mypy will issue the following complaint:

> mypy demo.py
demo.py:48: error: Cannot instantiate abstract class "Base" with abstract attribute "impl"  [abstract]
Found 1 error in 1 file (checked 1 source file)

The strange thing is why there is no error when there are two implementations, but there will be an error when there are three or more.

I tried pyright and pycharm, and they both gave no error messages for the above two codes, and I didn't find any reports or explanations of the problem on the search engine.

Environment

  • Mypy version used: 1.15.0
  • Mypy command-line flags: mypy demo.py
  • Python version used: 3.13.2

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrongtopic-join-v-unionUsing join vs. using unions

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions