1use polars::lazy::dsl;
2use polars_core::with_match_physical_integer_polars_type;
3use polars_ops::series::ClosedInterval;
4use polars_plan::constants::get_literal_name;
5use pyo3::prelude::*;
6
7use crate::error::PyPolarsErr;
8use crate::expr::datatype::PyDataTypeExpr;
9use crate::prelude::*;
10use crate::utils::EnterPolarsExt;
11use crate::{PyExpr, PySeries};
12
13#[pyfunction]
14pub fn int_range(start: PyExpr, end: PyExpr, step: i64, dtype: PyDataTypeExpr) -> PyExpr {
15 let start = start.inner;
16 let end = end.inner;
17 let dtype = dtype.inner;
18 dsl::int_range(start, end, step, dtype).into()
19}
20
21#[pyfunction]
23pub fn eager_int_range(
24 py: Python<'_>,
25 lower: &Bound<'_, PyAny>,
26 upper: &Bound<'_, PyAny>,
27 step: &Bound<'_, PyAny>,
28 dtype: PyDataTypeExpr,
29) -> PyResult<PySeries> {
30 let dtype = dtype.inner;
31 let Some(dtype) = dtype.into_literal() else {
32 return Err(PyPolarsErr::from(
33 polars_err!(ComputeError: "eager `int_range` cannot be given lazy datatype expression"),
34 )
35 .into());
36 };
37
38 if !dtype.is_integer() {
39 return Err(PyPolarsErr::from(
40 polars_err!(SchemaMismatch: "non-integer `dtype` passed to `int_range`: '{}'", dtype),
41 )
42 .into());
43 }
44
45 with_match_physical_integer_polars_type!(dtype, |$T| {
46 let start_v: <$T as PolarsNumericType>::Native = lower.extract()?;
47 let end_v: <$T as PolarsNumericType>::Native = upper.extract()?;
48 let step: i64 = step.extract()?;
49 py.enter_polars_series(|| new_int_range::<$T>(start_v, end_v, step, get_literal_name()))
50 })
51}
52
53#[pyfunction]
54pub fn int_ranges(
55 start: PyExpr,
56 end: PyExpr,
57 step: PyExpr,
58 dtype: PyDataTypeExpr,
59) -> PyResult<PyExpr> {
60 let dtype = dtype.inner;
61 Ok(dsl::int_ranges(start.inner, end.inner, step.inner, dtype).into())
62}
63
64#[pyfunction]
65pub fn date_range(
66 start: PyExpr,
67 end: PyExpr,
68 interval: &str,
69 closed: Wrap<ClosedWindow>,
70) -> PyResult<PyExpr> {
71 let start = start.inner;
72 let end = end.inner;
73 let interval = Duration::try_parse(interval).map_err(PyPolarsErr::from)?;
74 let closed = closed.0;
75 let out = dsl::date_range(
76 Some(start),
77 Some(end),
78 Some(interval),
79 None, closed,
81 )
82 .map_err(PyPolarsErr::from)?;
83 Ok(out.into())
84}
85
86#[pyfunction]
87pub fn date_ranges(
88 start: PyExpr,
89 end: PyExpr,
90 interval: &str,
91 closed: Wrap<ClosedWindow>,
92) -> PyResult<PyExpr> {
93 let start = start.inner;
94 let end = end.inner;
95 let interval = Duration::try_parse(interval).map_err(PyPolarsErr::from)?;
96 let closed = closed.0;
97 let out = dsl::date_ranges(
98 Some(start),
99 Some(end),
100 Some(interval),
101 None, closed,
103 )
104 .map_err(PyPolarsErr::from)?;
105 Ok(out.into())
106}
107
108#[pyfunction]
109#[pyo3(signature = (start, end, interval, closed, time_unit, time_zone))]
110pub fn datetime_range(
111 start: PyExpr,
112 end: PyExpr,
113 interval: &str,
114 closed: Wrap<ClosedWindow>,
115 time_unit: Option<Wrap<TimeUnit>>,
116 time_zone: Wrap<Option<TimeZone>>,
117) -> PyResult<PyExpr> {
118 let start = start.inner;
119 let end = end.inner;
120 let interval = Duration::try_parse(interval).map_err(PyPolarsErr::from)?;
121 let closed = closed.0;
122 let time_unit = time_unit.map(|x| x.0);
123 let time_zone = time_zone.0;
124 let out = dsl::datetime_range(
125 Some(start),
126 Some(end),
127 Some(interval),
128 None, closed,
130 time_unit,
131 time_zone,
132 )
133 .map_err(PyPolarsErr::from)?;
134 Ok(out.into())
135}
136
137#[pyfunction]
138#[pyo3(signature = (start, end, interval, closed, time_unit, time_zone))]
139pub fn datetime_ranges(
140 start: PyExpr,
141 end: PyExpr,
142 interval: &str,
143 closed: Wrap<ClosedWindow>,
144 time_unit: Option<Wrap<TimeUnit>>,
145 time_zone: Wrap<Option<TimeZone>>,
146) -> PyResult<PyExpr> {
147 let start = start.inner;
148 let end = end.inner;
149 let interval = Duration::try_parse(interval).map_err(PyPolarsErr::from)?;
150 let closed = closed.0;
151 let time_unit = time_unit.map(|x| x.0);
152 let time_zone = time_zone.0;
153 let out = dsl::datetime_ranges(
154 Some(start),
155 Some(end),
156 Some(interval),
157 None, closed,
159 time_unit,
160 time_zone,
161 )
162 .map_err(PyPolarsErr::from)?;
163 Ok(out.into())
164}
165
166#[pyfunction]
167pub fn time_range(
168 start: PyExpr,
169 end: PyExpr,
170 every: &str,
171 closed: Wrap<ClosedWindow>,
172) -> PyResult<PyExpr> {
173 let start = start.inner;
174 let end = end.inner;
175 let every = Duration::try_parse(every).map_err(PyPolarsErr::from)?;
176 let closed = closed.0;
177 Ok(dsl::time_range(start, end, every, closed).into())
178}
179
180#[pyfunction]
181pub fn time_ranges(
182 start: PyExpr,
183 end: PyExpr,
184 every: &str,
185 closed: Wrap<ClosedWindow>,
186) -> PyResult<PyExpr> {
187 let start = start.inner;
188 let end = end.inner;
189 let every = Duration::try_parse(every).map_err(PyPolarsErr::from)?;
190 let closed = closed.0;
191 Ok(dsl::time_ranges(start, end, every, closed).into())
192}
193
194#[pyfunction]
195pub fn linear_space(
196 start: PyExpr,
197 end: PyExpr,
198 num_samples: PyExpr,
199 closed: Wrap<ClosedInterval>,
200) -> PyResult<PyExpr> {
201 let start = start.inner;
202 let end = end.inner;
203 let num_samples = num_samples.inner;
204 let closed = closed.0;
205 Ok(dsl::linear_space(start, end, num_samples, closed).into())
206}
207
208#[pyfunction]
209pub fn linear_spaces(
210 start: PyExpr,
211 end: PyExpr,
212 num_samples: PyExpr,
213 closed: Wrap<ClosedInterval>,
214 as_array: bool,
215) -> PyResult<PyExpr> {
216 let start = start.inner;
217 let end = end.inner;
218 let num_samples = num_samples.inner;
219 let closed = closed.0;
220 let out =
221 dsl::linear_spaces(start, end, num_samples, closed, as_array).map_err(PyPolarsErr::from)?;
222 Ok(out.into())
223}