polars_python/expr/
string.rs

1use polars::prelude::*;
2use pyo3::prelude::*;
3
4use crate::PyExpr;
5use crate::conversion::Wrap;
6use crate::error::PyPolarsErr;
7
8#[pymethods]
9impl PyExpr {
10    fn str_join(&self, delimiter: &str, ignore_nulls: bool) -> Self {
11        self.inner
12            .clone()
13            .str()
14            .join(delimiter, ignore_nulls)
15            .into()
16    }
17
18    #[pyo3(signature = (format, strict, exact, cache))]
19    fn str_to_date(&self, format: Option<String>, strict: bool, exact: bool, cache: bool) -> Self {
20        let format = format.map(|x| x.into());
21
22        let options = StrptimeOptions {
23            format,
24            strict,
25            exact,
26            cache,
27        };
28        self.inner.clone().str().to_date(options).into()
29    }
30
31    #[pyo3(signature = (format, time_unit, time_zone, strict, exact, cache, ambiguous))]
32    fn str_to_datetime(
33        &self,
34        format: Option<String>,
35        time_unit: Option<Wrap<TimeUnit>>,
36        time_zone: Wrap<Option<TimeZone>>,
37        strict: bool,
38        exact: bool,
39        cache: bool,
40        ambiguous: Self,
41    ) -> Self {
42        let format = format.map(|x| x.into());
43        let time_zone = time_zone.0;
44
45        let options = StrptimeOptions {
46            format,
47            strict,
48            exact,
49            cache,
50        };
51        self.inner
52            .clone()
53            .str()
54            .to_datetime(
55                time_unit.map(|tu| tu.0),
56                time_zone,
57                options,
58                ambiguous.inner,
59            )
60            .into()
61    }
62
63    #[pyo3(signature = (format, strict, cache))]
64    fn str_to_time(&self, format: Option<String>, strict: bool, cache: bool) -> Self {
65        let format = format.map(|x| x.into());
66
67        let options = StrptimeOptions {
68            format,
69            strict,
70            cache,
71            exact: true,
72        };
73        self.inner.clone().str().to_time(options).into()
74    }
75
76    fn str_strip_chars(&self, matches: Self) -> Self {
77        self.inner.clone().str().strip_chars(matches.inner).into()
78    }
79
80    fn str_strip_chars_start(&self, matches: Self) -> Self {
81        self.inner
82            .clone()
83            .str()
84            .strip_chars_start(matches.inner)
85            .into()
86    }
87
88    fn str_strip_chars_end(&self, matches: Self) -> Self {
89        self.inner
90            .clone()
91            .str()
92            .strip_chars_end(matches.inner)
93            .into()
94    }
95
96    fn str_strip_prefix(&self, prefix: Self) -> Self {
97        self.inner.clone().str().strip_prefix(prefix.inner).into()
98    }
99
100    fn str_strip_suffix(&self, suffix: Self) -> Self {
101        self.inner.clone().str().strip_suffix(suffix.inner).into()
102    }
103
104    fn str_slice(&self, offset: Self, length: Self) -> Self {
105        self.inner
106            .clone()
107            .str()
108            .slice(offset.inner, length.inner)
109            .into()
110    }
111
112    fn str_head(&self, n: Self) -> Self {
113        self.inner.clone().str().head(n.inner).into()
114    }
115
116    fn str_tail(&self, n: Self) -> Self {
117        self.inner.clone().str().tail(n.inner).into()
118    }
119
120    fn str_to_uppercase(&self) -> Self {
121        self.inner.clone().str().to_uppercase().into()
122    }
123
124    fn str_to_lowercase(&self) -> Self {
125        self.inner.clone().str().to_lowercase().into()
126    }
127
128    #[cfg(feature = "nightly")]
129    fn str_to_titlecase(&self) -> Self {
130        self.inner.clone().str().to_titlecase().into()
131    }
132
133    fn str_len_bytes(&self) -> Self {
134        self.inner.clone().str().len_bytes().into()
135    }
136
137    fn str_len_chars(&self) -> Self {
138        self.inner.clone().str().len_chars().into()
139    }
140
141    #[cfg(feature = "regex")]
142    fn str_replace_n(&self, pat: Self, val: Self, literal: bool, n: i64) -> Self {
143        self.inner
144            .clone()
145            .str()
146            .replace_n(pat.inner, val.inner, literal, n)
147            .into()
148    }
149
150    #[cfg(feature = "regex")]
151    fn str_replace_all(&self, pat: Self, val: Self, literal: bool) -> Self {
152        self.inner
153            .clone()
154            .str()
155            .replace_all(pat.inner, val.inner, literal)
156            .into()
157    }
158
159    fn str_normalize(&self, form: Wrap<UnicodeForm>) -> Self {
160        self.inner.clone().str().normalize(form.0).into()
161    }
162
163    fn str_reverse(&self) -> Self {
164        self.inner.clone().str().reverse().into()
165    }
166
167    fn str_pad_start(&self, length: usize, fill_char: char) -> Self {
168        self.inner.clone().str().pad_start(length, fill_char).into()
169    }
170
171    fn str_pad_end(&self, length: usize, fill_char: char) -> Self {
172        self.inner.clone().str().pad_end(length, fill_char).into()
173    }
174
175    fn str_zfill(&self, length: Self) -> Self {
176        self.inner.clone().str().zfill(length.inner).into()
177    }
178
179    #[pyo3(signature = (pat, literal, strict))]
180    #[cfg(feature = "regex")]
181    fn str_contains(&self, pat: Self, literal: Option<bool>, strict: bool) -> Self {
182        match literal {
183            Some(true) => self.inner.clone().str().contains_literal(pat.inner).into(),
184            _ => self.inner.clone().str().contains(pat.inner, strict).into(),
185        }
186    }
187
188    #[pyo3(signature = (pat, literal, strict))]
189    #[cfg(feature = "regex")]
190    fn str_find(&self, pat: Self, literal: Option<bool>, strict: bool) -> Self {
191        match literal {
192            Some(true) => self.inner.clone().str().find_literal(pat.inner).into(),
193            _ => self.inner.clone().str().find(pat.inner, strict).into(),
194        }
195    }
196
197    fn str_ends_with(&self, sub: Self) -> Self {
198        self.inner.clone().str().ends_with(sub.inner).into()
199    }
200
201    fn str_starts_with(&self, sub: Self) -> Self {
202        self.inner.clone().str().starts_with(sub.inner).into()
203    }
204
205    fn str_hex_encode(&self) -> Self {
206        self.inner.clone().str().hex_encode().into()
207    }
208
209    #[cfg(feature = "binary_encoding")]
210    fn str_hex_decode(&self, strict: bool) -> Self {
211        self.inner.clone().str().hex_decode(strict).into()
212    }
213
214    fn str_base64_encode(&self) -> Self {
215        self.inner.clone().str().base64_encode().into()
216    }
217
218    #[cfg(feature = "binary_encoding")]
219    fn str_base64_decode(&self, strict: bool) -> Self {
220        self.inner.clone().str().base64_decode(strict).into()
221    }
222
223    fn str_to_integer(&self, base: Self, strict: bool) -> Self {
224        self.inner
225            .clone()
226            .str()
227            .to_integer(base.inner, strict)
228            .with_fmt("str.to_integer")
229            .into()
230    }
231
232    #[cfg(feature = "extract_jsonpath")]
233    #[pyo3(signature = (dtype=None, infer_schema_len=None))]
234    fn str_json_decode(
235        &self,
236        dtype: Option<Wrap<DataType>>,
237        infer_schema_len: Option<usize>,
238    ) -> Self {
239        let dtype = dtype.map(|wrap| wrap.0);
240        self.inner
241            .clone()
242            .str()
243            .json_decode(dtype, infer_schema_len)
244            .into()
245    }
246
247    #[cfg(feature = "extract_jsonpath")]
248    fn str_json_path_match(&self, pat: Self) -> Self {
249        self.inner.clone().str().json_path_match(pat.inner).into()
250    }
251
252    fn str_extract(&self, pat: Self, group_index: usize) -> Self {
253        self.inner
254            .clone()
255            .str()
256            .extract(pat.inner, group_index)
257            .into()
258    }
259
260    fn str_extract_all(&self, pat: Self) -> Self {
261        self.inner.clone().str().extract_all(pat.inner).into()
262    }
263
264    #[cfg(feature = "extract_groups")]
265    fn str_extract_groups(&self, pat: &str) -> PyResult<Self> {
266        Ok(self
267            .inner
268            .clone()
269            .str()
270            .extract_groups(pat)
271            .map_err(PyPolarsErr::from)?
272            .into())
273    }
274
275    fn str_count_matches(&self, pat: Self, literal: bool) -> Self {
276        self.inner
277            .clone()
278            .str()
279            .count_matches(pat.inner, literal)
280            .into()
281    }
282
283    fn str_split(&self, by: Self) -> Self {
284        self.inner.clone().str().split(by.inner).into()
285    }
286
287    fn str_split_inclusive(&self, by: Self) -> Self {
288        self.inner.clone().str().split_inclusive(by.inner).into()
289    }
290
291    fn str_split_exact(&self, by: Self, n: usize) -> Self {
292        self.inner.clone().str().split_exact(by.inner, n).into()
293    }
294
295    fn str_split_exact_inclusive(&self, by: Self, n: usize) -> Self {
296        self.inner
297            .clone()
298            .str()
299            .split_exact_inclusive(by.inner, n)
300            .into()
301    }
302
303    fn str_splitn(&self, by: Self, n: usize) -> Self {
304        self.inner.clone().str().splitn(by.inner, n).into()
305    }
306
307    fn str_to_decimal(&self, infer_len: usize) -> Self {
308        self.inner.clone().str().to_decimal(infer_len).into()
309    }
310
311    #[cfg(feature = "find_many")]
312    fn str_contains_any(&self, patterns: PyExpr, ascii_case_insensitive: bool) -> Self {
313        self.inner
314            .clone()
315            .str()
316            .contains_any(patterns.inner, ascii_case_insensitive)
317            .into()
318    }
319    #[cfg(feature = "find_many")]
320    fn str_replace_many(
321        &self,
322        patterns: PyExpr,
323        replace_with: PyExpr,
324        ascii_case_insensitive: bool,
325    ) -> Self {
326        self.inner
327            .clone()
328            .str()
329            .replace_many(patterns.inner, replace_with.inner, ascii_case_insensitive)
330            .into()
331    }
332
333    #[cfg(feature = "find_many")]
334    fn str_extract_many(
335        &self,
336        patterns: PyExpr,
337        ascii_case_insensitive: bool,
338        overlapping: bool,
339    ) -> Self {
340        self.inner
341            .clone()
342            .str()
343            .extract_many(patterns.inner, ascii_case_insensitive, overlapping)
344            .into()
345    }
346
347    #[cfg(feature = "find_many")]
348    fn str_find_many(
349        &self,
350        patterns: PyExpr,
351        ascii_case_insensitive: bool,
352        overlapping: bool,
353    ) -> Self {
354        self.inner
355            .clone()
356            .str()
357            .find_many(patterns.inner, ascii_case_insensitive, overlapping)
358            .into()
359    }
360
361    #[cfg(feature = "regex")]
362    fn str_escape_regex(&self) -> Self {
363        self.inner.clone().str().escape_regex().into()
364    }
365}