Let a config-only command work on no database

`settings` and `download-models` read the configuration and open nothing, but
resolved a scope to be constructed, so `--db-name nope` failed them over a
selection they never use. `HaikuRAGApp` takes no scope for those, and asking it
for one is an error rather than a silent default.
This commit is contained in:
Yiorgis Gozadinos 2026-08-27 17:44:23 +03:00
parent 4d7fdd2d26
commit cad472e999
No known key found for this signature in database
3 changed files with 58 additions and 9 deletions

View file

@ -35,16 +35,25 @@ logger = logging.getLogger(__name__)
class HaikuRAGApp:
def __init__(
self,
scope: "DatabaseScope",
scope: "DatabaseScope | None" = None,
config: AppConfig | None = None,
read_only: bool = False,
):
"""The databases this command works on, resolved by whoever built it."""
self.scope = scope
"""The databases this command works on, resolved by whoever built it.
`scope` is None for configuration-only commands.
"""
self._scope = scope
self.config = config if config is not None else get_config()
self.read_only = read_only
self.console = Console()
@property
def scope(self) -> "DatabaseScope":
"""The databases this command works on."""
assert self._scope is not None, "this command works on no database"
return self._scope
@property
def _one(self) -> "DatabaseRef":
"""The one database this command works on.

View file

@ -461,9 +461,7 @@ def settings():
config = get_config()
# Neither of these opens a database; the scope is whatever is configured.
app = HaikuRAGApp(
scope=resolve_scope(covers_set=True), config=config, read_only=True
)
app = HaikuRAGApp(config=config, read_only=True)
app.show_settings()
@ -781,9 +779,7 @@ def tag_restore(
def download_models_cmd():
from haiku.rag.app import HaikuRAGApp
app = HaikuRAGApp(
scope=resolve_scope(covers_set=True), config=get_config(), read_only=True
)
app = HaikuRAGApp(config=get_config(), read_only=True)
try:
asyncio.run(app.download_models())
except Exception as e:

View file

@ -326,6 +326,50 @@ class TestSelectingADatabaseByName:
assert cli_module._db_name is None
class TestCommandsThatWorkOnNoDatabase:
"""`settings` and `download-models` read the configuration. A name that
selects a database is nothing to them, including a wrong one."""
def test_settings_ignores_an_unknown_name(self, tmp_path, monkeypatch):
import haiku.rag.config as config_module
monkeypatch.setattr(config_module, "_config", None)
config_file = tmp_path / "haiku.rag.yaml"
config_file.write_text("lancedb:\n databases:\n alpha: /data/a.lancedb\n")
result = runner.invoke(
cli, ["--config", str(config_file), "--db-name", "nope", "settings"]
)
assert result.exit_code == 0, result.output
assert "haiku.rag configuration" in result.output
def test_download_models_ignores_an_unknown_name(self, tmp_path, monkeypatch):
import haiku.rag.config as config_module
monkeypatch.setattr(config_module, "_config", None)
config_file = tmp_path / "haiku.rag.yaml"
config_file.write_text("lancedb:\n databases:\n alpha: /data/a.lancedb\n")
downloaded: list[object] = []
async def nothing_to_download(config):
downloaded.append(config)
return
yield # pragma: no cover - an empty async generator needs one
monkeypatch.setattr(
"haiku.rag.client.downloads.download_models", nothing_to_download
)
result = runner.invoke(
cli,
["--config", str(config_file), "--db-name", "nope", "download-models"],
)
assert result.exit_code == 0, result.output
assert len(downloaded) == 1
class TestResolvingTheDatabasePath:
def test_a_path_wins_when_nothing_is_selected(self, monkeypatch):
monkeypatch.setattr("haiku.rag.cli._db_name", None)