gesp/
python.rs

1use crate::{
2    ParseableLanguage,
3    config::{
4        ConfigurableLanguage, Formattable, FormattableVec, PrettyPrintError, fill_in_to_pretty,
5    },
6    format::EmptyPlaceholder,
7    formats::formattable_vec,
8};
9
10pub struct Python {
11    module: Vec<rustpython_ast::Stmt>,
12}
13
14pub type PythonParseError = crate::LanguageParseError<rustpython_parser::ParseError>;
15
16impl ParseableLanguage for Python {
17    type CustomError = rustpython_parser::ParseError;
18
19    fn parse(s: &str) -> Result<Self, crate::LanguageParseError<Self::CustomError>> {
20        use rustpython_ast::Mod;
21        use rustpython_parser::{Mode, lexer::lex, parse_tokens};
22
23        let tokens = lex(s, Mode::Expression);
24        let ast = parse_tokens(tokens, Mode::Module, "<embedded>")
25            .map_err(crate::LanguageParseError::Custom)?;
26        match ast {
27            Mod::Module(m) => Ok(Self { module: m.body }),
28            _ => Err(crate::LanguageParseError::ParserError),
29        }
30    }
31}
32
33impl ConfigurableLanguage for Python {
34    type Formats = PythonFormats;
35
36    fn pretty_print<W: std::fmt::Write>(
37        &self,
38        f: &mut W,
39        config: &Self::Formats,
40    ) -> Result<(), PrettyPrintError> {
41        for (idx, stmt) in self.module.iter().enumerate() {
42            if idx > 0 {
43                f.write_char('\n').map_err(PrettyPrintError::Fmt)?;
44            }
45            stmt.pretty_print(f, config)?;
46        }
47        Ok(())
48    }
49}
50
51impl ConfigurableLanguage for rustpython_ast::Stmt {
52    type Formats = PythonFormats;
53
54    fn pretty_print<W: std::fmt::Write>(
55        &self,
56        f: &mut W,
57        formats: &Self::Formats,
58    ) -> Result<(), PrettyPrintError> {
59        match self {
60            rustpython_ast::Stmt::FunctionDef(stmt_function_def) => f
61                .write_str(&stmt_function_def.format(formats)?)
62                .map_err(PrettyPrintError::Fmt),
63            rustpython_ast::Stmt::AsyncFunctionDef(stmt_async_function_def) => f
64                .write_str(&stmt_async_function_def.format(formats)?)
65                .map_err(PrettyPrintError::Fmt),
66            rustpython_ast::Stmt::ClassDef(stmt_class_def) => f
67                .write_str(&stmt_class_def.format(formats)?)
68                .map_err(PrettyPrintError::Fmt),
69            rustpython_ast::Stmt::Return(stmt_return) => f
70                .write_str(&stmt_return.format(formats)?)
71                .map_err(PrettyPrintError::Fmt),
72            rustpython_ast::Stmt::Delete(stmt_delete) => f
73                .write_str(&stmt_delete.format(formats)?)
74                .map_err(PrettyPrintError::Fmt),
75            rustpython_ast::Stmt::Assign(stmt_assign) => f
76                .write_str(&stmt_assign.format(formats)?)
77                .map_err(PrettyPrintError::Fmt),
78            rustpython_ast::Stmt::TypeAlias(stmt_type_alias) => f
79                .write_str(&stmt_type_alias.format(formats)?)
80                .map_err(PrettyPrintError::Fmt),
81            rustpython_ast::Stmt::AugAssign(stmt_aug_assign) => f
82                .write_str(&stmt_aug_assign.format(formats)?)
83                .map_err(PrettyPrintError::Fmt),
84            rustpython_ast::Stmt::AnnAssign(stmt_ann_assign) => f
85                .write_str(&stmt_ann_assign.format(formats)?)
86                .map_err(PrettyPrintError::Fmt),
87            rustpython_ast::Stmt::For(stmt_for) => f
88                .write_str(&stmt_for.format(formats)?)
89                .map_err(PrettyPrintError::Fmt),
90            rustpython_ast::Stmt::AsyncFor(stmt_async_for) => f
91                .write_str(&stmt_async_for.format(formats)?)
92                .map_err(PrettyPrintError::Fmt),
93            rustpython_ast::Stmt::While(stmt_while) => f
94                .write_str(&stmt_while.format(formats)?)
95                .map_err(PrettyPrintError::Fmt),
96            rustpython_ast::Stmt::If(stmt_if) => if stmt_if.orelse.is_empty() {
97                f.write_str(
98                    &IfWithoutElse {
99                        test: *stmt_if.test.clone(),
100                        body: stmt_if.body.clone(),
101                    }
102                    .format(formats)?,
103                )
104            } else {
105                f.write_str(
106                    &IfWithElse {
107                        test: *stmt_if.test.clone(),
108                        body: stmt_if.body.clone(),
109                        orelse: stmt_if.orelse.clone(),
110                    }
111                    .format(formats)?,
112                )
113            }
114            .map_err(PrettyPrintError::Fmt),
115            rustpython_ast::Stmt::With(stmt_with) => f
116                .write_str(&stmt_with.format(formats)?)
117                .map_err(PrettyPrintError::Fmt),
118            rustpython_ast::Stmt::AsyncWith(stmt_async_with) => f
119                .write_str(&stmt_async_with.format(formats)?)
120                .map_err(PrettyPrintError::Fmt),
121            rustpython_ast::Stmt::Match(stmt_match) => f
122                .write_str(&stmt_match.format(formats)?)
123                .map_err(PrettyPrintError::Fmt),
124            rustpython_ast::Stmt::Raise(stmt_raise) => f
125                .write_str(&stmt_raise.format(formats)?)
126                .map_err(PrettyPrintError::Fmt),
127            rustpython_ast::Stmt::Try(stmt_try) => f
128                .write_str(&stmt_try.format(formats)?)
129                .map_err(PrettyPrintError::Fmt),
130            rustpython_ast::Stmt::TryStar(stmt_try_star) => f
131                .write_str(&stmt_try_star.format(formats)?)
132                .map_err(PrettyPrintError::Fmt),
133            rustpython_ast::Stmt::Assert(stmt_assert) => f
134                .write_str(&stmt_assert.format(formats)?)
135                .map_err(PrettyPrintError::Fmt),
136            rustpython_ast::Stmt::Import(stmt_import) => f
137                .write_str(&stmt_import.format(formats)?)
138                .map_err(PrettyPrintError::Fmt),
139            rustpython_ast::Stmt::ImportFrom(stmt_import_from) => f
140                .write_str(&stmt_import_from.format(formats)?)
141                .map_err(PrettyPrintError::Fmt),
142            rustpython_ast::Stmt::Global(stmt_global) => f
143                .write_str(&stmt_global.format(formats)?)
144                .map_err(PrettyPrintError::Fmt),
145            rustpython_ast::Stmt::Nonlocal(stmt_nonlocal) => f
146                .write_str(&stmt_nonlocal.format(formats)?)
147                .map_err(PrettyPrintError::Fmt),
148            rustpython_ast::Stmt::Expr(stmt_expr) => f
149                .write_str(&stmt_expr.format(formats)?)
150                .map_err(PrettyPrintError::Fmt),
151            rustpython_ast::Stmt::Pass(stmt_pass) => f
152                .write_str(&stmt_pass.format(formats)?)
153                .map_err(PrettyPrintError::Fmt),
154            rustpython_ast::Stmt::Break(stmt_break) => f
155                .write_str(&stmt_break.format(formats)?)
156                .map_err(PrettyPrintError::Fmt),
157            rustpython_ast::Stmt::Continue(stmt_continue) => f
158                .write_str(&stmt_continue.format(formats)?)
159                .map_err(PrettyPrintError::Fmt),
160        }
161    }
162}
163
164impl ConfigurableLanguage for rustpython_ast::Expr {
165    type Formats = PythonFormats;
166
167    fn pretty_print<W: std::fmt::Write>(
168        &self,
169        f: &mut W,
170        formats: &Self::Formats,
171    ) -> Result<(), PrettyPrintError> {
172        match self {
173            rustpython_ast::Expr::BoolOp(expr_bool_op) => f
174                .write_str(&match expr_bool_op.op {
175                    rustpython_ast::BoolOp::And => AndExpression {
176                        operands: expr_bool_op.values.clone(),
177                    }
178                    .format(formats)?,
179                    rustpython_ast::BoolOp::Or => OrExpression {
180                        operands: expr_bool_op.values.clone(),
181                    }
182                    .format(formats)?,
183                })
184                .map_err(PrettyPrintError::Fmt),
185            rustpython_ast::Expr::NamedExpr(expr_named_expr) => f
186                .write_str(&expr_named_expr.format(formats)?)
187                .map_err(PrettyPrintError::Fmt),
188            rustpython_ast::Expr::BinOp(expr_bin_op) => f
189                .write_str(&match expr_bin_op.op {
190                    rustpython_ast::Operator::Add => AddExpression {
191                        left: *expr_bin_op.left.clone(),
192                        right: *expr_bin_op.right.clone(),
193                    }
194                    .format(formats)?,
195                    rustpython_ast::Operator::Sub => SubExpression {
196                        left: *expr_bin_op.left.clone(),
197                        right: *expr_bin_op.right.clone(),
198                    }
199                    .format(formats)?,
200                    rustpython_ast::Operator::Mult => MultExpression {
201                        left: *expr_bin_op.left.clone(),
202                        right: *expr_bin_op.right.clone(),
203                    }
204                    .format(formats)?,
205                    rustpython_ast::Operator::MatMult => MatMultExpression {
206                        left: *expr_bin_op.left.clone(),
207                        right: *expr_bin_op.right.clone(),
208                    }
209                    .format(formats)?,
210                    rustpython_ast::Operator::Div => DivExpression {
211                        left: *expr_bin_op.left.clone(),
212                        right: *expr_bin_op.right.clone(),
213                    }
214                    .format(formats)?,
215                    rustpython_ast::Operator::Mod => ModExpression {
216                        left: *expr_bin_op.left.clone(),
217                        right: *expr_bin_op.right.clone(),
218                    }
219                    .format(formats)?,
220                    rustpython_ast::Operator::Pow => PowExpression {
221                        left: *expr_bin_op.left.clone(),
222                        right: *expr_bin_op.right.clone(),
223                    }
224                    .format(formats)?,
225                    rustpython_ast::Operator::LShift => LShiftExpression {
226                        left: *expr_bin_op.left.clone(),
227                        right: *expr_bin_op.right.clone(),
228                    }
229                    .format(formats)?,
230                    rustpython_ast::Operator::RShift => RShiftExpression {
231                        left: *expr_bin_op.left.clone(),
232                        right: *expr_bin_op.right.clone(),
233                    }
234                    .format(formats)?,
235                    rustpython_ast::Operator::BitOr => BitOrExpression {
236                        left: *expr_bin_op.left.clone(),
237                        right: *expr_bin_op.right.clone(),
238                    }
239                    .format(formats)?,
240                    rustpython_ast::Operator::BitXor => BitXorExpression {
241                        left: *expr_bin_op.left.clone(),
242                        right: *expr_bin_op.right.clone(),
243                    }
244                    .format(formats)?,
245                    rustpython_ast::Operator::BitAnd => BitAndExpression {
246                        left: *expr_bin_op.left.clone(),
247                        right: *expr_bin_op.right.clone(),
248                    }
249                    .format(formats)?,
250                    rustpython_ast::Operator::FloorDiv => FloorDivExpression {
251                        left: *expr_bin_op.left.clone(),
252                        right: *expr_bin_op.right.clone(),
253                    }
254                    .format(formats)?,
255                })
256                .map_err(PrettyPrintError::Fmt),
257            rustpython_ast::Expr::UnaryOp(expr_unary_op) => f
258                .write_str(&match expr_unary_op.op {
259                    rustpython_ast::UnaryOp::Invert => InvertExpression {
260                        operand: *expr_unary_op.operand.clone(),
261                    }
262                    .format(formats)?,
263                    rustpython_ast::UnaryOp::Not => NotExpression {
264                        operand: *expr_unary_op.operand.clone(),
265                    }
266                    .format(formats)?,
267                    rustpython_ast::UnaryOp::UAdd => UnaryAddExpression {
268                        operand: *expr_unary_op.operand.clone(),
269                    }
270                    .format(formats)?,
271                    rustpython_ast::UnaryOp::USub => UnarySubExpression {
272                        operand: *expr_unary_op.operand.clone(),
273                    }
274                    .format(formats)?,
275                })
276                .map_err(PrettyPrintError::Fmt),
277            rustpython_ast::Expr::Lambda(expr_lambda) => f
278                .write_str(&expr_lambda.format(formats)?)
279                .map_err(PrettyPrintError::Fmt),
280            rustpython_ast::Expr::IfExp(expr_if_exp) => f
281                .write_str(&expr_if_exp.format(formats)?)
282                .map_err(PrettyPrintError::Fmt),
283            rustpython_ast::Expr::Dict(expr_dict) => f
284                .write_str(&expr_dict.format(formats)?)
285                .map_err(PrettyPrintError::Fmt),
286            rustpython_ast::Expr::Set(expr_set) => f
287                .write_str(&expr_set.format(formats)?)
288                .map_err(PrettyPrintError::Fmt),
289            rustpython_ast::Expr::ListComp(expr_list_comp) => f
290                .write_str(&expr_list_comp.format(formats)?)
291                .map_err(PrettyPrintError::Fmt),
292            rustpython_ast::Expr::SetComp(expr_set_comp) => f
293                .write_str(&expr_set_comp.format(formats)?)
294                .map_err(PrettyPrintError::Fmt),
295            rustpython_ast::Expr::DictComp(expr_dict_comp) => f
296                .write_str(&expr_dict_comp.format(formats)?)
297                .map_err(PrettyPrintError::Fmt),
298            rustpython_ast::Expr::GeneratorExp(expr_generator_exp) => f
299                .write_str(&expr_generator_exp.format(formats)?)
300                .map_err(PrettyPrintError::Fmt),
301            rustpython_ast::Expr::Await(expr_await) => f
302                .write_str(&expr_await.format(formats)?)
303                .map_err(PrettyPrintError::Fmt),
304            rustpython_ast::Expr::Yield(expr_yield) => f
305                .write_str(&expr_yield.format(formats)?)
306                .map_err(PrettyPrintError::Fmt),
307            rustpython_ast::Expr::YieldFrom(expr_yield_from) => f
308                .write_str(&expr_yield_from.format(formats)?)
309                .map_err(PrettyPrintError::Fmt),
310            rustpython_ast::Expr::Compare(expr_compare) => {
311                // Convert multiple compares to boolean ands with binary compare operators
312
313                let combinations = (std::iter::once(*expr_compare.left.clone()))
314                    .chain(expr_compare.comparators.clone())
315                    .zip(expr_compare.comparators.clone())
316                    .zip(expr_compare.ops.iter());
317
318                let mut operands = Vec::new();
319                for ((left, right), op) in combinations {
320                    operands.push(match op {
321                        rustpython_ast::CmpOp::Eq => {
322                            EqualExpression { left, right }.format(formats)?
323                        }
324                        rustpython_ast::CmpOp::NotEq => {
325                            NotEqualExpression { left, right }.format(formats)?
326                        }
327                        rustpython_ast::CmpOp::Lt => {
328                            LessThanExpression { left, right }.format(formats)?
329                        }
330                        rustpython_ast::CmpOp::LtE => {
331                            LessThanOrEqualExpression { left, right }.format(formats)?
332                        }
333                        rustpython_ast::CmpOp::Gt => {
334                            GreaterThanExpression { left, right }.format(formats)?
335                        }
336                        rustpython_ast::CmpOp::GtE => {
337                            GreaterThanOrEqualExpression { left, right }.format(formats)?
338                        }
339                        rustpython_ast::CmpOp::Is => {
340                            IsExpression { left, right }.format(formats)?
341                        }
342                        rustpython_ast::CmpOp::IsNot => {
343                            IsNotExpression { left, right }.format(formats)?
344                        }
345                        rustpython_ast::CmpOp::In => {
346                            InExpression { left, right }.format(formats)?
347                        }
348                        rustpython_ast::CmpOp::NotIn => {
349                            NotInExpression { left, right }.format(formats)?
350                        }
351                    });
352                }
353
354                f.write_str(&AndExpressionForCompare { operands }.format(formats)?)
355                    .map_err(PrettyPrintError::Fmt)
356            }
357            rustpython_ast::Expr::Call(expr_call) => f
358                .write_str(&{
359                    if let rustpython_ast::Expr::Name(rustpython_ast::ExprName {
360                        id: name, ..
361                    }) = *expr_call.func.clone()
362                    {
363                        if name.as_str() == "print" {
364                            if expr_call.args.len() == 1 && expr_call.keywords.is_empty() {
365                                PythonPrintWithOneArgument {
366                                    argument: expr_call.args[0].clone(),
367                                }
368                                .format(formats)?
369                            } else if expr_call.keywords.is_empty() {
370                                PythonPrintWithMultipleArguments {
371                                    arguments: expr_call.args.clone(),
372                                }
373                                .format(formats)?
374                            } else {
375                                expr_call.format(formats)?
376                            }
377                        } else if name.as_str() == "input" {
378                            if expr_call.args.is_empty() && expr_call.keywords.is_empty() {
379                                PythonInputNoArgument.format(formats)?
380                            } else if expr_call.args.len() == 1 && expr_call.keywords.is_empty() {
381                                PythonInputWithOneArgument {
382                                    argument: expr_call.args[0].clone(),
383                                }
384                                .format(formats)?
385                            } else {
386                                expr_call.format(formats)?
387                            }
388                        } else {
389                            expr_call.format(formats)?
390                        }
391                    } else {
392                        expr_call.format(formats)?
393                    }
394                })
395                .map_err(PrettyPrintError::Fmt),
396            rustpython_ast::Expr::FormattedValue(expr_formatted_value) => f
397                .write_str(&expr_formatted_value.format(formats)?)
398                .map_err(PrettyPrintError::Fmt),
399            rustpython_ast::Expr::JoinedStr(expr_joined_str) => f
400                .write_str(&expr_joined_str.format(formats)?)
401                .map_err(PrettyPrintError::Fmt),
402            rustpython_ast::Expr::Constant(expr_constant) => f
403                .write_str(&expr_constant.format(formats)?)
404                .map_err(PrettyPrintError::Fmt),
405            rustpython_ast::Expr::Attribute(expr_attribute) => f
406                .write_str(&expr_attribute.format(formats)?)
407                .map_err(PrettyPrintError::Fmt),
408            rustpython_ast::Expr::Subscript(expr_subscript) => f
409                .write_str(&expr_subscript.format(formats)?)
410                .map_err(PrettyPrintError::Fmt),
411            rustpython_ast::Expr::Starred(expr_starred) => f
412                .write_str(&expr_starred.format(formats)?)
413                .map_err(PrettyPrintError::Fmt),
414            rustpython_ast::Expr::Name(expr_name) => f
415                .write_str(&expr_name.format(formats)?)
416                .map_err(PrettyPrintError::Fmt),
417            rustpython_ast::Expr::List(expr_list) => f
418                .write_str(&expr_list.format(formats)?)
419                .map_err(PrettyPrintError::Fmt),
420            rustpython_ast::Expr::Tuple(expr_tuple) => f
421                .write_str(&expr_tuple.format(formats)?)
422                .map_err(PrettyPrintError::Fmt),
423            rustpython_ast::Expr::Slice(expr_slice) => f
424                .write_str(&expr_slice.format(formats)?)
425                .map_err(PrettyPrintError::Fmt),
426        }
427    }
428}
429
430crate::formats::formats!(
431    struct PythonFormats {
432        // Statements
433        function_def: rustpython_ast::StmtFunctionDef: PythonFunctionDefPlaceholder {
434            /// The name of the function
435            Name => name,
436            /// The arguments of the function
437            Arguments => args,
438            /// The body of the function
439            Body => body,
440            /// The list of decorators to be applied, stored outermost first (i.e. the first in the list will be applied last).
441            DecoratorList => decorator_list,
442            /// The return annotation
443            Returns => returns,
444            /// an optional string with the type annotation as a comment
445            TypeComment => type_comment,
446            /// A list of type parameters
447            TypeParams => type_params
448        },
449
450        async_function_def: rustpython_ast::StmtAsyncFunctionDef: PythonAsyncFunctionDefPlaceholder {
451            /// The name of the function
452            Name => name,
453            /// The arguments of the function
454            Arguments => args,
455            /// The body of the function
456            Body => body,
457            /// The list of decorators to be applied, stored outermost first (i.e. the first in the list will be applied last).
458            DecoratorList => decorator_list,
459            /// The return annotation
460            Returns => returns,
461            /// an optional string with the type annotation as a comment
462            TypeComment => type_comment,
463            /// A list of type parameters
464            TypeParams => type_params
465        },
466
467        class_def: rustpython_ast::StmtClassDef: PythonClassDefPlaceholder {
468            /// The name of the class
469            Name => name,
470            /// a list of nodes for explicitly specified base classes
471            Bases => bases,
472            /// a list of keyword nodes, principally for ‘metaclass’. Other keywords will be passed to the metaclass, as per PEP 3115.
473            Keywords => keywords,
474            /// The body of the class
475            Body => body,
476            /// The list of decorators to be applied, stored outermost first (i.e. the first in the list will be applied last).
477            DecoratorList => decorator_list,
478            /// A list of type parameters
479            TypeParams => type_params
480        },
481
482        r#return: rustpython_ast::StmtReturn: PythonReturnPlaceholder {
483            /// The optional expression to be returned
484            Value => value
485        },
486
487        delete: rustpython_ast::StmtDelete: PythonDeletePlaceholder {
488            /// Expressions evaluating to the targets to be deleted
489            Targets => targets
490        },
491
492        assign: rustpython_ast::StmtAssign: PythonAssignPlaceholder {
493            /// Expressions evaluating to the targets to be assigned to
494            /// Each expression is assigned the same value
495            /// Expressions evaluating to tuples lead to unpacking
496            Targets => targets,
497            /// The value to assign
498            Value => value,
499            /// An optional comment with type annotation
500            TypeComment => type_comment
501        },
502
503        type_alias: rustpython_ast::StmtTypeAlias: PythonTypeAliasPlaceholder {
504            /// The name of the alias
505            Name => name,
506            /// The type parameters
507            TypeParams => type_params,
508            /// The value of the alias
509            Value => value
510        },
511
512        // TODO: make separate types for each operator (so they can be formatted independently)
513        augmented_assign: rustpython_ast::StmtAugAssign: PythonAugmentedAssignPlaceholder {
514            /// Expression evaluating to the target to be augment assigned to
515            Target => target,
516          //  /// The operator used in the augmented assign
517          //  Operator => op,
518            /// The value to assign
519            Value => value
520        },
521
522        // MAYBE TODO: use the 'simple' field to differentiate between two types?
523        annotated_assign: rustpython_ast::StmtAnnAssign: PythonAnnotatedAssignPlaceholder {
524            /// Expression evaluating to the target to be annotated assigned to
525            Target => target,
526            /// The operator used in the augmented assign
527            Annotation => annotation,
528            /// An optional value to assign
529            Value => value
530        },
531
532        r#for: rustpython_ast::StmtFor: PythonForPlaceholder {
533            /// The iterating 'variable' expression:
534            /// holds the variable(s) the loop assigns to.
535            Target => target,
536            /// The iterable to iterate over
537            Iter => iter,
538            /// The statements to execute for each value of the target.
539            Body => body,
540            /// The statements to execute when the loop finishes normally, rather than via a break statement
541            OrElse => orelse,
542            /// An optional comment with type annotation
543            TypeComment => type_comment
544        },
545
546        async_for: rustpython_ast::StmtAsyncFor: PythonAsyncForPlaceholder {
547            /// The iterating 'variable' expression:
548            /// holds the variable(s) the loop assigns to.
549            Target => target,
550            /// The iterable to iterate over
551            Iter => iter,
552            /// The statements to execute for each value of the target.
553            Body => body,
554            /// The statements to execute when the loop finishes normally, rather than via a break statement
555            OrElse => orelse,
556            /// An optional comment with type annotation
557            TypeComment => type_comment
558        },
559
560        r#while: rustpython_ast::StmtWhile: PythonWhilePlaceholder {
561            /// The condition expression
562            Test => test,
563            /// The statements to execute as long as the condition evaluates to true.
564            Body => body,
565            /// The statements to execute when the loop finishes normally, rather than via a break statement
566            OrElse => orelse
567        },
568
569        if_without_else: IfWithoutElse: PythonIfWithoutElsePlaceholder {
570            /// The condition expression
571            Test => test,
572            /// The statements to execute whem the condition evaluates to true.
573            Body => body
574        },
575
576        if_with_else: IfWithElse: PythonIfWithElsePlaceholder {
577            /// The condition expression
578            Test => test,
579            /// The statements to execute whem the condition evaluates to true.
580            Body => body,
581            /// The statements to execute whem the condition evaluates to false.
582            OrElse => orelse
583        },
584
585
586        with: rustpython_ast::StmtWith: PythonWithPlaceholder {
587            /// The context managers
588            Items => items,
589            /// The statements to execute within the context
590            Body => body,
591            /// An optional comment with type annotation
592            TypeComment => type_comment
593        },
594
595        async_with: rustpython_ast::StmtAsyncWith: PythonAsyncWithPlaceholder {
596            /// The context managers
597            Items => items,
598            /// The statements to execute within the context
599            Body => body,
600            /// An optional comment with type annotation
601            TypeComment => type_comment
602        },
603
604        r#match: rustpython_ast::StmtMatch: PythonMatchPlaceholder {
605            /// The expression whose value to match over
606            Subject => subject,
607            /// The cases to test one by one
608            Cases => cases
609        },
610
611        raise: rustpython_ast::StmtRaise: PythonRaisePlaceholder {
612            /// The expression evaluating to the exception to raise
613            Exception => exc,
614            /// The expression evaluating to the cause of the raise
615            Cause => cause
616        },
617
618        r#try: rustpython_ast::StmtTry: PythonTryPlaceholder {
619            /// The body of the try statement
620            Body => body,
621            /// The exception handlers (behind 'except')
622            Handlers => handlers,
623            /// The statements to execute when the try finishes normally, rather than via an exception
624            OrElse => orelse,
625            /// The statements to execute af the try body (and optional else) (whether or not an exception happened in the try body)
626            FinalBody => finalbody
627        },
628
629        r#try_star: rustpython_ast::StmtTryStar: PythonTryStarPlaceholder {
630            /// The body of the try star statement
631            Body => body,
632            /// The exception handlers (behind 'except*')
633            Handlers => handlers,
634            /// The statements to execute when the try finishes normally, rather than via an exception
635            OrElse => orelse,
636            /// The statements to execute af the try body (and optional else) (whether or not an exception happened in the try body)
637            FinalBody => finalbody
638        },
639
640        assert: rustpython_ast::StmtAssert: PythonAssertPlaceholder {
641            /// The test expression evaluated by the assert
642            Test => test,
643            /// The message shown when the assert fails
644            Message => msg
645        },
646
647        import: rustpython_ast::StmtImport: PythonImportPlaceholder {
648            /// The names (aliases) to import
649            Names => names
650        },
651
652        import_from: rustpython_ast::StmtImportFrom: PythonImportFromPlaceholder {
653            /// The module to import from (None if 'from . import x')
654            Module => module,
655            /// The names (aliases) to import
656            Names => names
657        },
658
659        global: rustpython_ast::StmtGlobal: PythonGlobalPlaceholder {
660            /// The identifiers to make global
661            Names => names
662        },
663
664        non_local: rustpython_ast::StmtNonlocal: PythonNonLocalPlaceholder {
665            /// The identifiers to make non local
666            Names => names
667        },
668
669        expression_statement: rustpython_ast::StmtExpr: PythonExpressionStatementPlaceholder {
670            /// The expression
671            Value => value
672        },
673
674        pass: rustpython_ast::StmtPass: PythonPassPlaceholder EmptyPlaceholder,
675        r#break: rustpython_ast::StmtBreak: PythonBreakPlaceholder EmptyPlaceholder,
676        r#continue: rustpython_ast::StmtContinue: PythonContinuePlaceholder EmptyPlaceholder,
677
678
679        // Expressions
680
681        // splitted rustpython_ast::ExprBoolOp
682        /*boolean_expression: rustpython_ast::ExprBoolOp: PythonExprBoolOpPlaceholder {
683            /// The operator in this expression
684            Operator,
685            /// The operands vector (2 or more expressions)
686            Operands
687        },*/
688        // TODO: maybe change to Left and Right operands
689        and_expression: AndExpression: PythonExprAndPlaceholder {
690            /// The operands vector (2 or more expressions)
691            Operands => operands
692        },
693        or_expression: OrExpression: PythonExprOrPlaceholder {
694            /// The operands vector (2 or more expressions)
695            Operands => operands
696        },
697
698        // assignment with return value (x := 5)
699        named_expr: rustpython_ast::ExprNamedExpr: PythonNamedExprPlaceholder {
700            /// Expression evaluating to the target to be assigned to
701            Target => target,
702            /// The value to assign
703            Value => value
704        },
705
706        add_operation: AddExpression: PythonExprAddPlaceholder {
707            /// The left operand expression
708            Left => left,
709            /// The right operand expression
710            Right => right
711        },
712
713        sub_operation: SubExpression: PythonExprSubPlaceholder {
714            /// The left operand expression
715            Left => left,
716            /// The right operand expression
717            Right => right
718        },
719
720        mul_operation: MultExpression: PythonExprMultPlaceholder {
721            /// The left operand expression
722            Left => left,
723            /// The right operand expression
724            Right => right
725        },
726
727        mat_mul_operation: MatMultExpression: PythonExprMatMultPlaceholder {
728            /// The left operand expression
729            Left => left,
730            /// The right operand expression
731            Right => right
732        },
733
734        div_operation: DivExpression: PythonExprDivPlaceholder {
735            /// The left operand expression
736            Left => left,
737            /// The right operand expression
738            Right => right
739        },
740
741        mod_operation: ModExpression: PythonExprModPlaceholder {
742            /// The left operand expression
743            Left => left,
744            /// The right operand expression
745            Right => right
746        },
747
748        pow_operation: PowExpression: PythonExprPowPlaceholder {
749            /// The left operand expression
750            Left => left,
751            /// The right operand expression
752            Right => right
753        },
754
755        lshift_operation: LShiftExpression: PythonExprLShiftPlaceholder {
756            /// The left operand expression
757            Left => left,
758            /// The right operand expression
759            Right => right
760        },
761
762        rshift_operation: RShiftExpression: PythonExprRShiftPlaceholder {
763            /// The left operand expression
764            Left => left,
765            /// The right operand expression
766            Right => right
767        },
768
769        bit_or_operation: BitOrExpression: PythonExprBitOrPlaceholder {
770            /// The left operand expression
771            Left => left,
772            /// The right operand expression
773            Right => right
774        },
775
776        bit_xor_operation: BitXorExpression: PythonExprBitXorPlaceholder {
777            /// The left operand expression
778            Left => left,
779            /// The right operand expression
780            Right => right
781        },
782
783        bit_and_operation: BitAndExpression: PythonExprBitAndPlaceholder {
784            /// The left operand expression
785            Left => left,
786            /// The right operand expression
787            Right => right
788        },
789
790        floor_div_operation: FloorDivExpression: PythonExprFloorDivPlaceholder {
791            /// The left operand expression
792            Left => left,
793            /// The right operand expression
794            Right => right
795        },
796
797        invert_operation: InvertExpression: PythonExprInvertPlaceholder {
798            /// The operand expression
799            Operand => operand
800        },
801
802        not_operation: NotExpression: PythonExprNotPlaceholder {
803            /// The operand expression
804            Operand => operand
805        },
806
807        unary_add_operation: UnaryAddExpression: PythonExprUnaryAddPlaceholder {
808            /// The operand expression
809            Operand => operand
810        },
811
812        unary_sub_operation: UnarySubExpression: PythonExprUnarySubPlaceholder {
813            /// The operand expression
814            Operand => operand
815        },
816
817        lambda: rustpython_ast::ExprLambda: PythonLambdaPlaceholder {
818            /// The arguments of the lambda
819            Arguments => args,
820            /// The body of the lambda (an expression)
821            Body => body
822        },
823
824        if_expression: rustpython_ast::ExprIfExp: PythonIfExprPlaceholder {
825            /// The condition expression
826            Test => test,
827            /// The expression to execute when the condition evaluates to true.
828            Body => body,
829            /// The statements to execute when the condition evaluates to false.
830            OrElse => orelse
831        },
832
833        dict_expression: rustpython_ast::ExprDict: PythonDictExprPlaceholder {
834            /// The keys
835            Keys => keys,
836            /// The values
837            Values => values
838        },
839
840        set_expression: rustpython_ast::ExprSet: PythonSetExprPlaceholder {
841            /// The elements
842            Elements => elts
843        },
844
845        list_comprehension: rustpython_ast::ExprListComp: PythonListComprehensionPlaceholder {
846            /// The expression computed for each element
847            Body => elt,
848            /// The generators to generate each element
849            Generators => generators
850        },
851
852        set_comprehension: rustpython_ast::ExprSetComp: PythonSetComprehensionPlaceholder {
853            /// The expression computed for each element
854            Body => elt,
855            /// The generators to generate each element
856            Generators => generators
857        },
858
859        dict_comprehension: rustpython_ast::ExprDictComp: PythonDictComprehensionPlaceholder {
860            /// The key (expression) computer for each element
861            Key => key,
862            /// The value (expression) computer for each element
863            Value => value,
864            /// The generators to generate each element
865            Generators => generators
866        },
867
868        generator_comprehension: rustpython_ast::ExprGeneratorExp: PythonGeneratorComprehensionPlaceholder {
869            /// The expression computed for each element (lazy)
870            Body => elt,
871            /// The generators to generate each element
872            Generators => generators
873        },
874
875        r#await: rustpython_ast::ExprAwait: PythonAwaitPlaceholder {
876            /// The expression to be awaited
877            Value => value
878        },
879
880        r#yield: rustpython_ast::ExprYield: PythonYieldPlaceholder {
881            /// The expression to be yielded
882            Value => value
883        },
884
885        r#yield_from: rustpython_ast::ExprYieldFrom: PythonYieldFromPlaceholder {
886            /// The expression to be yielded
887            Value => value
888        },
889
890        // Splitted comparisons
891        equal_operation: EqualExpression: PythonEqualPlaceholder {
892            /// The left operand expression
893            Left => left,
894            /// The right operand expression
895            Right => right
896        },
897
898        not_equal_operation: NotEqualExpression: PythonNotEqualPlaceholder {
899            /// The left operand expression
900            Left => left,
901            /// The right operand expression
902            Right => right
903        },
904
905        less_than_operation: LessThanExpression: PythonLessThanPlaceholder {
906            /// The left operand expression
907            Left => left,
908            /// The right operand expression
909            Right => right
910        },
911
912        less_than_or_equal_operation: LessThanOrEqualExpression: PythonLessThanOrEqualPlaceholder {
913            /// The left operand expression
914            Left => left,
915            /// The right operand expression
916            Right => right
917        },
918
919        greater_than_operation: GreaterThanExpression: PythonGreaterThanPlaceholder {
920            /// The left operand expression
921            Left => left,
922            /// The right operand expression
923            Right => right
924        },
925
926        greater_than_or_equal_operation: GreaterThanOrEqualExpression: PythonGreaterThanOrEqualPlaceholder {
927            /// The left operand expression
928            Left => left,
929            /// The right operand expression
930            Right => right
931        },
932
933        is_operation: IsExpression: PythonIsPlaceholder {
934            /// The left operand expression
935            Left => left,
936            /// The right operand expression
937            Right => right
938        },
939
940        is_not_operation: IsNotExpression: PythonIsNotPlaceholder {
941            /// The left operand expression
942            Left => left,
943            /// The right operand expression
944            Right => right
945        },
946
947        in_operation: InExpression: PythonInPlaceholder {
948            /// The left operand expression
949            Left => left,
950            /// The right operand expression
951            Right => right
952        },
953
954        not_in_operation: NotInExpression: PythonNotInPlaceholder {
955            /// The left operand expression
956            Left => left,
957            /// The right operand expression
958            Right => right
959        },
960
961        call: rustpython_ast::ExprCall: PythonCallPlaceholder {
962            /// Expression evaluating to the function
963            Function => func,
964            /// The positional arguments
965            PositionalArguments => args,
966            /// The keyword arguments
967            KeywordArguments => keywords
968        },
969
970        print_call_one_argument: PythonPrintWithOneArgument: PythonPrintWithOneArgumentPlaceholder {
971            /// Expression evaluating to the value to be printed
972            Argument => argument
973        },
974
975        print_call_multiple_arguments: PythonPrintWithMultipleArguments: PythonPrintWithMultipleArgumentsPlaceholder {
976            /// Expressions evaluating to the values to be printed with a space in between
977            Arguments => arguments
978        },
979
980        input_call_no_argument: PythonInputNoArgument: EmptyPlaceholder,
981
982        input_call_one_argument: PythonInputWithOneArgument: PythonInputWithOneArgumentPlaceholder {
983            /// Expression evaluating to the value to be printed
984            Argument => argument
985        },
986
987        formatted_value: rustpython_ast::ExprFormattedValue: PythonFormattedValuePlaceholder {
988            /// The expression given between {}
989            Value => value,
990            /// The specification given after :
991            FormatSpecification => format_spec
992        },
993
994        joined_string: rustpython_ast::ExprJoinedStr: PythonJoinedStringPlaceholder {
995            /// The expressions which are joined together
996            Values => values
997        },
998
999        constant_expression: rustpython_ast::ExprConstant: PythonConstantExpressionPlaceholder {
1000            /// The constant
1001            Value => value
1002        },
1003
1004        // Maybe TODO: use the context?
1005        attribute: rustpython_ast::ExprAttribute: PythonAttributePlaceholder {
1006            /// The value (expression) of which the attribute is taken
1007            Value => value,
1008            /// The attribute Identifier
1009            Attribute => attr
1010        },
1011
1012        // Maybe TODO: use the context?
1013        subscript: rustpython_ast::ExprSubscript: PythonSubscriptPlaceholder {
1014            /// The value (expression) of which the subscript is taken
1015            Value => value,
1016            /// The slice expression
1017            Slice => slice
1018        },
1019
1020        // Maybe TODO: use the context?
1021        starred: rustpython_ast::ExprStarred: PythonStarredPlaceholder {
1022            /// The value (expression) which is starred
1023            Value => value
1024        },
1025
1026        // Maybe TODO: use the context?
1027        name: rustpython_ast::ExprName: PythonNamePlaceholder {
1028            /// The identifier
1029            Identifier => id
1030        },
1031
1032        // Maybe TODO: use the context?
1033        list: rustpython_ast::ExprList: PythonListPlaceholder {
1034            /// The elements (expressions) of the list
1035            Elements => elts
1036        },
1037
1038        // Maybe TODO: use the context?
1039        tuple: rustpython_ast::ExprTuple: PythonTuplePlaceholder {
1040            /// The elements (expressions) of the tuple
1041            Elements => elts
1042        },
1043
1044        slice: rustpython_ast::ExprSlice: PythonSlicePlaceholder {
1045            /// The (optional) lower value of the slice
1046            Lower => lower,
1047            /// The (optional) upper value of the slice
1048            Upper => upper,
1049            /// The (optional) step of the slice
1050            Step => step
1051        },
1052
1053        // 'base types'
1054        identifier: rustpython_ast::Identifier: PythonIdentifierPlaceholder {
1055            /// The name of the identifier
1056            Value for to_string
1057        },
1058
1059        arguments: rustpython_ast::Arguments: PythonArgumentsPlaceholder {
1060            /// The arguments which can only be passed positionally (not by name)
1061            /// These are specified before , /, in the argument list: [PEP](https://peps.python.org/pep-0570/)
1062            PositionOnlyArguments => posonlyargs,
1063            /// The arguments which can be passed both positionally and by name
1064            Arguments => args,
1065            /// *d
1066            VariableNumberArguments => vararg,
1067            /// The arguments which can only be passed by name (not positionally)
1068            KeywordOnlyArguments => kwonlyargs,
1069            /// **d: The other keyword arguments
1070            KeywordArguments => kwarg
1071        },
1072
1073        argument: rustpython_ast::Arg: PythonArgumentPlaceholder {
1074            /// The name of the argument
1075            Identifier => arg,
1076            /// An optional annotation expression
1077            Annotation => annotation,
1078            /// An optional comment with type annotation
1079            TypeComment => type_comment
1080        },
1081
1082        argument_with_default: rustpython_ast::ArgWithDefault: PythonArgumentWithDefaultPlaceholder {
1083            /// The argument itself
1084            Argument => def,
1085            /// The default value
1086            Default => default
1087        },
1088
1089        // TODO: async variant?
1090        comprehension: rustpython_ast::Comprehension: PythonComprehensionPlaceholder {
1091            /// The part before (`in`)
1092            Target => target,
1093            /// The iterator (part after `in`)
1094            Iterator => iter,
1095            /// The conditions (vector of expressions)
1096            Ifs => ifs
1097        },
1098
1099        keyword: rustpython_ast::Keyword: PythonKeywordPlaceholder {
1100            /// The identifier of the variable
1101            Name => arg,
1102            /// The value associated with the name
1103            Value => value
1104        },
1105
1106        constant_none: ConstantNone: PythonConstantNonePlaceholder EmptyPlaceholder,
1107
1108        constant_bool: ConstantBool: PythonConstantBoolPlaceholder {
1109            // The boolean value
1110            Value => value
1111        },
1112
1113        constant_string: ConstantString: PythonConstantStringPlaceholder {
1114            // The string value
1115            Value => value
1116        },
1117
1118        constant_bytes: ConstantBytes: PythonConstantBytesPlaceholder {
1119            // The bytes vector
1120            Bytes => bytes
1121        },
1122
1123        constant_integer: ConstantInt: PythonConstantIntegerPlaceholder {
1124            // The integer value
1125            Value => value
1126        },
1127
1128        constant_tuples: ConstantTuple: PythonConstantTuplePlaceholder {
1129            // The containing values
1130            Items => items
1131        },
1132
1133        constant_float: ConstantFloat: PythonConstantFloatPlaceholder {
1134            // The float value
1135            Value => value
1136        },
1137
1138        constant_complex: ConstantComplex: PythonConstantComplexPlaceholder {
1139            // The real part of the complex value
1140            Real => real,
1141            // The imaginary part of the complex value
1142            Imaginary => imaginary
1143        },
1144
1145        constant_ellipsis: ConstantEllipsis: PythonConstantEllipsisPlaceholder EmptyPlaceholder,
1146
1147        with_item: rustpython_ast::WithItem: PythonWithItemPlaceholder {
1148            /// The expression creating the context manager
1149            ContextExpr => context_expr,
1150            /// The part after 'as'
1151            OptionalVariables => optional_vars
1152        },
1153
1154        match_case: rustpython_ast::MatchCase: PythonMatchCasePlaceholder {
1155            /// The pattern to match for this case
1156            Pattern => pattern,
1157            /// The (optional) additional guard which has to be true
1158            Guard => guard,
1159            /// The body which is executed if both the pattern matches and the guard is true.
1160            Body => body
1161        },
1162
1163        except_handler: rustpython_ast::ExceptHandlerExceptHandler: PythonExceptHandlerPlaceholder {
1164            /// The error type to catch
1165            Type => type_,
1166            /// The name to give the error variable
1167            Name => name,
1168            /// The body of the exception handler
1169            Body => body
1170        },
1171
1172        alias: rustpython_ast::Alias: PythonAliasPlaceholder {
1173            /// The original name
1174            Original => name,
1175            /// The (optional) new name
1176            AsName => asname
1177        }
1178
1179    }
1180);
1181
1182pub struct AndExpressionForCompare {
1183    operands: Vec<String>,
1184}
1185
1186impl Formattable<PythonFormats> for AndExpressionForCompare {
1187    fn format(&self, formatting: &PythonFormats) -> Result<String, PrettyPrintError> {
1188        if self.operands.len() == 1 {
1189            Ok(self.operands[0].clone())
1190        } else {
1191            formatting
1192                .and_expression
1193                .filled_in_string(
1194                    "comparison_operators",
1195                    &vec![(PythonExprAndPlaceholder::Operands, self.operands.clone())]
1196                        .into_iter()
1197                        .collect(),
1198                )
1199                .map_err(fill_in_to_pretty("and_expression (for comparisons)"))
1200        }
1201    }
1202}
1203
1204pub struct AndExpression {
1205    operands: Vec<rustpython_ast::Expr>,
1206}
1207
1208pub struct OrExpression {
1209    operands: Vec<rustpython_ast::Expr>,
1210}
1211
1212macro_rules! binary_expression {
1213    ($ident: ident) => {
1214        pub struct $ident {
1215            left: rustpython_ast::Expr,
1216            right: rustpython_ast::Expr,
1217        }
1218    };
1219}
1220
1221binary_expression!(AddExpression);
1222binary_expression!(SubExpression);
1223binary_expression!(MultExpression);
1224binary_expression!(MatMultExpression);
1225binary_expression!(DivExpression);
1226binary_expression!(ModExpression);
1227binary_expression!(PowExpression);
1228binary_expression!(LShiftExpression);
1229binary_expression!(RShiftExpression);
1230binary_expression!(BitOrExpression);
1231binary_expression!(BitXorExpression);
1232binary_expression!(BitAndExpression);
1233binary_expression!(FloorDivExpression);
1234
1235binary_expression!(EqualExpression);
1236binary_expression!(NotEqualExpression);
1237binary_expression!(LessThanExpression);
1238binary_expression!(LessThanOrEqualExpression);
1239binary_expression!(GreaterThanExpression);
1240binary_expression!(GreaterThanOrEqualExpression);
1241binary_expression!(IsExpression);
1242binary_expression!(IsNotExpression);
1243binary_expression!(InExpression);
1244binary_expression!(NotInExpression);
1245
1246macro_rules! unary_expression {
1247    ($ident: ident) => {
1248        pub struct $ident {
1249            operand: rustpython_ast::Expr,
1250        }
1251    };
1252}
1253
1254unary_expression!(InvertExpression);
1255unary_expression!(NotExpression);
1256unary_expression!(UnaryAddExpression);
1257unary_expression!(UnarySubExpression);
1258pub struct ConstantNone;
1259pub struct ConstantBool {
1260    value: bool,
1261}
1262pub struct ConstantString {
1263    value: String,
1264}
1265
1266// Type needed as FormattableVec is implemented for all Vec<T: Formattable>
1267pub struct LiteralBytes(Vec<u8>);
1268
1269pub struct ConstantBytes {
1270    bytes: LiteralBytes,
1271}
1272pub struct ConstantInt {
1273    value: rustpython_ast::bigint::BigInt,
1274}
1275pub struct ConstantTuple {
1276    items: Vec<rustpython_ast::Constant>,
1277}
1278pub struct ConstantFloat {
1279    value: f64,
1280}
1281pub struct ConstantComplex {
1282    real: f64,
1283    imaginary: f64,
1284}
1285pub struct ConstantEllipsis;
1286
1287pub struct IfWithoutElse {
1288    pub test: rustpython_ast::Expr,
1289    pub body: Vec<rustpython_ast::Stmt>,
1290}
1291
1292pub struct IfWithElse {
1293    pub test: rustpython_ast::Expr,
1294    pub body: Vec<rustpython_ast::Stmt>,
1295    pub orelse: Vec<rustpython_ast::Stmt>,
1296}
1297
1298pub struct PythonPrintWithOneArgument {
1299    argument: rustpython_ast::Expr,
1300}
1301
1302pub struct PythonPrintWithMultipleArguments {
1303    arguments: Vec<rustpython_ast::Expr>,
1304}
1305
1306pub struct PythonInputNoArgument;
1307
1308pub struct PythonInputWithOneArgument {
1309    argument: rustpython_ast::Expr,
1310}
1311
1312impl Formattable<PythonFormats> for LiteralBytes {
1313    fn format(&self, _formatting: &PythonFormats) -> Result<String, PrettyPrintError> {
1314        Err(PrettyPrintError::UnsupportedFeature {
1315            description: format!("Literal byte arrays"),
1316        })
1317    }
1318}
1319formattable_vec!(LiteralBytes);
1320
1321impl Formattable<PythonFormats> for rustpython_ast::bigint::BigInt {
1322    fn format(&self, _formatting: &PythonFormats) -> Result<String, PrettyPrintError> {
1323        Ok(self.to_string())
1324    }
1325}
1326formattable_vec!(rustpython_ast::bigint::BigInt);
1327
1328impl Formattable<PythonFormats> for rustpython_ast::ExceptHandler {
1329    fn format(&self, formatting: &PythonFormats) -> Result<String, PrettyPrintError> {
1330        match self {
1331            rustpython_ast::ExceptHandler::ExceptHandler(except_handler_except_handler) => {
1332                except_handler_except_handler.format(formatting)
1333            }
1334        }
1335    }
1336}
1337formattable_vec!(rustpython_ast::ExceptHandler);
1338
1339impl Formattable<PythonFormats> for rustpython_ast::Constant {
1340    fn format(&self, formatting: &PythonFormats) -> Result<String, PrettyPrintError> {
1341        match self {
1342            rustpython_ast::Constant::None => ConstantNone.format(formatting),
1343            rustpython_ast::Constant::Bool(bool) => {
1344                ConstantBool { value: *bool }.format(formatting)
1345            }
1346            rustpython_ast::Constant::Str(s) => {
1347                ConstantString { value: s.clone() }.format(formatting)
1348            }
1349            rustpython_ast::Constant::Bytes(items) => ConstantBytes {
1350                bytes: LiteralBytes(items.clone()),
1351            }
1352            .format(formatting),
1353            rustpython_ast::Constant::Int(big_int) => ConstantInt {
1354                value: big_int.clone(),
1355            }
1356            .format(formatting),
1357            rustpython_ast::Constant::Tuple(constants) => ConstantTuple {
1358                items: constants.clone(),
1359            }
1360            .format(formatting),
1361            rustpython_ast::Constant::Float(f) => ConstantFloat { value: *f }.format(formatting),
1362            rustpython_ast::Constant::Complex { real, imag } => ConstantComplex {
1363                real: *real,
1364                imaginary: *imag,
1365            }
1366            .format(formatting),
1367            rustpython_ast::Constant::Ellipsis => ConstantEllipsis.format(formatting),
1368        }
1369    }
1370}
1371
1372formattable_vec!(rustpython_ast::Constant);
1373
1374impl Formattable<PythonFormats> for rustpython_ast::Stmt {
1375    fn format(&self, formatting: &PythonFormats) -> Result<String, PrettyPrintError> {
1376        let mut f = String::new();
1377        self.pretty_print(&mut f, formatting)?;
1378        Ok(f)
1379    }
1380}
1381formattable_vec!(rustpython_ast::Stmt);
1382
1383impl FormattableVec<PythonFormats> for Vec<Option<rustpython_ast::Expr>> {
1384    fn format_vec(&self, _formatting: &PythonFormats) -> Result<Vec<String>, PrettyPrintError> {
1385        Err(PrettyPrintError::UnsupportedFeature {
1386            description: format!("vec option expr"),
1387        })
1388        /*let mut f = String::new();
1389        for (idx, stmt) in self.iter().enumerate() {
1390            if idx > 0 {
1391                f.push('\n');
1392            }
1393            f.push_str(&stmt.format(formatting)?);
1394        }
1395        Ok(f)*/
1396    }
1397}
1398
1399impl Formattable<PythonFormats> for rustpython_ast::Expr {
1400    fn format(&self, formatting: &PythonFormats) -> Result<String, PrettyPrintError> {
1401        let mut f = String::new();
1402        self.pretty_print(&mut f, formatting)?;
1403        Ok(f)
1404    }
1405}
1406formattable_vec!(rustpython_ast::Expr);
1407
1408// Not implemented
1409impl Formattable<PythonFormats> for rustpython_ast::TypeParam {
1410    fn format(&self, formatting: &PythonFormats) -> Result<String, PrettyPrintError> {
1411        Err(PrettyPrintError::UnsupportedFeature {
1412            description: format!("Type params"),
1413        })
1414    }
1415}
1416formattable_vec!(rustpython_ast::TypeParam);
1417
1418// Not yet implemented
1419impl Formattable<PythonFormats> for rustpython_ast::Pattern {
1420    fn format(&self, formatting: &PythonFormats) -> Result<String, PrettyPrintError> {
1421        Err(PrettyPrintError::UnsupportedFeature {
1422            description: format!("Patterns"),
1423        })
1424    }
1425}
1426formattable_vec!(rustpython_ast::Pattern);
1427
1428pub fn example_format() -> PythonFormats {
1429    use crate::format::{Format, PossibleFormat};
1430    use std::str::FromStr;
1431
1432    PythonFormats {
1433            input_call_no_argument: PossibleFormat::empty(),
1434            input_call_one_argument: PossibleFormat::empty(),
1435            print_call_one_argument: PossibleFormat::empty(),
1436            print_call_multiple_arguments: PossibleFormat::empty(),
1437            function_def: PossibleFormat::empty(),
1438            async_function_def: PossibleFormat::empty(),
1439            class_def: PossibleFormat::empty(),
1440            r#return: PossibleFormat::empty(),
1441            delete: PossibleFormat::empty(),
1442            assign: Format::from_str(r"evaluate\ $value\ and\ assign\ it\ to\ $targets").expect("format parsing to work").into(),
1443            type_alias: PossibleFormat::empty(),
1444            augmented_assign: PossibleFormat::empty(),
1445            annotated_assign: PossibleFormat::empty(),
1446            r#for: PossibleFormat::empty(),
1447            async_for: PossibleFormat::empty(),
1448            r#while: PossibleFormat::empty(),
1449            if_without_else: Format::from_str(r"When\n
1450>>>>$test\n
1451    is\ seen\ as\ true\n
1452        >>>>do\n
1453            >>>>$body
1454            <<<<
1455        <<<<
1456<<<<").expect("parsing to work").into(),
1457            if_with_else: Format::from_str(
1458                r"When\n
1459>>>>$test\n
1460    is\ seen\ as\ true\n
1461    >>>>do\n
1462        >>>>$body
1463        <<<<
1464    <<<<\n
1465    else,\ if\ it\ is\ seen\ as\ false,\n
1466    >>>>do\n
1467        >>>>$or_else
1468        <<<<
1469    <<<<
1470<<<<"
1471            ).expect("parsing to work")
1472            .into(),
1473            with: PossibleFormat::empty(),
1474            async_with: PossibleFormat::empty(),
1475            r#match: PossibleFormat::empty(),
1476            raise: PossibleFormat::empty(),
1477            r#try: PossibleFormat::empty(),
1478            try_star: PossibleFormat::empty(),
1479            assert: PossibleFormat::empty(),
1480            import: PossibleFormat::empty(),
1481            import_from: PossibleFormat::empty(),
1482            global: PossibleFormat::empty(),
1483            non_local: PossibleFormat::empty(),
1484            expression_statement: PossibleFormat::empty(),
1485            pass: PossibleFormat::empty(),
1486            r#break: PossibleFormat::empty(),
1487            r#continue: PossibleFormat::empty(),
1488            and_expression: Format::from_str(r"
1489each\ of\ the\ following\ conditions\ (when\ one\ evaluates\ to\ false,\ we\ do\ not\ evaluate\ the\ remaining\ conditions)\n
1490    >>>>{{{{ $operands as -\ $operands & \n }}}}
1491    <<<<
1492").expect("parsing to work")
1493            .into(),
1494            or_expression: PossibleFormat::empty(),
1495            named_expr: PossibleFormat::empty(),
1496            add_operation: Format::from_str(r"($left\ +\ $right)").expect("parsing to work").into(),
1497            sub_operation: Format::from_str(r"($left\ -\ $right)").expect("parsing to work").into(),
1498            mul_operation: Format::from_str(r"($left\ *\ $right)").expect("parsing to work").into(),
1499            mat_mul_operation: Format::from_str(r"($left\ @\ $right)").expect("parsing to work").into(),
1500            div_operation: Format::from_str(r"($left\ /\ $right)").expect("parsing to work").into(),
1501            mod_operation: Format::from_str(r"($left\ %\ $right)").expect("parsing to work").into(),
1502            pow_operation: Format::from_str(r"($left\ **\ $right)").expect("parsing to work").into(),
1503            lshift_operation: PossibleFormat::empty(),
1504            rshift_operation: PossibleFormat::empty(),
1505            bit_or_operation: PossibleFormat::empty(),
1506            bit_xor_operation: PossibleFormat::empty(),
1507            bit_and_operation: PossibleFormat::empty(),
1508            floor_div_operation: Format::from_str(r"($left\ //\ $right)").expect("parsing to work").into(),
1509            invert_operation: PossibleFormat::empty(),
1510            not_operation: PossibleFormat::empty(),
1511            unary_add_operation: PossibleFormat::empty(),
1512            unary_sub_operation: PossibleFormat::empty(),
1513            lambda: PossibleFormat::empty(),
1514            if_expression: PossibleFormat::empty(),
1515            dict_expression: PossibleFormat::empty(),
1516            set_expression: PossibleFormat::empty(),
1517            list_comprehension: PossibleFormat::empty(),
1518            set_comprehension: PossibleFormat::empty(),
1519            dict_comprehension: PossibleFormat::empty(),
1520            generator_comprehension: PossibleFormat::empty(),
1521            r#await: PossibleFormat::empty(),
1522            r#yield: PossibleFormat::empty(),
1523            yield_from: PossibleFormat::empty(),
1524            equal_operation: Format::from_str(r"the\ equality\ comparison\ of\ the\ result\ of\ $left\ with\ the\ result\ of\ $right").expect("failed parsing").into(),
1525            not_equal_operation: Format::from_str(r"the\ result\ of\ $left\ is\ different\ from\ the\ result\ of\ $right").expect("failed parsing").into(),
1526            less_than_operation: Format::from_str(r"the\ result\ of\ $left\ is\ less\ than\ the\ result\ of\ $right").expect("failed parsing").into(),
1527            less_than_or_equal_operation: Format::from_str(r"the\ result\ of\ $left\ is\ less\ than\ or\ equal\ to\ the\ result\ of\ $right").expect("failed parsing").into(),
1528            greater_than_operation: Format::from_str(r"the\ result\ of\ $left\ is\ greater\ than\ the\ result\ of\ $right").expect("failed parsing").into(),
1529            greater_than_or_equal_operation: Format::from_str(r"the\ result\ of\ $left\ is\ greater\ than\ or\ equal\ to\ the\ result\ of\ $right").expect("failed parsing").into(),
1530            is_operation: Format::from_str(r"the\ result\ of\ $left\ refers\ to\ the\ same\ object\ as\ the\ result\ of\ $right").expect("failed parsing").into(),
1531            is_not_operation: Format::from_str(r"the\ result\ of\ $left\ does\ not\ refer\ to\ the\ same\ object\ as\ the\ result\ of\ $right").expect("failed parsing").into(),    
1532            in_operation: PossibleFormat::empty(),
1533            not_in_operation: PossibleFormat::empty(),
1534            call: PossibleFormat::empty(),
1535            formatted_value: PossibleFormat::empty(),
1536            joined_string: PossibleFormat::empty(),
1537            constant_expression: Format::from_str(r"the\ literal\ $value").expect("parsing failed").into(),
1538            attribute: PossibleFormat::empty(),
1539            subscript: PossibleFormat::empty(),
1540            starred: PossibleFormat::empty(),
1541            name: Format::from_str(r"the\ variable\ $identifier").expect("parsing failed").into(),
1542            list: PossibleFormat::empty(),
1543            tuple: PossibleFormat::empty(),
1544            slice: PossibleFormat::empty(),
1545            identifier: Format::from_str("$value").expect("parsing failed").into(),
1546            arguments: PossibleFormat::empty(),
1547            argument: PossibleFormat::empty(),
1548            argument_with_default: PossibleFormat::empty(),
1549            comprehension: PossibleFormat::empty(),
1550            keyword: PossibleFormat::empty(),
1551            constant_none: Format::from_str("None").expect("parsing failed").into(),
1552            constant_bool: Format::from_str(r"boolean\ $value").expect("parsing failed").into(),
1553            constant_string: Format::from_str(r#"string\ "$value""#).expect("parsing failed").into(),
1554            constant_bytes: PossibleFormat::empty(),
1555            constant_integer: Format::from_str(r#"integer\ $value"#).expect("parsing failed").into(), 
1556            constant_tuples: PossibleFormat::empty(),
1557            constant_float: Format::from_str(r#"float\ $value"#).expect("parsing failed").into(), 
1558            constant_complex: PossibleFormat::empty(),
1559            constant_ellipsis: PossibleFormat::empty(),
1560            with_item: PossibleFormat::empty(),
1561            match_case: PossibleFormat::empty(),
1562            except_handler: PossibleFormat::empty(),
1563            alias: PossibleFormat::empty(),
1564        }
1565}
1566
1567#[cfg(test)]
1568mod test {
1569
1570    use super::*;
1571
1572    use pretty_assertions::assert_eq;
1573
1574    #[test]
1575    fn simple_if_true() {
1576        let code = r#"if True:
1577  a = 10"#;
1578
1579        let parsed = Python::parse(code).expect("Parsing to work");
1580
1581        println!("{:?}", parsed.module);
1582
1583        let mut result = String::new();
1584
1585        let formats = example_format();
1586
1587        parsed
1588            .pretty_print(&mut result, &formats)
1589            .expect("pretty printing to work");
1590
1591        assert_eq!(
1592            result,
1593            r#"When
1594    the literal boolean true
1595    is seen as true
1596        do
1597            evaluate the literal integer 10 and assign it to the variable a"#
1598        )
1599    }
1600
1601    #[test]
1602    fn simple_if_false_with_else() {
1603        let code = r#"if False:
1604  a = 10
1605else:
1606  b = "test""#;
1607
1608        let parsed = Python::parse(code).expect("Parsing to work");
1609
1610        println!("{:?}", parsed.module);
1611
1612        let mut result = String::new();
1613
1614        let formats = example_format();
1615
1616        parsed
1617            .pretty_print(&mut result, &formats)
1618            .expect("pretty printing to work");
1619
1620        assert_eq!(
1621            result,
1622            r#"When
1623    the literal boolean false
1624    is seen as true
1625        do
1626            evaluate the literal integer 10 and assign it to the variable a
1627    else, if it is seen as false,
1628        do
1629            evaluate the literal string "test" and assign it to the variable b"#
1630        )
1631    }
1632
1633    #[test]
1634    fn if_one_comparison() {
1635        let code = r#"if 3.5 == 3:
1636  a = 10"#;
1637
1638        let parsed = Python::parse(code).expect("Parsing to work");
1639
1640        println!("{:?}", parsed.module);
1641
1642        let mut result = String::new();
1643
1644        let formats = example_format();
1645
1646        parsed
1647            .pretty_print(&mut result, &formats)
1648            .expect("pretty printing to work");
1649
1650        assert_eq!(
1651            result,
1652            r#"When
1653    the equality comparison of the result of the literal float 3.5 with the result of the literal integer 3
1654    is seen as true
1655        do
1656            evaluate the literal integer 10 and assign it to the variable a"#
1657        )
1658    }
1659
1660    #[test]
1661    fn if_two_comparisons() {
1662        let code = r#"if 3.5 == 3 <= 5:
1663  a = 10"#;
1664
1665        let parsed = Python::parse(code).expect("Parsing to work");
1666
1667        println!("{:?}", parsed.module);
1668
1669        let mut result = String::new();
1670
1671        let formats = example_format();
1672
1673        parsed
1674            .pretty_print(&mut result, &formats)
1675            .expect("pretty printing to work");
1676
1677        assert_eq!(
1678            result,
1679            r#"When
1680    each of the following conditions (when one evaluates to false, we do not evaluate the remaining conditions)
1681        - the equality comparison of the result of the literal float 3.5 with the result of the literal integer 3
1682        - the result of the literal integer 3 is less than or equal to the result of the literal integer 5
1683    is seen as true
1684        do
1685            evaluate the literal integer 10 and assign it to the variable a"#
1686        )
1687    }
1688
1689    #[test]
1690    fn if_eight_ands() {
1691        let code = r#"if 3.5 == "test" and test < "test" and 5 > 9 and "test" <= "test" and "test" >= testing and 8.5 != 17 and test is not None and test is None:
1692  a = 10 + 8"#;
1693
1694        let parsed = Python::parse(code).expect("Parsing to work");
1695
1696        println!("{:?}", parsed.module);
1697
1698        let mut result = String::new();
1699
1700        let formats = example_format();
1701
1702        parsed
1703            .pretty_print(&mut result, &formats)
1704            .expect("pretty printing to work");
1705
1706        assert_eq!(
1707            result,
1708            r#"When
1709    each of the following conditions (when one evaluates to false, we do not evaluate the remaining conditions)
1710        - the equality comparison of the result of the literal float 3.5 with the result of the literal string "test"
1711        - the result of the variable test is less than the result of the literal string "test"
1712        - the result of the literal integer 5 is greater than the result of the literal integer 9
1713        - the result of the literal string "test" is less than or equal to the result of the literal string "test"
1714        - the result of the literal string "test" is greater than or equal to the result of the variable testing
1715        - the result of the literal float 8.5 is different from the result of the literal integer 17
1716        - the result of the variable test does not refer to the same object as the result of the literal None
1717        - the result of the variable test refers to the same object as the result of the literal None
1718    is seen as true
1719        do
1720            evaluate (the literal integer 10 + the literal integer 8) and assign it to the variable a"#
1721        )
1722    }
1723}