Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-plan/src/dsl/format.rs
8327 views
1
use std::fmt::{self, Write};
2
3
use crate::prelude::*;
4
5
/// Wrapper for formatting expressions with comma-separated arguments; also
6
/// streamlines column refs to their quoted names (e.g.: `col("x") -> "x").
7
struct FmtArgs<'a>(&'a [Expr]);
8
9
impl fmt::Display for FmtArgs<'_> {
10
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11
for (i, expr) in self.0.iter().enumerate() {
12
if i > 0 {
13
f.write_str(", ")?;
14
}
15
match expr {
16
// unpack column to name...
17
Expr::Column(name) => write!(f, "\"{name}\"")?,
18
// ...leaving other expressions as-is
19
other => write!(f, "{other:?}")?,
20
}
21
}
22
Ok(())
23
}
24
}
25
26
impl fmt::Display for Expr {
27
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28
fmt::Debug::fmt(self, f)
29
}
30
}
31
32
impl fmt::Debug for Expr {
33
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34
use Expr::*;
35
match self {
36
Element => f.write_str("element()"),
37
#[cfg(feature = "dynamic_group_by")]
38
Rolling {
39
function,
40
index_column,
41
period,
42
offset,
43
closed_window: _,
44
} => {
45
write!(
46
f,
47
"{:?}.rolling(by='{}', offset={}, period={})",
48
function, index_column, offset, period
49
)
50
},
51
Over {
52
function,
53
partition_by,
54
order_by,
55
mapping: _,
56
} => {
57
if let Some((order_by, _)) = order_by {
58
write!(
59
f,
60
"{function:?}.over(partition_by: {partition_by:?}, order_by: {order_by:?})"
61
)
62
} else {
63
write!(f, "{function:?}.over({partition_by:?})")
64
}
65
},
66
DataTypeFunction(dtype_fn) => fmt::Debug::fmt(dtype_fn, f),
67
Len => write!(f, "len()"),
68
Explode {
69
input: expr,
70
options,
71
} => {
72
write!(f, "{expr:?}.explode(")?;
73
if !options.empty_as_null {
74
f.write_str("empty_as_null=false")?;
75
}
76
if !options.keep_nulls {
77
if options.empty_as_null {
78
f.write_str(", ")?;
79
}
80
f.write_str("keep_nulls=false")?;
81
}
82
f.write_char(')')
83
},
84
Alias(expr, name) => write!(f, "{expr:?}.alias(\"{name}\")"),
85
Column(name) => write!(f, "col(\"{name}\")"),
86
Literal(v) => write!(f, "{v:?}"),
87
BinaryExpr { left, op, right } => write!(f, "[({left:?}) {op:?} ({right:?})]"),
88
Sort { expr, options } => {
89
if options.descending {
90
write!(f, "{expr:?}.sort(desc)")
91
} else {
92
write!(f, "{expr:?}.sort(asc)")
93
}
94
},
95
SortBy {
96
expr,
97
by,
98
sort_options,
99
} => {
100
write!(
101
f,
102
"{expr:?}.sort_by(by={by:?}, sort_option={sort_options:?})",
103
)
104
},
105
Filter { input, by } => {
106
write!(f, "{input:?}.filter({by:?})")
107
},
108
Gather {
109
expr,
110
idx,
111
returns_scalar,
112
null_on_oob,
113
} => {
114
if *returns_scalar {
115
if *null_on_oob {
116
write!(f, "{expr:?}.get({idx:?}, null_on_oob=true)")
117
} else {
118
write!(f, "{expr:?}.get({idx:?})")
119
}
120
} else if *null_on_oob {
121
write!(f, "{expr:?}.gather({idx:?}, null_on_oob=true)")
122
} else {
123
write!(f, "{expr:?}.gather({idx:?})")
124
}
125
},
126
SubPlan(lf, _) => {
127
write!(f, ".subplan({lf:?})")
128
},
129
Agg(agg) => {
130
use AggExpr::*;
131
match agg {
132
Min {
133
input,
134
propagate_nans,
135
} => {
136
if *propagate_nans {
137
write!(f, "{input:?}.nan_min()")
138
} else {
139
write!(f, "{input:?}.min()")
140
}
141
},
142
Max {
143
input,
144
propagate_nans,
145
} => {
146
if *propagate_nans {
147
write!(f, "{input:?}.nan_max()")
148
} else {
149
write!(f, "{input:?}.max()")
150
}
151
},
152
Median(expr) => write!(f, "{expr:?}.median()"),
153
Mean(expr) => write!(f, "{expr:?}.mean()"),
154
First(expr) => write!(f, "{expr:?}.first()"),
155
FirstNonNull(expr) => write!(f, "{expr:?}.first_non_null()"),
156
Last(expr) => write!(f, "{expr:?}.last()"),
157
LastNonNull(expr) => write!(f, "{expr:?}.last_non_null()"),
158
Item { input, allow_empty } => {
159
if *allow_empty {
160
write!(f, "{input:?}.item(allow_empty=true)")
161
} else {
162
write!(f, "{input:?}.item()")
163
}
164
},
165
Implode(expr) => write!(f, "{expr:?}.list()"),
166
NUnique(expr) => write!(f, "{expr:?}.n_unique()"),
167
Sum(expr) => write!(f, "{expr:?}.sum()"),
168
AggGroups(expr) => write!(f, "{expr:?}.groups()"),
169
Count {
170
input,
171
include_nulls: false,
172
} => write!(f, "{input:?}.count()"),
173
Count {
174
input,
175
include_nulls: true,
176
} => write!(f, "{input:?}.len()"),
177
Var(expr, _) => write!(f, "{expr:?}.var()"),
178
Std(expr, _) => write!(f, "{expr:?}.std()"),
179
Quantile { expr, .. } => write!(f, "{expr:?}.quantile()"),
180
}
181
},
182
Cast {
183
expr,
184
dtype,
185
options,
186
} => {
187
if options.is_strict() {
188
write!(f, "{expr:?}.strict_cast({dtype:?})")
189
} else {
190
write!(f, "{expr:?}.cast({dtype:?})")
191
}
192
},
193
Ternary {
194
predicate,
195
truthy,
196
falsy,
197
} => write!(
198
f,
199
".when({predicate:?}).then({truthy:?}).otherwise({falsy:?})",
200
),
201
Function { input, function } => {
202
#[cfg(feature = "dtype-struct")]
203
if matches!(function, FunctionExpr::AsStruct) {
204
return write!(f, "as_struct({})", FmtArgs(input));
205
}
206
207
match input.len() {
208
0 => write!(f, "{function}()"),
209
1 => write!(f, "{:?}.{function}()", input[0]),
210
_ => write!(f, "{:?}.{function}({:?})", input[0], &input[1..]),
211
}
212
},
213
Display {
214
inputs, fmt_str, ..
215
} => match inputs.len() {
216
0 => write!(f, "{fmt_str}()"),
217
1 => write!(f, "{:?}.{fmt_str}()", inputs[0]),
218
_ => write!(f, "{:?}.{fmt_str}({:?})", inputs[0], &inputs[1..]),
219
},
220
AnonymousFunction {
221
input,
222
fmt_str,
223
function,
224
..
225
} => {
226
let name = match function {
227
LazySerde::Named { name, .. } => name.as_str(),
228
_ => fmt_str.as_str(),
229
};
230
231
match input.len() {
232
0 => write!(f, "{name}()"),
233
1 => write!(f, "{:?}.{name}()", input[0]),
234
_ => write!(f, "{:?}.{name}({:?})", input[0], &input[1..]),
235
}
236
},
237
Eval {
238
expr: input,
239
evaluation,
240
variant,
241
} => match variant {
242
EvalVariant::List => write!(f, "{input:?}.list.eval({evaluation:?})"),
243
EvalVariant::ListAgg => write!(f, "{input:?}.list.agg({evaluation:?})"),
244
EvalVariant::Array { as_list: false } => {
245
write!(f, "{input:?}.arr.eval({evaluation:?})")
246
},
247
EvalVariant::Array { as_list: true } => {
248
write!(f, "{input:?}.arr.eval({evaluation:?}, as_list=true)")
249
},
250
EvalVariant::ArrayAgg => write!(f, "{input:?}.arr.agg({evaluation:?})"),
251
EvalVariant::Cumulative { min_samples } => write!(
252
f,
253
"{input:?}.Cumulative_eval({evaluation:?}, min_samples={min_samples}"
254
),
255
},
256
#[cfg(feature = "dtype-struct")]
257
StructEval {
258
expr: input,
259
evaluation,
260
} => {
261
write!(f, "{input:?}.struct.eval({evaluation:?}")
262
},
263
Slice {
264
input,
265
offset,
266
length,
267
} => write!(f, "{input:?}.slice(offset={offset:?}, length={length:?})",),
268
KeepName(e) => write!(f, "{e:?}.name.keep()"),
269
RenameAlias { expr, function } => match function {
270
RenameAliasFn::Prefix(s) => write!(f, "{expr:?}.name.prefix({s})"),
271
RenameAliasFn::Suffix(s) => write!(f, "{expr:?}.name.suffix({s})"),
272
RenameAliasFn::ToLowercase => write!(f, "{expr:?}.name.to_lowercase()"),
273
RenameAliasFn::ToUppercase => write!(f, "{expr:?}.name.to_uppercase()"),
274
RenameAliasFn::Map(_) => write!(f, "{expr:?}.name.map()"),
275
RenameAliasFn::Replace {
276
pattern,
277
value,
278
literal: false,
279
} => write!(f, "{expr:?}.replace(\"{pattern}\", \"{value}\")"),
280
RenameAliasFn::Replace {
281
pattern,
282
value,
283
literal: true,
284
} => write!(
285
f,
286
"{expr:?}.replace(\"{pattern}\", \"{value}\", literal=true)"
287
),
288
},
289
Selector(s) => fmt::Display::fmt(s, f),
290
#[cfg(feature = "dtype-struct")]
291
Field(names) => write!(f, "pl.field({names:?})"),
292
}
293
}
294
}
295
296