Mypy: "Class cannot subclass (has type "Any")"

Greetings! It’s my very first topic on this forum so I apologize in advance if this has already been answered somewhere else.

EDIT: forgot to mention:

  • OS: Windows 11
  • Python: 3.10.15

I’m developing a software which is divided into two separately shipped packages:

  • a toolkit package;
  • a core package.

This is because the toolkit gives the opportunity to other contributors to build plugins to attach to the core.

In the toolkit I have the following classes (I’m just leaving the class declaration since the content is not relevant - I think):

toolkit\log.py

from abc import ABC

class Loggable(ABC):
    ...

toolkit\handler.py

from toolkit.log import Loggable
from abc import ABCMeta

class Handler(Loggable, metaclass=ABCMeta):
    ...

The Loggable class provides a standard interface to provide log messages which are written in the core logger.
The Handler class is an example implementation of how to use the Loggable class to extend another abstract class.
While writing this topic I realize that Loggable doesn’t have to be abstract as well for my purposes but for now I’ll just leave it at that.

In the core package, I have an implementation of Handler:

core\handler.py

from toolkit.handler import Handler

class EngineHandler(Handler):
    ...

Now when running mypy on the core package, I get the following error:

Class cannot subclass "Handler" (has type "Any")

What exactly is going on here? Why is it complaining about this inheritance? Is it related to the content of the Handler or Loggable classes somehow?

Hi Jacopo! Most likely mypy isn’t able to follow the import to toolkit, which causes Handler to have an inferred type of Any. That often happens for one of two reasons: 1) toolkit isn’t installed in the environment that mypy is running in (or otherwise added to the mypy path), or 2) toolkit doesn’t expose PEP 561 typing information (usually due to a missing py.typed marker file).

Usually, there will be other errors in mypy’s output that will hint at what’s going on (unless you suppress them with e.g. a # type: ignore on the import or setting ignore_missing_imports = true in your config file).

See also Creating PEP 561 compatible packages from the mypy docs and Packaging Type Information from PEP 561 for more details on including type information with your package.

2 Likes

@bschubert thank you for the swift reply. I’m still new to proper packaging techniques so this is very insightful for me. I’ll have a look and try to see how to solve it then. Much appreciate it!

EDIT: it worked. For other’s who may encounter this thread, this is what I did:

  • added py.typed to my package main directory (in my case src\toolkit\py.typed)
  • added py.typed in MANIFEST.in with
    • include toolkit\py.typed
  • I use pyproject.toml, so I added the package data option:
[tool.setuptools.package-data]
"toolkit" = ["py.typed"]