Skip to content

Commit 9c6244b

Browse files
committed
Give PyArray<PyObject> another try.
1 parent 29f2737 commit 9c6244b

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

src/dtype.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,9 @@ impl DataType {
179179
///
180180
/// A type `T` that implements this trait should be safe when managed in numpy array,
181181
/// thus implementing this trait is marked unsafe.
182-
/// For example, we don't support `PyObject` because of [an odd segfault](https://github.com/PyO3/rust-numpy/pull/143),
183-
/// although numpy itself supports it.
182+
/// This means that all data types except for `DataType::Object` are assumed to be trivially copyable.
183+
/// Furthermore, it is assumed that for `DataType::Object` the elements are pointers into the Python heap
184+
/// and that the corresponding `Clone` implemenation will never panic as it only increases the reference count.
184185
pub unsafe trait Element: Clone + Send {
185186
/// `DataType` corresponding to this type.
186187
const DATA_TYPE: DataType;
@@ -246,3 +247,10 @@ cfg_if! {
246247
impl_num_element!(u64, Uint64, NPY_ULONG, NPY_ULONGLONG);
247248
}
248249
}
250+
251+
unsafe impl Element for PyObject {
252+
const DATA_TYPE: DataType = DataType::Object;
253+
fn is_same_type(dtype: &PyArrayDescr) -> bool {
254+
dtype.get_typenum() == NPY_TYPES::NPY_OBJECT as i32
255+
}
256+
}

tests/to_py.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,3 +169,26 @@ fn forder_into_pyarray() {
169169
pyo3::py_run!(py, fmat_py, "assert fmat_py.flags['F_CONTIGUOUS']")
170170
})
171171
}
172+
173+
#[test]
174+
fn to_pyarray_object_vec() {
175+
use pyo3::{
176+
types::{PyDict, PyString},
177+
ToPyObject,
178+
};
179+
use std::cmp::Ordering;
180+
181+
pyo3::Python::with_gil(|py| {
182+
let dict = PyDict::new(py);
183+
let string = PyString::new(py, "Hello:)");
184+
let vec = vec![dict.to_object(py), string.to_object(py)];
185+
let arr = vec.to_pyarray(py).readonly();
186+
187+
for (a, b) in vec.iter().zip(arr.as_slice().unwrap().iter()) {
188+
assert_eq!(
189+
a.as_ref(py).compare(b).map_err(|e| e.print(py)).unwrap(),
190+
Ordering::Equal
191+
);
192+
}
193+
})
194+
}

0 commit comments

Comments
 (0)