Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions python/lance_namespace/src/lance_namespace/rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,23 +102,34 @@ def object_id_str(id_list: list[str], delimiter: str = ".", obj: Any = None) ->
object_type = type(obj).__name__ if obj is not None else "Unknown"
raise ValueError(f"Object of type '{object_type}' must have an 'id' field")
if len(id_list) == 0:
return delimiter
return delimiter.join(id_list)
id_str = delimiter
else:
id_str = delimiter.join(id_list)
if id_str == ".":
# https://github.com/lancedb/lance-namespace/issues/248
# Escape single dot to avoid server path normalization issues
id_str = "%2E"
return id_str


class LanceRestNamespace(LanceNamespace):
"""REST implementation of Lance Namespace."""

def __init__(self, **kwargs):
configuration = Configuration()
config = RestNamespaceConfig(kwargs)
if "uri" in kwargs:
configuration.host = kwargs["uri"]
if "safe_chars_for_path_param" in kwargs:
configuration.safe_chars_for_path_param = kwargs["safe_chars_for_path_param"]
if config.delimiter() == "." and not configuration.safe_chars_for_path_param:
configuration.safe_chars_for_path_param = "%"

self.api_client = ApiClient(configuration)
self.namespace_api = NamespaceApi(self.api_client)
self.table_api = TableApi(self.api_client)
self.transaction_api = TransactionApi(self.api_client)
self.config = RestNamespaceConfig(kwargs)
self.config = config
self.uri = kwargs.get("uri", "")

def namespace_id(self) -> str:
Expand Down
5 changes: 3 additions & 2 deletions python/lance_namespace/tests/test_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,11 @@ def test_object_id_with_list_id():
assert object_id_str(obj.id, ".", obj) == "ns1.ns2.table1"

def test_object_id_with_empty_list_id():
"""Test object with empty id list returns delimiter."""
"""Test object with empty id list returns delimiter.
Single dot will be escaped to %2E."""
obj = Mock()
obj.id = []
assert object_id_str(obj.id, ".", obj) == "."
assert object_id_str(obj.id, ".", obj) == "%2E"

def test_object_id_with_string_id():
"""Test object with id field as list containing single string."""
Expand Down