From 96f6728c7169fa11c5aa72e4107ce76ce5f52d81 Mon Sep 17 00:00:00 2001 From: Adam Gutglick Date: Fri, 27 Mar 2026 13:42:33 +0000 Subject: [PATCH 1/3] Cache python class imports Signed-off-by: Adam Gutglick --- vortex-python/src/arrays/from_arrow.rs | 17 +++++--- vortex-python/src/arrow.rs | 30 ++++++------- vortex-python/src/classes.rs | 59 ++++++++++++++++++++++++++ vortex-python/src/io.rs | 10 +++-- vortex-python/src/lib.rs | 1 + vortex-python/src/scalar/into_py.rs | 4 +- 6 files changed, 92 insertions(+), 29 deletions(-) create mode 100644 vortex-python/src/classes.rs diff --git a/vortex-python/src/arrays/from_arrow.rs b/vortex-python/src/arrays/from_arrow.rs index 857cf946071..0b6b0767bd1 100644 --- a/vortex-python/src/arrays/from_arrow.rs +++ b/vortex-python/src/arrays/from_arrow.rs @@ -20,22 +20,25 @@ use vortex::error::VortexResult; use crate::arrays::PyArrayRef; use crate::arrow::FromPyArrow; +use crate::classes::array_class; +use crate::classes::chunked_array_class; +use crate::classes::table_class; use crate::error::PyVortexError; use crate::error::PyVortexResult; /// Convert an Arrow object to a Vortex array. pub(super) fn from_arrow(obj: &Borrowed<'_, '_, PyAny>) -> PyVortexResult { - let pa = obj.py().import("pyarrow")?; - let pa_array = pa.getattr("Array")?; - let chunked_array = pa.getattr("ChunkedArray")?; - let table = pa.getattr("Table")?; + let py = obj.py(); + let pa_array = array_class(py)?; + let chunked_array = chunked_array_class(py)?; + let table = table_class(py)?; - if obj.is_instance(&pa_array)? { + if obj.is_instance(pa_array)? { let arrow_array = ArrowArrayData::from_pyarrow(&obj.as_borrowed()).map(make_array)?; let is_nullable = arrow_array.is_nullable(); let enc_array = ArrayRef::from_arrow(arrow_array.as_ref(), is_nullable)?; Ok(PyArrayRef::from(enc_array)) - } else if obj.is_instance(&chunked_array)? { + } else if obj.is_instance(chunked_array)? { let chunks: Vec> = obj.getattr("chunks")?.extract()?; let encoded_chunks = chunks .iter() @@ -51,7 +54,7 @@ pub(super) fn from_arrow(obj: &Borrowed<'_, '_, PyAny>) -> PyVortexResult FromPyArrow<'_, 'py> for DataType { impl ToPyArrow for DataType { fn to_pyarrow(&self, py: Python) -> PyResult> { let c_schema = FFI_ArrowSchema::try_from(self).map_err(to_py_err)?; - let module = py.import("pyarrow")?; - let class = module.getattr("DataType")?; - let dtype = class.call_method1("_import_from_c", (&raw const c_schema as Py_uintptr_t,))?; + let dtype = data_type_class(py)? + .call_method1("_import_from_c", (&raw const c_schema as Py_uintptr_t,))?; Ok(dtype.into()) } } @@ -124,9 +129,8 @@ impl<'py> FromPyArrow<'_, 'py> for Field { impl ToPyArrow for Field { fn to_pyarrow(&self, py: Python) -> PyResult> { let c_schema = FFI_ArrowSchema::try_from(self).map_err(to_py_err)?; - let module = py.import("pyarrow")?; - let class = module.getattr("Field")?; - let dtype = class.call_method1("_import_from_c", (&raw const c_schema as Py_uintptr_t,))?; + let dtype = field_class(py)? + .call_method1("_import_from_c", (&raw const c_schema as Py_uintptr_t,))?; Ok(dtype.into()) } } @@ -157,10 +161,8 @@ impl<'py> FromPyArrow<'_, 'py> for Schema { impl ToPyArrow for Schema { fn to_pyarrow(&self, py: Python) -> PyResult> { let c_schema = FFI_ArrowSchema::try_from(self).map_err(to_py_err)?; - let module = py.import("pyarrow")?; - let class = module.getattr("Schema")?; - let schema = - class.call_method1("_import_from_c", (&raw const c_schema as Py_uintptr_t,))?; + let schema = schema_class(py)? + .call_method1("_import_from_c", (&raw const c_schema as Py_uintptr_t,))?; Ok(schema.into()) } } @@ -207,9 +209,7 @@ impl ToPyArrow for ArrayData { let array = FFI_ArrowArray::new(self); let schema = FFI_ArrowSchema::try_from(self.data_type()).map_err(to_py_err)?; - let module = py.import("pyarrow")?; - let class = module.getattr("Array")?; - let array = class.call_method1( + let array = array_class(py)?.call_method1( "_import_from_c", ( addr_of!(array) as Py_uintptr_t, @@ -323,10 +323,8 @@ impl IntoPyArrow for Box { fn into_pyarrow(self, py: Python) -> PyResult> { let mut stream = FFI_ArrowArrayStream::new(self); - let module = py.import("pyarrow")?; - let class = module.getattr("RecordBatchReader")?; let args = PyTuple::new(py, [&raw mut stream as Py_uintptr_t])?; - let reader = class.call_method1("_import_from_c", args)?; + let reader = record_batch_reader_class(py)?.call_method1("_import_from_c", args)?; Ok(Py::from(reader)) } diff --git a/vortex-python/src/classes.rs b/vortex-python/src/classes.rs new file mode 100644 index 00000000000..a9e881ed160 --- /dev/null +++ b/vortex-python/src/classes.rs @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: Copyright the Vortex contributors + +//! Caching often accesses classes that are accessed across the C ABI + +use pyo3::Bound; +use pyo3::Py; +use pyo3::PyResult; +use pyo3::Python; +use pyo3::sync::PyOnceLock; +use pyo3::types::PyType; + +/// Returns the pyarrow.DataType class +pub fn data_type_class(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> { + static TYPE: PyOnceLock> = PyOnceLock::new(); + TYPE.import(py, "pyarrow", "DataType") +} + +/// Returns the pyarrow.Field class +pub fn field_class(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> { + static TYPE: PyOnceLock> = PyOnceLock::new(); + TYPE.import(py, "pyarrow", "Field") +} + +/// Returns the pyarrow.Schema class +pub fn schema_class(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> { + static TYPE: PyOnceLock> = PyOnceLock::new(); + TYPE.import(py, "pyarrow", "Schema") +} + +/// Returns the pyarrow.Array class +pub fn array_class(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> { + static TYPE: PyOnceLock> = PyOnceLock::new(); + TYPE.import(py, "pyarrow", "Array") +} + +/// Returns the pyarrow.ChunkedArray class +pub fn chunked_array_class(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> { + static TYPE: PyOnceLock> = PyOnceLock::new(); + TYPE.import(py, "pyarrow", "ChunkedArray") +} + +/// Returns the pyarrow.RecordBatchReader class +pub fn record_batch_reader_class(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> { + static TYPE: PyOnceLock> = PyOnceLock::new(); + TYPE.import(py, "pyarrow", "RecordBatchReader") +} + +/// Returns the pyarrow.Table class +pub fn table_class(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> { + static TYPE: PyOnceLock> = PyOnceLock::new(); + TYPE.import(py, "pyarrow", "Table") +} + +/// Returns the pyarrow.Decimal class +pub fn decimal_class(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> { + static TYPE: PyOnceLock> = PyOnceLock::new(); + TYPE.import(py, "decimal", "Decimal") +} diff --git a/vortex-python/src/io.rs b/vortex-python/src/io.rs index f839b20cbb1..684b3f2fc5a 100644 --- a/vortex-python/src/io.rs +++ b/vortex-python/src/io.rs @@ -30,6 +30,8 @@ use crate::TOKIO_RUNTIME; use crate::arrays::PyArray; use crate::arrays::PyArrayRef; use crate::arrow::FromPyArrow; +use crate::classes::record_batch_reader_class; +use crate::classes::table_class; use crate::dataset::PyVortexDataset; use crate::error::PyVortexResult; use crate::expr::PyExpr; @@ -425,11 +427,11 @@ fn try_arrow_stream_to_iterator( ob: &Borrowed<'_, '_, PyAny>, ) -> PyResult> { let py = ob.py(); - let pa = py.import("pyarrow")?; - let pa_table = pa.getattr("Table")?; - let pa_record_batch_reader = pa.getattr("RecordBatchReader")?; - if ob.is_instance(&pa_table)? || ob.is_instance(&pa_record_batch_reader)? { + let pa_table = table_class(py)?; + let pa_record_batch_reader = record_batch_reader_class(py)?; + + if ob.is_instance(pa_table)? || ob.is_instance(pa_record_batch_reader)? { // Convert to Arrow stream using FFI let arrow_stream = ArrowArrayStreamReader::from_pyarrow(ob)?; let dtype = DType::from_arrow(arrow_stream.schema()); diff --git a/vortex-python/src/lib.rs b/vortex-python/src/lib.rs index be399ea8d6e..a3ede4210a9 100644 --- a/vortex-python/src/lib.rs +++ b/vortex-python/src/lib.rs @@ -13,6 +13,7 @@ use pyo3::prelude::*; pub(crate) mod arrays; pub mod arrow; +pub(crate) mod classes; #[cfg(feature = "tui")] mod cli; mod compress; diff --git a/vortex-python/src/scalar/into_py.rs b/vortex-python/src/scalar/into_py.rs index 6842d0a622c..6e2f7124f24 100644 --- a/vortex-python/src/scalar/into_py.rs +++ b/vortex-python/src/scalar/into_py.rs @@ -31,6 +31,7 @@ use vortex::scalar::Scalar; use vortex::scalar::StructScalar; use crate::PyVortex; +use crate::classes::decimal_class; impl<'py> IntoPyObject<'py> for PyVortex<&'_ Scalar> { type Target = PyAny; @@ -204,8 +205,7 @@ fn decimal_value_to_py( scale: i8, decimal_value: DecimalValue, ) -> PyResult> { - let m = py.import("decimal")?; - let decimal_class = m.getattr("Decimal")?; + let decimal_class = decimal_class(py)?; match_each_decimal_value!(decimal_value, |value| { let (whole, decimal) = value.decimal_parts(scale); From 9fb47798b84056c7981ff5b5419525bf8887137b Mon Sep 17 00:00:00 2001 From: Adam Gutglick Date: Fri, 27 Mar 2026 14:01:02 +0000 Subject: [PATCH 2/3] Intern all static strings Signed-off-by: Adam Gutglick --- uv.lock | 2 +- vortex-python/src/arrays/from_arrow.rs | 5 ++- vortex-python/src/arrays/mod.rs | 7 ++-- vortex-python/src/arrays/py/mod.rs | 3 +- vortex-python/src/arrays/py/vtable.rs | 2 +- vortex-python/src/arrow.rs | 56 ++++++++++++++++---------- vortex-python/src/lib.rs | 5 ++- vortex-python/src/serde/parts.rs | 4 +- 8 files changed, 52 insertions(+), 32 deletions(-) diff --git a/uv.lock b/uv.lock index f4bc78120f4..2b6ed4cacee 100644 --- a/uv.lock +++ b/uv.lock @@ -1921,7 +1921,7 @@ requires-dist = [ { name = "polars", marker = "extra == 'polars'", specifier = ">=1.31.0" }, { name = "pyarrow", specifier = ">=17.0.0" }, { name = "ray", marker = "extra == 'ray'", specifier = ">=2.48" }, - { name = "substrait", specifier = ">=0.23.0,<0.85.0" }, + { name = "substrait", specifier = ">=0.23.0,<0.29.0" }, { name = "typing-extensions", specifier = ">=4.5.0" }, ] provides-extras = ["duckdb", "numpy", "pandas", "polars", "ray"] diff --git a/vortex-python/src/arrays/from_arrow.rs b/vortex-python/src/arrays/from_arrow.rs index 0b6b0767bd1..beb142a1625 100644 --- a/vortex-python/src/arrays/from_arrow.rs +++ b/vortex-python/src/arrays/from_arrow.rs @@ -8,6 +8,7 @@ use arrow_data::ArrayData as ArrowArrayData; use arrow_schema::DataType; use arrow_schema::Field; use pyo3::exceptions::PyValueError; +use pyo3::intern; use pyo3::prelude::*; use vortex::array::ArrayRef; use vortex::array::IntoArray; @@ -39,7 +40,7 @@ pub(super) fn from_arrow(obj: &Borrowed<'_, '_, PyAny>) -> PyVortexResult> = obj.getattr("chunks")?.extract()?; + let chunks: Vec> = obj.getattr(intern!(py, "chunks"))?.extract()?; let encoded_chunks = chunks .iter() .map(|a| { @@ -48,7 +49,7 @@ pub(super) fn from_arrow(obj: &Borrowed<'_, '_, PyAny>) -> PyVortexResult>>()?; let dtype: DType = obj - .getattr("type") + .getattr(intern!(py, "type")) .and_then(|v| DataType::from_pyarrow(&v.as_borrowed())) .map(|dt| DType::from_arrow(&Field::new("_", dt, false)))?; Ok(PyArrayRef::from( diff --git a/vortex-python/src/arrays/mod.rs b/vortex-python/src/arrays/mod.rs index 674f45ddc2c..413365a02b0 100644 --- a/vortex-python/src/arrays/mod.rs +++ b/vortex-python/src/arrays/mod.rs @@ -15,6 +15,7 @@ use pyo3::IntoPyObjectExt; use pyo3::exceptions::PyIndexError; use pyo3::exceptions::PyTypeError; use pyo3::exceptions::PyValueError; +use pyo3::intern; use pyo3::prelude::*; use pyo3::types::PyDict; use pyo3::types::PyList; @@ -742,7 +743,7 @@ impl PyArray { let dtype_buffers: Vec> = dtype_buffers.iter().map(|b| b.to_vec()).collect(); let vortex_module = PyModule::import(py, "vortex")?; - let unpickle_fn = vortex_module.getattr("_unpickle_array")?; + let unpickle_fn = vortex_module.getattr(intern!(py, "_unpickle_array"))?; let args = (array_buffers, dtype_buffers).into_pyobject(py)?; Ok((unpickle_fn, args.into_any())) @@ -769,7 +770,7 @@ impl PyArray { let dtype_buffers = encoder.encode(EncoderMessage::DType(array.dtype()))?; let pickle_module = PyModule::import(py, "pickle")?; - let pickle_buffer_class = pickle_module.getattr("PickleBuffer")?; + let pickle_buffer_class = pickle_module.getattr(intern!(py, "PickleBuffer"))?; let mut pickle_buffers = Vec::new(); for buf in array_buffers.into_iter() { @@ -788,7 +789,7 @@ impl PyArray { } let vortex_module = PyModule::import(py, "vortex")?; - let unpickle_fn = vortex_module.getattr("_unpickle_array")?; + let unpickle_fn = vortex_module.getattr(intern!(py, "_unpickle_array"))?; let args = (pickle_buffers, dtype_pickle_buffers).into_pyobject(py)?; Ok((unpickle_fn, args.into_any())) diff --git a/vortex-python/src/arrays/py/mod.rs b/vortex-python/src/arrays/py/mod.rs index f15ffbaed9b..d19c91865c7 100644 --- a/vortex-python/src/arrays/py/mod.rs +++ b/vortex-python/src/arrays/py/mod.rs @@ -9,6 +9,7 @@ pub(crate) use array::*; use pyo3::Bound; use pyo3::PyAny; use pyo3::exceptions::PyValueError; +use pyo3::intern; use pyo3::prelude::PyAnyMethods; pub(crate) use python::*; use vortex::array::vtable::ArrayId; @@ -19,7 +20,7 @@ use crate::error::PyVortexResult; /// Extract the array id from a Python class `id` attribute. pub fn id_from_obj(cls: &Bound) -> PyVortexResult { Ok(ArrayId::new_arc( - cls.getattr("id") + cls.getattr(intern!(cls.py(), "id")) .map_err(|_| { PyValueError::new_err(format!( "PyEncoding subclass {cls:?} must have an 'id' attribute" diff --git a/vortex-python/src/arrays/py/vtable.rs b/vortex-python/src/arrays/py/vtable.rs index a27008f45e6..481293fab03 100644 --- a/vortex-python/src/arrays/py/vtable.rs +++ b/vortex-python/src/arrays/py/vtable.rs @@ -118,7 +118,7 @@ impl VTable for PythonVTable { } let bytes = obj - .call_method("__vx_metadata__", (), None) + .call_method(intern!(py, "__vx_metadata__"), (), None) .map_err(|e| vortex_err!("{}", e))? .cast::() .map_err(|_| vortex_err!("Expected array metadata to be Python bytes"))? diff --git a/vortex-python/src/arrow.rs b/vortex-python/src/arrow.rs index a1365ba364a..1ca4be5981f 100644 --- a/vortex-python/src/arrow.rs +++ b/vortex-python/src/arrow.rs @@ -31,6 +31,7 @@ use pyo3::exceptions::PyValueError; use pyo3::ffi::Py_uintptr_t; use pyo3::ffi::c_str; use pyo3::import_exception; +use pyo3::intern; use pyo3::prelude::*; use pyo3::types::PyCapsule; use pyo3::types::PyTuple; @@ -75,13 +76,14 @@ pub trait IntoPyArrow { impl<'py> FromPyArrow<'_, 'py> for DataType { fn from_pyarrow(value: &Borrowed<'_, 'py, PyAny>) -> PyResult { - if !value.hasattr("__arrow_c_schema__")? { + let py = value.py(); + if !value.hasattr(intern!(py, "__arrow_c_schema__"))? { return Err(PyValueError::new_err( "Expected __arrow_c_schema__ attribute to be set.", )); } - let capsule = value.getattr("__arrow_c_schema__")?.call0()?; + let capsule = value.getattr(intern!(py, "__arrow_c_schema__"))?.call0()?; let capsule = capsule.cast::()?; let schema_ptr = unsafe { @@ -98,21 +100,24 @@ impl<'py> FromPyArrow<'_, 'py> for DataType { impl ToPyArrow for DataType { fn to_pyarrow(&self, py: Python) -> PyResult> { let c_schema = FFI_ArrowSchema::try_from(self).map_err(to_py_err)?; - let dtype = data_type_class(py)? - .call_method1("_import_from_c", (&raw const c_schema as Py_uintptr_t,))?; + let dtype = data_type_class(py)?.call_method1( + intern!(py, "_import_from_c"), + (&raw const c_schema as Py_uintptr_t,), + )?; Ok(dtype.into()) } } impl<'py> FromPyArrow<'_, 'py> for Field { fn from_pyarrow(value: &Borrowed<'_, 'py, PyAny>) -> PyResult { - if !value.hasattr("__arrow_c_schema__")? { + let py = value.py(); + if !value.hasattr(intern!(py, "__arrow_c_schema__"))? { return Err(PyValueError::new_err( "Expected __arrow_c_schema__ attribute to be set.", )); } - let capsule = value.getattr("__arrow_c_schema__")?.call0()?; + let capsule = value.getattr(intern!(py, "__arrow_c_schema__"))?.call0()?; let capsule = capsule.cast::()?; let schema_ptr = unsafe { @@ -129,21 +134,24 @@ impl<'py> FromPyArrow<'_, 'py> for Field { impl ToPyArrow for Field { fn to_pyarrow(&self, py: Python) -> PyResult> { let c_schema = FFI_ArrowSchema::try_from(self).map_err(to_py_err)?; - let dtype = field_class(py)? - .call_method1("_import_from_c", (&raw const c_schema as Py_uintptr_t,))?; + let dtype = field_class(py)?.call_method1( + intern!(py, "_import_from_c"), + (&raw const c_schema as Py_uintptr_t,), + )?; Ok(dtype.into()) } } impl<'py> FromPyArrow<'_, 'py> for Schema { fn from_pyarrow(value: &Borrowed<'_, 'py, PyAny>) -> PyResult { - if !value.hasattr("__arrow_c_schema__")? { + let py = value.py(); + if !value.hasattr(intern!(py, "__arrow_c_schema__"))? { return Err(PyValueError::new_err( "Expected __arrow_c_schema__ attribute to be set.", )); } - let capsule = value.getattr("__arrow_c_schema__")?.call0()?; + let capsule = value.getattr(intern!(py, "__arrow_c_schema__"))?.call0()?; let capsule = capsule.cast::()?; let schema_ptr = unsafe { @@ -161,21 +169,24 @@ impl<'py> FromPyArrow<'_, 'py> for Schema { impl ToPyArrow for Schema { fn to_pyarrow(&self, py: Python) -> PyResult> { let c_schema = FFI_ArrowSchema::try_from(self).map_err(to_py_err)?; - let schema = schema_class(py)? - .call_method1("_import_from_c", (&raw const c_schema as Py_uintptr_t,))?; + let schema = schema_class(py)?.call_method1( + intern!(py, "_import_from_c"), + (&raw const c_schema as Py_uintptr_t,), + )?; Ok(schema.into()) } } impl<'py> FromPyArrow<'_, 'py> for ArrayData { fn from_pyarrow(value: &Borrowed<'_, 'py, PyAny>) -> PyResult { - if !value.hasattr("__arrow_c_array__")? { + let py = value.py(); + if !value.hasattr(intern!(py, "__arrow_c_array__"))? { return Err(PyValueError::new_err( "Expected __arrow_c_array__ attribute to be set.", )); } - let tuple = value.getattr("__arrow_c_array__")?.call0()?; + let tuple = value.getattr(intern!(py, "__arrow_c_array__"))?.call0()?; if !tuple.is_instance_of::() { return Err(PyTypeError::new_err( @@ -210,7 +221,7 @@ impl ToPyArrow for ArrayData { let schema = FFI_ArrowSchema::try_from(self.data_type()).map_err(to_py_err)?; let array = array_class(py)?.call_method1( - "_import_from_c", + intern!(py, "_import_from_c"), ( addr_of!(array) as Py_uintptr_t, addr_of!(schema) as Py_uintptr_t, @@ -222,13 +233,14 @@ impl ToPyArrow for ArrayData { impl<'py> FromPyArrow<'_, 'py> for RecordBatch { fn from_pyarrow(value: &Borrowed<'_, 'py, PyAny>) -> PyResult { - if !value.hasattr("__arrow_c_array__")? { + let py = value.py(); + if !value.hasattr(intern!(py, "__arrow_c_array__"))? { return Err(PyValueError::new_err( "Expected __arrow_c_array__ attribute to be set.", )); } - let tuple = value.getattr("__arrow_c_array__")?.call0()?; + let tuple = value.getattr(intern!(py, "__arrow_c_array__"))?.call0()?; if !tuple.is_instance_of::() { return Err(PyTypeError::new_err( @@ -286,20 +298,21 @@ impl ToPyArrow for RecordBatch { let reader = RecordBatchIterator::new(vec![Ok(self.clone())], self.schema()); let reader: Box = Box::new(reader); let py_reader = reader.into_pyarrow(py)?; - py_reader.call_method0(py, "read_next_batch") + py_reader.call_method0(py, intern!(py, "read_next_batch")) } } /// Supports conversion from `pyarrow.RecordBatchReader` to [ArrowArrayStreamReader]. impl<'py> FromPyArrow<'_, 'py> for ArrowArrayStreamReader { fn from_pyarrow(value: &Borrowed<'_, 'py, PyAny>) -> PyResult { - if !value.hasattr("__arrow_c_stream__")? { + let py = value.py(); + if !value.hasattr(intern!(py, "__arrow_c_stream__"))? { return Err(PyValueError::new_err( "Expected __arrow_c_stream__ attribute to be set.", )); } - let capsule = value.getattr("__arrow_c_stream__")?.call0()?; + let capsule = value.getattr(intern!(py, "__arrow_c_stream__"))?.call0()?; let capsule = capsule.cast::()?; let array_ptr = capsule @@ -324,7 +337,8 @@ impl IntoPyArrow for Box { let mut stream = FFI_ArrowArrayStream::new(self); let args = PyTuple::new(py, [&raw mut stream as Py_uintptr_t])?; - let reader = record_batch_reader_class(py)?.call_method1("_import_from_c", args)?; + let reader = + record_batch_reader_class(py)?.call_method1(intern!(py, "_import_from_c"), args)?; Ok(Py::from(reader)) } diff --git a/vortex-python/src/lib.rs b/vortex-python/src/lib.rs index a3ede4210a9..c84f09588ef 100644 --- a/vortex-python/src/lib.rs +++ b/vortex-python/src/lib.rs @@ -9,6 +9,7 @@ use std::ops::Deref; use std::sync::LazyLock; use pyo3::exceptions::PyRuntimeError; +use pyo3::intern; use pyo3::prelude::*; pub(crate) mod arrays; @@ -112,10 +113,10 @@ pub fn install_module(name: &str, module: &Bound) -> PyResult<()> { module .py() .import("sys")? - .getattr("modules")? + .getattr(intern!(module.py(), "modules"))? .set_item(name, module)?; // needs to be set *after* `add_submodule()` - module.setattr("__name__", name)?; + module.setattr(intern!(module.py(), "__name__"), name)?; Ok(()) } diff --git a/vortex-python/src/serde/parts.rs b/vortex-python/src/serde/parts.rs index 1f558a4d0a6..2decc0a926a 100644 --- a/vortex-python/src/serde/parts.rs +++ b/vortex-python/src/serde/parts.rs @@ -7,6 +7,7 @@ use pyo3::Bound; use pyo3::PyAny; use pyo3::PyRef; use pyo3::Python; +use pyo3::intern; use pyo3::prelude::PyAnyMethods; use pyo3::pyclass; use pyo3::pymethods; @@ -100,7 +101,8 @@ impl PyArrayParts { let addr = buffer.as_ptr() as usize; let size = buffer.len(); let base = &slf; - let pa_buffer = pyarrow.call_method("foreign_buffer", (addr, size, base), None)?; + let pa_buffer = + pyarrow.call_method(intern!(py, "foreign_buffer"), (addr, size, base), None)?; buffers.push(pa_buffer); } From edb409b8c42b3fbc8245519165e6f6bd0998201b Mon Sep 17 00:00:00 2001 From: Adam Gutglick Date: Fri, 27 Mar 2026 14:04:32 +0000 Subject: [PATCH 3/3] cleanup vortex-python/build.rs Signed-off-by: Adam Gutglick --- vortex-python/build.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/vortex-python/build.rs b/vortex-python/build.rs index 1a552ef69f3..51b482e42db 100644 --- a/vortex-python/build.rs +++ b/vortex-python/build.rs @@ -2,9 +2,8 @@ // SPDX-FileCopyrightText: Copyright the Vortex contributors fn main() { - let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default(); - - if target_os == "macos" { + #[cfg(target_os = "macos")] + { // For pyo3 to successfully link on macOS. // See https://stackoverflow.com/a/77382609 println!("cargo:rustc-link-arg=-undefined");