Source code for dscat.paths

"""Locating the monorepo root and the generated catalogue paths.

The catalogue (SQLite index + converted docs) lives at ``<root>/.catalogue`` and is
regenerable; raw datasets live (gitignored) at ``<root>/data/<dataset>/<ship-folder>``.
"""

from __future__ import annotations

import os
from pathlib import Path


[docs] def find_repo_root(start: Path | None = None) -> Path: """Walk up from ``start`` (or CWD) to the workspace root. Honours ``DSCAT_ROOT`` if set. Otherwise the root is the nearest ancestor that holds a ``data/`` directory or a ``pyproject.toml`` declaring a uv workspace. """ env = os.environ.get("DSCAT_ROOT") if env: return Path(env).expanduser().resolve() start = (start or Path.cwd()).resolve() for d in (start, *start.parents): if (d / "data").is_dir(): return d pp = d / "pyproject.toml" if pp.is_file(): try: if "[tool.uv.workspace]" in pp.read_text(encoding="utf-8"): return d except OSError: pass return start
[docs] def data_root(root: Path) -> Path: """Return the raw-datasets directory, ``<root>/data``.""" return root / "data"
[docs] def catalogue_dir(root: Path) -> Path: """Return the generated-catalogue directory, ``<root>/.catalogue``.""" return root / ".catalogue"
[docs] def index_path(root: Path) -> Path: """Return the path to the SQLite index, ``<root>/.catalogue/index.db``.""" return catalogue_dir(root) / "index.db"
[docs] def docs_cache_dir(root: Path) -> Path: """Return the converted-documents cache directory, ``<root>/.catalogue/docs``.""" return catalogue_dir(root) / "docs"