Skip to content

Commit 3f35b6f

Browse files
authored
Merge pull request #266 from aldanor/feature/pydescr-new
Add `PyArrayDescr::new()`
2 parents 7cc945c + 436ec9a commit 3f35b6f

File tree

2 files changed

+45
-13
lines changed

2 files changed

+45
-13
lines changed

CHANGELOG.md

+14-13
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,23 @@
88
- `PyArray::from_exact_iter` does not unsoundly trust `ExactSizeIterator::len` any more ([#262](https://github.com/PyO3/rust-numpy/pull/262))
99
- `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))
1010
- `rayon` feature is now removed, and directly specifying the feature via `ndarray` dependency is recommended ([#250](https://github.com/PyO3/rust-numpy/pull/250))
11-
- Descriptors rework and related changes ([#256](https://github.com/PyO3/rust-numpy/pull/256)):
12-
- Remove `DataType`
13-
- Add the top-level `dtype` function for easy access to registered dtypes
14-
- Add `PyArrayDescr::of`, `PyArrayDescr::into_dtype_ptr` and `PyArrayDescr::is_equiv_to`
15-
- `Element` trait has been simplified to just `IS_COPY` const and `get_dtype` method
11+
- `Element` trait and `PyArrayDescr` changes ([#256](https://github.com/PyO3/rust-numpy/pull/256)):
12+
- `Element` trait has been simplified to `get_dtype()` and `IS_COPY`
13+
- New `PyArrayDescr` methods: `of`, `into_dtype_ptr`, `is_equiv_to`
14+
- Added `numpy::dtype` function
1615
- `Element` is now implemented for `isize`
17-
- `c32` and `c64` aliases have been replaced with `Complex32` and `Complex64`
16+
- `c32` / `c64` have been renamed with `Complex32` / `Complex64`
1817
- `ShapeError` has been split into `TypeError` and `DimensionalityError`
19-
- `i32`, `i64`, `u32` and `u64` are now guaranteed to map to
20-
`np.int32`, `np.int64`, `np.uint32` and `np.uint64` respectively
21-
- Remove `cfg_if` dependency
22-
- New methods in `PyArrayDescr`, catching up with `np.dtype`:
18+
- `i32`, `i64`, `u32`, `u64` are now guaranteed to map to `np.u?int{32,64}`.
19+
- Removed `cfg_if` dependency
20+
- Removed `DataType` enum
21+
- Added `PyArrayDescr::new` constructor
22+
([#266](https://github.com/PyO3/rust-numpy/pull/266))
23+
- New `PyArrayDescr` methods
24+
([#266](https://github.com/PyO3/rust-numpy/pull/261)):
2325
- `num`, `base`, `ndim`, `shape`, `byteorder`, `char`, `kind`, `itemsize`,
24-
`alignment`, `flags`, `has_object`, `is_aligned_struct`, `names`
25-
- Added `get_field` to query fields of structured dtypes
26-
- Additional helper methods: `has_subarray`, `has_fields`, `is_native_byteorder`
26+
`alignment`, `flags`, `has_object`, `is_aligned_struct`, `names`,
27+
`get_field`, `has_subarray`, `has_fields`, `is_native_byteorder`
2728
- Renamed `get_type` to `typeobj`
2829

2930
- v0.15.1

src/dtype.rs

+31
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::mem::size_of;
22
use std::os::raw::{
33
c_char, c_int, c_long, c_longlong, c_short, c_uint, c_ulong, c_ulonglong, c_ushort,
44
};
5+
use std::ptr;
56

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

5960
impl PyArrayDescr {
61+
/// Creates a new dtype object from an arbitrary object.
62+
///
63+
/// Equivalent to invoking the constructor of `np.dtype`.
64+
#[inline]
65+
pub fn new<'py, T: ToPyObject + ?Sized>(py: Python<'py>, obj: &T) -> PyResult<&'py Self> {
66+
Self::new_impl(py, obj.to_object(py))
67+
}
68+
69+
fn new_impl<'py>(py: Python<'py>, obj: PyObject) -> PyResult<&'py Self> {
70+
let mut descr: *mut PyArray_Descr = ptr::null_mut();
71+
unsafe {
72+
// None is an invalid input here and is not converted to NPY_DEFAULT_TYPE
73+
PY_ARRAY_API.PyArray_DescrConverter2(obj.as_ptr(), &mut descr as *mut _);
74+
py.from_owned_ptr_or_err(descr as _)
75+
}
76+
}
77+
6078
/// Returns `self` as `*mut PyArray_Descr`.
6179
pub fn as_dtype_ptr(&self) -> *mut PyArray_Descr {
6280
self.as_ptr() as _
@@ -423,6 +441,19 @@ mod tests {
423441
use super::{dtype, Complex32, Complex64, Element, PyArrayDescr};
424442
use crate::npyffi::{NPY_ALIGNED_STRUCT, NPY_ITEM_HASOBJECT, NPY_NEEDS_PYAPI, NPY_TYPES};
425443

444+
#[test]
445+
fn test_dtype_new() {
446+
pyo3::Python::with_gil(|py| {
447+
assert_eq!(PyArrayDescr::new(py, "float64").unwrap(), dtype::<f64>(py));
448+
let d = PyArrayDescr::new(py, [("a", "O"), ("b", "?")].as_ref()).unwrap();
449+
assert_eq!(d.names(), Some(vec!["a", "b"]));
450+
assert!(d.has_object());
451+
assert_eq!(d.get_field("a").unwrap().0, dtype::<PyObject>(py));
452+
assert_eq!(d.get_field("b").unwrap().0, dtype::<bool>(py));
453+
assert!(PyArrayDescr::new(py, &123_usize).is_err());
454+
});
455+
}
456+
426457
#[test]
427458
fn test_dtype_names() {
428459
fn type_name<T: Element>(py: pyo3::Python) -> &str {

0 commit comments

Comments
 (0)