fix: remote python sdk namespace typing (#2620)

This changes the default values for some namespace parameters in the
remote python SDK from None to [], to match the underlying code it
calls.

Prior to this commit, failing to supply "namespace" with the remote SDK
would cause an error because the underlying code it dispatches to does
not consider None to be valid input.
This commit is contained in:
Wyatt Alt
2025-09-02 16:32:32 -07:00
committed by GitHub
parent cc38453391
commit a9ea785b15
5 changed files with 39 additions and 14 deletions

View File

@@ -95,9 +95,10 @@ class DBConnection(EnforceOverrides):
@abstractmethod
def table_names(
self,
namespace: List[str] = [],
page_token: Optional[str] = None,
limit: int = 10,
*,
namespace: List[str] = [],
) -> Iterable[str]:
"""List all tables in this database, in sorted order
@@ -543,9 +544,10 @@ class LanceDBConnection(DBConnection):
@override
def table_names(
self,
namespace: List[str] = [],
page_token: Optional[str] = None,
limit: int = 10,
*,
namespace: List[str] = [],
) -> Iterable[str]:
"""Get the names of all tables in the database. The names are sorted.

View File

@@ -138,9 +138,10 @@ class LanceNamespaceDBConnection(DBConnection):
@override
def table_names(
self,
namespace: List[str] = [],
page_token: Optional[str] = None,
limit: int = 10,
*,
namespace: List[str] = [],
) -> Iterable[str]:
request = ListTablesRequest(id=namespace, page_token=page_token, limit=limit)
response = self._ns.list_tables(request)
@@ -190,7 +191,7 @@ class LanceNamespaceDBConnection(DBConnection):
json_schema = _convert_pyarrow_schema_to_json(schema)
# Create table request with namespace
table_id = (namespace or []) + [name]
table_id = namespace + [name]
request = CreateTableRequest(id=table_id, var_schema=json_schema)
# Create empty Arrow IPC stream bytes
@@ -219,7 +220,7 @@ class LanceNamespaceDBConnection(DBConnection):
storage_options: Optional[Dict[str, str]] = None,
index_cache_size: Optional[int] = None,
) -> Table:
table_id = (namespace or []) + [name]
table_id = namespace + [name]
request = DescribeTableRequest(id=table_id)
response = self._ns.describe_table(request)
@@ -236,9 +237,9 @@ class LanceNamespaceDBConnection(DBConnection):
)
@override
def drop_table(self, name: str, namespace: Optional[List[str]] = None):
def drop_table(self, name: str, namespace: List[str] = []):
# Use namespace drop_table directly
table_id = (namespace or []) + [name]
table_id = namespace + [name]
request = DropTableRequest(id=table_id)
self._ns.drop_table(request)
@@ -247,8 +248,8 @@ class LanceNamespaceDBConnection(DBConnection):
self,
cur_name: str,
new_name: str,
cur_namespace: Optional[List[str]] = None,
new_namespace: Optional[List[str]] = None,
cur_namespace: List[str] = [],
new_namespace: List[str] = [],
):
raise NotImplementedError(
"rename_table is not supported for namespace connections"
@@ -261,7 +262,7 @@ class LanceNamespaceDBConnection(DBConnection):
)
@override
def drop_all_tables(self, namespace: Optional[List[str]] = None):
def drop_all_tables(self, namespace: List[str] = []):
for table_name in self.table_names(namespace=namespace):
self.drop_table(table_name, namespace=namespace)

View File

@@ -151,9 +151,10 @@ class RemoteDBConnection(DBConnection):
@override
def table_names(
self,
namespace: List[str] = [],
page_token: Optional[str] = None,
limit: int = 10,
*,
namespace: List[str] = [],
) -> Iterable[str]:
"""List the names of all tables in the database.
@@ -343,7 +344,7 @@ class RemoteDBConnection(DBConnection):
return RemoteTable(table, self.db_name)
@override
def drop_table(self, name: str, namespace: Optional[List[str]] = None):
def drop_table(self, name: str, namespace: List[str] = []):
"""Drop a table from the database.
Parameters
@@ -361,8 +362,8 @@ class RemoteDBConnection(DBConnection):
self,
cur_name: str,
new_name: str,
cur_namespace: Optional[List[str]] = None,
new_namespace: Optional[List[str]] = None,
cur_namespace: List[str] = [],
new_namespace: List[str] = [],
):
"""Rename a table in the database.

View File

@@ -175,6 +175,18 @@ def test_table_names(tmp_db: lancedb.DBConnection):
tmp_db.create_table("test3", data=data)
assert tmp_db.table_names() == ["test1", "test2", "test3"]
# Test that positional arguments for page_token and limit
result = list(tmp_db.table_names("test1", 1)) # page_token="test1", limit=1
assert result == ["test2"], f"Expected ['test2'], got {result}"
# Test mixed positional and keyword arguments
result = list(tmp_db.table_names("test2", limit=2))
assert result == ["test3"], f"Expected ['test3'], got {result}"
# Test that namespace parameter can be passed as keyword
result = list(tmp_db.table_names(namespace=[]))
assert len(result) == 3
@pytest.mark.asyncio
async def test_table_names_async(tmp_path):

View File

@@ -420,6 +420,10 @@ class TestNamespaceConnection:
assert "table2" in table_names
assert len(table_names) == 1
# Test that drop_table works without explicit namespace parameter
db.drop_table("table2")
assert len(list(db.table_names())) == 0
# Should not be able to open dropped table
with pytest.raises(RuntimeError):
db.open_table("table1")
@@ -487,6 +491,11 @@ class TestNamespaceConnection:
# Verify all tables are gone
assert len(list(db.table_names())) == 0
# Test that table_names works with keyword-only namespace parameter
db.create_table("test_table", schema=schema)
result = list(db.table_names(namespace=[]))
assert "test_table" in result
def test_table_operations(self):
"""Test various table operations through namespace."""
db = lancedb.connect_namespace("temp", {"root": self.temp_dir})