From 92f24b915785495a079cd249439962976665b51d Mon Sep 17 00:00:00 2001 From: Minh Vu Date: Sun, 21 Jun 2026 20:44:46 +0200 Subject: [PATCH] fix: return error for nullable PyArrow structs --- arrow-pyarrow-testing/tests/pyarrow.rs | 33 ++++++++++++++++++++++++-- arrow-pyarrow/src/lib.rs | 10 ++++---- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/arrow-pyarrow-testing/tests/pyarrow.rs b/arrow-pyarrow-testing/tests/pyarrow.rs index 6f3606478c72..42324aefcf5a 100644 --- a/arrow-pyarrow-testing/tests/pyarrow.rs +++ b/arrow-pyarrow-testing/tests/pyarrow.rs @@ -42,9 +42,9 @@ use arrow_array::{ Array, ArrayRef, BinaryViewArray, Int32Array, RecordBatch, StringArray, StringViewArray, }; use arrow_pyarrow::{FromPyArrow, ToPyArrow}; -use pyo3::exceptions::PyTypeError; -use pyo3::types::{PyAnyMethods, PyModule}; use pyo3::Python; +use pyo3::exceptions::{PyTypeError, PyValueError}; +use pyo3::types::{PyAnyMethods, PyModule}; use std::ffi::CString; use std::sync::Arc; @@ -125,6 +125,35 @@ value = NotATuple() }); } +#[test] +fn test_from_pyarrow_nullable_struct_array() { + Python::initialize(); + + Python::attach(|py| { + let code = CString::new( + r#" +import pyarrow as pa + +value = pa.array( + [{"a": 1}, None], + type=pa.struct([pa.field("a", pa.int32())]), +) +"#, + ) + .unwrap(); + + let module = PyModule::from_code(py, code.as_c_str(), c"test.py", c"test_module").unwrap(); + let value = module.getattr("value").unwrap(); + + let err = RecordBatch::from_pyarrow_bound(&value).unwrap_err(); + assert!(err.is_instance_of::(py)); + assert_eq!( + err.to_string(), + "ValueError: Cannot convert nullable StructArray to RecordBatch, see StructArray documentation" + ); + }); +} + fn binary_view_column(num_variadic_buffers: usize) -> BinaryViewArray { let long_scalar = b"but soft what light through yonder window breaks".as_slice(); let mut builder = BinaryViewBuilder::new().with_fixed_block_size(long_scalar.len() as u32); diff --git a/arrow-pyarrow/src/lib.rs b/arrow-pyarrow/src/lib.rs index c0d91d081113..c6038bc49866 100644 --- a/arrow-pyarrow/src/lib.rs +++ b/arrow-pyarrow/src/lib.rs @@ -369,11 +369,11 @@ impl FromPyArrow for RecordBatch { let schema = unsafe { Arc::new(Schema::try_from(schema_ptr.as_ref()).map_err(to_py_err)?) }; let (_fields, columns, nulls) = array.into_parts(); - assert_eq!( - nulls.map(|n| n.null_count()).unwrap_or_default(), - 0, - "Cannot convert nullable StructArray to RecordBatch, see StructArray documentation" - ); + if nulls.map(|n| n.null_count()).unwrap_or_default() != 0 { + return Err(PyValueError::new_err( + "Cannot convert nullable StructArray to RecordBatch, see StructArray documentation", + )); + } return RecordBatch::try_new_with_options(schema, columns, &options).map_err(to_py_err); }