1use std::fmt;
2
3use crate::prelude::*;
4
5impl fmt::Display for Expr {
6 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7 fmt::Debug::fmt(self, f)
8 }
9}
10
11impl fmt::Debug for Expr {
12 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
13 use Expr::*;
14 match self {
15 Window {
16 function,
17 partition_by,
18 order_by,
19 options,
20 } => match options {
21 #[cfg(feature = "dynamic_group_by")]
22 WindowType::Rolling(options) => {
23 write!(
24 f,
25 "{:?}.rolling(by='{}', offset={}, period={})",
26 function, options.index_column, options.offset, options.period
27 )
28 },
29 _ => {
30 if let Some((order_by, _)) = order_by {
31 write!(
32 f,
33 "{function:?}.over(partition_by: {partition_by:?}, order_by: {order_by:?})"
34 )
35 } else {
36 write!(f, "{function:?}.over({partition_by:?})")
37 }
38 },
39 },
40 DataTypeFunction(dtype_fn) => fmt::Debug::fmt(dtype_fn, f),
41 Len => write!(f, "len()"),
42 Explode {
43 input: expr,
44 skip_empty: false,
45 } => write!(f, "{expr:?}.explode()"),
46 Explode {
47 input: expr,
48 skip_empty: true,
49 } => write!(f, "{expr:?}.explode(skip_empty)"),
50 Alias(expr, name) => write!(f, "{expr:?}.alias(\"{name}\")"),
51 Column(name) => write!(f, "col(\"{name}\")"),
52 Literal(v) => write!(f, "{v:?}"),
53 BinaryExpr { left, op, right } => write!(f, "[({left:?}) {op:?} ({right:?})]"),
54 Sort { expr, options } => {
55 if options.descending {
56 write!(f, "{expr:?}.sort(desc)")
57 } else {
58 write!(f, "{expr:?}.sort(asc)")
59 }
60 },
61 SortBy {
62 expr,
63 by,
64 sort_options,
65 } => {
66 write!(
67 f,
68 "{expr:?}.sort_by(by={by:?}, sort_option={sort_options:?})",
69 )
70 },
71 Filter { input, by } => {
72 write!(f, "{input:?}.filter({by:?})")
73 },
74 Gather {
75 expr,
76 idx,
77 returns_scalar,
78 } => {
79 if *returns_scalar {
80 write!(f, "{expr:?}.get({idx:?})")
81 } else {
82 write!(f, "{expr:?}.gather({idx:?})")
83 }
84 },
85 SubPlan(lf, _) => {
86 write!(f, ".subplan({lf:?})")
87 },
88 Agg(agg) => {
89 use AggExpr::*;
90 match agg {
91 Min {
92 input,
93 propagate_nans,
94 } => {
95 if *propagate_nans {
96 write!(f, "{input:?}.nan_min()")
97 } else {
98 write!(f, "{input:?}.min()")
99 }
100 },
101 Max {
102 input,
103 propagate_nans,
104 } => {
105 if *propagate_nans {
106 write!(f, "{input:?}.nan_max()")
107 } else {
108 write!(f, "{input:?}.max()")
109 }
110 },
111 Median(expr) => write!(f, "{expr:?}.median()"),
112 Mean(expr) => write!(f, "{expr:?}.mean()"),
113 First(expr) => write!(f, "{expr:?}.first()"),
114 Last(expr) => write!(f, "{expr:?}.last()"),
115 Implode(expr) => write!(f, "{expr:?}.list()"),
116 NUnique(expr) => write!(f, "{expr:?}.n_unique()"),
117 Sum(expr) => write!(f, "{expr:?}.sum()"),
118 AggGroups(expr) => write!(f, "{expr:?}.groups()"),
119 Count(expr, _) => write!(f, "{expr:?}.count()"),
120 Var(expr, _) => write!(f, "{expr:?}.var()"),
121 Std(expr, _) => write!(f, "{expr:?}.std()"),
122 Quantile { expr, .. } => write!(f, "{expr:?}.quantile()"),
123 }
124 },
125 Cast {
126 expr,
127 dtype,
128 options,
129 } => {
130 if options.is_strict() {
131 write!(f, "{expr:?}.strict_cast({dtype:?})")
132 } else {
133 write!(f, "{expr:?}.cast({dtype:?})")
134 }
135 },
136 Ternary {
137 predicate,
138 truthy,
139 falsy,
140 } => write!(
141 f,
142 ".when({predicate:?}).then({truthy:?}).otherwise({falsy:?})",
143 ),
144 Function { input, function } => {
145 if input.len() >= 2 {
146 write!(f, "{:?}.{function}({:?})", input[0], &input[1..])
147 } else {
148 write!(f, "{:?}.{function}()", input[0])
149 }
150 },
151 AnonymousFunction {
152 input,
153 fmt_str,
154 function,
155 ..
156 } => {
157 let name = match function {
158 LazySerde::Named { name, .. } => name.as_str(),
159 _ => fmt_str.as_str(),
160 };
161
162 if input.len() >= 2 {
163 write!(f, "{:?}.{}({:?})", input[0], name, &input[1..])
164 } else {
165 write!(f, "{:?}.{}()", input[0], name)
166 }
167 },
168 Eval {
169 expr: input,
170 evaluation,
171 variant,
172 } => match variant {
173 EvalVariant::List => write!(f, "{input:?}.list.eval({evaluation:?})"),
174 EvalVariant::Cumulative { min_samples } => write!(
175 f,
176 "{input:?}.Cumulative_eval({evaluation:?}, min_samples={min_samples}"
177 ),
178 },
179 Slice {
180 input,
181 offset,
182 length,
183 } => write!(f, "{input:?}.slice(offset={offset:?}, length={length:?})",),
184 KeepName(e) => write!(f, "{e:?}.name.keep()"),
185 RenameAlias { expr, function } => match function {
186 RenameAliasFn::Prefix(s) => write!(f, "{expr:?}.prefix({s})"),
187 RenameAliasFn::Suffix(s) => write!(f, "{expr:?}.suffix({s})"),
188 RenameAliasFn::ToLowercase => write!(f, "{expr:?}.to_lowercase()"),
189 RenameAliasFn::ToUppercase => write!(f, "{expr:?}.to_uppercase()"),
190 #[cfg(feature = "python")]
191 RenameAliasFn::Python(_) => write!(f, "{expr:?}.rename_alias()"),
192 RenameAliasFn::Rust(_) => write!(f, "{expr:?}.rename_alias()"),
193 },
194 Selector(s) => fmt::Display::fmt(s, f),
195 #[cfg(feature = "dtype-struct")]
196 Field(names) => write!(f, "pl.field({names:?})"),
197 }
198 }
199}