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