We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Validators and watchers should run hand-in-hand
When `init=True` in a `reactive` attribute, the `watch_` method for that attribute run, but the `validate_` method does not.
This seems rather confusing and we think that validators and watchers should always run hand-in-hand.
If the watcher is called, you should be confident that the incoming `new_value` has already been validated by the `validate_` method.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/textual/reactive.py`
Content:
```
1 from __future__ import annotations
2 
3 from functools import partial
4 from inspect import isawaitable
5 from typing import (
6     TYPE_CHECKING,
7     Any,
8     Awaitable,
9     Callable,
10     Generic,
11     Type,
12     TypeVar,
13     Union,
14 )
15 
16 from . import events
17 from ._callback import count_parameters, invoke
18 from ._types import MessageTarget
19 
20 if TYPE_CHECKING:
21     from .app import App
22     from .widget import Widget
23 
24     Reactable = Union[Widget, App]
25 
26 ReactiveType = TypeVar("ReactiveType")
27 
28 
29 class _NotSet:
30     pass
31 
32 
33 _NOT_SET = _NotSet()
34 
35 T = TypeVar("T")
36 
37 
38 class Reactive(Generic[ReactiveType]):
39     """Reactive descriptor.
40 
41     Args:
42         default (ReactiveType | Callable[[], ReactiveType]): A default value or callable that returns a default.
43         layout (bool, optional): Perform a layout on change. Defaults to False.
44         repaint (bool, optional): Perform a repaint on change. Defaults to True.
45         init (bool, optional): Call watchers on initialize (post mount). Defaults to False.
46         always_update (bool, optional): Call watchers even when the new value equals the old value. Defaults to False.
47     """
48 
49     def __init__(
50         self,
51         default: ReactiveType | Callable[[], ReactiveType],
52         *,
53         layout: bool = False,
54         repaint: bool = True,
55         init: bool = False,
56         always_update: bool = False,
57     ) -> None:
58         self._default = default
59         self._layout = layout
60         self._repaint = repaint
61         self._init = init
62         self._always_update = always_update
63 
64     @classmethod
65     def init(
66         cls,
67         default: ReactiveType | Callable[[], ReactiveType],
68         *,
69         layout: bool = False,
70         repaint: bool = True,
71         always_update: bool = False,
72     ) -> Reactive:
73         """A reactive variable that calls watchers and compute on initialize (post mount).
74 
75         Args:
76             default (ReactiveType | Callable[[], ReactiveType]): A default value or callable that returns a default.
77             layout (bool, optional): Perform a layout on change. Defaults to False.
78             repaint (bool, optional): Perform a repaint on change. Defaults to True.
79             always_update (bool, optional): Call watchers even when the new value equals the old value. Defaults to False.
80 
81         Returns:
82             Reactive: A Reactive instance which calls watchers or initialize.
83         """
84         return cls(
85             default,
86             layout=layout,
87             repaint=repaint,
88             init=True,
89             always_update=always_update,
90         )
91 
92     @classmethod
93     def var(
94         cls,
95         default: ReactiveType | Callable[[], ReactiveType],
96     ) -> Reactive:
97         """A reactive variable that doesn't update or layout.
98 
99         Args:
100             default (ReactiveType | Callable[[], ReactiveType]):  A default value or callable that returns a default.
101 
102         Returns:
103             Reactive: A Reactive descriptor.
104         """
105         return cls(default, layout=False, repaint=False, init=True)
106 
107     @classmethod
108     def _initialize_object(cls, obj: object) -> None:
109         """Set defaults and call any watchers / computes for the first time.
110 
111         Args:
112             obj (Reactable): An object with Reactive descriptors
113         """
114         if not hasattr(obj, "__reactive_initialized"):
115             startswith = str.startswith
116             for key in obj.__class__.__dict__:
117                 if startswith(key, "_default_"):
118                     name = key[9:]
119                     # Check defaults
120                     if not hasattr(obj, name):
121                         # Attribute has no value yet
122                         default = getattr(obj, key)
123                         default_value = default() if callable(default) else default
124                         # Set the default vale (calls `__set__`)
125                         setattr(obj, name, default_value)
126         setattr(obj, "__reactive_initialized", True)
127 
128     @classmethod
129     def _reset_object(cls, obj: object) -> None:
130         """Reset reactive structures on object (to avoid reference cycles).
131 
132         Args:
133             obj (object): A reactive object.
134         """
135         getattr(obj, "__watchers", {}).clear()
136         getattr(obj, "__computes", []).clear()
137 
138     def __set_name__(self, owner: Type[MessageTarget], name: str) -> None:
139 
140         # Check for compute method
141         if hasattr(owner, f"compute_{name}"):
142             # Compute methods are stored in a list called `__computes`
143             try:
144                 computes = getattr(owner, "__computes")
145             except AttributeError:
146                 computes = []
147                 setattr(owner, "__computes", computes)
148             computes.append(name)
149 
150         # The name of the attribute
151         self.name = name
152         # The internal name where the attribute's value is stored
153         self.internal_name = f"_reactive_{name}"
154         default = self._default
155         setattr(owner, f"_default_{name}", default)
156 
157     def __get__(self, obj: Reactable, obj_type: type[object]) -> ReactiveType:
158         _rich_traceback_omit = True
159         value: _NotSet | ReactiveType = getattr(obj, self.internal_name, _NOT_SET)
160         if isinstance(value, _NotSet):
161             # No value present, we need to set the default
162             init_name = f"_default_{self.name}"
163             default = getattr(obj, init_name)
164             default_value = default() if callable(default) else default
165             # Set and return the value
166             setattr(obj, self.internal_name, default_value)
167             if self._init:
168                 self._check_watchers(obj, self.name, default_value)
169             return default_value
170         return value
171 
172     def __set__(self, obj: Reactable, value: ReactiveType) -> None:
173         _rich_traceback_omit = True
174         name = self.name
175         current_value = getattr(obj, name)
176         # Check for validate function
177         validate_function = getattr(obj, f"validate_{name}", None)
178         # Check if this is the first time setting the value
179         first_set = getattr(obj, f"__first_set_{self.internal_name}", True)
180         # Call validate, but not on first set.
181         if callable(validate_function) and not first_set:
182             value = validate_function(value)
183         # If the value has changed, or this is the first time setting the value
184         if current_value != value or first_set or self._always_update:
185             # Set the first set flag to False
186             setattr(obj, f"__first_set_{self.internal_name}", False)
187             # Store the internal value
188             setattr(obj, self.internal_name, value)
189             # Check all watchers
190             self._check_watchers(obj, name, current_value)
191             # Refresh according to descriptor flags
192             if self._layout or self._repaint:
193                 obj.refresh(repaint=self._repaint, layout=self._layout)
194 
195     @classmethod
196     def _check_watchers(cls, obj: Reactable, name: str, old_value: Any):
197         """Check watchers, and call watch methods / computes
198 
199         Args:
200             obj (Reactable): The reactable object.
201             name (str): Attribute name.
202             old_value (Any): The old (previous) value of the attribute.
203             first_set (bool, optional): True if this is the first time setting the value. Defaults to False.
204         """
205         _rich_traceback_omit = True
206         # Get the current value.
207         internal_name = f"_reactive_{name}"
208         value = getattr(obj, internal_name)
209 
210         async def await_watcher(awaitable: Awaitable) -> None:
211             """Coroutine to await an awaitable returned from a watcher"""
212             _rich_traceback_omit = True
213             await awaitable
214             # Watcher may have changed the state, so run compute again
215             obj.post_message_no_wait(
216                 events.Callback(sender=obj, callback=partial(Reactive._compute, obj))
217             )
218 
219         def invoke_watcher(
220             watch_function: Callable, old_value: object, value: object
221         ) -> bool:
222             """Invoke a watch function.
223 
224             Args:
225                 watch_function (Callable): A watch function, which may be sync or async.
226                 old_value (object): The old value of the attribute.
227                 value (object): The new value of the attribute.
228 
229             Returns:
230                 bool: True if the watcher was run, or False if it was posted.
231             """
232             _rich_traceback_omit = True
233             if count_parameters(watch_function) == 2:
234                 watch_result = watch_function(old_value, value)
235             else:
236                 watch_result = watch_function(value)
237             if isawaitable(watch_result):
238                 # Result is awaitable, so we need to await it within an async context
239                 obj.post_message_no_wait(
240                     events.Callback(
241                         sender=obj, callback=partial(await_watcher, watch_result)
242                     )
243                 )
244                 return False
245             else:
246                 return True
247 
248         # Compute is only required if a watcher runs immediately, not if they were posted.
249         require_compute = False
250         watch_function = getattr(obj, f"watch_{name}", None)
251         if callable(watch_function):
252             require_compute = require_compute or invoke_watcher(
253                 watch_function, old_value, value
254             )
255 
256         watchers: list[Callable] = getattr(obj, "__watchers", {}).get(name, [])
257         for watcher in watchers:
258             require_compute = require_compute or invoke_watcher(
259                 watcher, old_value, value
260             )
261 
262         if require_compute:
263             # Run computes
264             obj.post_message_no_wait(
265                 events.Callback(sender=obj, callback=partial(Reactive._compute, obj))
266             )
267 
268     @classmethod
269     async def _compute(cls, obj: Reactable) -> None:
270         """Invoke all computes.
271 
272         Args:
273             obj (Reactable): Reactable object.
274         """
275         _rich_traceback_guard = True
276         computes = getattr(obj, "__computes", [])
277         for compute in computes:
278             try:
279                 compute_method = getattr(obj, f"compute_{compute}")
280             except AttributeError:
281                 continue
282 
283             value = await invoke(compute_method)
284             setattr(obj, compute, value)
285 
286 
287 class reactive(Reactive[ReactiveType]):
288     """Create a reactive attribute.
289 
290     Args:
291         default (ReactiveType | Callable[[], ReactiveType]): A default value or callable that returns a default.
292         layout (bool, optional): Perform a layout on change. Defaults to False.
293         repaint (bool, optional): Perform a repaint on change. Defaults to True.
294         init (bool, optional): Call watchers on initialize (post mount). Defaults to True.
295         always_update (bool, optional): Call watchers even when the new value equals the old value. Defaults to False.
296     """
297 
298     def __init__(
299         self,
300         default: ReactiveType | Callable[[], ReactiveType],
301         *,
302         layout: bool = False,
303         repaint: bool = True,
304         init: bool = True,
305         always_update: bool = False,
306     ) -> None:
307         super().__init__(
308             default,
309             layout=layout,
310             repaint=repaint,
311             init=init,
312             always_update=always_update,
313         )
314 
315 
316 class var(Reactive[ReactiveType]):
317     """Create a reactive attribute (with no auto-refresh).
318 
319     Args:
320         default (ReactiveType | Callable[[], ReactiveType]): A default value or callable that returns a default.
321         init (bool, optional): Call watchers on initialize (post mount). Defaults to True.
322     """
323 
324     def __init__(
325         self, default: ReactiveType | Callable[[], ReactiveType], init: bool = True
326     ) -> None:
327         super().__init__(default, layout=False, repaint=False, init=init)
328 
329 
330 def watch(
331     obj: Reactable,
332     attribute_name: str,
333     callback: Callable[[Any], object],
334     init: bool = True,
335 ) -> None:
336     """Watch a reactive variable on an object.
337 
338     Args:
339         obj (Reactable): The parent object.
340         attribute_name (str): The attribute to watch.
341         callback (Callable[[Any], object]): A callable to call when the attribute changes.
342         init (bool, optional): True to call watcher initialization. Defaults to True.
343     """
344 
345     if not hasattr(obj, "__watchers"):
346         setattr(obj, "__watchers", {})
347     watchers: dict[str, list[Callable]] = getattr(obj, "__watchers")
348     watcher_list = watchers.setdefault(attribute_name, [])
349     if callback in watcher_list:
350         return
351     watcher_list.append(callback)
352     if init:
353         current_value = getattr(obj, attribute_name, None)
354         Reactive._check_watchers(obj, attribute_name, current_value)
355
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/textual/reactive.py b/src/textual/reactive.py
--- a/src/textual/reactive.py
+++ b/src/textual/reactive.py
@@ -177,8 +177,8 @@
         validate_function = getattr(obj, f"validate_{name}", None)
         # Check if this is the first time setting the value
         first_set = getattr(obj, f"__first_set_{self.internal_name}", True)
-        # Call validate, but not on first set.
-        if callable(validate_function) and not first_set:
+        # Call validate
+        if callable(validate_function):
             value = validate_function(value)
         # If the value has changed, or this is the first time setting the value
         if current_value != value or first_set or self._always_update:

{"golden_diff": "diff --git a/src/textual/reactive.py b/src/textual/reactive.py\n--- a/src/textual/reactive.py\n+++ b/src/textual/reactive.py\n@@ -177,8 +177,8 @@\n         validate_function = getattr(obj, f\"validate_{name}\", None)\n         # Check if this is the first time setting the value\n         first_set = getattr(obj, f\"__first_set_{self.internal_name}\", True)\n-        # Call validate, but not on first set.\n-        if callable(validate_function) and not first_set:\n+        # Call validate\n+        if callable(validate_function):\n             value = validate_function(value)\n         # If the value has changed, or this is the first time setting the value\n         if current_value != value or first_set or self._always_update:\n", "issue": "Validators and watchers should run hand-in-hand\nWhen `init=True` in a `reactive` attribute, the `watch_` method for that attribute run, but the `validate_` method does not.\nThis seems rather confusing and we think that validators and watchers should always run hand-in-hand.\nIf the watcher is called, you should be confident that the incoming `new_value` has already been validated by the `validate_` method.\n", "before_files": [{"content": "from __future__ import annotations\n\nfrom functools import partial\nfrom inspect import isawaitable\nfrom typing import (\n    TYPE_CHECKING,\n    Any,\n    Awaitable,\n    Callable,\n    Generic,\n    Type,\n    TypeVar,\n    Union,\n)\n\nfrom . import events\nfrom ._callback import count_parameters, invoke\nfrom ._types import MessageTarget\n\nif TYPE_CHECKING:\n    from .app import App\n    from .widget import Widget\n\n    Reactable = Union[Widget, App]\n\nReactiveType = TypeVar(\"ReactiveType\")\n\n\nclass _NotSet:\n    pass\n\n\n_NOT_SET = _NotSet()\n\nT = TypeVar(\"T\")\n\n\nclass Reactive(Generic[ReactiveType]):\n    \"\"\"Reactive descriptor.\n\n    Args:\n        default (ReactiveType | Callable[[], ReactiveType]): A default value or callable that returns a default.\n        layout (bool, optional): Perform a layout on change. Defaults to False.\n        repaint (bool, optional): Perform a repaint on change. Defaults to True.\n        init (bool, optional): Call watchers on initialize (post mount). Defaults to False.\n        always_update (bool, optional): Call watchers even when the new value equals the old value. Defaults to False.\n    \"\"\"\n\n    def __init__(\n        self,\n        default: ReactiveType | Callable[[], ReactiveType],\n        *,\n        layout: bool = False,\n        repaint: bool = True,\n        init: bool = False,\n        always_update: bool = False,\n    ) -> None:\n        self._default = default\n        self._layout = layout\n        self._repaint = repaint\n        self._init = init\n        self._always_update = always_update\n\n    @classmethod\n    def init(\n        cls,\n        default: ReactiveType | Callable[[], ReactiveType],\n        *,\n        layout: bool = False,\n        repaint: bool = True,\n        always_update: bool = False,\n    ) -> Reactive:\n        \"\"\"A reactive variable that calls watchers and compute on initialize (post mount).\n\n        Args:\n            default (ReactiveType | Callable[[], ReactiveType]): A default value or callable that returns a default.\n            layout (bool, optional): Perform a layout on change. Defaults to False.\n            repaint (bool, optional): Perform a repaint on change. Defaults to True.\n            always_update (bool, optional): Call watchers even when the new value equals the old value. Defaults to False.\n\n        Returns:\n            Reactive: A Reactive instance which calls watchers or initialize.\n        \"\"\"\n        return cls(\n            default,\n            layout=layout,\n            repaint=repaint,\n            init=True,\n            always_update=always_update,\n        )\n\n    @classmethod\n    def var(\n        cls,\n        default: ReactiveType | Callable[[], ReactiveType],\n    ) -> Reactive:\n        \"\"\"A reactive variable that doesn't update or layout.\n\n        Args:\n            default (ReactiveType | Callable[[], ReactiveType]):  A default value or callable that returns a default.\n\n        Returns:\n            Reactive: A Reactive descriptor.\n        \"\"\"\n        return cls(default, layout=False, repaint=False, init=True)\n\n    @classmethod\n    def _initialize_object(cls, obj: object) -> None:\n        \"\"\"Set defaults and call any watchers / computes for the first time.\n\n        Args:\n            obj (Reactable): An object with Reactive descriptors\n        \"\"\"\n        if not hasattr(obj, \"__reactive_initialized\"):\n            startswith = str.startswith\n            for key in obj.__class__.__dict__:\n                if startswith(key, \"_default_\"):\n                    name = key[9:]\n                    # Check defaults\n                    if not hasattr(obj, name):\n                        # Attribute has no value yet\n                        default = getattr(obj, key)\n                        default_value = default() if callable(default) else default\n                        # Set the default vale (calls `__set__`)\n                        setattr(obj, name, default_value)\n        setattr(obj, \"__reactive_initialized\", True)\n\n    @classmethod\n    def _reset_object(cls, obj: object) -> None:\n        \"\"\"Reset reactive structures on object (to avoid reference cycles).\n\n        Args:\n            obj (object): A reactive object.\n        \"\"\"\n        getattr(obj, \"__watchers\", {}).clear()\n        getattr(obj, \"__computes\", []).clear()\n\n    def __set_name__(self, owner: Type[MessageTarget], name: str) -> None:\n\n        # Check for compute method\n        if hasattr(owner, f\"compute_{name}\"):\n            # Compute methods are stored in a list called `__computes`\n            try:\n                computes = getattr(owner, \"__computes\")\n            except AttributeError:\n                computes = []\n                setattr(owner, \"__computes\", computes)\n            computes.append(name)\n\n        # The name of the attribute\n        self.name = name\n        # The internal name where the attribute's value is stored\n        self.internal_name = f\"_reactive_{name}\"\n        default = self._default\n        setattr(owner, f\"_default_{name}\", default)\n\n    def __get__(self, obj: Reactable, obj_type: type[object]) -> ReactiveType:\n        _rich_traceback_omit = True\n        value: _NotSet | ReactiveType = getattr(obj, self.internal_name, _NOT_SET)\n        if isinstance(value, _NotSet):\n            # No value present, we need to set the default\n            init_name = f\"_default_{self.name}\"\n            default = getattr(obj, init_name)\n            default_value = default() if callable(default) else default\n            # Set and return the value\n            setattr(obj, self.internal_name, default_value)\n            if self._init:\n                self._check_watchers(obj, self.name, default_value)\n            return default_value\n        return value\n\n    def __set__(self, obj: Reactable, value: ReactiveType) -> None:\n        _rich_traceback_omit = True\n        name = self.name\n        current_value = getattr(obj, name)\n        # Check for validate function\n        validate_function = getattr(obj, f\"validate_{name}\", None)\n        # Check if this is the first time setting the value\n        first_set = getattr(obj, f\"__first_set_{self.internal_name}\", True)\n        # Call validate, but not on first set.\n        if callable(validate_function) and not first_set:\n            value = validate_function(value)\n        # If the value has changed, or this is the first time setting the value\n        if current_value != value or first_set or self._always_update:\n            # Set the first set flag to False\n            setattr(obj, f\"__first_set_{self.internal_name}\", False)\n            # Store the internal value\n            setattr(obj, self.internal_name, value)\n            # Check all watchers\n            self._check_watchers(obj, name, current_value)\n            # Refresh according to descriptor flags\n            if self._layout or self._repaint:\n                obj.refresh(repaint=self._repaint, layout=self._layout)\n\n    @classmethod\n    def _check_watchers(cls, obj: Reactable, name: str, old_value: Any):\n        \"\"\"Check watchers, and call watch methods / computes\n\n        Args:\n            obj (Reactable): The reactable object.\n            name (str): Attribute name.\n            old_value (Any): The old (previous) value of the attribute.\n            first_set (bool, optional): True if this is the first time setting the value. Defaults to False.\n        \"\"\"\n        _rich_traceback_omit = True\n        # Get the current value.\n        internal_name = f\"_reactive_{name}\"\n        value = getattr(obj, internal_name)\n\n        async def await_watcher(awaitable: Awaitable) -> None:\n            \"\"\"Coroutine to await an awaitable returned from a watcher\"\"\"\n            _rich_traceback_omit = True\n            await awaitable\n            # Watcher may have changed the state, so run compute again\n            obj.post_message_no_wait(\n                events.Callback(sender=obj, callback=partial(Reactive._compute, obj))\n            )\n\n        def invoke_watcher(\n            watch_function: Callable, old_value: object, value: object\n        ) -> bool:\n            \"\"\"Invoke a watch function.\n\n            Args:\n                watch_function (Callable): A watch function, which may be sync or async.\n                old_value (object): The old value of the attribute.\n                value (object): The new value of the attribute.\n\n            Returns:\n                bool: True if the watcher was run, or False if it was posted.\n            \"\"\"\n            _rich_traceback_omit = True\n            if count_parameters(watch_function) == 2:\n                watch_result = watch_function(old_value, value)\n            else:\n                watch_result = watch_function(value)\n            if isawaitable(watch_result):\n                # Result is awaitable, so we need to await it within an async context\n                obj.post_message_no_wait(\n                    events.Callback(\n                        sender=obj, callback=partial(await_watcher, watch_result)\n                    )\n                )\n                return False\n            else:\n                return True\n\n        # Compute is only required if a watcher runs immediately, not if they were posted.\n        require_compute = False\n        watch_function = getattr(obj, f\"watch_{name}\", None)\n        if callable(watch_function):\n            require_compute = require_compute or invoke_watcher(\n                watch_function, old_value, value\n            )\n\n        watchers: list[Callable] = getattr(obj, \"__watchers\", {}).get(name, [])\n        for watcher in watchers:\n            require_compute = require_compute or invoke_watcher(\n                watcher, old_value, value\n            )\n\n        if require_compute:\n            # Run computes\n            obj.post_message_no_wait(\n                events.Callback(sender=obj, callback=partial(Reactive._compute, obj))\n            )\n\n    @classmethod\n    async def _compute(cls, obj: Reactable) -> None:\n        \"\"\"Invoke all computes.\n\n        Args:\n            obj (Reactable): Reactable object.\n        \"\"\"\n        _rich_traceback_guard = True\n        computes = getattr(obj, \"__computes\", [])\n        for compute in computes:\n            try:\n                compute_method = getattr(obj, f\"compute_{compute}\")\n            except AttributeError:\n                continue\n\n            value = await invoke(compute_method)\n            setattr(obj, compute, value)\n\n\nclass reactive(Reactive[ReactiveType]):\n    \"\"\"Create a reactive attribute.\n\n    Args:\n        default (ReactiveType | Callable[[], ReactiveType]): A default value or callable that returns a default.\n        layout (bool, optional): Perform a layout on change. Defaults to False.\n        repaint (bool, optional): Perform a repaint on change. Defaults to True.\n        init (bool, optional): Call watchers on initialize (post mount). Defaults to True.\n        always_update (bool, optional): Call watchers even when the new value equals the old value. Defaults to False.\n    \"\"\"\n\n    def __init__(\n        self,\n        default: ReactiveType | Callable[[], ReactiveType],\n        *,\n        layout: bool = False,\n        repaint: bool = True,\n        init: bool = True,\n        always_update: bool = False,\n    ) -> None:\n        super().__init__(\n            default,\n            layout=layout,\n            repaint=repaint,\n            init=init,\n            always_update=always_update,\n        )\n\n\nclass var(Reactive[ReactiveType]):\n    \"\"\"Create a reactive attribute (with no auto-refresh).\n\n    Args:\n        default (ReactiveType | Callable[[], ReactiveType]): A default value or callable that returns a default.\n        init (bool, optional): Call watchers on initialize (post mount). Defaults to True.\n    \"\"\"\n\n    def __init__(\n        self, default: ReactiveType | Callable[[], ReactiveType], init: bool = True\n    ) -> None:\n        super().__init__(default, layout=False, repaint=False, init=init)\n\n\ndef watch(\n    obj: Reactable,\n    attribute_name: str,\n    callback: Callable[[Any], object],\n    init: bool = True,\n) -> None:\n    \"\"\"Watch a reactive variable on an object.\n\n    Args:\n        obj (Reactable): The parent object.\n        attribute_name (str): The attribute to watch.\n        callback (Callable[[Any], object]): A callable to call when the attribute changes.\n        init (bool, optional): True to call watcher initialization. Defaults to True.\n    \"\"\"\n\n    if not hasattr(obj, \"__watchers\"):\n        setattr(obj, \"__watchers\", {})\n    watchers: dict[str, list[Callable]] = getattr(obj, \"__watchers\")\n    watcher_list = watchers.setdefault(attribute_name, [])\n    if callback in watcher_list:\n        return\n    watcher_list.append(callback)\n    if init:\n        current_value = getattr(obj, attribute_name, None)\n        Reactive._check_watchers(obj, attribute_name, current_value)\n", "path": "src/textual/reactive.py"}], "after_files": [{"content": "from __future__ import annotations\n\nfrom functools import partial\nfrom inspect import isawaitable\nfrom typing import (\n    TYPE_CHECKING,\n    Any,\n    Awaitable,\n    Callable,\n    Generic,\n    Type,\n    TypeVar,\n    Union,\n)\n\nfrom . import events\nfrom ._callback import count_parameters, invoke\nfrom ._types import MessageTarget\n\nif TYPE_CHECKING:\n    from .app import App\n    from .widget import Widget\n\n    Reactable = Union[Widget, App]\n\nReactiveType = TypeVar(\"ReactiveType\")\n\n\nclass _NotSet:\n    pass\n\n\n_NOT_SET = _NotSet()\n\nT = TypeVar(\"T\")\n\n\nclass Reactive(Generic[ReactiveType]):\n    \"\"\"Reactive descriptor.\n\n    Args:\n        default (ReactiveType | Callable[[], ReactiveType]): A default value or callable that returns a default.\n        layout (bool, optional): Perform a layout on change. Defaults to False.\n        repaint (bool, optional): Perform a repaint on change. Defaults to True.\n        init (bool, optional): Call watchers on initialize (post mount). Defaults to False.\n        always_update (bool, optional): Call watchers even when the new value equals the old value. Defaults to False.\n    \"\"\"\n\n    def __init__(\n        self,\n        default: ReactiveType | Callable[[], ReactiveType],\n        *,\n        layout: bool = False,\n        repaint: bool = True,\n        init: bool = False,\n        always_update: bool = False,\n    ) -> None:\n        self._default = default\n        self._layout = layout\n        self._repaint = repaint\n        self._init = init\n        self._always_update = always_update\n\n    @classmethod\n    def init(\n        cls,\n        default: ReactiveType | Callable[[], ReactiveType],\n        *,\n        layout: bool = False,\n        repaint: bool = True,\n        always_update: bool = False,\n    ) -> Reactive:\n        \"\"\"A reactive variable that calls watchers and compute on initialize (post mount).\n\n        Args:\n            default (ReactiveType | Callable[[], ReactiveType]): A default value or callable that returns a default.\n            layout (bool, optional): Perform a layout on change. Defaults to False.\n            repaint (bool, optional): Perform a repaint on change. Defaults to True.\n            always_update (bool, optional): Call watchers even when the new value equals the old value. Defaults to False.\n\n        Returns:\n            Reactive: A Reactive instance which calls watchers or initialize.\n        \"\"\"\n        return cls(\n            default,\n            layout=layout,\n            repaint=repaint,\n            init=True,\n            always_update=always_update,\n        )\n\n    @classmethod\n    def var(\n        cls,\n        default: ReactiveType | Callable[[], ReactiveType],\n    ) -> Reactive:\n        \"\"\"A reactive variable that doesn't update or layout.\n\n        Args:\n            default (ReactiveType | Callable[[], ReactiveType]):  A default value or callable that returns a default.\n\n        Returns:\n            Reactive: A Reactive descriptor.\n        \"\"\"\n        return cls(default, layout=False, repaint=False, init=True)\n\n    @classmethod\n    def _initialize_object(cls, obj: object) -> None:\n        \"\"\"Set defaults and call any watchers / computes for the first time.\n\n        Args:\n            obj (Reactable): An object with Reactive descriptors\n        \"\"\"\n        if not hasattr(obj, \"__reactive_initialized\"):\n            startswith = str.startswith\n            for key in obj.__class__.__dict__:\n                if startswith(key, \"_default_\"):\n                    name = key[9:]\n                    # Check defaults\n                    if not hasattr(obj, name):\n                        # Attribute has no value yet\n                        default = getattr(obj, key)\n                        default_value = default() if callable(default) else default\n                        # Set the default vale (calls `__set__`)\n                        setattr(obj, name, default_value)\n        setattr(obj, \"__reactive_initialized\", True)\n\n    @classmethod\n    def _reset_object(cls, obj: object) -> None:\n        \"\"\"Reset reactive structures on object (to avoid reference cycles).\n\n        Args:\n            obj (object): A reactive object.\n        \"\"\"\n        getattr(obj, \"__watchers\", {}).clear()\n        getattr(obj, \"__computes\", []).clear()\n\n    def __set_name__(self, owner: Type[MessageTarget], name: str) -> None:\n\n        # Check for compute method\n        if hasattr(owner, f\"compute_{name}\"):\n            # Compute methods are stored in a list called `__computes`\n            try:\n                computes = getattr(owner, \"__computes\")\n            except AttributeError:\n                computes = []\n                setattr(owner, \"__computes\", computes)\n            computes.append(name)\n\n        # The name of the attribute\n        self.name = name\n        # The internal name where the attribute's value is stored\n        self.internal_name = f\"_reactive_{name}\"\n        default = self._default\n        setattr(owner, f\"_default_{name}\", default)\n\n    def __get__(self, obj: Reactable, obj_type: type[object]) -> ReactiveType:\n        _rich_traceback_omit = True\n        value: _NotSet | ReactiveType = getattr(obj, self.internal_name, _NOT_SET)\n        if isinstance(value, _NotSet):\n            # No value present, we need to set the default\n            init_name = f\"_default_{self.name}\"\n            default = getattr(obj, init_name)\n            default_value = default() if callable(default) else default\n            # Set and return the value\n            setattr(obj, self.internal_name, default_value)\n            if self._init:\n                self._check_watchers(obj, self.name, default_value)\n            return default_value\n        return value\n\n    def __set__(self, obj: Reactable, value: ReactiveType) -> None:\n        _rich_traceback_omit = True\n        name = self.name\n        current_value = getattr(obj, name)\n        # Check for validate function\n        validate_function = getattr(obj, f\"validate_{name}\", None)\n        # Check if this is the first time setting the value\n        first_set = getattr(obj, f\"__first_set_{self.internal_name}\", True)\n        # Call validate\n        if callable(validate_function):\n            value = validate_function(value)\n        # If the value has changed, or this is the first time setting the value\n        if current_value != value or first_set or self._always_update:\n            # Set the first set flag to False\n            setattr(obj, f\"__first_set_{self.internal_name}\", False)\n            # Store the internal value\n            setattr(obj, self.internal_name, value)\n            # Check all watchers\n            self._check_watchers(obj, name, current_value)\n            # Refresh according to descriptor flags\n            if self._layout or self._repaint:\n                obj.refresh(repaint=self._repaint, layout=self._layout)\n\n    @classmethod\n    def _check_watchers(cls, obj: Reactable, name: str, old_value: Any):\n        \"\"\"Check watchers, and call watch methods / computes\n\n        Args:\n            obj (Reactable): The reactable object.\n            name (str): Attribute name.\n            old_value (Any): The old (previous) value of the attribute.\n            first_set (bool, optional): True if this is the first time setting the value. Defaults to False.\n        \"\"\"\n        _rich_traceback_omit = True\n        # Get the current value.\n        internal_name = f\"_reactive_{name}\"\n        value = getattr(obj, internal_name)\n\n        async def await_watcher(awaitable: Awaitable) -> None:\n            \"\"\"Coroutine to await an awaitable returned from a watcher\"\"\"\n            _rich_traceback_omit = True\n            await awaitable\n            # Watcher may have changed the state, so run compute again\n            obj.post_message_no_wait(\n                events.Callback(sender=obj, callback=partial(Reactive._compute, obj))\n            )\n\n        def invoke_watcher(\n            watch_function: Callable, old_value: object, value: object\n        ) -> bool:\n            \"\"\"Invoke a watch function.\n\n            Args:\n                watch_function (Callable): A watch function, which may be sync or async.\n                old_value (object): The old value of the attribute.\n                value (object): The new value of the attribute.\n\n            Returns:\n                bool: True if the watcher was run, or False if it was posted.\n            \"\"\"\n            _rich_traceback_omit = True\n            if count_parameters(watch_function) == 2:\n                watch_result = watch_function(old_value, value)\n            else:\n                watch_result = watch_function(value)\n            if isawaitable(watch_result):\n                # Result is awaitable, so we need to await it within an async context\n                obj.post_message_no_wait(\n                    events.Callback(\n                        sender=obj, callback=partial(await_watcher, watch_result)\n                    )\n                )\n                return False\n            else:\n                return True\n\n        # Compute is only required if a watcher runs immediately, not if they were posted.\n        require_compute = False\n        watch_function = getattr(obj, f\"watch_{name}\", None)\n        if callable(watch_function):\n            require_compute = require_compute or invoke_watcher(\n                watch_function, old_value, value\n            )\n\n        watchers: list[Callable] = getattr(obj, \"__watchers\", {}).get(name, [])\n        for watcher in watchers:\n            require_compute = require_compute or invoke_watcher(\n                watcher, old_value, value\n            )\n\n        if require_compute:\n            # Run computes\n            obj.post_message_no_wait(\n                events.Callback(sender=obj, callback=partial(Reactive._compute, obj))\n            )\n\n    @classmethod\n    async def _compute(cls, obj: Reactable) -> None:\n        \"\"\"Invoke all computes.\n\n        Args:\n            obj (Reactable): Reactable object.\n        \"\"\"\n        _rich_traceback_guard = True\n        computes = getattr(obj, \"__computes\", [])\n        for compute in computes:\n            try:\n                compute_method = getattr(obj, f\"compute_{compute}\")\n            except AttributeError:\n                continue\n\n            value = await invoke(compute_method)\n            setattr(obj, compute, value)\n\n\nclass reactive(Reactive[ReactiveType]):\n    \"\"\"Create a reactive attribute.\n\n    Args:\n        default (ReactiveType | Callable[[], ReactiveType]): A default value or callable that returns a default.\n        layout (bool, optional): Perform a layout on change. Defaults to False.\n        repaint (bool, optional): Perform a repaint on change. Defaults to True.\n        init (bool, optional): Call watchers on initialize (post mount). Defaults to True.\n        always_update (bool, optional): Call watchers even when the new value equals the old value. Defaults to False.\n    \"\"\"\n\n    def __init__(\n        self,\n        default: ReactiveType | Callable[[], ReactiveType],\n        *,\n        layout: bool = False,\n        repaint: bool = True,\n        init: bool = True,\n        always_update: bool = False,\n    ) -> None:\n        super().__init__(\n            default,\n            layout=layout,\n            repaint=repaint,\n            init=init,\n            always_update=always_update,\n        )\n\n\nclass var(Reactive[ReactiveType]):\n    \"\"\"Create a reactive attribute (with no auto-refresh).\n\n    Args:\n        default (ReactiveType | Callable[[], ReactiveType]): A default value or callable that returns a default.\n        init (bool, optional): Call watchers on initialize (post mount). Defaults to True.\n    \"\"\"\n\n    def __init__(\n        self, default: ReactiveType | Callable[[], ReactiveType], init: bool = True\n    ) -> None:\n        super().__init__(default, layout=False, repaint=False, init=init)\n\n\ndef watch(\n    obj: Reactable,\n    attribute_name: str,\n    callback: Callable[[Any], object],\n    init: bool = True,\n) -> None:\n    \"\"\"Watch a reactive variable on an object.\n\n    Args:\n        obj (Reactable): The parent object.\n        attribute_name (str): The attribute to watch.\n        callback (Callable[[Any], object]): A callable to call when the attribute changes.\n        init (bool, optional): True to call watcher initialization. Defaults to True.\n    \"\"\"\n\n    if not hasattr(obj, \"__watchers\"):\n        setattr(obj, \"__watchers\", {})\n    watchers: dict[str, list[Callable]] = getattr(obj, \"__watchers\")\n    watcher_list = watchers.setdefault(attribute_name, [])\n    if callback in watcher_list:\n        return\n    watcher_list.append(callback)\n    if init:\n        current_value = getattr(obj, attribute_name, None)\n        Reactive._check_watchers(obj, attribute_name, current_value)\n", "path": "src/textual/reactive.py"}]}