Skip to content

Commit e9ab6bd

Browse files
committed
Return &PyArray instead of PyArray, in all APIs
1 parent d4a7610 commit e9ab6bd

File tree

2 files changed

+53
-26
lines changed

2 files changed

+53
-26
lines changed

src/array.rs

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,13 @@ impl<T> PyArray<T> {
5959
}
6060

6161
/// Constructs `PyArray` from raw python object without incrementing reference counts.
62-
pub unsafe fn from_owned_ptr(py: Python, ptr: *mut pyo3::ffi::PyObject) -> Self {
63-
let obj = PyObject::from_owned_ptr(py, ptr);
64-
PyArray(obj, PhantomData)
62+
pub unsafe fn from_owned_ptr(py: Python, ptr: *mut pyo3::ffi::PyObject) -> &Self {
63+
py.from_owned_ptr(ptr)
6564
}
6665

6766
/// Constructs PyArray from raw python object and increments reference counts.
68-
pub unsafe fn from_borrowed_ptr(py: Python, ptr: *mut pyo3::ffi::PyObject) -> Self {
69-
let obj = PyObject::from_borrowed_ptr(py, ptr);
70-
PyArray(obj, PhantomData)
67+
pub unsafe fn from_borrowed_ptr(py: Python, ptr: *mut pyo3::ffi::PyObject) -> &Self {
68+
py.from_owned_ptr(ptr)
7169
}
7270

7371
/// Returns the number of dimensions in the array.
@@ -162,7 +160,7 @@ impl<T: TypeNum> PyArray<T> {
162160
/// assert_eq!(pyarray.as_slice().unwrap(), &[1, 2, 3, 4, 5]);
163161
/// # }
164162
/// ```
165-
pub fn from_boxed_slice(py: Python, v: Box<[T]>) -> PyArray<T> {
163+
pub fn from_boxed_slice(py: Python, v: Box<[T]>) -> &Self {
166164
IntoPyArray::into_pyarray(v, py)
167165
}
168166

@@ -180,7 +178,7 @@ impl<T: TypeNum> PyArray<T> {
180178
/// assert_eq!(pyarray.as_slice().unwrap(), &[1, 2, 3, 4, 5]);
181179
/// # }
182180
/// ```
183-
pub fn from_iter(py: Python, i: impl IntoIterator<Item = T>) -> PyArray<T> {
181+
pub fn from_iter(py: Python, i: impl IntoIterator<Item = T>) -> &Self {
184182
i.into_iter().collect::<Vec<_>>().into_pyarray(py)
185183
}
186184

@@ -196,7 +194,7 @@ impl<T: TypeNum> PyArray<T> {
196194
/// assert_eq!(pyarray.as_slice().unwrap(), &[1, 2, 3, 4, 5]);
197195
/// # }
198196
/// ```
199-
pub fn from_vec(py: Python, v: Vec<T>) -> PyArray<T> {
197+
pub fn from_vec(py: Python, v: Vec<T>) -> &Self {
200198
IntoPyArray::into_pyarray(v, py)
201199
}
202200

@@ -217,7 +215,7 @@ impl<T: TypeNum> PyArray<T> {
217215
/// assert!(PyArray::from_vec2(gil.python(), &np, &vec![vec![1], vec![2, 3]]).is_err());
218216
/// # }
219217
/// ```
220-
pub fn from_vec2(py: Python, v: &Vec<Vec<T>>) -> Result<PyArray<T>, ArrayCastError> {
218+
pub fn from_vec2<'py>(py: Python<'py>, v: &Vec<Vec<T>>) -> Result<&'py Self, ArrayCastError> {
221219
let last_len = v.last().map_or(0, |v| v.len());
222220
if v.iter().any(|v| v.len() != last_len) {
223221
return Err(ArrayCastError::FromVec);
@@ -250,7 +248,10 @@ impl<T: TypeNum> PyArray<T> {
250248
/// assert!(PyArray::from_vec3(gil.python(), &np, &vec![vec![vec![1], vec![]]]).is_err());
251249
/// # }
252250
/// ```
253-
pub fn from_vec3(py: Python, v: &Vec<Vec<Vec<T>>>) -> Result<PyArray<T>, ArrayCastError> {
251+
pub fn from_vec3<'py>(
252+
py: Python<'py>,
253+
v: &Vec<Vec<Vec<T>>>,
254+
) -> Result<&'py PyArray<T>, ArrayCastError> {
254255
let dim2 = v.last().map_or(0, |v| v.len());
255256
if v.iter().any(|v| v.len() != dim2) {
256257
return Err(ArrayCastError::FromVec);
@@ -279,7 +280,7 @@ impl<T: TypeNum> PyArray<T> {
279280
/// assert_eq!(pyarray.as_array().unwrap(), array![[1, 2], [3, 4]].into_dyn());
280281
/// # }
281282
/// ```
282-
pub fn from_ndarray<D>(py: Python, arr: Array<T, D>) -> PyArray<T>
283+
pub fn from_ndarray<D>(py: Python, arr: Array<T, D>) -> &Self
283284
where
284285
D: Dimension,
285286
{
@@ -356,12 +357,12 @@ impl<T: TypeNum> PyArray<T> {
356357
/// Construct a new PyArray given a raw pointer and dimensions.
357358
///
358359
/// Please use `new` or from methods instead.
359-
pub unsafe fn new_(
360-
py: Python,
360+
pub unsafe fn new_<'py>(
361+
py: Python<'py>,
361362
dims: &[usize],
362363
strides: *mut npy_intp,
363364
data: *mut c_void,
364-
) -> Self {
365+
) -> &'py Self {
365366
let dims: Vec<_> = dims.iter().map(|d| *d as npy_intp).collect();
366367
let ptr = PyArrayAPI.PyArray_New(
367368
PyArrayAPI.get_type_object(npyffi::ArrayType::PyArray_Type),
@@ -391,7 +392,7 @@ impl<T: TypeNum> PyArray<T> {
391392
/// assert_eq!(pyarray.shape(), &[4, 5, 6]);
392393
/// # }
393394
/// ```
394-
pub fn new(py: Python, dims: &[usize]) -> Self {
395+
pub fn new<'py>(py: Python<'py>, dims: &[usize]) -> &'py Self {
395396
unsafe { Self::new_(py, dims, null_mut(), null_mut()) }
396397
}
397398

@@ -410,7 +411,7 @@ impl<T: TypeNum> PyArray<T> {
410411
/// assert_eq!(pyarray.as_array().unwrap(), array![[0, 0], [0, 0]].into_dyn());
411412
/// # }
412413
/// ```
413-
pub fn zeros(py: Python, dims: &[usize], is_fortran: bool) -> Self {
414+
pub fn zeros<'py>(py: Python<'py>, dims: &[usize], is_fortran: bool) -> &'py Self {
414415
let dims: Vec<npy_intp> = dims.iter().map(|d| *d as npy_intp).collect();
415416
unsafe {
416417
let descr = PyArrayAPI.PyArray_DescrFromType(T::typenum_default());
@@ -440,7 +441,7 @@ impl<T: TypeNum> PyArray<T> {
440441
/// let pyarray = PyArray::<i32>::arange(gil.python(), &np, -2.0, 4.0, 3.0);
441442
/// assert_eq!(pyarray.as_slice().unwrap(), &[-2, 1]);
442443
/// # }
443-
pub fn arange(py: Python, start: f64, stop: f64, step: f64) -> Self {
444+
pub fn arange<'py>(py: Python<'py>, start: f64, stop: f64, step: f64) -> &'py Self {
444445
unsafe {
445446
let ptr = PyArrayAPI.PyArray_Arange(start, stop, step, T::typenum_default());
446447
Self::from_owned_ptr(py, ptr)
@@ -473,6 +474,32 @@ impl<T: TypeNum> PyArray<T> {
473474
}
474475
}
475476

477+
/// Move the data of self into `other`, performing a data-type conversion if necessary.
478+
/// # Example
479+
/// ```
480+
/// # extern crate pyo3; extern crate numpy; fn main() {
481+
/// use numpy::{PyArray, PyArrayModule, IntoPyArray};
482+
/// let gil = pyo3::Python::acquire_gil();
483+
/// let np = PyArrayModule::import(gil.python()).unwrap();
484+
/// let pyarray_f = PyArray::<f64>::arange(gil.python(), &np, 2.0, 5.0, 1.0);
485+
/// let mut pyarray_i = PyArray::<i64>::new(gil.python(), &np, &[3]);
486+
/// assert!(pyarray_f.move_to(&np, &mut pyarray_i).is_ok());
487+
/// assert_eq!(pyarray_i.as_slice().unwrap(), &[2, 3, 4]);
488+
/// # }
489+
pub fn move_to<U: TypeNum>(&self, other: &mut PyArray<U>) -> Result<(), ArrayCastError> {
490+
let self_ptr = self.as_array_ptr();
491+
let other_ptr = other.as_array_ptr();
492+
let result = unsafe { PyArrayAPI.PyArray_MoveInto(other_ptr, self_ptr) };
493+
if result == -1 {
494+
Err(ArrayCastError::Numpy {
495+
from: T::npy_data_type(),
496+
to: U::npy_data_type(),
497+
})
498+
} else {
499+
Ok(())
500+
}
501+
}
502+
476503
/// Cast the `PyArray<T>` to `PyArray<U>`, by allocating a new array.
477504
/// # Example
478505
/// ```
@@ -484,11 +511,11 @@ impl<T: TypeNum> PyArray<T> {
484511
/// let pyarray_i = pyarray_f.cast::<i32>(gil.python(), &np, false).unwrap();
485512
/// assert_eq!(pyarray_i.as_slice().unwrap(), &[2, 3, 4]);
486513
/// # }
487-
pub fn cast<U: TypeNum>(
514+
pub fn cast<'py, U: TypeNum>(
488515
&self,
489-
py: Python,
516+
py: Python<'py>,
490517
is_fortran: bool,
491-
) -> Result<PyArray<U>, ArrayCastError> {
518+
) -> Result<&'py PyArray<U>, ArrayCastError> {
492519
let ptr = unsafe {
493520
let descr = PyArrayAPI.PyArray_DescrFromType(U::typenum_default());
494521
PyArrayAPI.PyArray_CastToType(

src/convert.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ use super::*;
2424
/// ```
2525
pub trait IntoPyArray {
2626
type Item: TypeNum;
27-
fn into_pyarray(self, Python) -> PyArray<Self::Item>;
27+
fn into_pyarray(self, Python) -> &PyArray<Self::Item>;
2828
}
2929

3030
impl<T: TypeNum> IntoPyArray for Box<[T]> {
3131
type Item = T;
32-
fn into_pyarray(self, py: Python) -> PyArray<Self::Item> {
32+
fn into_pyarray(self, py: Python) -> &PyArray<Self::Item> {
3333
let dims = [self.len()];
3434
let ptr = Box::into_raw(self);
3535
unsafe { PyArray::new_(py, &dims, null_mut(), ptr as *mut c_void) }
@@ -38,15 +38,15 @@ impl<T: TypeNum> IntoPyArray for Box<[T]> {
3838

3939
impl<T: TypeNum> IntoPyArray for Vec<T> {
4040
type Item = T;
41-
fn into_pyarray(self, py: Python) -> PyArray<Self::Item> {
41+
fn into_pyarray(self, py: Python) -> &PyArray<Self::Item> {
4242
let dims = [self.len()];
4343
unsafe { PyArray::new_(py, &dims, null_mut(), into_raw(self)) }
4444
}
4545
}
4646

4747
impl<A: TypeNum, D: Dimension> IntoPyArray for Array<A, D> {
4848
type Item = A;
49-
fn into_pyarray(self, py: Python) -> PyArray<Self::Item> {
49+
fn into_pyarray(self, py: Python) -> &PyArray<Self::Item> {
5050
let dims: Vec<_> = self.shape().iter().cloned().collect();
5151
let mut strides: Vec<_> = self
5252
.strides()
@@ -65,7 +65,7 @@ macro_rules! array_impls {
6565
$(
6666
impl<T: TypeNum> IntoPyArray for [T; $N] {
6767
type Item = T;
68-
fn into_pyarray(self, py: Python) -> PyArray<T> {
68+
fn into_pyarray(self, py: Python) -> &PyArray<T> {
6969
let dims = [$N];
7070
let ptr = Box::into_raw(Box::new(self));
7171
unsafe {

0 commit comments

Comments
 (0)