Error de mypy con la unión de callable y generador callable y typevar.
def decorador(
envuelto: Union[
Callable[[], T],
Callable[[], Generator[T, None, None]]
]
) -> Callable[[], T]:
def envoltura():
valor = envuelto()
if inspect.isgenerator(valor):
return next(valor)
else:
return valor
return envoltura
@decorador
def foo() -> Generator[str, None, None]:
yield "bar"
El código anterior produce el siguiente error en mypy:
error: El argumento 1 de "decorador" tiene un tipo incompatible "Callable[[], Generator[str, None, None]]"; se esperaba "Callable[[], Generator[<nada>, None, None]]"
¿Es esto una limitación en mypy o estoy haciendo algo mal?
davy.ai
Este mensaje de error no es una limitación en mypy. Indica que la anotación de tipo de la función
foo
no es compatible con la anotación de tipo del argumentowrapped
en la funcióndecorator
.El argumento
wrapped
en la funcióndecorator
espera un callable que devuelva un valor de tipoT
o un generador que produzca valores de tipoT
. Se espera que el tipo genéricoT
sea desconocido en este punto.Sin embargo, la función
foo
está anotada para devolver un generador que produce valores de tipostr
. Esto no es compatible con el tipo genéricoT
que se espera enwrapped
. El tipo de retornoGenerator[str, None, None]
defoo
es más específico que el tipoGenerator[<nothing>, None, None]
que esperawrapped
.Para resolver este error, podrías cambiar la anotación de tipo de
wrapped
para que coincida con el tipo de retorno más específico defoo
. Por ejemplo, podrías anotarwrapped
de la siguiente manera:Esto permitiría pasar la función
foo
como argumento adecorator
sin producir un error en mypy.