Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migrate PyArray contructors to Bound API (Part 1) #416

Merged
merged 5 commits into from
Mar 25, 2024
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
162 changes: 115 additions & 47 deletions src/array.rs

Large diffs are not rendered by default.

44 changes: 22 additions & 22 deletions src/borrow/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
//! ```rust
//! # use std::panic::{catch_unwind, AssertUnwindSafe};
//! #
//! use numpy::PyArray1;
//! use numpy::{PyArray1, PyArrayMethods};
//! use ndarray::Zip;
//! use pyo3::Python;
//! use pyo3::{Python, Bound};
//!
//! fn add(x: &PyArray1<f64>, y: &PyArray1<f64>, z: &PyArray1<f64>) {
//! fn add(x: &Bound<'_, PyArray1<f64>>, y: &Bound<'_, PyArray1<f64>>, z: &Bound<'_, PyArray1<f64>>) {
//! let x1 = x.readonly();
//! let y1 = y.readonly();
//! let mut z1 = z.readwrite();
Expand All @@ -41,19 +41,19 @@
//! }
//!
//! Python::with_gil(|py| {
//! let x = PyArray1::<f64>::zeros(py, 42, false);
//! let y = PyArray1::<f64>::zeros(py, 42, false);
//! let z = PyArray1::<f64>::zeros(py, 42, false);
//! let x = PyArray1::<f64>::zeros_bound(py, 42, false);
//! let y = PyArray1::<f64>::zeros_bound(py, 42, false);
//! let z = PyArray1::<f64>::zeros_bound(py, 42, false);
//!
//! // Will work as the three arrays are distinct.
//! add(x, y, z);
//! add(&x, &y, &z);
//!
//! // Will work as `x1` and `y1` are compatible borrows.
//! add(x, x, z);
//! add(&x, &x, &z);
//!
//! // Will fail at runtime due to conflict between `y1` and `z1`.
//! let res = catch_unwind(AssertUnwindSafe(|| {
//! add(x, y, y);
//! add(&x, &y, &y);
//! }));
//! assert!(res.is_err());
//! });
Expand Down Expand Up @@ -91,15 +91,15 @@
//! ```rust
//! # use std::panic::{catch_unwind, AssertUnwindSafe};
//! #
//! use numpy::PyArray2;
//! use pyo3::{types::IntoPyDict, Python};
//! use numpy::{PyArray2, PyArrayMethods};
//! use pyo3::{types::{IntoPyDict, PyAnyMethods}, Python};
//!
//! Python::with_gil(|py| {
//! let array = PyArray2::<f64>::zeros(py, (10, 10), false);
//! let locals = [("array", array)].into_py_dict(py);
//! let array = PyArray2::<f64>::zeros_bound(py, (10, 10), false);
//! let locals = [("array", array)].into_py_dict_bound(py);
//!
//! let view1 = py.eval("array[:, ::3]", None, Some(locals)).unwrap().downcast::<PyArray2<f64>>().unwrap();
//! let view2 = py.eval("array[:, 1::3]", None, Some(locals)).unwrap().downcast::<PyArray2<f64>>().unwrap();
//! let view1 = py.eval_bound("array[:, ::3]", None, Some(&locals)).unwrap().downcast_into::<PyArray2<f64>>().unwrap();
//! let view2 = py.eval_bound("array[:, 1::3]", None, Some(&locals)).unwrap().downcast_into::<PyArray2<f64>>().unwrap();
//!
//! // A false conflict as the views do not actually share any elements.
//! let res = catch_unwind(AssertUnwindSafe(|| {
Expand Down Expand Up @@ -589,7 +589,7 @@ mod tests {
#[test]
fn test_debug_formatting() {
Python::with_gil(|py| {
let array = PyArray::<f64, _>::zeros(py, (1, 2, 3), false);
let array = PyArray::<f64, _>::zeros_bound(py, (1, 2, 3), false);

{
let shared = array.readonly();
Expand All @@ -615,7 +615,7 @@ mod tests {
#[should_panic(expected = "AlreadyBorrowed")]
fn cannot_clone_exclusive_borrow_via_deref() {
Python::with_gil(|py| {
let array = PyArray::<f64, _>::zeros(py, (3, 2, 1), false);
let array = PyArray::<f64, _>::zeros_bound(py, (3, 2, 1), false);

let exclusive = array.readwrite();
let _shared = exclusive.clone();
Expand All @@ -625,14 +625,14 @@ mod tests {
#[test]
fn failed_resize_does_not_double_release() {
Python::with_gil(|py| {
let array = PyArray::<f64, _>::zeros(py, 10, false);
let array = PyArray::<f64, _>::zeros_bound(py, 10, false);

// The view will make the internal reference check of `PyArray_Resize` fail.
let locals = [("array", array)].into_py_dict(py);
let locals = [("array", &array)].into_py_dict_bound(py);
let _view = py
.eval("array[:]", None, Some(locals))
.eval_bound("array[:]", None, Some(&locals))
.unwrap()
.downcast::<PyArray1<f64>>()
.downcast_into::<PyArray1<f64>>()
.unwrap();

let exclusive = array.readwrite();
Expand All @@ -643,7 +643,7 @@ mod tests {
#[test]
fn ineffective_resize_does_not_conflict() {
Python::with_gil(|py| {
let array = PyArray::<f64, _>::zeros(py, 10, false);
let array = PyArray::<f64, _>::zeros_bound(py, 10, false);

let exclusive = array.readwrite();
assert!(exclusive.resize(10).is_ok());
Expand Down
103 changes: 52 additions & 51 deletions src/borrow/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,8 +447,9 @@ mod tests {
use ndarray::Array;
use pyo3::types::IntoPyDict;

use crate::array::{PyArray, PyArray1, PyArray2, PyArray3};
use crate::array::{PyArray, PyArray1, PyArray2, PyArray3, PyArrayMethods};
use crate::convert::IntoPyArray;
use crate::untyped_array::PyUntypedArrayMethods;

fn get_borrow_flags<'py>(py: Python<'py>) -> &'py BorrowFlagsInner {
let shared = get_or_insert_shared(py).unwrap();
Expand All @@ -459,13 +460,13 @@ mod tests {
#[test]
fn without_base_object() {
Python::with_gil(|py| {
let array = PyArray::<f64, _>::zeros(py, (1, 2, 3), false);
let array = PyArray::<f64, _>::zeros_bound(py, (1, 2, 3), false);

let base = unsafe { (*array.as_array_ptr()).base };
assert!(base.is_null());

let base_address = base_address(py, array.as_array_ptr());
assert_eq!(base_address, array as *const _ as *mut c_void);
assert_eq!(base_address, array.as_ptr().cast());

let data_range = data_range(array.as_array_ptr());
assert_eq!(data_range.0, array.data() as *mut c_char);
Expand Down Expand Up @@ -494,25 +495,25 @@ mod tests {
#[test]
fn view_without_base_object() {
Python::with_gil(|py| {
let array = PyArray::<f64, _>::zeros(py, (1, 2, 3), false);
let array = PyArray::<f64, _>::zeros_bound(py, (1, 2, 3), false);

let locals = [("array", array)].into_py_dict(py);
let locals = [("array", &array)].into_py_dict_bound(py);
let view = py
.eval("array[:,:,0]", None, Some(locals))
.eval_bound("array[:,:,0]", None, Some(&locals))
.unwrap()
.downcast::<PyArray2<f64>>()
.downcast_into::<PyArray2<f64>>()
.unwrap();
assert_ne!(
view as *const _ as *mut c_void,
array as *const _ as *mut c_void
view.as_ptr().cast::<c_void>(),
array.as_ptr().cast::<c_void>()
);

let base = unsafe { (*view.as_array_ptr()).base };
assert_eq!(base as *mut c_void, array as *const _ as *mut c_void);
assert_eq!(base as *mut c_void, array.as_ptr().cast::<c_void>());

let base_address = base_address(py, view.as_array_ptr());
assert_ne!(base_address, view as *const _ as *mut c_void);
assert_eq!(base_address, base as *mut c_void);
assert_ne!(base_address, view.as_ptr().cast::<c_void>());
assert_eq!(base_address, base.cast::<c_void>());

let data_range = data_range(view.as_array_ptr());
assert_eq!(data_range.0, array.data() as *mut c_char);
Expand Down Expand Up @@ -556,43 +557,43 @@ mod tests {
#[test]
fn view_of_view_without_base_object() {
Python::with_gil(|py| {
let array = PyArray::<f64, _>::zeros(py, (1, 2, 3), false);
let array = PyArray::<f64, _>::zeros_bound(py, (1, 2, 3), false);

let locals = [("array", array)].into_py_dict(py);
let locals = [("array", &array)].into_py_dict_bound(py);
let view1 = py
.eval("array[:,:,0]", None, Some(locals))
.eval_bound("array[:,:,0]", None, Some(&locals))
.unwrap()
.downcast::<PyArray2<f64>>()
.downcast_into::<PyArray2<f64>>()
.unwrap();
assert_ne!(
view1 as *const _ as *mut c_void,
array as *const _ as *mut c_void
view1.as_ptr().cast::<c_void>(),
array.as_ptr().cast::<c_void>()
);

let locals = [("view1", view1)].into_py_dict(py);
let locals = [("view1", &view1)].into_py_dict(py);
let view2 = py
.eval("view1[:,0]", None, Some(locals))
.unwrap()
.downcast::<PyArray1<f64>>()
.unwrap();
assert_ne!(
view2 as *const _ as *mut c_void,
array as *const _ as *mut c_void
view2.as_ptr().cast::<c_void>(),
array.as_ptr().cast::<c_void>()
);
assert_ne!(
view2 as *const _ as *mut c_void,
view1 as *const _ as *mut c_void
view2.as_ptr().cast::<c_void>(),
view1.as_ptr().cast::<c_void>()
);

let base = unsafe { (*view2.as_array_ptr()).base };
assert_eq!(base as *mut c_void, array as *const _ as *mut c_void);
assert_eq!(base as *mut c_void, array.as_ptr().cast::<c_void>());

let base = unsafe { (*view1.as_array_ptr()).base };
assert_eq!(base as *mut c_void, array as *const _ as *mut c_void);
assert_eq!(base as *mut c_void, array.as_ptr().cast::<c_void>());

let base_address = base_address(py, view2.as_array_ptr());
assert_ne!(base_address, view2 as *const _ as *mut c_void);
assert_ne!(base_address, view1 as *const _ as *mut c_void);
assert_ne!(base_address, view2.as_ptr().cast::<c_void>());
assert_ne!(base_address, view1.as_ptr().cast::<c_void>());
assert_eq!(base_address, base as *mut c_void);

let data_range = data_range(view2.as_array_ptr());
Expand Down Expand Up @@ -656,25 +657,25 @@ mod tests {
#[test]
fn view_with_negative_strides() {
Python::with_gil(|py| {
let array = PyArray::<f64, _>::zeros(py, (1, 2, 3), false);
let array = PyArray::<f64, _>::zeros_bound(py, (1, 2, 3), false);

let locals = [("array", array)].into_py_dict(py);
let locals = [("array", &array)].into_py_dict_bound(py);
let view = py
.eval("array[::-1,:,::-1]", None, Some(locals))
.eval_bound("array[::-1,:,::-1]", None, Some(&locals))
.unwrap()
.downcast::<PyArray3<f64>>()
.downcast_into::<PyArray3<f64>>()
.unwrap();
assert_ne!(
view as *const _ as *mut c_void,
array as *const _ as *mut c_void
view.as_ptr().cast::<c_void>(),
array.as_ptr().cast::<c_void>()
);

let base = unsafe { (*view.as_array_ptr()).base };
assert_eq!(base as *mut c_void, array as *const _ as *mut c_void);
assert_eq!(base.cast::<c_void>(), array.as_ptr().cast::<c_void>());

let base_address = base_address(py, view.as_array_ptr());
assert_ne!(base_address, view as *const _ as *mut c_void);
assert_eq!(base_address, base as *mut c_void);
assert_ne!(base_address, view.as_ptr().cast::<c_void>());
assert_eq!(base_address, base.cast::<c_void>());

let data_range = data_range(view.as_array_ptr());
assert_eq!(view.data(), unsafe { array.data().offset(2) });
Expand All @@ -688,13 +689,13 @@ mod tests {
#[test]
fn array_with_zero_dimensions() {
Python::with_gil(|py| {
let array = PyArray::<f64, _>::zeros(py, (1, 0, 3), false);
let array = PyArray::<f64, _>::zeros_bound(py, (1, 0, 3), false);

let base = unsafe { (*array.as_array_ptr()).base };
assert!(base.is_null());

let base_address = base_address(py, array.as_array_ptr());
assert_eq!(base_address, array as *const _ as *mut c_void);
assert_eq!(base_address, array.as_ptr().cast::<c_void>());

let data_range = data_range(array.as_array_ptr());
assert_eq!(data_range.0, array.data() as *mut c_char);
Expand All @@ -705,13 +706,13 @@ mod tests {
#[test]
fn view_with_non_dividing_strides() {
Python::with_gil(|py| {
let array = PyArray::<f64, _>::zeros(py, (10, 10), false);
let locals = [("array", array)].into_py_dict(py);
let array = PyArray::<f64, _>::zeros_bound(py, (10, 10), false);
let locals = [("array", array)].into_py_dict_bound(py);

let view1 = py
.eval("array[:,::3]", None, Some(locals))
.eval_bound("array[:,::3]", None, Some(&locals))
.unwrap()
.downcast::<PyArray2<f64>>()
.downcast_into::<PyArray2<f64>>()
.unwrap();

let key1 = borrow_key(view1.as_array_ptr());
Expand All @@ -720,9 +721,9 @@ mod tests {
assert_eq!(key1.gcd_strides, 8);

let view2 = py
.eval("array[:,1::3]", None, Some(locals))
.eval_bound("array[:,1::3]", None, Some(&locals))
.unwrap()
.downcast::<PyArray2<f64>>()
.downcast_into::<PyArray2<f64>>()
.unwrap();

let key2 = borrow_key(view2.as_array_ptr());
Expand All @@ -731,9 +732,9 @@ mod tests {
assert_eq!(key2.gcd_strides, 8);

let view3 = py
.eval("array[:,::2]", None, Some(locals))
.eval_bound("array[:,::2]", None, Some(&locals))
.unwrap()
.downcast::<PyArray2<f64>>()
.downcast_into::<PyArray2<f64>>()
.unwrap();

let key3 = borrow_key(view3.as_array_ptr());
Expand All @@ -742,9 +743,9 @@ mod tests {
assert_eq!(key3.gcd_strides, 16);

let view4 = py
.eval("array[:,1::2]", None, Some(locals))
.eval_bound("array[:,1::2]", None, Some(&locals))
.unwrap()
.downcast::<PyArray2<f64>>()
.downcast_into::<PyArray2<f64>>()
.unwrap();

let key4 = borrow_key(view4.as_array_ptr());
Expand All @@ -764,8 +765,8 @@ mod tests {
#[test]
fn borrow_multiple_arrays() {
Python::with_gil(|py| {
let array1 = PyArray::<f64, _>::zeros(py, 10, false);
let array2 = PyArray::<f64, _>::zeros(py, 10, false);
let array1 = PyArray::<f64, _>::zeros_bound(py, 10, false);
let array2 = PyArray::<f64, _>::zeros_bound(py, 10, false);

let base1 = base_address(py, array1.as_array_ptr());
let base2 = base_address(py, array2.as_array_ptr());
Expand Down Expand Up @@ -809,7 +810,7 @@ mod tests {
#[test]
fn borrow_multiple_views() {
Python::with_gil(|py| {
let array = PyArray::<f64, _>::zeros(py, 10, false);
let array = PyArray::<f64, _>::zeros_bound(py, 10, false);
let base = base_address(py, array.as_array_ptr());

let locals = [("array", array)].into_py_dict(py);
Expand Down
Loading
Loading