Pylance ругается на вызов Union аргумента функции
У меня есть следующий код как минимально воспроизводимый пример:
from typing import Any, Callable, Generic, Optional, TypeVar, Union
from random import choice
T1 = TypeVar("T1")
class qux(Generic[T1]):
def foo(self) -> Callable[[T1], None]:
def foo_wrapper(arg:T1):
print(f'Bar wrapper called with argument {arg}')
return foo_wrapper
def bar(self) -> Callable[[], None]:
def bar_wrapper():
print('Foo wrapper called without arguments')
return bar_wrapper
def buzz(self, func:Union[Callable[[T1], Any], Callable[[], Any]], arg: Optional[T1] = None):
if arg:
func(arg)
else:
func()
def choice_impl(self, flag:bool):
if flag:
return self.foo()
else:
return self.bar()
qux_instance = qux()
value = None
if choice((True, False)):
value = 42
flag = value is not None
implementation = qux_instance.choice_impl(flag=flag)
if flag:
qux_instance.buzz(func=implementation, arg=value)
else:
qux_instance.buzz(func=implementation)
Pylance ругается на строку 21:
Expected 0 positional arguments (parameter) arg: T1@qux
и 23:
Expected 1 more positional argument (parameter) func: ((T1@qux) -> Any) | (() -> Any)
потому что он не знает, какая сигнатура у аргумента func функции buzz будет на момент вызова. Хотя этот код всегда выполняется без ошибок. Как мне решить эту проблему? Это баг Pylance или это связанно с проблемой останова? Или это у меня руки кривые?
Ответы (1 шт):
Автор решения: insolor
→ Ссылка
В данном случае можно использовать cast из модуля typing:
def buzz(self, func:Union[Callable[[T1], Any], Callable[[], Any]], arg: Optional[T1] = None):
if arg:
cast(Callable[[T1], Any], func)(arg)
else:
cast(Callable[[], Any], func)()
Но это по сути отключает защиту, статический анализатор никак не сможет проверить соответствие, что вы передали функцию с одним аргументом и аргумент для нее или функцию без аргументов, и не передали аргумент.