From affffc1013a18960af31bd544addc8a72803e96b Mon Sep 17 00:00:00 2001 From: Yiorgis Gozadinos Date: Wed, 14 Jan 2026 18:24:41 +0200 Subject: [PATCH] Extract get_package_versions() for info & modals --- haiku_rag_slim/haiku/rag/app.py | 24 +++++----------- .../haiku/rag/inspector/widgets/info_modal.py | 28 ++++++++----------- haiku_rag_slim/haiku/rag/utils.py | 21 ++++++++++++++ tests/test_utils.py | 18 ++++++++++++ 4 files changed, 57 insertions(+), 34 deletions(-) diff --git a/haiku_rag_slim/haiku/rag/app.py b/haiku_rag_slim/haiku/rag/app.py index 63615a27..0725d035 100644 --- a/haiku_rag_slim/haiku/rag/app.py +++ b/haiku_rag_slim/haiku/rag/app.py @@ -2,7 +2,6 @@ import asyncio import json import logging from datetime import datetime -from importlib.metadata import version as pkg_version from pathlib import Path from typing import TYPE_CHECKING @@ -29,7 +28,7 @@ from haiku.rag.store.models.document import Document if TYPE_CHECKING: from haiku.rag.store.models import SearchResult -from haiku.rag.utils import format_bytes, format_citations_rich +from haiku.rag.utils import format_bytes, format_citations_rich, get_package_versions logger = logging.getLogger(__name__) @@ -86,16 +85,7 @@ class HaikuRAGApp: self.console.print(f"[red]Failed to open database: {e}[/red]") return - ldb_version = pkg_version("lancedb") - hr_version = pkg_version("haiku.rag-slim") - try: - docling_version = pkg_version("docling") - except Exception: - docling_version = "not installed" - pydantic_ai_version = pkg_version("pydantic-ai-slim") - from docling_core.types.doc.document import DoclingDocument - - docling_document_version = DoclingDocument.model_construct().version + versions = get_package_versions() # Get comprehensive table statistics (this also runs migrations) from haiku.rag.store.engine import Store @@ -209,19 +199,19 @@ class HaikuRAGApp: self.console.rule() self.console.print("[bold]Versions[/bold]") self.console.print( - f" [repr.attrib_name]haiku.rag[/repr.attrib_name]: {hr_version}" + f" [repr.attrib_name]haiku.rag[/repr.attrib_name]: {versions['haiku_rag']}" ) self.console.print( - f" [repr.attrib_name]lancedb[/repr.attrib_name]: {ldb_version}" + f" [repr.attrib_name]lancedb[/repr.attrib_name]: {versions['lancedb']}" ) self.console.print( - f" [repr.attrib_name]docling[/repr.attrib_name]: {docling_version}" + f" [repr.attrib_name]docling[/repr.attrib_name]: {versions['docling']}" ) self.console.print( - f" [repr.attrib_name]pydantic-ai[/repr.attrib_name]: {pydantic_ai_version}" + f" [repr.attrib_name]pydantic-ai[/repr.attrib_name]: {versions['pydantic_ai']}" ) self.console.print( - f" [repr.attrib_name]docling-document schema[/repr.attrib_name]: {docling_document_version}" + f" [repr.attrib_name]docling-document schema[/repr.attrib_name]: {versions['docling_document_schema']}" ) async def history(self, table: str | None = None, limit: int | None = None): diff --git a/haiku_rag_slim/haiku/rag/inspector/widgets/info_modal.py b/haiku_rag_slim/haiku/rag/inspector/widgets/info_modal.py index 91715f2f..4fc647a5 100644 --- a/haiku_rag_slim/haiku/rag/inspector/widgets/info_modal.py +++ b/haiku_rag_slim/haiku/rag/inspector/widgets/info_modal.py @@ -1,5 +1,4 @@ import json -from importlib.metadata import version as pkg_version from pathlib import Path from typing import TYPE_CHECKING @@ -9,7 +8,7 @@ from textual.containers import Vertical, VerticalScroll from textual.screen import ModalScreen from textual.widgets import Static -from haiku.rag.utils import format_bytes +from haiku.rag.utils import format_bytes, get_package_versions if TYPE_CHECKING: from haiku.rag.client import HaikuRAG @@ -84,18 +83,7 @@ class InfoModal(ModalScreen): # pragma: no cover return # Get versions - try: - ldb_version = pkg_version("lancedb") - except Exception: - ldb_version = "unknown" - try: - hr_version = pkg_version("haiku.rag-slim") - except Exception: - hr_version = "unknown" - try: - docling_version = pkg_version("docling") - except Exception: - docling_version = "unknown" + versions = get_package_versions() # Get stats from store table_stats = self.client.store.get_stats() @@ -199,9 +187,15 @@ class InfoModal(ModalScreen): # pragma: no cover lines.append("") lines.append("[bold]Versions[/bold]") - lines.append(f"[bold $accent]haiku.rag[/bold $accent]: {hr_version}") - lines.append(f"[bold $accent]lancedb[/bold $accent]: {ldb_version}") - lines.append(f"[bold $accent]docling[/bold $accent]: {docling_version}") + lines.append(f"[bold $accent]haiku.rag[/bold $accent]: {versions['haiku_rag']}") + lines.append(f"[bold $accent]lancedb[/bold $accent]: {versions['lancedb']}") + lines.append(f"[bold $accent]docling[/bold $accent]: {versions['docling']}") + lines.append( + f"[bold $accent]pydantic-ai[/bold $accent]: {versions['pydantic_ai']}" + ) + lines.append( + f"[bold $accent]docling-document schema[/bold $accent]: {versions['docling_document_schema']}" + ) self._content_widget.update("\n".join(lines)) diff --git a/haiku_rag_slim/haiku/rag/utils.py b/haiku_rag_slim/haiku/rag/utils.py index 3d24d50d..49424643 100644 --- a/haiku_rag_slim/haiku/rag/utils.py +++ b/haiku_rag_slim/haiku/rag/utils.py @@ -419,6 +419,27 @@ def build_prompt(base_prompt: str, config: "AppConfig") -> str: return base_prompt +def get_package_versions() -> dict[str, str]: + """Get versions of haiku.rag and its dependencies. + + Returns: + Dict with keys: haiku_rag, lancedb, docling, pydantic_ai, docling_document_schema + """ + from docling_core.types.doc.document import DoclingDocument + + versions = { + "haiku_rag": metadata.version("haiku.rag-slim"), + "lancedb": metadata.version("lancedb"), + "pydantic_ai": metadata.version("pydantic-ai-slim"), + "docling_document_schema": DoclingDocument.model_construct().version, + } + try: + versions["docling"] = metadata.version("docling") + except metadata.PackageNotFoundError: + versions["docling"] = "not installed" + return versions + + async def is_up_to_date() -> tuple[bool, Version, Version]: """Check whether haiku.rag is current. diff --git a/tests/test_utils.py b/tests/test_utils.py index 9afbe48c..8256cf3f 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -300,3 +300,21 @@ def test_get_model_with_all_settings(): ) result = get_model(model_config) assert isinstance(result, OpenAIChatModel) + + +def test_get_package_versions(): + """Test get_package_versions returns expected keys.""" + from haiku.rag.utils import get_package_versions + + versions = get_package_versions() + + assert "haiku_rag" in versions + assert "lancedb" in versions + assert "docling" in versions + assert "pydantic_ai" in versions + assert "docling_document_schema" in versions + + # All should be non-empty strings + for key, value in versions.items(): + assert isinstance(value, str) + assert len(value) > 0