From 81e05cba7aa9983d4c5df78b33bd7a115ba97fa7 Mon Sep 17 00:00:00 2001 From: Yiorgis Gozadinos Date: Fri, 28 Aug 2026 14:02:56 +0300 Subject: [PATCH] Name what a command calls its database, and whether it exists `tag_restore` reached into `HaikuRAGApp._display_path` and `_path`, and seven places spelled out `self._is_local and not self._path.exists()`. `display_path` and `database_missing` say both, and `database_missing` is False for a database behind a URI, which has no path to check. `init` keeps its own check: it asks the opposite question. --- haiku_rag_slim/haiku/rag/app.py | 38 ++++++++++++++++++++------------- haiku_rag_slim/haiku/rag/cli.py | 6 +++--- tests/test_app.py | 2 +- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/haiku_rag_slim/haiku/rag/app.py b/haiku_rag_slim/haiku/rag/app.py index 472c3bd2..7d037c21 100644 --- a/haiku_rag_slim/haiku/rag/app.py +++ b/haiku_rag_slim/haiku/rag/app.py @@ -101,10 +101,18 @@ class HaikuRAGApp: return self._connection[1] @property - def _display_path(self) -> "Path | str": + def display_path(self) -> "Path | str": """What a one-database command calls the database it opened.""" return self._one.db_path or self._one.uri + @property + def database_missing(self) -> bool: + """Whether the one local database this command resolved to does not exist. + + Always False for a database behind a URI, which has no path to check. + """ + return self._is_local and not self._path.exists() + async def init(self): """Initialize a new database.""" if self._is_local and self._path.exists(): @@ -116,7 +124,7 @@ class HaikuRAGApp: async with HaikuRAG._covering(self.scope, self.config, create=True): pass self.console.print( - f"[bold green]Database initialized at {self._display_path}[/bold green]" + f"[bold green]Database initialized at {self.display_path}[/bold green]" ) async def info(self): @@ -127,10 +135,10 @@ class HaikuRAGApp: # Basic: show path/URI self.console.print("[bold]haiku.rag database info[/bold]") self.console.print( - f" [repr.attrib_name]path[/repr.attrib_name]: {self._display_path}" + f" [repr.attrib_name]path[/repr.attrib_name]: {self.display_path}" ) - if self._is_local and not self._path.exists(): + if self.database_missing: self.console.print("[red]Database path does not exist.[/red]") return @@ -258,10 +266,10 @@ class HaikuRAGApp: self.console.print("[bold]haiku.rag doctor[/bold]") self.console.print( - f" [repr.attrib_name]path[/repr.attrib_name]: {self._display_path}" + f" [repr.attrib_name]path[/repr.attrib_name]: {self.display_path}" ) - if self._is_local and not self._path.exists(): + if self.database_missing: self.console.print("[red]Database path does not exist.[/red]") return True @@ -329,7 +337,7 @@ class HaikuRAGApp: """ from haiku.rag.store.engine import Store - if self._is_local and not self._path.exists(): + if self.database_missing: self.console.print("[red]Database path does not exist.[/red]") return @@ -425,7 +433,7 @@ class HaikuRAGApp: async def create_tag(self, name: str): """Tag the current version of every table.""" - if self._is_local and not self._path.exists(): + if self.database_missing: raise ValueError(f"Database path does not exist: {self._path}") async with self._tag_write_store() as store: await store.create_tag(name) @@ -433,7 +441,7 @@ class HaikuRAGApp: async def list_tags(self): """List database tags, flagging partial ones.""" - if self._is_local and not self._path.exists(): + if self.database_missing: raise ValueError(f"Database path does not exist: {self._path}") async with self._tag_read_store() as store: tags = await store.list_tags() @@ -454,7 +462,7 @@ class HaikuRAGApp: async def delete_tag(self, name: str): """Delete a tag from every table that has it.""" - if self._is_local and not self._path.exists(): + if self.database_missing: raise ValueError(f"Database path does not exist: {self._path}") async with self._tag_write_store() as store: await store.delete_tag(name) @@ -469,7 +477,7 @@ class HaikuRAGApp: Raises: ValueError: If the database path does not exist. """ - if self._is_local and not self._path.exists(): + if self.database_missing: raise ValueError(f"Database path does not exist: {self._path}") async with self._tag_write_store() as store: safety_tag = await store.restore_tag(name) @@ -886,7 +894,7 @@ class HaikuRAGApp: f"[repr.attrib_name]created at[/repr.attrib_name]: {doc.created_at} [repr.attrib_name]updated at[/repr.attrib_name]: {doc.updated_at}" ) # `list` does not load content, which is where the docling blobs live, so - # the header would otherwise announce a field the command declined to fetch. + # the header prints only for a fetched field. if doc.content: self.console.print("[repr.attrib_name]content[/repr.attrib_name]:") self.console.print(content) @@ -932,9 +940,9 @@ class HaikuRAGApp: The server opens its own client and validates it on startup, so nothing is opened here first. """ - # The resolved scope, not a derived path and configuration: a path - # would override a configured URI, and deriving drops the name results - # and citations carry. + # The resolved scope: a path overrides a configured URI, and a derived + # single-database configuration drops the name results and citations + # carry. server = _mcp_server_covering(self.scope, self.config, self.read_only) try: if transport == "stdio": diff --git a/haiku_rag_slim/haiku/rag/cli.py b/haiku_rag_slim/haiku/rag/cli.py index 36c8124b..a066c00c 100644 --- a/haiku_rag_slim/haiku/rag/cli.py +++ b/haiku_rag_slim/haiku/rag/cli.py @@ -756,11 +756,11 @@ def tag_restore( ), ): app = create_app(db) - if app._is_local and not app._path.exists(): - typer.echo(f"Error: Database path does not exist: {app._path}", err=True) + if app.database_missing: + typer.echo(f"Error: Database path does not exist: {app.display_path}", err=True) raise typer.Exit(1) if not yes: - typer.echo(f"Database: {app._display_path}") + typer.echo(f"Database: {app.display_path}") typer.echo(f"Tag: {name}") typer.echo("This changes the live database state across all tables.") typer.echo("Stop all ingestion and other writers before continuing.") diff --git a/tests/test_app.py b/tests/test_app.py index 27c278f8..d0c910fc 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -449,7 +449,7 @@ def test_remote_uri_is_the_display_path(tmp_path): config = AppConfig(lancedb=LanceDBConfig(uri="s3://bucket/path")) app = HaikuRAGApp(scope=for_path(None, config), config=config) - assert app._display_path == "s3://bucket/path" + assert app.display_path == "s3://bucket/path" assert app._is_local is False