From 379684391ee7b5043f96db4be0ee99d1b6b32abe Mon Sep 17 00:00:00 2001 From: Brendan Clement Date: Tue, 2 Jun 2026 14:02:22 -0700 Subject: [PATCH] feat: deprecate replace_field_metadata for update_field_metadata (#3484) ### Summary Deprecates the Python replace_field_metadata (on Table and AsyncTable) in favor of update_field_metadata. Mirrors Lance, which already deprecated Dataset.replace_field_metadata for update_field_metadata. Stacked on top of #3482 as this was a follow-up task after adding update_field_metadata --- python/python/lancedb/table.py | 16 ++++++++++++++++ python/src/table.rs | 25 ++++++------------------- rust/lancedb/src/table.rs | 8 ++++---- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/python/python/lancedb/table.py b/python/python/lancedb/table.py index deb289fd6..7adc2cc54 100644 --- a/python/python/lancedb/table.py +++ b/python/python/lancedb/table.py @@ -3666,10 +3666,18 @@ class LanceTable(Table): """ LOOP.run(self._table.migrate_v2_manifest_paths()) + @deprecation.deprecated( + deprecated_in="0.33.1", + current_version=__version__, + details="Use update_field_metadata() instead.", + ) def replace_field_metadata(self, field_name: str, new_metadata: Dict[str, str]): """ Replace the metadata of a field in the schema + .. deprecated:: 0.33.1 + Use :func:`update_field_metadata` instead. + Parameters ---------- field_name: str @@ -5554,12 +5562,20 @@ class AsyncTable: """ await self._inner.migrate_manifest_paths_v2() + @deprecation.deprecated( + deprecated_in="0.33.1", + current_version=__version__, + details="Use update_field_metadata() instead.", + ) async def replace_field_metadata( self, field_name: str, new_metadata: dict[str, str] ): """ Replace the metadata of a field in the schema + .. deprecated:: 0.33.1 + Use :func:`update_field_metadata` instead. + Parameters ---------- field_name: str diff --git a/python/src/table.rs b/python/src/table.rs index a0462caf3..dc5f5ec0c 100644 --- a/python/src/table.rs +++ b/python/src/table.rs @@ -21,7 +21,7 @@ use lancedb::table::{ }; use pyo3::{ Bound, FromPyObject, Py, PyAny, PyRef, PyResult, Python, - exceptions::{PyKeyError, PyRuntimeError, PyValueError}, + exceptions::{PyRuntimeError, PyValueError}, pyclass, pymethods, types::{IntoPyDict, PyAnyMethods, PyDict, PyDictMethods}, }; @@ -1123,28 +1123,15 @@ impl Table { field_name: String, metadata: &Bound<'_, PyDict>, ) -> PyResult> { - let mut new_metadata = HashMap::::new(); - for (column_name, value) in metadata.into_iter() { - let key: String = column_name.extract()?; - let value: String = value.extract()?; - new_metadata.insert(key, value); + // Deprecated: forwards to the update_field_metadata path (replace mode). + let mut update = FieldMetadataUpdate::new(field_name).replace(); + for (key, value) in metadata.into_iter() { + update = update.set(key.extract::()?, value.extract::()?); } let inner = self_.inner_ref()?.clone(); future_into_py(self_.py(), async move { - let native_tbl = inner - .as_native() - .ok_or_else(|| PyValueError::new_err("This cannot be run on a remote table"))?; - let schema = native_tbl.manifest().await.infer_error()?.schema; - let field = schema - .field(&field_name) - .ok_or_else(|| PyKeyError::new_err(format!("Field {} not found", field_name)))?; - - native_tbl - .replace_field_metadata(vec![(field.id as u32, new_metadata)]) - .await - .infer_error()?; - + inner.update_field_metadata(&[update]).await.infer_error()?; Ok(()) }) } diff --git a/rust/lancedb/src/table.rs b/rust/lancedb/src/table.rs index 0eb6b578a..355483f0c 100644 --- a/rust/lancedb/src/table.rs +++ b/rust/lancedb/src/table.rs @@ -2604,6 +2604,7 @@ impl NativeTable { /// field id and the second element is a hashmap of metadata key-value /// pairs. /// + #[deprecated(since = "0.33.1", note = "Use `update_field_metadata` instead")] pub async fn replace_field_metadata( &self, new_values: impl IntoIterator)>, @@ -3167,7 +3168,6 @@ pub struct FragmentSummaryStats { #[cfg(test)] #[allow(deprecated)] mod tests { - use std::collections::HashMap; use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Duration; @@ -4480,10 +4480,10 @@ mod tests { Some(&"test_val2_update".to_string()) ); - let mut new_field_metadata = HashMap::::new(); - new_field_metadata.insert("test_field_key1".into(), "test_field_val1".into()); native_tbl - .replace_field_metadata(vec![(field.id as u32, new_field_metadata)]) + .update_field_metadata(&[ + FieldMetadataUpdate::new("i").set("test_field_key1", "test_field_val1") + ]) .await .unwrap();