Name the remedy for a missing configured database and list the databases an unknown name could have meant
A configured or default database that does not exist raises SourceUnavailableError with the way to create it and without its location. An unknown --db-name lists the databases there are, configured or default. The CHANGELOG records Store.db_path, SingleDatabaseSession(ref, config), the empty lancedb.uri migration and the error-type change.
This commit is contained in:
parent
3814b2bc78
commit
187946a7ae
8 changed files with 47 additions and 15 deletions
|
|
@ -5,7 +5,8 @@
|
|||
### Removed
|
||||
|
||||
- `lancedb.uri`. Write `lancedb.databases: {NAME: <location>}`; a config carrying
|
||||
`uri` fails to load with that message.
|
||||
`uri` fails to load with that message. Configurations generated by
|
||||
`init-config` through 0.81 carry `uri: ""` and must drop the key.
|
||||
- `HAIKU_RAG_DB`. Capabilities cover the databases the configuration places, or
|
||||
the `db_path` argument.
|
||||
- `DB_PATH` in the `app/` backend and `examples/custom_agent_agui.py`. Both load
|
||||
|
|
@ -33,6 +34,12 @@
|
|||
- `DatabaseRef(name, location, given)` replaces `DatabaseRef(name, uri, db_path)`;
|
||||
`DatabaseScope.at(path)` added; `locate_database` returns `Path | str`.
|
||||
`IngesterApp(config, scope)` takes a resolved scope in place of `db_path`.
|
||||
`SingleDatabaseSession(ref, config)` replaces `SingleDatabaseSession(db_path,
|
||||
config, source=)`. `Store.db_path` is `None` for a database behind a URI.
|
||||
- Opening a configured or default database that does not exist raises
|
||||
`SourceUnavailableError` naming the database and the remedy (`haiku-rag init`
|
||||
or `create=True`), where the default database raised `FileNotFoundError` with
|
||||
its path. A database given as a path still raises `FileNotFoundError`.
|
||||
- `Store(location, config)`, `connect_lancedb(location, config)`,
|
||||
`gather_database_info(location, config)` and `run_doctor(config, location, ...)`
|
||||
take the database location, a path or a URI. `ConnectionMode.of(location)`
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ async with HaikuRAG(create=True) as client:
|
|||
|
||||
The [default location](index.md#configuration-file-locations) is platform-specific (e.g., `~/Library/Application Support/haiku.rag/` on macOS).
|
||||
|
||||
Opening a nonexistent local database given as a path raises `FileNotFoundError`, naming the path. This prevents accidental database creation from typos or misconfigured paths. A database placed by `lancedb.databases` raises `SourceUnavailableError` instead, naming the database and not its location.
|
||||
Opening a nonexistent local database given as a path raises `FileNotFoundError`, naming the path. This prevents accidental database creation from typos or misconfigured paths. A configured or default database raises `SourceUnavailableError` instead, naming the database and not its location.
|
||||
|
||||
## Remote Storage
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ async with HaikuRAG("path/to/database.lancedb", read_only=True) as client:
|
|||
`async with` is the lifecycle. A caller that owns the client some other way releases it with `await client.aclose()`, which does the same work for every client shape. `client.close()` closes the connection to one database and nothing else, since draining the background vacuum and releasing the embedder and reranker are awaitable; it refuses a client covering several.
|
||||
|
||||
!!! note
|
||||
Databases must be explicitly created with `create=True` or via `haiku-rag init` before use. Opening a nonexistent local database given as a path raises `FileNotFoundError`, naming the path; one placed by `lancedb.databases` raises `SourceUnavailableError`, which names the database rather than its location. A path beside a configured `lancedb.databases` raises `AmbiguousDatabaseError`.
|
||||
Databases must be explicitly created with `create=True` or via `haiku-rag init` before use. Opening a nonexistent local database given as a path raises `FileNotFoundError`, naming the path; a configured or default database raises `SourceUnavailableError`, which names the database rather than its location. A path beside a configured `lancedb.databases` raises `AmbiguousDatabaseError`.
|
||||
|
||||
!!! note
|
||||
Read-only mode is useful for safely accessing databases without risk of modification. It blocks all write operations and downgrades an embedding provider/name mismatch to a warning instead of raising `ConfigMismatchError`.
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ class DatabaseScope:
|
|||
if database_name is not None:
|
||||
if database_name not in declared:
|
||||
raise UnknownDatabaseError(
|
||||
f"unknown database {database_name!r}; lancedb.databases names "
|
||||
f"unknown database {database_name!r}; the databases are "
|
||||
f"{', '.join(sorted(declared))}"
|
||||
)
|
||||
return cls(
|
||||
|
|
|
|||
|
|
@ -113,13 +113,15 @@ class SingleDatabaseSession:
|
|||
# A path the caller gave may be named: the caller knows it already.
|
||||
if self.ref.given:
|
||||
raise
|
||||
failure = type(error).__name__
|
||||
failure = (
|
||||
"does not exist; create it with `haiku-rag init` or `create=True`"
|
||||
if isinstance(error, FileNotFoundError)
|
||||
else f"could not be opened: {type(error).__name__}"
|
||||
)
|
||||
if failure is not None:
|
||||
# Raised outside the handler: the exception carries neither a cause
|
||||
# nor a location-bearing context.
|
||||
raise SourceUnavailableError(
|
||||
f"database {self.source!r} could not be opened: {failure}"
|
||||
)
|
||||
raise SourceUnavailableError(f"database {self.source!r} {failure}")
|
||||
self.document_repository = DocumentRepository(self.store)
|
||||
self.chunk_repository = ChunkRepository(self.store)
|
||||
self.document_item_repository = DocumentItemRepository(self.store)
|
||||
|
|
|
|||
|
|
@ -557,12 +557,6 @@ class TestPlacingTheIngesterDatabase:
|
|||
with pytest.raises(typer.BadParameter, match="no name"):
|
||||
_scope_for(Path("/"))
|
||||
|
||||
def test_a_python_caller_cannot_pass_a_path(self):
|
||||
from haiku.rag.ingester.app import IngesterApp
|
||||
|
||||
with pytest.raises(TypeError):
|
||||
IngesterApp(config=AppConfig(), db_path="/db/other.lancedb") # type: ignore[call-arg] # ty: ignore[unknown-argument]
|
||||
|
||||
def test_one_configured_database_is_accepted(self, tmp_path):
|
||||
"""A one-entry mapping names which database to write."""
|
||||
config = AppConfig(
|
||||
|
|
|
|||
|
|
@ -474,6 +474,25 @@ class TestFailureNaming:
|
|||
assert str(tmp_path) not in str(caught.value)
|
||||
assert caught.value.__cause__ is None
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_a_missing_default_database_names_the_remedy(self, tmp_path):
|
||||
"""The location stays out of the message; the way to create the
|
||||
database does not."""
|
||||
from haiku.rag.config.models import AppConfig, StorageConfig
|
||||
|
||||
config = AppConfig(storage=StorageConfig(data_dir=tmp_path / "empty"))
|
||||
|
||||
with pytest.raises(SourceUnavailableError) as caught:
|
||||
async with HaikuRAG(config=config):
|
||||
pass
|
||||
|
||||
message = str(caught.value)
|
||||
assert "database 'haiku.rag' does not exist" in message
|
||||
assert "haiku-rag init" in message
|
||||
assert "create=True" in message
|
||||
assert str(tmp_path) not in message
|
||||
assert caught.value.__cause__ is None
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_a_database_given_as_a_path_keeps_its_error(self, tmp_path):
|
||||
"""The caller gave the path, so the error may name it."""
|
||||
|
|
|
|||
|
|
@ -54,11 +54,21 @@ class TestResolution:
|
|||
assert scope.names == ("beta",)
|
||||
|
||||
def test_an_unknown_name_is_refused(self):
|
||||
"""The message lists the databases there are, configured or default."""
|
||||
config = _config(databases={"alpha": "/data/alpha.lancedb"})
|
||||
|
||||
with pytest.raises(UnknownDatabaseError, match="unknown database 'nope'"):
|
||||
with pytest.raises(
|
||||
UnknownDatabaseError,
|
||||
match="unknown database 'nope'.*the databases are alpha",
|
||||
):
|
||||
DatabaseScope.resolve(config, database_name="nope")
|
||||
|
||||
with pytest.raises(
|
||||
UnknownDatabaseError,
|
||||
match="unknown database 'nope'.*the databases are haiku.rag",
|
||||
):
|
||||
DatabaseScope.resolve(_config(), database_name="nope")
|
||||
|
||||
def test_no_selector_covers_the_configured_set_in_order(self):
|
||||
config = _config(
|
||||
databases={"beta": "/data/b.lancedb", "alpha": "/data/a.lancedb"}
|
||||
|
|
|
|||
Loading…
Reference in a new issue