feat(sdk): expose table overrides for remote tables

This commit is contained in:
ChilePiquin
2026-09-18 12:06:48 -06:00
parent 7955c50929
commit 2ef1173724
8 changed files with 444 additions and 1 deletions
+3
View File
@@ -494,6 +494,9 @@ class Table:
async def set_lsm_write_spec(self, spec: LsmWriteSpec) -> None: ...
async def unset_lsm_write_spec(self) -> None: ...
async def get_lsm_write_spec(self) -> Optional[LsmWriteSpec]: ...
async def get_table_overrides(self) -> str: ...
async def update_table_overrides(self, overrides_json: str) -> str: ...
async def reset_table_overrides(self) -> str: ...
async def checkpoint_lsm(self) -> None: ...
async def flush_lsm(self) -> None: ...
async def compact_lsm(self) -> None: ...
+62
View File
@@ -5,6 +5,7 @@ from __future__ import annotations
import asyncio
import inspect
import json
import deprecation
import warnings
from abc import ABC, abstractmethod
@@ -4449,6 +4450,36 @@ class LanceTable(Table):
[`AsyncTable.get_lsm_write_spec`][lancedb.AsyncTable.get_lsm_write_spec]."""
return LOOP.run(self._table.get_lsm_write_spec())
def get_table_overrides(self) -> dict[str, Any]:
"""Read Enterprise table overrides for this table.
Table overrides configure Enterprise-managed background behavior such as
automatic compaction, cleanup, and reindex execution. This method is
supported only on remote Enterprise tables.
"""
return LOOP.run(self._table.get_table_overrides())
def update_table_overrides(self, **overrides: Any) -> dict[str, Any]:
"""Merge Enterprise table overrides into the current table overrides.
Only fields supplied in ``overrides`` are changed; unrelated existing
overrides are preserved by the remote service update flow.
Examples
--------
>>> table.update_table_overrides(
... job_types={
... "compaction": {"enabled": True},
... "cleanup": {"enabled": False},
... }
... )
"""
return LOOP.run(self._table.update_table_overrides(**overrides))
def reset_table_overrides(self) -> dict[str, Any]:
"""Clear Enterprise table overrides for this table."""
return LOOP.run(self._table.reset_table_overrides())
def checkpoint_lsm(self) -> None:
"""Synchronous version of
[`AsyncTable.checkpoint_lsm`][lancedb.AsyncTable.checkpoint_lsm]."""
@@ -5188,6 +5219,37 @@ class AsyncTable:
"""
return await self._inner.get_lsm_write_spec()
async def get_table_overrides(self) -> dict[str, Any]:
"""Read Enterprise table overrides for this table.
Table overrides configure Enterprise-managed background behavior such as
automatic compaction, cleanup, and reindex execution. This method is
supported only on remote Enterprise tables.
"""
return json.loads(await self._inner.get_table_overrides())
async def update_table_overrides(self, **overrides: Any) -> dict[str, Any]:
"""Merge Enterprise table overrides into the current table overrides.
Only fields supplied in ``overrides`` are changed; unrelated existing
overrides are preserved by the remote service update flow.
Examples
--------
>>> await table.update_table_overrides(
... job_types={
... "compaction": {"enabled": True},
... "cleanup": {"enabled": False},
... }
... )
"""
encoded = json.dumps(overrides)
return json.loads(await self._inner.update_table_overrides(encoded))
async def reset_table_overrides(self) -> dict[str, Any]:
"""Clear Enterprise table overrides for this table."""
return json.loads(await self._inner.reset_table_overrides())
async def checkpoint_lsm(self) -> None:
"""Converge this table's LSM write path into its base table.
+61
View File
@@ -4,6 +4,7 @@
import ctypes
import gc
import json
import os
import sys
import threading
@@ -1640,6 +1641,66 @@ def test_create_index_method(mock_create_index, mem_db: DBConnection):
)
@patch("lancedb.table.AsyncTable.get_table_overrides")
def test_get_table_overrides_method(mock_get_table_overrides, mem_db: DBConnection):
expected = {"job_types": {"cleanup": {"enabled": False}}}
mock_get_table_overrides.return_value = expected
table = mem_db.create_table("test", data=[{"id": 1}])
assert table.get_table_overrides() == expected
mock_get_table_overrides.assert_called_once_with()
@patch("lancedb.table.AsyncTable.update_table_overrides")
def test_update_table_overrides_method(
mock_update_table_overrides, mem_db: DBConnection
):
overrides = {
"job_types": {
"cleanup": {"enabled": False},
"index": {
"scalar": {
"reindex": {
"row_threshold": 1000,
"ttl_millis": 300000,
}
}
},
}
}
mock_update_table_overrides.return_value = overrides
table = mem_db.create_table("test", data=[{"id": 1}])
assert table.update_table_overrides(**overrides) == overrides
mock_update_table_overrides.assert_called_once_with(**overrides)
@patch("lancedb.table.AsyncTable.reset_table_overrides")
def test_reset_table_overrides_method(mock_reset_table_overrides, mem_db: DBConnection):
expected = {}
mock_reset_table_overrides.return_value = expected
table = mem_db.create_table("test", data=[{"id": 1}])
assert table.reset_table_overrides() == expected
mock_reset_table_overrides.assert_called_once_with()
@pytest.mark.asyncio
async def test_async_update_table_overrides_encodes_json():
class MockInner:
async def update_table_overrides(self, encoded_overrides):
assert json.loads(encoded_overrides) == {
"job_types": {"cleanup": {"enabled": False}}
}
return json.dumps({"job_types": {"cleanup": {"enabled": False}}})
table = lancedb.table.AsyncTable(MockInner())
assert await table.update_table_overrides(
job_types={"cleanup": {"enabled": False}}
) == {"job_types": {"cleanup": {"enabled": False}}}
@patch("lancedb.table.AsyncTable.create_index")
def test_create_index_name_and_train_parameters(
mock_create_index, mem_db: DBConnection
+39
View File
@@ -1603,6 +1603,45 @@ impl Table {
})
}
pub fn get_table_overrides(self_: PyRef<'_, Self>) -> PyResult<Bound<'_, PyAny>> {
let inner = self_.inner_ref()?.clone();
future_into_py(self_.py(), async move {
let overrides = inner.get_table_overrides().await.infer_error()?;
serde_json::to_string(&overrides).map_err(|err| {
PyRuntimeError::new_err(format!("Failed to serialize table overrides: {err}"))
})
})
}
pub fn update_table_overrides<'a>(
self_: PyRef<'a, Self>,
overrides_json: String,
) -> PyResult<Bound<'a, PyAny>> {
let inner = self_.inner_ref()?.clone();
future_into_py(self_.py(), async move {
let overrides = serde_json::from_str(&overrides_json).map_err(|err| {
PyValueError::new_err(format!("Invalid table overrides JSON: {err}"))
})?;
let overrides = inner
.update_table_overrides(overrides)
.await
.infer_error()?;
serde_json::to_string(&overrides).map_err(|err| {
PyRuntimeError::new_err(format!("Failed to serialize table overrides: {err}"))
})
})
}
pub fn reset_table_overrides(self_: PyRef<'_, Self>) -> PyResult<Bound<'_, PyAny>> {
let inner = self_.inner_ref()?.clone();
future_into_py(self_.py(), async move {
let overrides = inner.reset_table_overrides().await.infer_error()?;
serde_json::to_string(&overrides).map_err(|err| {
PyRuntimeError::new_err(format!("Failed to serialize table overrides: {err}"))
})
})
}
/// Converge the table's LSM write path into its base table.
///
/// Best-effort: with writes flowing, new rows may land after the last