我正在尝试实现一个Python重试装饰器,我可以在其中传递一个
return_value_generator
,如果函数用完重试尝试,它将生成一个返回值。
我目前有以下内容:
Param = ParamSpec('Param')
ReturnType = TypeVar('ReturnType')
def retry(*, retries: int = 3, return_value_generator: Callable[[], ReturnType] | None = None):
def decorator(func: Callable[Param, Awaitable[ReturnType]]) -> Callable[Param, Awaitable[ReturnType]]:
@functools.wraps(func)
async def wrapper(*args: Param.args, **kwargs: Param.kwargs) -> ReturnType:
retries_left = retries
while True:
try:
return await func(*args, **kwargs)
except Exception:
if retries_left <= 0:
if return_value_generator is not None:
return return_value_generator()
raise
return wrapper
return decorator
@retry(return_value_generator=lambda: [None])
async def get_cache_values(cache, keys: list[str]) -> list[bytes | None]:
"""
Returns cache values for the given keys or None if the cache doesn't
exist for a specific key.
"""
...
类型检查器(pyright)在装饰函数上给我以下错误消息:
Type parameter "_T_co@Awaitable" is covariant, but "list[bytes | None]" is not a subtype of "list[None]"
问题似乎是我以一种方式定义装饰器,其中
return_value_generator
是定义返回类型的,但我实际上希望内部装饰函数定义return_value_generator
的返回类型。
我希望类型检查器验证
list[bytes | None]
是否是 list[None]
的子类型,而不是检查
list[None]
是否是
list[bytes | None]
的子类型
有没有办法以这种方式设置装饰器?
我尝试创建一个新的类型变量,如下所示:
ReturnTypeSubtype = TypeVar('ReturnTypeSubtype', bound=ReturnType)
def retry(*, retries: int = 3, return_value_generator: Callable[[], ReturnTypeSubtype] | None = None):
...
但是我从
ReturnTypeSubtype
声明的类型检查器收到以下错误消息:
Type variable "ReturnType" has no meaning in this context