Skip to content
Merged
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
2 changes: 1 addition & 1 deletion arrow-pyarrow-integration-testing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ crate-type = ["cdylib"]

[dependencies]
arrow = { path = "../arrow", features = ["pyarrow"] }
pyo3 = { version = "0.25.1", features = ["extension-module"] }
pyo3 = { version = "0.26.0", features = ["extension-module"] }
14 changes: 9 additions & 5 deletions arrow-pyarrow-integration-testing/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ fn to_py_err(err: ArrowError) -> PyErr {

/// Returns `array + array` of an int64 array.
#[pyfunction]
fn double(array: &Bound<PyAny>, py: Python) -> PyResult<PyObject> {
fn double<'py>(array: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyAny>> {
let py = array.py();
// import
let array = make_array(ArrayData::from_pyarrow_bound(array)?);

Expand All @@ -61,21 +62,24 @@ fn double(array: &Bound<PyAny>, py: Python) -> PyResult<PyObject> {
/// calls a lambda function that receives and returns an array
/// whose result must be the array multiplied by two
#[pyfunction]
fn double_py(lambda: &Bound<PyAny>, py: Python) -> PyResult<bool> {
fn double_py(lambda: &Bound<PyAny>) -> PyResult<bool> {
// create
let array = Arc::new(Int64Array::from(vec![Some(1), None, Some(3)]));
let expected = Arc::new(Int64Array::from(vec![Some(2), None, Some(6)])) as ArrayRef;

// to py
let pyarray = array.to_data().to_pyarrow(py)?;
let pyarray = array.to_data().to_pyarrow(lambda.py())?;
let pyarray = lambda.call1((pyarray,))?;
let array = make_array(ArrayData::from_pyarrow_bound(&pyarray)?);

Ok(array == expected)
}

#[pyfunction]
fn make_empty_array(datatype: PyArrowType<DataType>, py: Python) -> PyResult<PyObject> {
fn make_empty_array<'py>(
datatype: PyArrowType<DataType>,
py: Python<'py>,
) -> PyResult<Bound<'py, PyAny>> {
let array = new_empty_array(&datatype.0);

array.to_data().to_pyarrow(py)
Expand All @@ -95,7 +99,7 @@ fn substring(array: PyArrowType<ArrayData>, start: i64) -> PyResult<PyArrowType<

/// Returns the concatenate
#[pyfunction]
fn concatenate(array: PyArrowType<ArrayData>, py: Python) -> PyResult<PyObject> {
fn concatenate<'py>(array: PyArrowType<ArrayData>, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
let array = make_array(array.0);

// concat
Expand Down
2 changes: 1 addition & 1 deletion arrow-pyarrow-testing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,4 @@ publish = false
# Note no dependency on arrow, to ensure arrow-pyarrow can be used by itself
arrow-array = { path = "../arrow-array" }
arrow-pyarrow = { path = "../arrow-pyarrow" }
pyo3 = { version = "0.25", default-features = false }
pyo3 = { version = "0.26.0", default-features = false }
16 changes: 8 additions & 8 deletions arrow-pyarrow-testing/tests/pyarrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ use std::sync::Arc;

#[test]
fn test_to_pyarrow() {
pyo3::prepare_freethreaded_python();
Python::initialize();

let a: ArrayRef = Arc::new(Int32Array::from(vec![1, 2]));
let b: ArrayRef = Arc::new(StringArray::from(vec!["a", "b"]));
Expand All @@ -56,11 +56,11 @@ fn test_to_pyarrow() {
let input = RecordBatch::try_from_iter(vec![("a", a), ("b", b), ("c", c)]).unwrap();
println!("input: {input:?}");

let res = Python::with_gil(|py| {
let res = Python::attach(|py| {
let py_input = input.to_pyarrow(py)?;
let records = RecordBatch::from_pyarrow_bound(py_input.bind(py))?;
let records = RecordBatch::from_pyarrow_bound(&py_input)?;
let py_records = records.to_pyarrow(py)?;
RecordBatch::from_pyarrow_bound(py_records.bind(py))
RecordBatch::from_pyarrow_bound(&py_records)
})
.unwrap();

Expand All @@ -69,7 +69,7 @@ fn test_to_pyarrow() {

#[test]
fn test_to_pyarrow_byte_view() {
pyo3::prepare_freethreaded_python();
Python::initialize();

for num_variadic_buffers in 0..=2 {
let string_view: ArrayRef = Arc::new(string_view_column(num_variadic_buffers));
Expand All @@ -82,11 +82,11 @@ fn test_to_pyarrow_byte_view() {
.unwrap();

println!("input: {input:?}");
let res = Python::with_gil(|py| {
let res = Python::attach(|py| {
let py_input = input.to_pyarrow(py)?;
let records = RecordBatch::from_pyarrow_bound(py_input.bind(py))?;
let records = RecordBatch::from_pyarrow_bound(&py_input)?;
let py_records = records.to_pyarrow(py)?;
RecordBatch::from_pyarrow_bound(py_records.bind(py))
RecordBatch::from_pyarrow_bound(&py_records)
})
.unwrap();

Expand Down
2 changes: 1 addition & 1 deletion arrow-pyarrow/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ all-features = true
arrow-array = { workspace = true, features = ["ffi"] }
arrow-data = { workspace = true }
arrow-schema = { workspace = true }
pyo3 = { version = "0.25.1", default-features = false }
pyo3 = { version = "0.26.0", default-features = false }
35 changes: 16 additions & 19 deletions arrow-pyarrow/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,17 +95,17 @@ pub trait FromPyArrow: Sized {
/// Create a new PyArrow object from a arrow-rs type.
pub trait ToPyArrow {
/// Convert the implemented type into a Python object without consuming it.
fn to_pyarrow(&self, py: Python) -> PyResult<PyObject>;
fn to_pyarrow<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>>;
}

/// Convert an arrow-rs type into a PyArrow object.
pub trait IntoPyArrow {
/// Convert the implemented type into a Python object while consuming it.
fn into_pyarrow(self, py: Python) -> PyResult<PyObject>;
fn into_pyarrow<'py>(self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>>;
}

impl<T: ToPyArrow> IntoPyArrow for T {
fn into_pyarrow(self, py: Python) -> PyResult<PyObject> {
fn into_pyarrow<'py>(self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
self.to_pyarrow(py)
}
}
Expand Down Expand Up @@ -172,7 +172,7 @@ impl FromPyArrow for DataType {
}

impl ToPyArrow for DataType {
fn to_pyarrow(&self, py: Python) -> PyResult<PyObject> {
fn to_pyarrow<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
let c_schema = FFI_ArrowSchema::try_from(self).map_err(to_py_err)?;
let c_schema_ptr = &c_schema as *const FFI_ArrowSchema;
let module = py.import("pyarrow")?;
Expand Down Expand Up @@ -208,7 +208,7 @@ impl FromPyArrow for Field {
}

impl ToPyArrow for Field {
fn to_pyarrow(&self, py: Python) -> PyResult<PyObject> {
fn to_pyarrow<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
let c_schema = FFI_ArrowSchema::try_from(self).map_err(to_py_err)?;
let c_schema_ptr = &c_schema as *const FFI_ArrowSchema;
let module = py.import("pyarrow")?;
Expand Down Expand Up @@ -244,7 +244,7 @@ impl FromPyArrow for Schema {
}

impl ToPyArrow for Schema {
fn to_pyarrow(&self, py: Python) -> PyResult<PyObject> {
fn to_pyarrow<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
let c_schema = FFI_ArrowSchema::try_from(self).map_err(to_py_err)?;
let c_schema_ptr = &c_schema as *const FFI_ArrowSchema;
let module = py.import("pyarrow")?;
Expand Down Expand Up @@ -303,7 +303,7 @@ impl FromPyArrow for ArrayData {
}

impl ToPyArrow for ArrayData {
fn to_pyarrow(&self, py: Python) -> PyResult<PyObject> {
fn to_pyarrow<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
let array = FFI_ArrowArray::new(self);
let schema = FFI_ArrowSchema::try_from(self.data_type()).map_err(to_py_err)?;

Expand All @@ -316,7 +316,7 @@ impl ToPyArrow for ArrayData {
addr_of!(schema) as Py_uintptr_t,
),
)?;
Ok(array.unbind())
Ok(array)
}
}

Expand All @@ -328,12 +328,12 @@ impl<T: FromPyArrow> FromPyArrow for Vec<T> {
}

impl<T: ToPyArrow> ToPyArrow for Vec<T> {
fn to_pyarrow(&self, py: Python) -> PyResult<PyObject> {
fn to_pyarrow<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
let values = self
.iter()
.map(|v| v.to_pyarrow(py))
.collect::<PyResult<Vec<_>>>()?;
Ok(PyList::new(py, values)?.unbind().into())
Ok(PyList::new(py, values)?.into_any())
}
}

Expand Down Expand Up @@ -412,12 +412,12 @@ impl FromPyArrow for RecordBatch {
}

impl ToPyArrow for RecordBatch {
fn to_pyarrow(&self, py: Python) -> PyResult<PyObject> {
fn to_pyarrow<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
// Workaround apache/arrow#37669 by returning RecordBatchIterator
let reader = RecordBatchIterator::new(vec![Ok(self.clone())], self.schema());
let reader: Box<dyn RecordBatchReader + Send> = Box::new(reader);
let py_reader = reader.into_pyarrow(py)?;
py_reader.call_method0(py, "read_next_batch")
py_reader.call_method0("read_next_batch")
}
}

Expand Down Expand Up @@ -463,7 +463,7 @@ impl FromPyArrow for ArrowArrayStreamReader {
impl IntoPyArrow for Box<dyn RecordBatchReader + Send> {
// We can't implement `ToPyArrow` for `T: RecordBatchReader + Send` because
// there is already a blanket implementation for `T: ToPyArrow`.
fn into_pyarrow(self, py: Python) -> PyResult<PyObject> {
fn into_pyarrow<'py>(self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
let mut stream = FFI_ArrowArrayStream::new(self);

let stream_ptr = (&mut stream) as *mut FFI_ArrowArrayStream;
Expand All @@ -472,13 +472,13 @@ impl IntoPyArrow for Box<dyn RecordBatchReader + Send> {
let args = PyTuple::new(py, [stream_ptr as Py_uintptr_t])?;
let reader = class.call_method1("_import_from_c", args)?;

Ok(PyObject::from(reader))
Ok(reader)
}
}

/// Convert a [`ArrowArrayStreamReader`] into a `pyarrow.RecordBatchReader`.
impl IntoPyArrow for ArrowArrayStreamReader {
fn into_pyarrow(self, py: Python) -> PyResult<PyObject> {
fn into_pyarrow<'py>(self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
let boxed: Box<dyn RecordBatchReader + Send> = Box::new(self);
boxed.into_pyarrow(py)
}
Expand Down Expand Up @@ -506,10 +506,7 @@ impl<'py, T: IntoPyArrow> IntoPyObject<'py> for PyArrowType<T> {
type Error = PyErr;

fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, PyErr> {
match self.0.into_pyarrow(py) {
Ok(obj) => Result::Ok(obj.into_bound(py)),
Err(err) => Result::Err(err),
}
self.0.into_pyarrow(py)
}
}

Expand Down
Loading