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 PyArrayDescr::new() #266

Merged
merged 2 commits into from
Jan 24, 2022
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
27 changes: 14 additions & 13 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,23 @@
- `PyArray::from_exact_iter` does not unsoundly trust `ExactSizeIterator::len` any more ([#262](https://github.com/PyO3/rust-numpy/pull/262))
- `PyArray::as_cell_slice` was removed as it unsoundly interacts with `PyReadonlyArray` allowing safe code to violate aliasing rules ([#260](https://github.com/PyO3/rust-numpy/pull/260))
- `rayon` feature is now removed, and directly specifying the feature via `ndarray` dependency is recommended ([#250](https://github.com/PyO3/rust-numpy/pull/250))
- Descriptors rework and related changes ([#256](https://github.com/PyO3/rust-numpy/pull/256)):
- Remove `DataType`
- Add the top-level `dtype` function for easy access to registered dtypes
- Add `PyArrayDescr::of`, `PyArrayDescr::into_dtype_ptr` and `PyArrayDescr::is_equiv_to`
- `Element` trait has been simplified to just `IS_COPY` const and `get_dtype` method
- `Element` trait and `PyArrayDescr` changes ([#256](https://github.com/PyO3/rust-numpy/pull/256)):
- `Element` trait has been simplified to `get_dtype()` and `IS_COPY`
- New `PyArrayDescr` methods: `of`, `into_dtype_ptr`, `is_equiv_to`
- Added `numpy::dtype` function
- `Element` is now implemented for `isize`
- `c32` and `c64` aliases have been replaced with `Complex32` and `Complex64`
- `c32` / `c64` have been renamed with `Complex32` / `Complex64`
- `ShapeError` has been split into `TypeError` and `DimensionalityError`
- `i32`, `i64`, `u32` and `u64` are now guaranteed to map to
`np.int32`, `np.int64`, `np.uint32` and `np.uint64` respectively
- Remove `cfg_if` dependency
- New methods in `PyArrayDescr`, catching up with `np.dtype`:
- `i32`, `i64`, `u32`, `u64` are now guaranteed to map to `np.u?int{32,64}`.
- Removed `cfg_if` dependency
- Removed `DataType` enum
- Added `PyArrayDescr::new` constructor
([#266](https://github.com/PyO3/rust-numpy/pull/266))
- New `PyArrayDescr` methods
([#266](https://github.com/PyO3/rust-numpy/pull/261)):
- `num`, `base`, `ndim`, `shape`, `byteorder`, `char`, `kind`, `itemsize`,
`alignment`, `flags`, `has_object`, `is_aligned_struct`, `names`
- Added `get_field` to query fields of structured dtypes
- Additional helper methods: `has_subarray`, `has_fields`, `is_native_byteorder`
`alignment`, `flags`, `has_object`, `is_aligned_struct`, `names`,
`get_field`, `has_subarray`, `has_fields`, `is_native_byteorder`
- Renamed `get_type` to `typeobj`

- v0.15.1
Expand Down
31 changes: 31 additions & 0 deletions src/dtype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::mem::size_of;
use std::os::raw::{
c_char, c_int, c_long, c_longlong, c_short, c_uint, c_ulong, c_ulonglong, c_ushort,
};
use std::ptr;

use num_traits::{Bounded, Zero};
use pyo3::{
Expand Down Expand Up @@ -57,6 +58,23 @@ pub fn dtype<T: Element>(py: Python) -> &PyArrayDescr {
}

impl PyArrayDescr {
/// Creates a new dtype object from an arbitrary object.
///
/// Equivalent to invoking the constructor of `np.dtype`.
#[inline]
pub fn new<'py, T: ToPyObject + ?Sized>(py: Python<'py>, obj: &T) -> PyResult<&'py Self> {
Self::new_impl(py, obj.to_object(py))
}

fn new_impl<'py>(py: Python<'py>, obj: PyObject) -> PyResult<&'py Self> {
let mut descr: *mut PyArray_Descr = ptr::null_mut();
unsafe {
// None is an invalid input here and is not converted to NPY_DEFAULT_TYPE
PY_ARRAY_API.PyArray_DescrConverter2(obj.as_ptr(), &mut descr as *mut _);
py.from_owned_ptr_or_err(descr as _)
}
}

/// Returns `self` as `*mut PyArray_Descr`.
pub fn as_dtype_ptr(&self) -> *mut PyArray_Descr {
self.as_ptr() as _
Expand Down Expand Up @@ -423,6 +441,19 @@ mod tests {
use super::{dtype, Complex32, Complex64, Element, PyArrayDescr};
use crate::npyffi::{NPY_ALIGNED_STRUCT, NPY_ITEM_HASOBJECT, NPY_NEEDS_PYAPI, NPY_TYPES};

#[test]
fn test_dtype_new() {
pyo3::Python::with_gil(|py| {
assert_eq!(PyArrayDescr::new(py, "float64").unwrap(), dtype::<f64>(py));
let d = PyArrayDescr::new(py, [("a", "O"), ("b", "?")].as_ref()).unwrap();
assert_eq!(d.names(), Some(vec!["a", "b"]));
assert!(d.has_object());
assert_eq!(d.get_field("a").unwrap().0, dtype::<PyObject>(py));
assert_eq!(d.get_field("b").unwrap().0, dtype::<bool>(py));
assert!(PyArrayDescr::new(py, &123_usize).is_err());
});
}

#[test]
fn test_dtype_names() {
fn type_name<T: Element>(py: pyo3::Python) -> &str {
Expand Down