polars_python/interop/numpy/
utils.rs1use std::ffi::{c_int, c_void};
2
3use ndarray::{Dim, Dimension};
4use numpy::npyffi::PyArrayObject;
5use numpy::{npyffi, Element, PyArrayDescr, PyArrayDescrMethods, ToNpyDims, PY_ARRAY_API};
6use polars_core::prelude::*;
7use pyo3::intern;
8use pyo3::prelude::*;
9use pyo3::types::PyTuple;
10
11pub(super) unsafe fn create_borrowed_np_array<I>(
13 py: Python,
14 dtype: Bound<PyArrayDescr>,
15 mut shape: Dim<I>,
16 flags: c_int,
17 data: *mut c_void,
18 owner: PyObject,
19) -> PyObject
20where
21 Dim<I>: Dimension + ToNpyDims,
22{
23 let array = PY_ARRAY_API.PyArray_NewFromDescr(
25 py,
26 PY_ARRAY_API.get_type_object(py, npyffi::NpyTypes::PyArray_Type),
27 dtype.into_dtype_ptr(),
28 shape.ndim_cint(),
29 shape.as_dims_ptr(),
30 std::ptr::null_mut(),
32 data,
33 flags,
34 std::ptr::null_mut(),
35 );
36
37 let owner_ptr = owner.as_ptr();
39 std::mem::forget(owner);
42 PY_ARRAY_API.PyArray_SetBaseObject(py, array as *mut PyArrayObject, owner_ptr);
43
44 Py::from_owned_ptr(py, array)
45}
46
47pub(super) fn dtype_supports_view(dtype: &DataType) -> bool {
49 match dtype {
50 dt if dt.is_primitive_numeric() => true,
51 DataType::Datetime(_, _) | DataType::Duration(_) => true,
52 DataType::Array(inner, _) => dtype_supports_view(inner.as_ref()),
53 _ => false,
54 }
55}
56
57pub(super) fn series_contains_null(s: &Series) -> bool {
61 if s.null_count() > 0 {
62 true
63 } else if let Ok(ca) = s.array() {
64 let s_inner = ca.get_inner();
65 series_contains_null(&s_inner)
66 } else {
67 false
68 }
69}
70
71pub(super) fn reshape_numpy_array(
73 py: Python,
74 arr: PyObject,
75 height: usize,
76 width: usize,
77) -> PyResult<PyObject> {
78 let shape = arr
79 .getattr(py, intern!(py, "shape"))?
80 .extract::<Vec<usize>>(py)?;
81
82 if shape.len() == 1 {
83 let new_shape = (height, width);
85 arr.call_method1(py, intern!(py, "reshape"), new_shape)
86 } else {
87 let mut new_shape_vec = vec![height, width];
88 for v in &shape[1..] {
89 new_shape_vec.push(*v)
90 }
91 let new_shape = PyTuple::new(py, new_shape_vec)?;
92 arr.call_method1(py, intern!(py, "reshape"), new_shape)
93 }
94}
95
96pub(super) fn polars_dtype_to_np_temporal_dtype<'a>(
98 py: Python<'a>,
99 dtype: &DataType,
100) -> Bound<'a, PyArrayDescr> {
101 use numpy::datetime::{units, Datetime, Timedelta};
102 match dtype {
103 DataType::Datetime(TimeUnit::Milliseconds, _) => {
104 Datetime::<units::Milliseconds>::get_dtype(py)
105 },
106 DataType::Datetime(TimeUnit::Microseconds, _) => {
107 Datetime::<units::Microseconds>::get_dtype(py)
108 },
109 DataType::Datetime(TimeUnit::Nanoseconds, _) => {
110 Datetime::<units::Nanoseconds>::get_dtype(py)
111 },
112 DataType::Duration(TimeUnit::Milliseconds) => {
113 Timedelta::<units::Milliseconds>::get_dtype(py)
114 },
115 DataType::Duration(TimeUnit::Microseconds) => {
116 Timedelta::<units::Microseconds>::get_dtype(py)
117 },
118 DataType::Duration(TimeUnit::Nanoseconds) => Timedelta::<units::Nanoseconds>::get_dtype(py),
119 _ => panic!("only Datetime/Duration inputs supported, got {}", dtype),
120 }
121}