Skip to content

impossible to type __prepare__ if metaclass inherits from type #10366

Closed
@bwo

Description

@bwo

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrong

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions