Python use metaclass, cause Vscode can't give type hint

76 views Asked by At

I create a metaclass and use it in class "Pool", then Vscode will not provide any type hintabout Pool

In python i create a metaclass like this:

class SignSingleton(type):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.__signObjDict = weakref.WeakValueDictionary()

    def __call__(self, *args):
        if args in self.__signObjDict:
            return self.__signObjDict[args]
        else:
            obj = super().__call__(*args)
            self.__signObjDict[args] = obj
            return obj

And use it like this:

class Pool(metaclass=SignSingleton):
    def __init__(self, name=None):
        self.pool = weakref.WeakValueDictionary()
        self.name = name or "UnnamedPool"

    def count(self) -> int:
        length = self.pool.__len__()
        return length

    def find(self, name, default: QObject = None) -> Optional[QObject]:
        if not self.pool.get(name):
            return default
        return self.pool.get(name)

    def __getitem__(self, name) -> Optional[QObject]:
        return self.pool.get(name)

    def __setitem__(self, key: str, value: QObject):
        self.pool[key] = value

    def __repr__(self):
        return str(self.name + ": ") + "{0.pool!r}".format(self)

Then I realized that vscode no longer gave me any type hint about Pool.

When removed the Metaclass from Pool, the type hint returned to normal. Python 3.11.5, Vscode 1.77.3

so w d f this shit effect vscode's type hint?

1

There are 1 answers

0
sudden_appearance On BEST ANSWER

You are overriding __call__() method without proper type hinting, that's why Pool is lacking type hinting . Try this:

import weakref
from typing import TypeVar, Type

T = TypeVar("T")


class SignSingleton(type):
    def __init__(cls, *args, **kwargs):
        super().__init__(*args, **kwargs)
        cls.__signObjDict = weakref.WeakValueDictionary()

    def __call__(cls: Type[T], *args) -> T:
        if args in cls.__signObjDict:
            return cls.__signObjDict[args]
        else:
            obj = super().__call__(*args)
            cls.__signObjDict[args] = obj
            return obj