Closed
Description
and the error messages are impenetrable.
Suppose you have this file:
from typing import Tuple, Any, Mapping
reveal_type(type.__prepare__)
class Foo(type):
@classmethod
def __prepare__(mcls, name: str, bases: Tuple[type, ...], **kwds: Any) -> Mapping[str, Any]:
return {}
mypy run:
$ mypy foo.py
foo.py:4: note: Revealed type is 'def (builtins.str, builtins.tuple[builtins.type], **kwds: Any) -> typing.Mapping[builtins.str, Any]'
foo.py:9: error: Signature of "__prepare__" incompatible with supertype "type"
Found 1 error in 1 file (checked 1 source file)
But … the "revealed type" is the type I gave it? (The second reported parameter, builtins.tuple[builtins.type]
, is reported incorrectly; if you try to give that parameter that type, you get this message:
foo.py:9: error: Argument 2 of "__prepare__" is incompatible with supertype "type"; supertype defines the argument type as "Tuple[type, ...]"
foo.py:9: note: This violates the Liskov substitution principle
, so the "revealed type" is clearly not quite right.)
Ok, let's look in typeshed:
def __prepare__(metacls, __name: str, __bases: Tuple[type, ...], **kwds: Any) -> Mapping[str, Any]: ...
hmmmmmm.
You can get mypy to accept this type for __prepare__
—if the class inherits from object
, rather than type
. But metaclasses in mypy's own repo (e.g. MaybeMissingMeta
) inherit from type
, and, as I understand it, this is correct, since metaclasses are types of types.
cc @neilvyas