@@ -19,14 +19,12 @@ use pyo3::{
19
19
Python , ToPyObject ,
20
20
} ;
21
21
22
+ use crate :: borrow:: { PyReadonlyArray , PyReadwriteArray } ;
22
23
use crate :: cold;
23
24
use crate :: convert:: { ArrayExt , IntoPyArray , NpyIndex , ToNpyDims , ToPyArray } ;
24
25
use crate :: dtype:: { Element , PyArrayDescr } ;
25
26
use crate :: error:: { DimensionalityError , FromVecError , NotContiguousError , TypeError } ;
26
27
use crate :: npyffi:: { self , npy_intp, NPY_ORDER , PY_ARRAY_API } ;
27
- #[ allow( deprecated) ]
28
- use crate :: npyiter:: { NpySingleIter , NpySingleIterBuilder , ReadWrite } ;
29
- use crate :: readonly:: PyReadonlyArray ;
30
28
use crate :: slice_container:: PySliceContainer ;
31
29
32
30
/// A safe, static-typed interface for
@@ -195,18 +193,8 @@ impl<T, D> PyArray<T, D> {
195
193
}
196
194
197
195
#[ inline( always) ]
198
- fn check_flag ( & self , flag : c_int ) -> bool {
199
- unsafe { * self . as_array_ptr ( ) } . flags & flag == flag
200
- }
201
-
202
- #[ inline( always) ]
203
- pub ( crate ) fn get_flag ( & self ) -> c_int {
204
- unsafe { * self . as_array_ptr ( ) } . flags
205
- }
206
-
207
- /// Returns a temporally unwriteable reference of the array.
208
- pub fn readonly ( & self ) -> PyReadonlyArray < T , D > {
209
- self . into ( )
196
+ pub ( crate ) fn check_flags ( & self , flags : c_int ) -> bool {
197
+ unsafe { * self . as_array_ptr ( ) } . flags & flags != 0
210
198
}
211
199
212
200
/// Returns `true` if the internal data of the array is C-style contiguous
@@ -228,18 +216,17 @@ impl<T, D> PyArray<T, D> {
228
216
/// });
229
217
/// ```
230
218
pub fn is_contiguous ( & self ) -> bool {
231
- self . check_flag ( npyffi:: NPY_ARRAY_C_CONTIGUOUS )
232
- | self . check_flag ( npyffi:: NPY_ARRAY_F_CONTIGUOUS )
219
+ self . check_flags ( npyffi:: NPY_ARRAY_C_CONTIGUOUS | npyffi:: NPY_ARRAY_F_CONTIGUOUS )
233
220
}
234
221
235
222
/// Returns `true` if the internal data of the array is Fortran-style contiguous.
236
223
pub fn is_fortran_contiguous ( & self ) -> bool {
237
- self . check_flag ( npyffi:: NPY_ARRAY_F_CONTIGUOUS )
224
+ self . check_flags ( npyffi:: NPY_ARRAY_F_CONTIGUOUS )
238
225
}
239
226
240
227
/// Returns `true` if the internal data of the array is C-style contiguous.
241
228
pub fn is_c_contiguous ( & self ) -> bool {
242
- self . check_flag ( npyffi:: NPY_ARRAY_C_CONTIGUOUS )
229
+ self . check_flags ( npyffi:: NPY_ARRAY_C_CONTIGUOUS )
243
230
}
244
231
245
232
/// Get `Py<PyArray>` from `&PyArray`, which is the owned wrapper of PyObject.
@@ -681,27 +668,61 @@ impl<T: Element, D: Dimension> PyArray<T, D> {
681
668
682
669
/// Get the immutable reference of the specified element, with checking the passed index is valid.
683
670
///
684
- /// Please consider the use of safe alternatives
685
- /// ([`PyReadonlyArray::get`](../struct.PyReadonlyArray.html#method.get)
686
- /// or [`get_owned`](#method.get_owned)) instead of this.
671
+ /// Consider using safe alternatives like [`PyReadonlyArray::get`].
672
+ ///
687
673
/// # Example
674
+ ///
688
675
/// ```
689
676
/// use numpy::PyArray;
690
- /// pyo3::Python::with_gil(|py| {
677
+ /// use pyo3::Python;
678
+ ///
679
+ /// Python::with_gil(|py| {
691
680
/// let arr = PyArray::arange(py, 0, 16, 1).reshape([2, 2, 4]).unwrap();
692
- /// assert_eq!(* unsafe { arr.get([1, 0, 3]) } .unwrap(), 11);
681
+ /// assert_eq!(unsafe { * arr.get([1, 0, 3]).unwrap() } , 11);
693
682
/// });
694
683
/// ```
695
684
///
696
685
/// # Safety
697
- /// If the internal array is not readonly and can be mutated from Python code,
698
- /// holding the slice might cause undefined behavior.
686
+ ///
687
+ /// Calling this method is undefined behaviour if the underlying array
688
+ /// is aliased mutably by other instances of `PyArray`
689
+ /// or concurrently modified by Python or other native code.
699
690
#[ inline( always) ]
700
691
pub unsafe fn get ( & self , index : impl NpyIndex < Dim = D > ) -> Option < & T > {
701
692
let offset = index. get_checked :: < T > ( self . shape ( ) , self . strides ( ) ) ?;
702
693
Some ( & * self . data ( ) . offset ( offset) )
703
694
}
704
695
696
+ /// Same as [`get`][Self::get], but returns `Option<&mut T>`.
697
+ ///
698
+ /// Consider using safe alternatives like [`PyReadwriteArray::get_mut`].
699
+ ///
700
+ /// # Example
701
+ ///
702
+ /// ```
703
+ /// use numpy::PyArray;
704
+ /// use pyo3::Python;
705
+ ///
706
+ /// Python::with_gil(|py| {
707
+ /// let arr = PyArray::arange(py, 0, 16, 1).reshape([2, 2, 4]).unwrap();
708
+ /// unsafe {
709
+ /// *arr.get_mut([1, 0, 3]).unwrap() = 42;
710
+ /// }
711
+ /// assert_eq!(unsafe { *arr.get([1, 0, 3]).unwrap() }, 42);
712
+ /// });
713
+ /// ```
714
+ ///
715
+ /// # Safety
716
+ ///
717
+ /// Calling this method is undefined behaviour if the underlying array
718
+ /// is aliased immutably by mutably by other instances of `PyArray`
719
+ /// or concurrently modified by Python or other native code.
720
+ #[ inline( always) ]
721
+ pub unsafe fn get_mut ( & self , index : impl NpyIndex < Dim = D > ) -> Option < & mut T > {
722
+ let offset = index. get_checked :: < T > ( self . shape ( ) , self . strides ( ) ) ?;
723
+ Some ( & mut * self . data ( ) . offset ( offset) )
724
+ }
725
+
705
726
/// Get the immutable reference of the specified element, without checking the
706
727
/// passed index is valid.
707
728
///
@@ -824,28 +845,37 @@ impl<T: Element, D: Dimension> PyArray<T, D> {
824
845
ToPyArray :: to_pyarray ( arr, py)
825
846
}
826
847
827
- /// Get the immutable view of the internal data of `PyArray`, as
828
- /// [`ndarray::ArrayView`](https://docs.rs/ndarray/latest/ndarray/type.ArrayView.html).
848
+ /// Get an immutable borrow of the NumPy array
849
+ pub fn readonly ( & self ) -> PyReadonlyArray < ' _ , T , D > {
850
+ PyReadonlyArray :: try_new ( self ) . unwrap ( )
851
+ }
852
+
853
+ /// Get a mutable borrow of the NumPy array
854
+ pub fn readwrite ( & self ) -> PyReadwriteArray < ' _ , T , D > {
855
+ PyReadwriteArray :: try_new ( self ) . unwrap ( )
856
+ }
857
+
858
+ /// Returns the internal array as [`ArrayView`].
829
859
///
830
- /// Please consider the use of safe alternatives
831
- /// ([`PyReadonlyArray::as_array`](../struct.PyReadonlyArray.html#method.as_array)
832
- /// or [`to_array`](#method.to_array)) instead of this.
860
+ /// See also [`PyReadonlyArray::as_array`].
833
861
///
834
862
/// # Safety
835
- /// If the internal array is not readonly and can be mutated from Python code,
836
- /// holding the `ArrayView` might cause undefined behavior.
863
+ ///
864
+ /// The existence of an exclusive reference to the internal data, e.g. `&mut [T]` or `ArrayViewMut`, implies undefined behavior.
837
865
pub unsafe fn as_array ( & self ) -> ArrayView < ' _ , T , D > {
838
866
let ( shape, ptr, inverted_axes) = self . ndarray_shape_ptr ( ) ;
839
867
let mut res = ArrayView :: from_shape_ptr ( shape, ptr) ;
840
868
inverted_axes. invert ( & mut res) ;
841
869
res
842
870
}
843
871
844
- /// Returns the internal array as [`ArrayViewMut`]. See also [`as_array`](#method.as_array).
872
+ /// Returns the internal array as [`ArrayViewMut`].
873
+ ///
874
+ /// See also [`PyReadwriteArray::as_array_mut`].
845
875
///
846
876
/// # Safety
847
- /// If another reference to the internal data exists(e.g., `&[T]` or `ArrayView`),
848
- /// it might cause undefined behavior.
877
+ ///
878
+ /// The existence of another reference to the internal data, e.g. `&[T]` or `ArrayView`, implies undefined behavior.
849
879
pub unsafe fn as_array_mut ( & self ) -> ArrayViewMut < ' _ , T , D > {
850
880
let ( shape, ptr, inverted_axes) = self . ndarray_shape_ptr ( ) ;
851
881
let mut res = ArrayViewMut :: from_shape_ptr ( shape, ptr) ;
@@ -921,7 +951,7 @@ impl<D: Dimension> PyArray<PyObject, D> {
921
951
///
922
952
/// let pyarray = PyArray::from_owned_object_array(py, array);
923
953
///
924
- /// assert!(pyarray.readonly().get(0).unwrap().as_ref(py).is_instance_of::<CustomElement>().unwrap());
954
+ /// assert!(pyarray.readonly().as_array(). get(0).unwrap().as_ref(py).is_instance_of::<CustomElement>().unwrap());
925
955
/// });
926
956
/// ```
927
957
pub fn from_owned_object_array < ' py , T > ( py : Python < ' py > , arr : Array < Py < T > , D > ) -> & ' py Self {
@@ -1043,21 +1073,6 @@ impl<T: Element> PyArray<T, Ix1> {
1043
1073
self . resize_ ( self . py ( ) , [ new_elems] , 1 , NPY_ORDER :: NPY_ANYORDER )
1044
1074
}
1045
1075
1046
- /// Iterates all elements of this array.
1047
- /// See [NpySingleIter](../npyiter/struct.NpySingleIter.html) for more.
1048
- ///
1049
- /// # Safety
1050
- ///
1051
- /// The iterator will produce mutable references into the array which must not be
1052
- /// aliased by other references for the life time of the iterator.
1053
- #[ deprecated(
1054
- note = "The wrappers of the array iterator API are deprecated, please use ndarray's `ArrayBase::iter_mut` instead."
1055
- ) ]
1056
- #[ allow( deprecated) ]
1057
- pub unsafe fn iter < ' py > ( & ' py self ) -> PyResult < NpySingleIter < ' py , T , ReadWrite > > {
1058
- NpySingleIterBuilder :: readwrite ( self ) . build ( )
1059
- }
1060
-
1061
1076
fn resize_ < D : IntoDimension > (
1062
1077
& self ,
1063
1078
py : Python ,
0 commit comments