-
-
Notifications
You must be signed in to change notification settings - Fork 786
Description
What is the problem or limitation you are having?
toga.Button's on_press parameter is annotated as callable|None, but it calls this callable like f(widget), so the callable has to accept a parameter:
import toga
from toga.style import Pack
from toga.style.pack import COLUMN
class HelloWorld(toga.App):
def startup(self) -> None:
main_box = toga.Box(style=Pack(direction=COLUMN))
button = toga.Button("Say Hello!", on_press=self.say_hello)
main_box.add(button)
self.main_window = toga.MainWindow(title=self.formal_name)
self.main_window.content = main_box
self.main_window.show()
def say_hello(self) -> None:
self.main_window.info_dialog("Hello!", "Hello!")
def main() -> None:
return HelloWorld()Clicking the button leads to an error, because say_hello has an incompatible signature.
Since on_press is not annotated as e.g. Callable[[Widget], None], static type checkers like mypy or PyCharm don't catch this error.
Describe the solution you'd like
I'd like on_pressed to be annotated as Callable[[Widget], Any], Callable[[Button], None], or whatever fits best and prevents such errors (I'm not deeply familiar with toga semantics).
Describe alternatives you've considered
One could also inspect the callable and only pass the widget as parameter if the signature expects a parameter.
This would also prevent runtime issues with callbacks not requiring a reference to the calling widget, which I think is the most common source for signature mismatches here.
However, a callback like show_number_dialog(x: int) -> None would still not be flagged by static type checking.
Additional context
No response