-
Hello, I am working on a code base that a construct similar to this: from typing import Callable, Literal, Union, overload
class A:
@overload
def foo(self) -> int: ...
@overload
def foo(self, now: Literal[True] = True) -> int: ...
@overload
def foo(self, now: Literal[False]) -> Callable[[], int]: ...
@overload
def foo(self, now: bool) -> Union[int, Callable[[], int]]: ...
def foo(self, now: bool = True) -> Union[int, Callable[[], int]]:
"""Does foo things."""
raise NotImplementedError()
class B(A):
def foo(self, now: Literal[True] = True) -> int:
assert now is True
return 42
class C(A):
def foo(self, now: bool = True) -> int:
assert now is True
return 42
class D(A):
def foo(self) -> int:
return 42
class E(A):
@overload
def foo(self) -> int: ...
@overload
def foo(self, now: Literal[True] = True) -> int: ...
@overload
def foo(self, now: Literal[False]) -> Callable[[], int]: ...
@overload
def foo(self, now: bool) -> Union[int, Callable[[], int]]: ...
def foo(self, now: bool = True) -> Union[int, Callable[[], int]]:
assert now is True
return 42 Pyright reports a Can someone explain what am I doing wrong, please? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
The type system assumes that any subclass of Here's a code sample that demonstrates why this is a problem: def func(a: A):
a.foo(now=False)
func(B()) This code snippet does not violate any type assignment rules because |
Beta Was this translation helpful? Give feedback.
-
Thank you very much for your answer. I am still struggling to understand why is it required to have the For example, if I add class F(A):
def foo(self, now: bool = True) -> Union[int, Callable[[], int]]:
if now:
return 42
else:
return lambda: 42 This runs fine with def func(a: A):
print(a.foo())
print(a.foo(now=True))
res = a.foo(now=False))
print(res()) but Pyright reports
If I add only one of the overload, pyright reports
The first line is reported for any of the overload used which is fair. After all, there’s no overload if there’s only one signature. So adding As far as I understand, the |
Beta Was this translation helpful? Give feedback.
No, that's a wrong assumption. If a subclass defines an overloaded method (whether or not that method is overriding a method in a parent class), you need to define the overload signatures for the method. You may find that it's useful to read this chapter of the Python typing spec. This section may also be useful because it defines assignability rules for callable types. An overridden method must be assignable to the method it is overriding.