mirror of
https://github.com/lancedb/lancedb.git
synced 2026-11-13 14:16:54 +00:00
fix(python): include namespaces in remote table repr (#4799)
A synchronous remote table opened in a namespace is displayed as if it
were in the database root. For example, `db.open_table("test",
namespace_path=["analytics", "features"])` shows
`RemoteTable(dev.test)`.
Include the cached namespace path using the existing `$`-delimited table
identifier: `RemoteTable(dev.analytics$features$test)`. Root output and
the leaf `table.name` stay the same. Using cached identity also keeps
repr available after pickle without reopening the native handle or
making a request.
Addresses the repr portion of ENT-3559. The native formatter already
carries the qualified identifier used by Python async and TypeScript;
this is a Python sync wrapper fix with no new API or naming rules.
Validation:
- Before the fix, three namespaced sync cases failed while root and
async controls passed. All six cases now pass through the real SDK and
mock HTTP endpoint.
- Covers default/explicit root, nested paths, valid
dotted/mixed-case/dashed names, and repr after pickle with the server
stopped. Requests remain limited to the original table open.
- Rebuilt current editable bindings in the repository's uv environment
with Python 3.12 and pinned Rust 1.97.0 through mbx.
- Ruff check and format check pass for the Python package (178 files).
- Required repository-wide Ruff check reports 48 pre-existing
diagnostics in six `docs/web-tests` files; the repository-wide format
check reports nine unchanged documentation files. Their source matches
the base commit. No lint suppression or documentation cleanup is
included.
This commit is contained in:
@@ -209,7 +209,8 @@ class RemoteTable(Table):
|
||||
LOOP.run(self._table.replace_field_metadata(field_name, new_metadata))
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"RemoteTable({self.db_name}.{self.name})"
|
||||
identifier = "$".join([*self._namespace_path, self.name])
|
||||
return f"RemoteTable({self.db_name}.{identifier})"
|
||||
|
||||
@property
|
||||
def schema(self) -> pa.Schema:
|
||||
|
||||
@@ -147,6 +147,65 @@ def missing_table_handler(cached, namespace_path):
|
||||
return handler, request_ids
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"namespace_path,name,identifier",
|
||||
[
|
||||
pytest.param(None, "test", "test", id="default-root"),
|
||||
pytest.param([], "test", "test", id="explicit-root"),
|
||||
pytest.param(["analytics"], "test", "analytics$test", id="namespace"),
|
||||
pytest.param(
|
||||
["analytics", "features"],
|
||||
"test",
|
||||
"analytics$features$test",
|
||||
id="nested",
|
||||
),
|
||||
pytest.param(
|
||||
["Team.Images", "raw-items"],
|
||||
"frame.info",
|
||||
"Team.Images$raw-items$frame.info",
|
||||
id="sql-quoted-names",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_remote_table_repr_namespace(namespace_path, name, identifier):
|
||||
requests = []
|
||||
path = f"/v1/table/{identifier}/describe/"
|
||||
|
||||
def handler(request):
|
||||
requests.append(request.path)
|
||||
assert request.path == path
|
||||
send_json(request, {})
|
||||
|
||||
expected = f"RemoteTable(dev.{identifier})"
|
||||
with mock_lancedb_connection(handler) as db:
|
||||
table = db.open_table(name, namespace_path=namespace_path)
|
||||
assert table.name == name
|
||||
assert repr(table) == expected
|
||||
restored = pickle.loads(pickle.dumps(table))
|
||||
|
||||
# A diagnostic repr must work from cached identity without reopening the handle.
|
||||
assert repr(restored) == expected
|
||||
assert requests == [path]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_async_remote_table_repr_namespace():
|
||||
requests = []
|
||||
path = "/v1/table/analytics$features$frame.info/describe/"
|
||||
|
||||
def handler(request):
|
||||
requests.append(request.path)
|
||||
assert request.path == path
|
||||
send_json(request, {})
|
||||
|
||||
async with mock_lancedb_connection_async(handler) as db:
|
||||
table = await db.open_table(
|
||||
"frame.info", namespace_path=["analytics", "features"]
|
||||
)
|
||||
assert repr(table) == "RemoteTable(analytics$features$frame.info)"
|
||||
assert requests == [path]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("cached", [False, True])
|
||||
@pytest.mark.parametrize("namespace_path", [[], ["ns"]])
|
||||
def test_remote_open_missing_table(cached, namespace_path, missing_table_handler):
|
||||
|
||||
Reference in New Issue
Block a user