From 43016e2b9de6c89e86b05ba6e61f924326322412 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 13 Aug 2021 21:11:26 +0100 Subject: [PATCH] remove boilerplate --- examples/calculator.py | 14 +++++++------- examples/code_viewer.py | 5 ++--- examples/grid.py | 2 +- src/textual/_callback.py | 3 ++- src/textual/message_pump.py | 2 +- src/textual/reactive.py | 13 ++++++++----- 6 files changed, 21 insertions(+), 18 deletions(-) diff --git a/examples/calculator.py b/examples/calculator.py index 0b764790b..ffdcefc7d 100644 --- a/examples/calculator.py +++ b/examples/calculator.py @@ -54,7 +54,7 @@ class FigletText: class Numbers(Widget): """The digital display of the calculator.""" - value: Reactive[str] = Reactive("0") + value = Reactive("0") def render(self) -> RenderableType: """Build a Rich renderable to render the calculator display.""" @@ -84,10 +84,10 @@ class Calculator(GridView): "=": YELLOW, } - display: Reactive[str] = Reactive("0") - show_ac: Reactive[bool] = Reactive(True) + display = Reactive("0") + show_ac = Reactive(True) - async def watch_display(self, value: str) -> None: + def watch_display(self, value: str) -> None: """Called when self.display is modified.""" # self.numbers is a widget that displays the calculator result # Setting the attribute value changes the display @@ -99,13 +99,13 @@ class Calculator(GridView): # Condition to show AC button over C return self.value in ("", "0") and self.display == "0" - async def watch_show_ac(self, show_ac: bool) -> None: + def watch_show_ac(self, show_ac: bool) -> None: """When the show_ac attribute change we need to update the buttons.""" # Show AC and hide C or vice versa self.c.visible = not show_ac self.ac.visible = show_ac - async def on_mount(self, event: events.Mount) -> None: + def on_mount(self) -> None: """Event when widget is first mounted (added to a parent view).""" # Attributes to store the current calculation @@ -153,7 +153,7 @@ class Calculator(GridView): *self.buttons.values(), clear=self.ac, numbers=self.numbers, zero=self.zero ) - async def message_button_pressed(self, message: ButtonPressed) -> None: + def message_button_pressed(self, message: ButtonPressed) -> None: """A message sent by the button widget""" assert isinstance(message.sender, Button) diff --git a/examples/code_viewer.py b/examples/code_viewer.py index 690001b32..b5418c428 100644 --- a/examples/code_viewer.py +++ b/examples/code_viewer.py @@ -5,7 +5,6 @@ from rich.console import RenderableType from rich.syntax import Syntax from rich.traceback import Traceback -from textual import events from textual.app import App from textual.widgets import Header, Footer, FileClick, ScrollView, DirectoryTree @@ -13,7 +12,7 @@ from textual.widgets import Header, Footer, FileClick, ScrollView, DirectoryTree class MyApp(App): """An example of a very simple Textual App""" - async def on_load(self, event: events.Load) -> None: + async def on_load(self) -> None: """Sent before going in to application mode.""" # Bind our basic keys @@ -28,7 +27,7 @@ class MyApp(App): os.path.join(os.path.basename(__file__), "../../") ) - async def on_mount(self, event: events.Mount) -> None: + async def on_mount(self) -> None: """Call after terminal goes in to application mode""" # Create our widgets diff --git a/examples/grid.py b/examples/grid.py index a8bd2ee31..7392bb1f1 100644 --- a/examples/grid.py +++ b/examples/grid.py @@ -4,7 +4,7 @@ from textual.widgets import Placeholder class GridTest(App): - async def on_mount(self, event: events.Mount) -> None: + async def on_mount(self) -> None: """Make a simple grid arrangement.""" grid = await self.view.dock_grid(edge="left", size=70, name="left") diff --git a/src/textual/_callback.py b/src/textual/_callback.py index de001e09c..f8b014581 100644 --- a/src/textual/_callback.py +++ b/src/textual/_callback.py @@ -25,4 +25,5 @@ async def invoke(callback: Callable, *params: object) -> Any: result = callback(*params[:parameter_count]) if isawaitable(result): - await result + result = await result + return result diff --git a/src/textual/message_pump.py b/src/textual/message_pump.py index 16a06669b..d1b8f42bb 100644 --- a/src/textual/message_pump.py +++ b/src/textual/message_pump.py @@ -255,7 +255,7 @@ class MessagePump: method = getattr(self, method_name, None) if method is not None: log(message, ">>>", self, verbosity=message.verbosity) - await method(message) + await invoke(method, message) if message.bubble and self._parent and not message._stop_propagation: if message.sender == self._parent: diff --git a/src/textual/reactive.py b/src/textual/reactive.py index e3a9cf6ba..6777af5c6 100644 --- a/src/textual/reactive.py +++ b/src/textual/reactive.py @@ -1,6 +1,6 @@ from __future__ import annotations -import inspect +from inspect import isawaitable from functools import partial from typing import ( Any, @@ -16,7 +16,7 @@ from typing import ( from . import log from . import events -from ._callback import count_parameters +from ._callback import count_parameters, invoke from ._types import MessageTarget if TYPE_CHECKING: @@ -90,9 +90,11 @@ class Reactive(Generic[ReactiveType]): ) -> None: _rich_traceback_guard = True if count_parameters(watch_function) == 2: - await watch_function(old_value, value) + watch_result = watch_function(old_value, value) else: - await watch_function(value) + watch_result = watch_function(value) + if isawaitable(watch_result): + await watch_result await Reactive.compute(obj) watch_function = getattr(obj, f"watch_{name}", None) @@ -125,7 +127,8 @@ class Reactive(Generic[ReactiveType]): compute_method = getattr(obj, f"compute_{compute}") except AttributeError: continue - value = await compute_method() + value = await invoke(compute_method) + # value = await compute_method() setattr(obj, compute, value)