From 898de5a69c03a6323b872d8775fa673d8d7d6cdf Mon Sep 17 00:00:00 2001 From: darrenburns Date: Thu, 13 Apr 2023 15:32:56 +0100 Subject: [PATCH] Fix for empty ListView bindings not firing (#2281) * Fix bindings not firing when ListView is empty * Regression test for empty ListView bindings not working * Update changelog --- CHANGELOG.md | 3 ++- src/textual/app.py | 2 +- tests/listview/test_inherit_listview.py | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e43b090c8..d124abb48e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## Unreleased -### Changed +### Changed - Changed signature of Driver. Technically a breaking change, but unlikely to affect anyone. - Breaking change: Timer.start is now private, and returns No @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Fixed order styles are applied in DataTable - allows combining of renderable styles and component classes https://github.com/Textualize/textual/pull/2272 +- Fix empty ListView preventing bindings from firing https://github.com/Textualize/textual/pull/2281 ## [0.19.1] - 2023-04-10 diff --git a/src/textual/app.py b/src/textual/app.py index fbe3f99297..24b876020d 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -2149,7 +2149,7 @@ async def run_action( action_target = getattr(self, destination) implicit_destination = True else: - action_target = default_namespace or self + action_target = default_namespace if default_namespace is not None else self action_name = target handled = await self._dispatch_action(action_target, action_name, params) diff --git a/tests/listview/test_inherit_listview.py b/tests/listview/test_inherit_listview.py index 520b4b21cf..7a0e636af1 100644 --- a/tests/listview/test_inherit_listview.py +++ b/tests/listview/test_inherit_listview.py @@ -1,19 +1,26 @@ from textual.app import App, ComposeResult +from textual.binding import Binding from textual.widgets import Label, ListItem, ListView class MyListView(ListView): """Test child class of a ListView.""" + BINDINGS = [Binding(key="s", action="set", description="Set")] + def __init__(self, items: int = 0) -> None: super().__init__() self._items = items + self.action_fired = False def compose(self) -> ComposeResult: """Compose the child widgets.""" for n in range(self._items): yield ListItem(Label(f"This is item {n}")) + def action_set(self) -> None: + self.action_fired = True + class ListViewApp(App[None]): """ListView test app.""" @@ -43,3 +50,11 @@ async def test_populated_inherited_list_view() -> None: assert pilot.app.query_one(MyListView).index == 0 await pilot.press("down") assert pilot.app.query_one(MyListView).index == 1 + + +async def test_actions_work_when_list_view_empty() -> None: + """Regression test for https://github.com/Textualize/textual/issues/2265""" + async with ListViewApp().run_test() as pilot: + await pilot.press("tab", "s") + list_view = pilot.app.query_one(MyListView) + assert list_view.action_fired