diff --git a/CLAUDE.md b/CLAUDE.md index 089018f..1f93e6f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -30,8 +30,8 @@ tests, and this `CLAUDE.md` live in this repo's tree. ### Core Components 1. **Protocol layer** (`src/mountainash_data/core/protocol.py`) - - `Backend` protocol — what every backend must implement (`connect()`) - - `Connection` protocol — what every connection must implement (`list_tables()`, `inspect_table()`, `to_relation()`, `close()`) + - `Backend` protocol — the single handle every backend must implement: `connect()`/`close()`/context-manager lifecycle, `list_tables()`/`list_namespaces()`/`list_catalogs()`, and `inspect_table()`/`inspect_namespace()`/`inspect_catalog()` + - There is deliberately no `to_relation()` on the protocol — bridging to the unified `mountainash` package is pull-side: `table()` returns a backend-native ibis Table and `ma.relation(ibis_table)` compiles against it directly 2. **Inspection model** (`src/mountainash_data/core/inspection.py`) - `CatalogInfo`, `NamespaceInfo`, `TableInfo`, `ColumnInfo` — shared physical metadata dataclasses @@ -244,7 +244,10 @@ conn = backend.connect() try: tables = conn.list_tables() info = conn.inspect_table("users") - relation = conn.to_relation("users") # → mountainash-expressions Relation + ibis_table = conn.table("users") # backend-native ibis Table + # Bridge to the unified mountainash package (pull-side): + # import mountainash as ma + # rel = ma.relation(ibis_table) # compiles against Ibis automatically finally: conn.close() diff --git a/README.md b/README.md index 7f315c4..fb608bb 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,10 @@ conn = backend.connect() try: tables = conn.list_tables() info = conn.inspect_table("my_table") - relation = conn.to_relation("my_table") # → mountainash-expressions Relation + ibis_table = conn.table("my_table") # backend-native ibis Table + # Bridge to the unified mountainash package (pull-side): + # import mountainash as ma + # rel = ma.relation(ibis_table) # compiles against Ibis automatically finally: conn.close() @@ -129,7 +132,7 @@ from mountainash_data import ( - **12-dialect ibis registry** — SQLite, DuckDB, MotherDuck, PostgreSQL, MySQL, MSSQL, Oracle, Snowflake, BigQuery, Redshift, Trino, PySpark - **Protocol-first design** — `Backend` and `Connection` protocols enable type-safe composition -- **Expressions seam** — `Connection.to_relation()` bridges to `mountainash-expressions` +- **mountainash seam (pull-side)** — `table()` returns a backend-native ibis Table; `ma.relation(table)` in the unified `mountainash` package compiles against it directly. There is deliberately no push-side `to_relation()` bridge in this package. - **Settings-driven** — pydantic settings for every dialect, factory auto-detection from URLs - **Comprehensive test suite** ensuring reliability diff --git a/src/mountainash_data/backends/iceberg/connection.py b/src/mountainash_data/backends/iceberg/connection.py index e1720f0..ff7ec24 100644 --- a/src/mountainash_data/backends/iceberg/connection.py +++ b/src/mountainash_data/backends/iceberg/connection.py @@ -13,9 +13,11 @@ - Schema caching - Thin delegation wrappers to ``operations.py`` for all mutations -``to_relation()`` is intentionally NOT implemented — it requires -mountainash-expressions to gain an Iceberg adapter, which is a separate -work item tracked in the spec. +There is deliberately no ``to_relation()`` here (or anywhere in this +package): bridging to the unified ``mountainash`` package is pull-side — +``ma.relation(...)`` over a backend-native handle. For Iceberg that handle +is not an ibis Table; reaching mountainash goes via an Arrow scan of the +loaded ``table()``, or via an Ibis engine reading the catalog. """ from __future__ import annotations diff --git a/tests/test_unit/backends/ibis/COVERAGE_GAP.md b/tests/test_unit/backends/ibis/COVERAGE_GAP.md deleted file mode 100644 index 074007b..0000000 --- a/tests/test_unit/backends/ibis/COVERAGE_GAP.md +++ /dev/null @@ -1,27 +0,0 @@ -# Coverage Gap: to_relation() not implemented - -**Task 4.9 — to_relation() seam to mountainash-expressions** - -The `mountainash-expressions` package does not expose a `Relation.from_ibis(table)` -API or equivalent. The `Relation` class in -`mountainash-expressions/src/mountainash/relations/core/relation_api/relation.py` -has no constructor that takes an ibis Table object. - -There is a `_from_ibis` helper in `typespec/extraction.py` but it returns a -`TypeSpec`, not a `Relation`. - -**Status:** BLOCKED — to_relation() cannot be implemented without a -`mountainash-expressions` API that creates a Relation from an ibis Table. - -**Resolution:** When mountainash-expressions adds `Relation.from_ibis()` or an -equivalent, implement `IbisConnection.to_relation(table_name)` in -`src/mountainash_data/backends/ibis/backend.py`: - -```python -def to_relation(self, table_name: str, namespace: str | None = None): - from mountainash.relations import Relation # adjust to actual import - ibis_table = self._ibis_conn.table(table_name) - return Relation.from_ibis(ibis_table) # adjust to actual API -``` - -**Confirmed:** 2026-04-07 during Phase 4 (Task 4.9) refactor.