this is a Python type-hinting question but I think a little bit of context will help before we get to the crux of the issue.
I have a class which accepts two parameters:
You connect the two by doing Signal.connect(Slot)
. This connection is persistent until you explicitly disconnect again and the slot will be executed on every emit of the signal. (For those familiar, this is the Qt PySide2 library). I am building an object that ensures that the slot will only be executed once on the first emit and then disconnected from the signal but I am struggling to type-hint properly with two mypy errors:
import typing as _t
from Qt import QtCore as _QtCore
_R = _t.TypeVar("_R")
class SingleShotConnect:
_INSTANCES: _t.ClassVar[_t.Set["SingleShotConnect"]] = set()
def __init__(
self,
signal: "_QtCore.SignalInstance",
slot: _t.Callable[..., _R],
) -> None:
self._signal = signal
self._slot = slot
self._signal.connect(self._single_shot_wrapper)
SingleShotConnect._INSTANCES.add(self)
# error: A function returning TypeVar should receive at least one argument containing the same TypeVar [type-var]
def _single_shot_wrapper(self, *args, **kwargs) -> _R:
self._signal.disconnect(self._single_shot_wrapper)
SingleShotConnect._INSTANCES.remove(self)
# error: Incompatible return value type (got "_R@__init__", expected "_R@_single_shot_wrapper")
return self._slot(*args, **kwargs)
As you can see, there are two errors related to _single_shot_wrapper()
which I am not sure how to fix? I do not have access to ParamSpec if that is a possible solution due to python version limitation.
The class needs to be generic in _R
in order for the type bound by __init__
to be available to _single_shot_wrapper
.
import typing as _t
from Qt import QtCore as _QtCore
_R = _t.TypeVar("_R")
class SingleShotConnect(_t.Generic[_R]):
# Might want SingleShotConnect[_R] here; did not test if
# necessary
_INSTANCES: _t.ClassVar[_t.Set["SingleShotConnect"]] = set()
def __init__(
self,
signal: "_QtCore.SignalInstance",
slot: _t.Callable[..., _R],
) -> None:
self._signal = signal
self._slot = slot
self._signal.connect(self._single_shot_wrapper)
SingleShotConnect._INSTANCES.add(self)
# error: A function returning TypeVar should receive at least one argument containing the same TypeVar [type-var]
def _single_shot_wrapper(self, *args, **kwargs) -> _R:
self._signal.disconnect(self._single_shot_wrapper)
SingleShotConnect._INSTANCES.remove(self)
# error: Incompatible return value type (got "_R@__init__", expected "_R@_single_shot_wrapper")
return self._slot(*args, **kwargs)