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