polars_plan/dsl/
format.rs

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}