Repository: Textualize/textual

Issue:
DirectoryTree.path no longer reactive
The `DirectoryTree.path` variable changing values no longer reloads the widget when it's changed. This behavior changed on the [0.49.0 release](https://github.com/Textualize/textual/releases/tag/v0.49.0). 

I expected the `path` attribute to be reactive, according to the `watch_path` docs:
> If the path is changed the directory tree will be repopulated using the new value as the root.

In the below examples I set a binding on the directory tree, `.` - this action should trigger the directory tree going refreshing to the current root's parent directory:

<details><summary>Example App</summary>
<p>

```py
import pathlib
from typing import Any, ClassVar, List

from rich.syntax import Syntax
from textual import on
from textual.app import App, ComposeResult
from textual.binding import BindingType
from textual.containers import Horizontal, VerticalScroll
from textual.widgets import DirectoryTree, Footer, Header, Static


class DirectoryTreeApp(App):
    """
    Directory Tree + Code Viewer App
    """

    BINDINGS: ClassVar[List[BindingType]] = [
        ("q", "quit", "Quit"),
        (".", "parent_dir", "Parent Directory"),
    ]

    def __init__(self, path: str, *args: Any, **kwargs: Any):
        super().__init__(*args, **kwargs)
        self.path = pathlib.Path(path).resolve()
        self.file_content = Static()
        self.directory_tree = DirectoryTree(path=self.path)

    def compose(self) -> ComposeResult:
        yield Header()
        yield Horizontal(self.directory_tree, VerticalScroll(self.file_content))
        yield Footer()

    @on(DirectoryTree.FileSelected)
    def handle_file_selected(self, message: DirectoryTree.FileSelected) -> None:
        file_content = message.path.read_text(errors="ignore")
        lexer = Syntax.guess_lexer(path=str(message.path))
        code = Syntax(code=file_content, lexer=lexer)
        self.file_content.update(code)

    def action_parent_dir(self) -> None:
        """
        Go to the parent directory
        """
        if self.directory_tree.path != self.directory_tree.path.parent:
            self.directory_tree.path = self.directory_tree.path.parent
            self.notify(message=f"Directory Changed: {self.directory_tree.path}")


app = DirectoryTreeApp(".")

if __name__ == "__main__":
    app.run()
```

</p>
</details> 

<details><summary>textual==0.48.2 screen recording</summary>
<p>

https://github.com/Textualize/textual/assets/49741340/1c38b3d6-6ada-4a63-8b66-0d0ac95b9112

</p>
</details> 

</p>
</details> 

<details><summary>textual==0.49.0 screen recording</summary>
<p>

https://github.com/Textualize/textual/assets/49741340/aed6f0a5-e9f2-4dda-bbe6-5f687aca4edb

</p>
</details> 


Discussion:
Confirmed with this:

```python
from textual import on
from textual.app import App, ComposeResult
from textual.widgets import DirectoryTree, Input

class DirTreePathIssueApp(App[None]):

    def compose(self) -> ComposeResult:
        yield Input()
        yield DirectoryTree(".")

    @on(Input.Submitted)
    def new_path(self, event: Input.Submitted) -> None:
        self.notify(f"Swapping to {event.value}")
        self.query_one(DirectoryTree).path = event.value

if __name__ == "__main__":
    DirTreePathIssueApp().run()
```

Most likely an unintended consequence of #4123.

Resolving patch:
diff --git a/src/textual/widgets/_directory_tree.py b/src/textual/widgets/_directory_tree.py
--- a/src/textual/widgets/_directory_tree.py
+++ b/src/textual/widgets/_directory_tree.py
@@ -332,6 +332,7 @@ async def watch_path(self) -> None:
         If the path is changed the directory tree will be repopulated using
         the new value as the root.
         """
+        self.reset_node(self.root, str(self.path), DirEntry(self.PATH(self.path)))
         await self.reload()
 
     def process_label(self, label: TextType) -> Text:


Test patch:
diff --git a/tests/directory_tree/test_change_path.py b/tests/directory_tree/test_change_path.py
new file mode 100644
--- /dev/null
+++ b/tests/directory_tree/test_change_path.py
@@ -0,0 +1,20 @@
+from pathlib import Path
+
+from textual.app import App, ComposeResult
+from textual.widgets import DirectoryTree
+
+
+class DirectoryTreeApp(App[None]):
+
+    def compose(self) -> ComposeResult:
+        yield DirectoryTree(".")
+
+
+async def test_change_directory_tree_path(tmpdir: Path) -> None:
+    """The DirectoryTree should react to the path changing."""
+
+    async with DirectoryTreeApp().run_test() as pilot:
+        assert pilot.app.query_one(DirectoryTree).root.data.path == Path(".")
+        pilot.app.query_one(DirectoryTree).path = tmpdir
+        await pilot.pause()
+        assert pilot.app.query_one(DirectoryTree).root.data.path == tmpdir