polars_python/series/
export.rs

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