polars_python/series/
export.rs1use polars_core::prelude::*;
2use polars_ffi::version_0::SeriesExport;
3use pyo3::IntoPyObjectExt;
4use pyo3::prelude::*;
5use pyo3::types::{PyCapsule, PyList};
6
7use super::PySeries;
8use crate::error::PyPolarsErr;
9use crate::interop;
10use crate::interop::arrow::to_py::series_to_stream;
11use crate::prelude::*;
12
13#[pymethods]
14impl PySeries {
15 pub fn to_list<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
18 let series = &self.series;
19
20 fn to_list_recursive<'py>(py: Python<'py>, series: &Series) -> PyResult<Bound<'py, PyAny>> {
21 let pylist = match series.dtype() {
22 DataType::Boolean => PyList::new(py, series.bool().map_err(PyPolarsErr::from)?)?,
23 DataType::UInt8 => PyList::new(py, series.u8().map_err(PyPolarsErr::from)?)?,
24 DataType::UInt16 => PyList::new(py, series.u16().map_err(PyPolarsErr::from)?)?,
25 DataType::UInt32 => PyList::new(py, series.u32().map_err(PyPolarsErr::from)?)?,
26 DataType::UInt64 => PyList::new(py, series.u64().map_err(PyPolarsErr::from)?)?,
27 DataType::Int8 => PyList::new(py, series.i8().map_err(PyPolarsErr::from)?)?,
28 DataType::Int16 => PyList::new(py, series.i16().map_err(PyPolarsErr::from)?)?,
29 DataType::Int32 => PyList::new(py, series.i32().map_err(PyPolarsErr::from)?)?,
30 DataType::Int64 => PyList::new(py, series.i64().map_err(PyPolarsErr::from)?)?,
31 DataType::Int128 => PyList::new(py, series.i128().map_err(PyPolarsErr::from)?)?,
32 DataType::Float32 => PyList::new(py, series.f32().map_err(PyPolarsErr::from)?)?,
33 DataType::Float64 => PyList::new(py, series.f64().map_err(PyPolarsErr::from)?)?,
34 DataType::Categorical(_, _) | DataType::Enum(_, _) => {
35 with_match_categorical_physical_type!(series.dtype().cat_physical().unwrap(), |$C| {
36 PyList::new(py, series.cat::<$C>().unwrap().iter_str())?
37 })
38 },
39 #[cfg(feature = "object")]
40 DataType::Object(_) => {
41 let v = PyList::empty(py);
42 for i in 0..series.len() {
43 let obj: Option<&ObjectValue> = series.get_object(i).map(|any| any.into());
44 v.append(obj)?;
45 }
46 v
47 },
48 DataType::List(_) => {
49 let v = PyList::empty(py);
50 let ca = series.list().map_err(PyPolarsErr::from)?;
51 for opt_s in ca.amortized_iter() {
52 match opt_s {
53 None => {
54 v.append(py.None())?;
55 },
56 Some(s) => {
57 let pylst = to_list_recursive(py, s.as_ref())?;
58 v.append(pylst)?;
59 },
60 }
61 }
62 v
63 },
64 DataType::Array(_, _) => {
65 let v = PyList::empty(py);
66 let ca = series.array().map_err(PyPolarsErr::from)?;
67 for opt_s in ca.amortized_iter() {
68 match opt_s {
69 None => {
70 v.append(py.None())?;
71 },
72 Some(s) => {
73 let pylst = to_list_recursive(py, s.as_ref())?;
74 v.append(pylst)?;
75 },
76 }
77 }
78 v
79 },
80 DataType::Date => {
81 let ca = series.date().map_err(PyPolarsErr::from)?;
82 return Wrap(ca).into_bound_py_any(py);
83 },
84 DataType::Time => {
85 let ca = series.time().map_err(PyPolarsErr::from)?;
86 return Wrap(ca).into_bound_py_any(py);
87 },
88 DataType::Datetime(_, _) => {
89 let ca = series.datetime().map_err(PyPolarsErr::from)?;
90 return Wrap(ca).into_bound_py_any(py);
91 },
92 DataType::Decimal(_, _) => {
93 let ca = series.decimal().map_err(PyPolarsErr::from)?;
94 return Wrap(ca).into_bound_py_any(py);
95 },
96 DataType::String => {
97 let ca = series.str().map_err(PyPolarsErr::from)?;
98 return Wrap(ca).into_bound_py_any(py);
99 },
100 DataType::Struct(_) => {
101 let ca = series.struct_().map_err(PyPolarsErr::from)?;
102 return Wrap(ca).into_bound_py_any(py);
103 },
104 DataType::Duration(_) => {
105 let ca = series.duration().map_err(PyPolarsErr::from)?;
106 return Wrap(ca).into_bound_py_any(py);
107 },
108 DataType::Binary => {
109 let ca = series.binary().map_err(PyPolarsErr::from)?;
110 return Wrap(ca).into_bound_py_any(py);
111 },
112 DataType::Null => {
113 let null: Option<u8> = None;
114 let n = series.len();
115 let iter = std::iter::repeat_n(null, n);
116 use std::iter::RepeatN;
117 struct NullIter {
118 iter: RepeatN<Option<u8>>,
119 n: usize,
120 }
121 impl Iterator for NullIter {
122 type Item = Option<u8>;
123
124 fn next(&mut self) -> Option<Self::Item> {
125 self.iter.next()
126 }
127 fn size_hint(&self) -> (usize, Option<usize>) {
128 (self.n, Some(self.n))
129 }
130 }
131 impl ExactSizeIterator for NullIter {}
132
133 PyList::new(py, NullIter { iter, n })?
134 },
135 DataType::Unknown(_) => {
136 panic!("to_list not implemented for unknown")
137 },
138 DataType::BinaryOffset => {
139 unreachable!()
140 },
141 };
142 Ok(pylist.into_any())
143 }
144
145 to_list_recursive(py, series)
146 }
147
148 #[allow(clippy::wrong_self_convention)]
150 fn to_arrow(&mut self, py: Python<'_>, compat_level: PyCompatLevel) -> PyResult<PyObject> {
151 self.rechunk(py, true)?;
152 let pyarrow = py.import("pyarrow")?;
153
154 interop::arrow::to_py::to_py_array(
155 self.series.to_arrow(0, compat_level.0),
156 &self.series.field().to_arrow(compat_level.0),
157 &pyarrow,
158 )
159 }
160
161 #[allow(unused_variables)]
162 #[pyo3(signature = (requested_schema=None))]
163 fn __arrow_c_stream__<'py>(
164 &self,
165 py: Python<'py>,
166 requested_schema: Option<PyObject>,
167 ) -> PyResult<Bound<'py, PyCapsule>> {
168 series_to_stream(&self.series, py)
169 }
170
171 pub fn _export(&mut self, _py: Python<'_>, location: usize) {
172 let export = polars_ffi::version_0::export_series(&self.series);
173 unsafe {
174 (location as *mut SeriesExport).write(export);
175 }
176 }
177}