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

Add a prelude to make the method traits easier to import #417

Merged
merged 3 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
18 changes: 9 additions & 9 deletions benches/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,48 +6,48 @@ use test::{black_box, Bencher};
use std::ops::Range;

use numpy::{PyArray1, PyArray2, PyArray3};
use pyo3::{PyAny, Python, ToPyObject};
use pyo3::{types::PyAnyMethods, Python, ToPyObject};

#[bench]
fn extract_success(bencher: &mut Bencher) {
Python::with_gil(|py| {
let any: &PyAny = PyArray2::<f64>::zeros(py, (10, 10), false);
let any = PyArray2::<f64>::zeros_bound(py, (10, 10), false).into_any();

bencher.iter(|| {
black_box(any).extract::<&PyArray2<f64>>().unwrap();
black_box(&any).extract::<&PyArray2<f64>>().unwrap();
});
});
}

#[bench]
fn extract_failure(bencher: &mut Bencher) {
Python::with_gil(|py| {
let any: &PyAny = PyArray2::<i32>::zeros(py, (10, 10), false);
let any = PyArray2::<f64>::zeros_bound(py, (10, 10), false).into_any();

bencher.iter(|| {
black_box(any).extract::<&PyArray2<f64>>().unwrap_err();
black_box(&any).extract::<&PyArray2<f64>>().unwrap_err();
});
});
}

#[bench]
fn downcast_success(bencher: &mut Bencher) {
Python::with_gil(|py| {
let any: &PyAny = PyArray2::<f64>::zeros(py, (10, 10), false);
let any = PyArray2::<f64>::zeros_bound(py, (10, 10), false).into_any();

bencher.iter(|| {
black_box(any).downcast::<PyArray2<f64>>().unwrap();
black_box(&any).downcast::<PyArray2<f64>>().unwrap();
});
});
}

#[bench]
fn downcast_failure(bencher: &mut Bencher) {
Python::with_gil(|py| {
let any: &PyAny = PyArray2::<i32>::zeros(py, (10, 10), false);
let any = PyArray2::<f64>::zeros_bound(py, (10, 10), false).into_any();

bencher.iter(|| {
black_box(any).downcast::<PyArray2<f64>>().unwrap_err();
black_box(&any).downcast::<PyArray2<f64>>().unwrap_err();
});
});
}
Expand Down
14 changes: 7 additions & 7 deletions benches/borrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
extern crate test;
use test::{black_box, Bencher};

use numpy::PyArray;
use numpy::{PyArray, PyArrayMethods};
use pyo3::Python;

#[bench]
fn initial_shared_borrow(bencher: &mut Bencher) {
Python::with_gil(|py| {
let array = PyArray::<f64, _>::zeros(py, (6, 5, 4, 3, 2, 1), false);
let array = PyArray::<f64, _>::zeros_bound(py, (6, 5, 4, 3, 2, 1), false);

bencher.iter(|| {
let array = black_box(array);
let array = black_box(&array);

let _shared = array.readonly();
});
Expand All @@ -22,12 +22,12 @@ fn initial_shared_borrow(bencher: &mut Bencher) {
#[bench]
fn additional_shared_borrow(bencher: &mut Bencher) {
Python::with_gil(|py| {
let array = PyArray::<f64, _>::zeros(py, (6, 5, 4, 3, 2, 1), false);
let array = PyArray::<f64, _>::zeros_bound(py, (6, 5, 4, 3, 2, 1), false);

let _shared = (0..128).map(|_| array.readonly()).collect::<Vec<_>>();

bencher.iter(|| {
let array = black_box(array);
let array = black_box(&array);

let _shared = array.readonly();
});
Expand All @@ -37,10 +37,10 @@ fn additional_shared_borrow(bencher: &mut Bencher) {
#[bench]
fn exclusive_borrow(bencher: &mut Bencher) {
Python::with_gil(|py| {
let array = PyArray::<f64, _>::zeros(py, (6, 5, 4, 3, 2, 1), false);
let array = PyArray::<f64, _>::zeros_bound(py, (6, 5, 4, 3, 2, 1), false);

bencher.iter(|| {
let array = black_box(array);
let array = black_box(&array);

let _exclusive = array.readwrite();
});
Expand Down
13 changes: 8 additions & 5 deletions src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,8 @@ impl<T: Element, D: Dimension> PyArray<T, D> {
/// # Example
///
/// ```
/// use numpy::{PyArray3, PyArrayMethods, PyUntypedArrayMethods};
/// use numpy::prelude::*;
/// use numpy::PyArray3;
/// use pyo3::Python;
///
/// Python::with_gil(|py| {
Expand Down Expand Up @@ -1329,7 +1330,8 @@ impl<T: Element, D> PyArray<T, D> {
/// # Example
///
/// ```
/// use numpy::{PyArray, PyArrayMethods, PyUntypedArrayMethods};
/// use numpy::prelude::*;
/// use numpy::PyArray;
/// use pyo3::Python;
///
/// Python::with_gil(|py| {
Expand Down Expand Up @@ -1846,8 +1848,8 @@ pub trait PyArrayMethods<'py, T, D>: PyUntypedArrayMethods<'py> {

/// Extends or truncates the dimensions of an array.
///
/// This method works only on [contiguous][PyUntypedArray::is_contiguous] arrays.
/// Missing elements will be initialized as if calling [`zeros`][Self::zeros].
/// This method works only on [contiguous][PyUntypedArrayMethods::is_contiguous] arrays.
/// Missing elements will be initialized as if calling [`zeros`][PyArray::zeros_bound].
///
/// See also [`ndarray.resize`][ndarray-resize] and [`PyArray_Resize`][PyArray_Resize].
///
Expand All @@ -1859,7 +1861,8 @@ pub trait PyArrayMethods<'py, T, D>: PyUntypedArrayMethods<'py> {
/// # Example
///
/// ```
/// use numpy::{PyArray, PyArrayMethods, PyUntypedArrayMethods};
/// use numpy::prelude::*;
/// use numpy::PyArray;
/// use pyo3::Python;
///
/// Python::with_gil(|py| {
Expand Down
7 changes: 6 additions & 1 deletion src/array_like.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,18 @@ use pyo3::{
};

use crate::array::PyArrayMethods;
use crate::sealed::Sealed;
use crate::{get_array_module, Element, IntoPyArray, PyArray, PyReadonlyArray};

pub trait Coerce: Sealed {
const VAL: bool;
}

mod sealed {
pub trait Sealed {}
}

use sealed::Sealed;

/// Marker type to indicate that the element type received via [`PyArrayLike`] must match the specified type exactly.
#[derive(Debug)]
pub struct TypeMustMatch;
Expand Down
7 changes: 6 additions & 1 deletion src/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use crate::array::{PyArray, PyArrayMethods};
use crate::dtype::Element;
use crate::error::MAX_DIMENSIONALITY_ERR;
use crate::npyffi::{self, npy_intp};
use crate::sealed::Sealed;
use crate::slice_container::PySliceContainer;

/// Conversion trait from owning Rust types into [`PyArray`].
Expand Down Expand Up @@ -273,6 +272,12 @@ pub trait ToNpyDims: Dimension + Sealed {
}
}

mod sealed {
pub trait Sealed {}
}

use sealed::Sealed;

impl<D> ToNpyDims for D where D: Dimension {}

/// Trait implemented by types that can be used to index an array.
Expand Down
16 changes: 8 additions & 8 deletions src/dtype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ impl PyArrayDescr {

/// Implementation of functionality for [`PyArrayDescr`].
#[doc(alias = "PyArrayDescr")]
pub trait PyArrayDescrMethods<'py>: sealed::Sealed {
pub trait PyArrayDescrMethods<'py>: Sealed {
/// Returns `self` as `*mut PyArray_Descr`.
fn as_dtype_ptr(&self) -> *mut PyArray_Descr;

Expand Down Expand Up @@ -553,6 +553,12 @@ pub trait PyArrayDescrMethods<'py>: sealed::Sealed {
fn get_field(&self, name: &str) -> PyResult<(Bound<'py, PyArrayDescr>, usize)>;
}

mod sealed {
pub trait Sealed {}
}

use sealed::Sealed;

impl<'py> PyArrayDescrMethods<'py> for Bound<'py, PyArrayDescr> {
fn as_dtype_ptr(&self) -> *mut PyArray_Descr {
self.as_ptr() as _
Expand Down Expand Up @@ -632,13 +638,7 @@ impl<'py> PyArrayDescrMethods<'py> for Bound<'py, PyArrayDescr> {
}
}

mod sealed {
use super::PyArrayDescr;

pub trait Sealed {}

impl Sealed for pyo3::Bound<'_, PyArrayDescr> {}
}
impl Sealed for Bound<'_, PyArrayDescr> {}

/// Represents that a type can be an element of `PyArray`.
///
Expand Down
19 changes: 15 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,21 @@ pub use crate::untyped_array::{PyUntypedArray, PyUntypedArrayMethods};

pub use ndarray::{array, Ix1, Ix2, Ix3, Ix4, Ix5, Ix6, IxDyn};

/// A prelude
///
/// The purpose of this module is to avoid direct imports of
/// the method traits defined by this crate via a glob import:
///
/// ```
/// # #![allow(unused_imports)]
/// use numpy::prelude::*;
/// ```
pub mod prelude {
pub use crate::array::{PyArray0Methods, PyArrayMethods};
pub use crate::dtype::PyArrayDescrMethods;
pub use crate::untyped_array::PyUntypedArrayMethods;
}

#[cfg(doctest)]
mod doctest {
macro_rules! doc_comment {
Expand All @@ -130,10 +145,6 @@ mod doctest {
doc_comment!(include_str!("../README.md"), readme);
}

mod sealed {
pub trait Sealed {}
}

#[cold]
#[inline(always)]
fn cold() {}
Expand Down
19 changes: 10 additions & 9 deletions src/untyped_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ impl PyUntypedArray {

/// Implementation of functionality for [`PyUntypedArray`].
#[doc(alias = "PyUntypedArray")]
pub trait PyUntypedArrayMethods<'py>: sealed::Sealed {
pub trait PyUntypedArrayMethods<'py>: Sealed {
/// Returns a raw pointer to the underlying [`PyArrayObject`][npyffi::PyArrayObject].
fn as_array_ptr(&self) -> *mut npyffi::PyArrayObject;

Expand Down Expand Up @@ -423,6 +423,12 @@ pub trait PyUntypedArrayMethods<'py>: sealed::Sealed {
}
}

mod sealed {
pub trait Sealed {}
}

use sealed::Sealed;

fn check_flags(obj: &npyffi::PyArrayObject, flags: i32) -> bool {
obj.flags & flags != 0
}
Expand All @@ -441,6 +447,8 @@ impl<'py> PyUntypedArrayMethods<'py> for Bound<'py, PyUntypedArray> {
}
}

impl Sealed for Bound<'_, PyUntypedArray> {}

// We won't be able to provide a `Deref` impl from `Bound<'_, PyArray<T, D>>` to
// `Bound<'_, PyUntypedArray>`, so this seems to be the next best thing to do
impl<'py, T, D> PyUntypedArrayMethods<'py> for Bound<'py, PyArray<T, D>> {
Expand All @@ -455,11 +463,4 @@ impl<'py, T, D> PyUntypedArrayMethods<'py> for Bound<'py, PyArray<T, D>> {
}
}

mod sealed {
use super::{PyArray, PyUntypedArray};

pub trait Sealed {}

impl Sealed for pyo3::Bound<'_, PyUntypedArray> {}
impl<T, D> Sealed for pyo3::Bound<'_, PyArray<T, D>> {}
}
impl<T, D> Sealed for Bound<'_, PyArray<T, D>> {}
Loading