[Python] How do I type the `__prepare__` method for a metaclass?

Discussão em 'Python' iniciado por Stack, Fevereiro 7, 2025.

  1. Stack

    Stack Membro Participativo

    I’m trying to write a simple metaclass that intercepts every function declaration and replaces it with a dummy function:

    from dataclasses import dataclass
    from typing import Any, Mapping


    @dataclass
    class DummyCall:
    args: tuple[Any, ...]
    kwargs: dict[str, Any]


    def _dummy_function(*args: Any, **kwargs: Any) -> DummyCall:
    return DummyCall(args, kwargs)


    class _dummy_dict(dict[str, Any]):
    def __setitem__(self, key: str, value: Any) -> None:
    if callable(value):
    super().__setitem__(key, _dummy_function)
    else:
    super().__setitem__(key, value)


    class dummy(type):
    @classmethod
    def __prepare__(metcls, name, bases, **kwds):
    return _dummy_dict()


    I now want to type-hint the __prepare__ method. I’ve tried the following:

    def __prepare__(*_, *__): …


    …but of course this doesn’t work. From the error I got I tried to reconstruct the type, and ended up with the following:

    def __prepare__(metcls: Any, name: str, bases: tuple[type, ...], **kwds: Any) -> Mapping[str, Any]: …


    Unfortunately, this still doesn’t satisfy MyPy. I get the following error:

    error: Signature of "__prepare__" incompatible with supertype "type"
    note: Superclass:
    note: def __prepare__(metacls, str, Tuple[type, ...], **kwds: Any) -> Mapping[str, object]
    note: Subclass:
    note: @classmethod
    note: def __prepare__(metcls, name: str, bases: Tuple[type, ...], **kwds: Any) -> Mapping[str, Any]


    I also interestingly get different errors in my code editor with a MyPy plugin:

    Signature of "__prepare__" incompatible with supertype "type"mypy
    Superclass:mypy
    @classmethodmypy
    def __prepare__(metacls, str, Tuple[type, ...], **kwds: Any) -> Mapping[str, object]mypy
    Subclass:mypy
    @classmethodmypy
    def __prepare__(metcls, name: str, bases: Tuple[type, ...], **kwds: Any) -> Mapping[str, Any]mypy


    Here, it is reported that the superclass definition is annotated with @classmethod, while the command-line mypy doesn’t say this.

    Continue reading...

Compartilhe esta Página