diff --git a/src/textual/reactive.py b/src/textual/reactive.py index 7fb8b3ba2..5e2515de8 100644 --- a/src/textual/reactive.py +++ b/src/textual/reactive.py @@ -241,11 +241,13 @@ class Reactive(Generic[ReactiveType]): events.Callback(callback=partial(await_watcher, watch_result)) ) - watch_function = getattr( - obj, f"_watch_{name}", getattr(obj, f"watch_{name}", None) - ) - if callable(watch_function): - invoke_watcher(watch_function, old_value, value) + private_watch_function = getattr(obj, f"_watch_{name}", None) + if callable(private_watch_function): + invoke_watcher(private_watch_function, old_value, value) + + public_watch_function = getattr(obj, f"watch_{name}", None) + if callable(public_watch_function): + invoke_watcher(public_watch_function, old_value, value) # Process "global" watchers watchers: list[tuple[Reactable, Callable]] diff --git a/tests/test_reactive.py b/tests/test_reactive.py index 74f944d48..2032406ae 100644 --- a/tests/test_reactive.py +++ b/tests/test_reactive.py @@ -390,8 +390,8 @@ async def test_watch_compute(): assert watch_called == [True, True, False, False, True, True, False, False] -async def test_private_watch() -> None: - """A private watch method should win over a public watch method.""" +async def test_public_and_private_watch() -> None: + """If a reactive/var has public and private watches both should get called.""" calls: dict[str, bool] = {"private": False, "public": False} @@ -409,4 +409,4 @@ async def test_private_watch() -> None: assert calls["public"] is False pilot.app.counter += 1 assert calls["private"] is True - assert calls["public"] is False + assert calls["public"] is True