Coverage Report

Created: 2026-08-13 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython3/Python/ast_unparse.c
Line
Count
Source
1
#include "Python.h"
2
#include "pycore_ast.h"           // expr_ty
3
#include "pycore_pystate.h"       // _PyInterpreterState_GET()
4
#include "pycore_runtime.h"       // _Py_ID()
5
#include <stdbool.h>
6
7
/* This limited unparser is used to convert annotations back to strings
8
 * during compilation rather than being a full AST unparser.
9
 * See ast.unparse for a full unparser (written in Python)
10
 */
11
12
_Py_DECLARE_STR(dbl_open_br, "{{");
13
_Py_DECLARE_STR(dbl_close_br, "}}");
14
15
/* Forward declarations for recursion via helper functions. */
16
static PyObject *
17
expr_as_unicode(expr_ty e, int level);
18
static int
19
append_ast_expr(PyUnicodeWriter *writer, expr_ty e, int level);
20
static int
21
append_templatestr(PyUnicodeWriter *writer, expr_ty e);
22
static int
23
append_joinedstr(PyUnicodeWriter *writer, expr_ty e, bool is_format_spec);
24
static int
25
append_interpolation(PyUnicodeWriter *writer, expr_ty e);
26
static int
27
append_formattedvalue(PyUnicodeWriter *writer, expr_ty e);
28
static int
29
append_ast_slice(PyUnicodeWriter *writer, expr_ty e);
30
31
static int
32
append_char(PyUnicodeWriter *writer, Py_UCS4 ch)
33
6.82k
{
34
6.82k
    return PyUnicodeWriter_WriteChar(writer, ch);
35
6.82k
}
36
37
static int
38
append_charp(PyUnicodeWriter *writer, const char *charp)
39
151k
{
40
151k
    return PyUnicodeWriter_WriteUTF8(writer, charp, -1);
41
151k
}
42
43
5.17k
#define APPEND_CHAR_FINISH(ch)  do { \
44
5.17k
        return append_char(writer, (ch)); \
45
5.17k
    } while (0)
46
47
2.31k
#define APPEND_STR_FINISH(str)  do { \
48
2.31k
        return append_charp(writer, (str)); \
49
2.31k
    } while (0)
50
51
1.65k
#define APPEND_CHAR(ch)  do { \
52
1.65k
        if (-1 == append_char(writer, (ch))) { \
53
0
            return -1; \
54
0
        } \
55
1.65k
    } while (0)
56
57
130k
#define APPEND_STR(str)  do { \
58
130k
        if (-1 == append_charp(writer, (str))) { \
59
0
            return -1; \
60
0
        } \
61
130k
    } while (0)
62
63
250k
#define APPEND_STR_IF(cond, str)  do { \
64
250k
        if ((cond) && -1 == append_charp(writer, (str))) { \
65
0
            return -1; \
66
0
        } \
67
250k
    } while (0)
68
69
368
#define APPEND_STR_IF_NOT_FIRST(str)  do { \
70
368
        APPEND_STR_IF(!first, (str)); \
71
368
        first = false; \
72
368
    } while (0)
73
74
236k
#define APPEND_EXPR(expr, pr)  do { \
75
236k
        if (-1 == append_ast_expr(writer, (expr), (pr))) { \
76
0
            return -1; \
77
0
        } \
78
236k
    } while (0)
79
80
491
#define APPEND(type, value)  do { \
81
491
        if (-1 == append_ast_ ## type(writer, (value))) { \
82
0
            return -1; \
83
0
        } \
84
491
    } while (0)
85
86
static int
87
append_repr(PyUnicodeWriter *writer, PyObject *obj)
88
105k
{
89
105k
    PyObject *repr = PyObject_Repr(obj);
90
105k
    if (!repr) {
91
0
        return -1;
92
0
    }
93
94
105k
    if ((PyFloat_CheckExact(obj) && isinf(PyFloat_AS_DOUBLE(obj))) ||
95
104k
        PyComplex_CheckExact(obj))
96
21.1k
    {
97
21.1k
        _Py_DECLARE_STR(str_replace_inf, "1e309");  // evaluates to inf
98
21.1k
        PyObject *new_repr = PyUnicode_Replace(
99
21.1k
            repr,
100
21.1k
            &_Py_ID(inf),
101
21.1k
            &_Py_STR(str_replace_inf),
102
21.1k
            -1
103
21.1k
        );
104
21.1k
        Py_DECREF(repr);
105
21.1k
        if (!new_repr) {
106
0
            return -1;
107
0
        }
108
21.1k
        repr = new_repr;
109
21.1k
    }
110
111
105k
    int ret = PyUnicodeWriter_WriteStr(writer, repr);
112
105k
    Py_DECREF(repr);
113
105k
    return ret;
114
105k
}
115
116
/* Priority levels */
117
118
enum {
119
    PR_TUPLE,
120
    PR_TEST,            /* 'if'-'else', 'lambda' */
121
    PR_OR,              /* 'or' */
122
    PR_AND,             /* 'and' */
123
    PR_NOT,             /* 'not' */
124
    PR_CMP,             /* '<', '>', '==', '>=', '<=', '!=',
125
                           'in', 'not in', 'is', 'is not' */
126
    PR_EXPR,
127
    PR_BOR = PR_EXPR,   /* '|' */
128
    PR_BXOR,            /* '^' */
129
    PR_BAND,            /* '&' */
130
    PR_SHIFT,           /* '<<', '>>' */
131
    PR_ARITH,           /* '+', '-' */
132
    PR_TERM,            /* '*', '@', '/', '%', '//' */
133
    PR_FACTOR,          /* unary '+', '-', '~' */
134
    PR_POWER,           /* '**' */
135
    PR_AWAIT,           /* 'await' */
136
    PR_ATOM,
137
};
138
139
static int
140
append_ast_boolop(PyUnicodeWriter *writer, expr_ty e, int level)
141
346
{
142
346
    Py_ssize_t i, value_count;
143
346
    asdl_expr_seq *values;
144
346
    const char *op = (e->v.BoolOp.op == And) ? " and " : " or ";
145
346
    int pr = (e->v.BoolOp.op == And) ? PR_AND : PR_OR;
146
147
346
    APPEND_STR_IF(level > pr, "(");
148
149
346
    values = e->v.BoolOp.values;
150
346
    value_count = asdl_seq_LEN(values);
151
152
1.35k
    for (i = 0; i < value_count; ++i) {
153
1.01k
        APPEND_STR_IF(i > 0, op);
154
1.01k
        APPEND_EXPR((expr_ty)asdl_seq_GET(values, i), pr + 1);
155
1.01k
    }
156
157
346
    APPEND_STR_IF(level > pr, ")");
158
346
    return 0;
159
346
}
160
161
static int
162
append_ast_binop(PyUnicodeWriter *writer, expr_ty e, int level)
163
101k
{
164
101k
    const char *op;
165
101k
    int pr;
166
101k
    bool rassoc = false;  /* is right-associative? */
167
168
101k
    switch (e->v.BinOp.op) {
169
12.7k
    case Add: op = " + "; pr = PR_ARITH; break;
170
14.3k
    case Sub: op = " - "; pr = PR_ARITH; break;
171
30.2k
    case Mult: op = " * "; pr = PR_TERM; break;
172
3.73k
    case MatMult: op = " @ "; pr = PR_TERM; break;
173
8.37k
    case Div: op = " / "; pr = PR_TERM; break;
174
2.46k
    case Mod: op = " % "; pr = PR_TERM; break;
175
1.96k
    case LShift: op = " << "; pr = PR_SHIFT; break;
176
728
    case RShift: op = " >> "; pr = PR_SHIFT; break;
177
335
    case BitOr: op = " | "; pr = PR_BOR; break;
178
13.1k
    case BitXor: op = " ^ "; pr = PR_BXOR; break;
179
461
    case BitAnd: op = " & "; pr = PR_BAND; break;
180
657
    case FloorDiv: op = " // "; pr = PR_TERM; break;
181
12.6k
    case Pow: op = " ** "; pr = PR_POWER; rassoc = true; break;
182
0
    default:
183
0
        PyErr_SetString(PyExc_SystemError,
184
0
                        "unknown binary operator");
185
0
        return -1;
186
101k
    }
187
188
101k
    APPEND_STR_IF(level > pr, "(");
189
101k
    APPEND_EXPR(e->v.BinOp.left, pr + rassoc);
190
101k
    APPEND_STR(op);
191
101k
    APPEND_EXPR(e->v.BinOp.right, pr + !rassoc);
192
101k
    APPEND_STR_IF(level > pr, ")");
193
101k
    return 0;
194
101k
}
195
196
static int
197
append_ast_unaryop(PyUnicodeWriter *writer, expr_ty e, int level)
198
18.3k
{
199
18.3k
    const char *op;
200
18.3k
    int pr;
201
202
18.3k
    switch (e->v.UnaryOp.op) {
203
181
    case Invert: op = "~"; pr = PR_FACTOR; break;
204
0
    case Not: op = "not "; pr = PR_NOT; break;
205
10.0k
    case UAdd: op = "+"; pr = PR_FACTOR; break;
206
8.05k
    case USub: op = "-"; pr = PR_FACTOR; break;
207
0
    default:
208
0
        PyErr_SetString(PyExc_SystemError,
209
0
                        "unknown unary operator");
210
0
        return -1;
211
18.3k
    }
212
213
18.3k
    APPEND_STR_IF(level > pr, "(");
214
18.3k
    APPEND_STR(op);
215
18.3k
    APPEND_EXPR(e->v.UnaryOp.operand, pr);
216
18.3k
    APPEND_STR_IF(level > pr, ")");
217
18.3k
    return 0;
218
18.3k
}
219
220
static int
221
append_ast_arg(PyUnicodeWriter *writer, arg_ty arg)
222
183
{
223
183
    if (PyUnicodeWriter_WriteStr(writer, arg->arg) < 0) {
224
0
        return -1;
225
0
    }
226
183
    if (arg->annotation) {
227
0
        APPEND_STR(": ");
228
0
        APPEND_EXPR(arg->annotation, PR_TEST);
229
0
    }
230
183
    return 0;
231
183
}
232
233
static int
234
append_ast_args(PyUnicodeWriter *writer, arguments_ty args)
235
221
{
236
221
    bool first;
237
221
    Py_ssize_t i, di, arg_count, posonlyarg_count, default_count;
238
239
221
    first = true;
240
241
    /* positional-only and positional arguments with defaults */
242
221
    posonlyarg_count = asdl_seq_LEN(args->posonlyargs);
243
221
    arg_count = asdl_seq_LEN(args->args);
244
221
    default_count = asdl_seq_LEN(args->defaults);
245
327
    for (i = 0; i < posonlyarg_count + arg_count; i++) {
246
106
        APPEND_STR_IF_NOT_FIRST(", ");
247
106
        if (i < posonlyarg_count){
248
4
            APPEND(arg, (arg_ty)asdl_seq_GET(args->posonlyargs, i));
249
102
        } else {
250
102
            APPEND(arg, (arg_ty)asdl_seq_GET(args->args, i-posonlyarg_count));
251
102
        }
252
253
106
        di = i - posonlyarg_count - arg_count + default_count;
254
106
        if (di >= 0) {
255
1
            APPEND_CHAR('=');
256
1
            APPEND_EXPR((expr_ty)asdl_seq_GET(args->defaults, di), PR_TEST);
257
1
        }
258
106
        if (posonlyarg_count && i + 1 == posonlyarg_count) {
259
2
            APPEND_STR(", /");
260
2
        }
261
106
    }
262
263
    /* vararg, or bare '*' if no varargs but keyword-only arguments present */
264
221
    if (args->vararg || asdl_seq_LEN(args->kwonlyargs)) {
265
70
        APPEND_STR_IF_NOT_FIRST(", ");
266
70
        APPEND_STR("*");
267
70
        if (args->vararg) {
268
70
            APPEND(arg, args->vararg);
269
70
        }
270
70
    }
271
272
    /* keyword-only arguments */
273
221
    arg_count = asdl_seq_LEN(args->kwonlyargs);
274
221
    default_count = asdl_seq_LEN(args->kw_defaults);
275
227
    for (i = 0; i < arg_count; i++) {
276
6
        APPEND_STR_IF_NOT_FIRST(", ");
277
6
        APPEND(arg, (arg_ty)asdl_seq_GET(args->kwonlyargs, i));
278
279
6
        di = i - arg_count + default_count;
280
6
        if (di >= 0) {
281
6
            expr_ty default_ = (expr_ty)asdl_seq_GET(args->kw_defaults, di);
282
6
            if (default_) {
283
3
                APPEND_CHAR('=');
284
3
                APPEND_EXPR(default_, PR_TEST);
285
3
            }
286
6
        }
287
6
    }
288
289
    /* **kwargs */
290
221
    if (args->kwarg) {
291
1
        APPEND_STR_IF_NOT_FIRST(", ");
292
1
        APPEND_STR("**");
293
1
        APPEND(arg, args->kwarg);
294
1
    }
295
296
221
    return 0;
297
221
}
298
299
static int
300
append_ast_lambda(PyUnicodeWriter *writer, expr_ty e, int level)
301
221
{
302
221
    APPEND_STR_IF(level > PR_TEST, "(");
303
221
    Py_ssize_t n_positional = (asdl_seq_LEN(e->v.Lambda.args->args) +
304
221
                               asdl_seq_LEN(e->v.Lambda.args->posonlyargs));
305
221
    APPEND_STR(n_positional ? "lambda " : "lambda");
306
221
    APPEND(args, e->v.Lambda.args);
307
221
    APPEND_STR(": ");
308
221
    APPEND_EXPR(e->v.Lambda.body, PR_TEST);
309
221
    APPEND_STR_IF(level > PR_TEST, ")");
310
221
    return 0;
311
221
}
312
313
static int
314
append_ast_ifexp(PyUnicodeWriter *writer, expr_ty e, int level)
315
648
{
316
648
    APPEND_STR_IF(level > PR_TEST, "(");
317
648
    APPEND_EXPR(e->v.IfExp.body, PR_TEST + 1);
318
648
    APPEND_STR(" if ");
319
648
    APPEND_EXPR(e->v.IfExp.test, PR_TEST + 1);
320
648
    APPEND_STR(" else ");
321
648
    APPEND_EXPR(e->v.IfExp.orelse, PR_TEST);
322
648
    APPEND_STR_IF(level > PR_TEST, ")");
323
648
    return 0;
324
648
}
325
326
static int
327
append_ast_dict(PyUnicodeWriter *writer, expr_ty e)
328
44
{
329
44
    Py_ssize_t i, value_count;
330
44
    expr_ty key_node;
331
332
44
    APPEND_CHAR('{');
333
44
    value_count = asdl_seq_LEN(e->v.Dict.values);
334
335
92
    for (i = 0; i < value_count; i++) {
336
48
        APPEND_STR_IF(i > 0, ", ");
337
48
        key_node = (expr_ty)asdl_seq_GET(e->v.Dict.keys, i);
338
48
        if (key_node != NULL) {
339
24
            APPEND_EXPR(key_node, PR_TEST);
340
24
            APPEND_STR(": ");
341
24
            APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Dict.values, i), PR_TEST);
342
24
        }
343
24
        else {
344
24
            APPEND_STR("**");
345
24
            APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Dict.values, i), PR_EXPR);
346
24
        }
347
48
    }
348
349
44
    APPEND_CHAR_FINISH('}');
350
44
}
351
352
static int
353
append_ast_set(PyUnicodeWriter *writer, expr_ty e)
354
307
{
355
307
    Py_ssize_t i, elem_count;
356
357
307
    APPEND_CHAR('{');
358
307
    elem_count = asdl_seq_LEN(e->v.Set.elts);
359
802
    for (i = 0; i < elem_count; i++) {
360
495
        APPEND_STR_IF(i > 0, ", ");
361
495
        APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Set.elts, i), PR_TEST);
362
495
    }
363
364
307
    APPEND_CHAR_FINISH('}');
365
307
}
366
367
static int
368
append_ast_list(PyUnicodeWriter *writer, expr_ty e)
369
26
{
370
26
    Py_ssize_t i, elem_count;
371
372
26
    APPEND_CHAR('[');
373
26
    elem_count = asdl_seq_LEN(e->v.List.elts);
374
122
    for (i = 0; i < elem_count; i++) {
375
96
        APPEND_STR_IF(i > 0, ", ");
376
96
        APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.List.elts, i), PR_TEST);
377
96
    }
378
379
26
    APPEND_CHAR_FINISH(']');
380
26
}
381
382
static int
383
append_ast_tuple(PyUnicodeWriter *writer, expr_ty e, int level)
384
720
{
385
720
    Py_ssize_t i, elem_count;
386
387
720
    elem_count = asdl_seq_LEN(e->v.Tuple.elts);
388
389
720
    if (elem_count == 0) {
390
239
        APPEND_STR_FINISH("()");
391
239
    }
392
393
481
    APPEND_STR_IF(level > PR_TUPLE, "(");
394
395
1.36k
    for (i = 0; i < elem_count; i++) {
396
883
        APPEND_STR_IF(i > 0, ", ");
397
883
        APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Tuple.elts, i), PR_TEST);
398
883
    }
399
400
481
    APPEND_STR_IF(elem_count == 1, ",");
401
481
    APPEND_STR_IF(level > PR_TUPLE, ")");
402
481
    return 0;
403
481
}
404
405
static int
406
append_ast_comprehension(PyUnicodeWriter *writer, comprehension_ty gen)
407
47
{
408
47
    Py_ssize_t i, if_count;
409
410
47
    APPEND_STR(gen->is_async ? " async for " : " for ");
411
47
    APPEND_EXPR(gen->target, PR_TUPLE);
412
47
    APPEND_STR(" in ");
413
47
    APPEND_EXPR(gen->iter, PR_TEST + 1);
414
415
47
    if_count = asdl_seq_LEN(gen->ifs);
416
184
    for (i = 0; i < if_count; i++) {
417
137
        APPEND_STR(" if ");
418
137
        APPEND_EXPR((expr_ty)asdl_seq_GET(gen->ifs, i), PR_TEST + 1);
419
137
    }
420
47
    return 0;
421
47
}
422
423
static int
424
append_ast_comprehensions(PyUnicodeWriter *writer, asdl_comprehension_seq *comprehensions)
425
26
{
426
26
    Py_ssize_t i, gen_count;
427
26
    gen_count = asdl_seq_LEN(comprehensions);
428
429
73
    for (i = 0; i < gen_count; i++) {
430
47
        APPEND(comprehension, (comprehension_ty)asdl_seq_GET(comprehensions, i));
431
47
    }
432
433
26
    return 0;
434
26
}
435
436
static int
437
append_ast_genexp(PyUnicodeWriter *writer, expr_ty e)
438
0
{
439
0
    APPEND_CHAR('(');
440
0
    APPEND_EXPR(e->v.GeneratorExp.elt, PR_TEST);
441
0
    APPEND(comprehensions, e->v.GeneratorExp.generators);
442
0
    APPEND_CHAR_FINISH(')');
443
0
}
444
445
static int
446
append_ast_listcomp(PyUnicodeWriter *writer, expr_ty e)
447
0
{
448
0
    APPEND_CHAR('[');
449
0
    APPEND_EXPR(e->v.ListComp.elt, PR_TEST);
450
0
    APPEND(comprehensions, e->v.ListComp.generators);
451
0
    APPEND_CHAR_FINISH(']');
452
0
}
453
454
static int
455
append_ast_setcomp(PyUnicodeWriter *writer, expr_ty e)
456
25
{
457
25
    APPEND_CHAR('{');
458
25
    APPEND_EXPR(e->v.SetComp.elt, PR_TEST);
459
25
    APPEND(comprehensions, e->v.SetComp.generators);
460
25
    APPEND_CHAR_FINISH('}');
461
25
}
462
463
static int
464
append_ast_dictcomp(PyUnicodeWriter *writer, expr_ty e)
465
1
{
466
1
    APPEND_CHAR('{');
467
1
    if (e->v.DictComp.value) {
468
1
        APPEND_EXPR(e->v.DictComp.key, PR_TEST);
469
1
        APPEND_STR(": ");
470
1
        APPEND_EXPR(e->v.DictComp.value, PR_TEST);
471
1
    }
472
0
    else {
473
0
        APPEND_STR("**");
474
0
        APPEND_EXPR(e->v.DictComp.key, PR_TEST);
475
0
    }
476
1
    APPEND(comprehensions, e->v.DictComp.generators);
477
1
    APPEND_CHAR_FINISH('}');
478
1
}
479
480
static int
481
append_ast_compare(PyUnicodeWriter *writer, expr_ty e, int level)
482
1.81k
{
483
1.81k
    const char *op;
484
1.81k
    Py_ssize_t i, comparator_count;
485
1.81k
    asdl_expr_seq *comparators;
486
1.81k
    asdl_int_seq *ops;
487
488
1.81k
    APPEND_STR_IF(level > PR_CMP, "(");
489
490
1.81k
    comparators = e->v.Compare.comparators;
491
1.81k
    ops = e->v.Compare.ops;
492
1.81k
    comparator_count = asdl_seq_LEN(comparators);
493
1.81k
    assert(comparator_count > 0);
494
1.81k
    assert(comparator_count == asdl_seq_LEN(ops));
495
496
1.81k
    APPEND_EXPR(e->v.Compare.left, PR_CMP + 1);
497
498
7.53k
    for (i = 0; i < comparator_count; i++) {
499
5.72k
        switch ((cmpop_ty)asdl_seq_GET(ops, i)) {
500
48
        case Eq:
501
48
            op = " == ";
502
48
            break;
503
8
        case NotEq:
504
8
            op = " != ";
505
8
            break;
506
3.31k
        case Lt:
507
3.31k
            op = " < ";
508
3.31k
            break;
509
787
        case LtE:
510
787
            op = " <= ";
511
787
            break;
512
1.05k
        case Gt:
513
1.05k
            op = " > ";
514
1.05k
            break;
515
64
        case GtE:
516
64
            op = " >= ";
517
64
            break;
518
224
        case Is:
519
224
            op = " is ";
520
224
            break;
521
0
        case IsNot:
522
0
            op = " is not ";
523
0
            break;
524
232
        case In:
525
232
            op = " in ";
526
232
            break;
527
0
        case NotIn:
528
0
            op = " not in ";
529
0
            break;
530
0
        default:
531
0
            PyErr_SetString(PyExc_SystemError,
532
0
                            "unexpected comparison kind");
533
0
            return -1;
534
5.72k
        }
535
536
5.72k
        APPEND_STR(op);
537
5.72k
        APPEND_EXPR((expr_ty)asdl_seq_GET(comparators, i), PR_CMP + 1);
538
5.72k
    }
539
540
1.81k
    APPEND_STR_IF(level > PR_CMP, ")");
541
1.81k
    return 0;
542
1.81k
}
543
544
static int
545
append_ast_keyword(PyUnicodeWriter *writer, keyword_ty kw)
546
14
{
547
14
    if (kw->arg == NULL) {
548
6
        APPEND_STR("**");
549
6
    }
550
8
    else {
551
8
        if (-1 == PyUnicodeWriter_WriteStr(writer, kw->arg)) {
552
0
            return -1;
553
0
        }
554
555
8
        APPEND_CHAR('=');
556
8
    }
557
558
14
    APPEND_EXPR(kw->value, PR_TEST);
559
14
    return 0;
560
14
}
561
562
static int
563
append_ast_call(PyUnicodeWriter *writer, expr_ty e)
564
263
{
565
263
    bool first;
566
263
    Py_ssize_t i, arg_count, kw_count;
567
263
    expr_ty expr;
568
569
263
    APPEND_EXPR(e->v.Call.func, PR_ATOM);
570
571
263
    arg_count = asdl_seq_LEN(e->v.Call.args);
572
263
    kw_count = asdl_seq_LEN(e->v.Call.keywords);
573
263
    if (arg_count == 1 && kw_count == 0) {
574
80
        expr = (expr_ty)asdl_seq_GET(e->v.Call.args, 0);
575
80
        if (expr->kind == GeneratorExp_kind) {
576
            /* Special case: a single generator expression. */
577
0
            return append_ast_genexp(writer, expr);
578
0
        }
579
80
    }
580
581
263
    APPEND_CHAR('(');
582
583
263
    first = true;
584
434
    for (i = 0; i < arg_count; i++) {
585
171
        APPEND_STR_IF_NOT_FIRST(", ");
586
171
        APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Call.args, i), PR_TEST);
587
171
    }
588
589
277
    for (i = 0; i < kw_count; i++) {
590
14
        APPEND_STR_IF_NOT_FIRST(", ");
591
14
        APPEND(keyword, (keyword_ty)asdl_seq_GET(e->v.Call.keywords, i));
592
14
    }
593
594
263
    APPEND_CHAR_FINISH(')');
595
263
}
596
597
static PyObject *
598
escape_braces(PyObject *orig)
599
10.4k
{
600
10.4k
    PyObject *temp;
601
10.4k
    PyObject *result;
602
10.4k
    temp = PyUnicode_Replace(orig, _Py_LATIN1_CHR('{'),
603
10.4k
                             &_Py_STR(dbl_open_br), -1);
604
10.4k
    if (!temp) {
605
0
        return NULL;
606
0
    }
607
10.4k
    result = PyUnicode_Replace(temp, _Py_LATIN1_CHR('}'),
608
10.4k
                               &_Py_STR(dbl_close_br), -1);
609
10.4k
    Py_DECREF(temp);
610
10.4k
    return result;
611
10.4k
}
612
613
static int
614
append_fstring_unicode(PyUnicodeWriter *writer, PyObject *unicode)
615
10.4k
{
616
10.4k
    PyObject *escaped;
617
10.4k
    int result = -1;
618
10.4k
    escaped = escape_braces(unicode);
619
10.4k
    if (escaped) {
620
10.4k
        result = PyUnicodeWriter_WriteStr(writer, escaped);
621
10.4k
        Py_DECREF(escaped);
622
10.4k
    }
623
10.4k
    return result;
624
10.4k
}
625
626
static int
627
append_fstring_element(PyUnicodeWriter *writer, expr_ty e, bool is_format_spec)
628
19.8k
{
629
19.8k
    switch (e->kind) {
630
10.4k
    case Constant_kind:
631
10.4k
        return append_fstring_unicode(writer, e->v.Constant.value);
632
3.48k
    case JoinedStr_kind:
633
3.48k
        return append_joinedstr(writer, e, is_format_spec);
634
0
    case TemplateStr_kind:
635
0
        return append_templatestr(writer, e);
636
4.20k
    case FormattedValue_kind:
637
4.20k
        return append_formattedvalue(writer, e);
638
1.62k
    case Interpolation_kind:
639
1.62k
        return append_interpolation(writer, e);
640
0
    default:
641
0
        PyErr_SetString(PyExc_SystemError,
642
0
                        "unknown expression kind inside f-string or t-string");
643
0
        return -1;
644
19.8k
    }
645
19.8k
}
646
647
/* Build body separately to enable wrapping the entire stream of Strs,
648
   Constants and FormattedValues in one opening and one closing quote. */
649
static PyObject *
650
build_ftstring_body(asdl_expr_seq *values, bool is_format_spec)
651
7.74k
{
652
7.74k
    PyUnicodeWriter *body_writer = PyUnicodeWriter_Create(256);
653
7.74k
    if (body_writer == NULL) {
654
0
        return NULL;
655
0
    }
656
657
7.74k
    Py_ssize_t value_count = asdl_seq_LEN(values);
658
24.0k
    for (Py_ssize_t i = 0; i < value_count; ++i) {
659
16.3k
        if (-1 == append_fstring_element(body_writer,
660
16.3k
                                         (expr_ty)asdl_seq_GET(values, i),
661
16.3k
                                         is_format_spec
662
16.3k
                                         )) {
663
0
            PyUnicodeWriter_Discard(body_writer);
664
0
            return NULL;
665
0
        }
666
16.3k
    }
667
668
7.74k
    return PyUnicodeWriter_Finish(body_writer);
669
7.74k
}
670
671
static int
672
append_templatestr(PyUnicodeWriter *writer, expr_ty e)
673
425
{
674
425
    int result = -1;
675
425
    PyObject *body = build_ftstring_body(e->v.TemplateStr.values, false);
676
425
    if (!body) {
677
0
        return -1;
678
0
    }
679
680
425
    if (-1 != append_charp(writer, "t") &&
681
425
        -1 != append_repr(writer, body))
682
425
    {
683
425
        result = 0;
684
425
    }
685
425
    Py_DECREF(body);
686
425
    return result;
687
425
}
688
689
static int
690
append_joinedstr(PyUnicodeWriter *writer, expr_ty e, bool is_format_spec)
691
7.31k
{
692
7.31k
    int result = -1;
693
7.31k
    PyObject *body = build_ftstring_body(e->v.JoinedStr.values, is_format_spec);
694
7.31k
    if (!body) {
695
0
        return -1;
696
0
    }
697
698
7.31k
    if (!is_format_spec) {
699
3.83k
        if (-1 != append_charp(writer, "f") &&
700
3.83k
            -1 != append_repr(writer, body))
701
3.83k
        {
702
3.83k
            result = 0;
703
3.83k
        }
704
3.83k
    }
705
3.48k
    else {
706
3.48k
        result = PyUnicodeWriter_WriteStr(writer, body);
707
3.48k
    }
708
7.31k
    Py_DECREF(body);
709
7.31k
    return result;
710
7.31k
}
711
712
static int
713
append_interpolation_str(PyUnicodeWriter *writer, PyObject *str)
714
5.82k
{
715
5.82k
    const char *outer_brace = "{";
716
5.82k
    if (PyUnicode_Find(str, _Py_LATIN1_CHR('{'), 0, 1, 1) == 0) {
717
        /* Expression starts with a brace, split it with a space from the outer
718
           one. */
719
131
        outer_brace = "{ ";
720
131
    }
721
5.82k
    if (-1 == append_charp(writer, outer_brace)) {
722
0
        return -1;
723
0
    }
724
5.82k
    if (-1 == PyUnicodeWriter_WriteStr(writer, str)) {
725
0
        return -1;
726
0
    }
727
5.82k
    return 0;
728
5.82k
}
729
730
static int
731
append_interpolation_value(PyUnicodeWriter *writer, expr_ty e)
732
4.20k
{
733
    /* Grammar allows PR_TUPLE, but use >PR_TEST for adding parenthesis
734
       around a lambda with ':' */
735
4.20k
    PyObject *temp_fv_str = expr_as_unicode(e, PR_TEST + 1);
736
4.20k
    if (!temp_fv_str) {
737
0
        return -1;
738
0
    }
739
4.20k
    int result = append_interpolation_str(writer, temp_fv_str);
740
4.20k
    Py_DECREF(temp_fv_str);
741
4.20k
    return result;
742
4.20k
}
743
744
static int
745
append_interpolation_conversion(PyUnicodeWriter *writer, int conversion)
746
5.82k
{
747
5.82k
    if (conversion < 0) {
748
4.05k
        return 0;
749
4.05k
    }
750
751
1.77k
    const char *conversion_str;
752
1.77k
    switch (conversion) {
753
904
    case 'a':
754
904
        conversion_str = "!a";
755
904
        break;
756
610
    case 'r':
757
610
        conversion_str = "!r";
758
610
        break;
759
259
    case 's':
760
259
        conversion_str = "!s";
761
259
        break;
762
0
    default:
763
0
        PyErr_SetString(PyExc_SystemError,
764
0
                        "unknown f-value conversion kind");
765
0
        return -1;
766
1.77k
    }
767
1.77k
    APPEND_STR(conversion_str);
768
1.77k
    return 0;
769
1.77k
}
770
771
static int
772
append_interpolation_format_spec(PyUnicodeWriter *writer, expr_ty e)
773
5.82k
{
774
5.82k
    if (e) {
775
3.48k
        if (-1 == PyUnicodeWriter_WriteChar(writer, ':') ||
776
3.48k
            -1 == append_fstring_element(writer, e, true))
777
0
        {
778
0
            return -1;
779
0
        }
780
3.48k
    }
781
5.82k
    return 0;
782
5.82k
}
783
784
static int
785
append_interpolation(PyUnicodeWriter *writer, expr_ty e)
786
1.62k
{
787
1.62k
    if (-1 == append_interpolation_str(writer, e->v.Interpolation.str)) {
788
0
        return -1;
789
0
    }
790
791
1.62k
    if (-1 == append_interpolation_conversion(writer, e->v.Interpolation.conversion)) {
792
0
        return -1;
793
0
    }
794
795
1.62k
    if (-1 == append_interpolation_format_spec(writer, e->v.Interpolation.format_spec)) {
796
0
        return -1;
797
0
    }
798
799
1.62k
    APPEND_STR_FINISH("}");
800
1.62k
}
801
802
static int
803
append_formattedvalue(PyUnicodeWriter *writer, expr_ty e)
804
4.20k
{
805
4.20k
    if (-1 == append_interpolation_value(writer, e->v.FormattedValue.value)) {
806
0
        return -1;
807
0
    }
808
809
4.20k
    if (-1 == append_interpolation_conversion(writer, e->v.FormattedValue.conversion)) {
810
0
        return -1;
811
0
    }
812
813
4.20k
    if (-1 == append_interpolation_format_spec(writer, e->v.FormattedValue.format_spec)) {
814
0
        return -1;
815
0
    }
816
817
4.20k
    APPEND_CHAR_FINISH('}');
818
4.20k
}
819
820
static int
821
append_ast_constant(PyUnicodeWriter *writer, PyObject *constant)
822
101k
{
823
101k
    if (PyTuple_CheckExact(constant)) {
824
0
        Py_ssize_t i, elem_count;
825
826
0
        elem_count = PyTuple_GET_SIZE(constant);
827
0
        APPEND_CHAR('(');
828
0
        for (i = 0; i < elem_count; i++) {
829
0
            APPEND_STR_IF(i > 0, ", ");
830
0
            if (append_ast_constant(writer, PyTuple_GET_ITEM(constant, i)) < 0) {
831
0
                return -1;
832
0
            }
833
0
        }
834
835
0
        APPEND_STR_IF(elem_count == 1, ",");
836
0
        APPEND_CHAR_FINISH(')');
837
0
    }
838
101k
    return append_repr(writer, constant);
839
101k
}
840
841
static int
842
append_ast_attribute(PyUnicodeWriter *writer, expr_ty e)
843
179
{
844
179
    const char *period;
845
179
    expr_ty v = e->v.Attribute.value;
846
179
    APPEND_EXPR(v, PR_ATOM);
847
848
    /* Special case: integers require a space for attribute access to be
849
       unambiguous. */
850
179
    if (v->kind == Constant_kind && PyLong_CheckExact(v->v.Constant.value)) {
851
11
        period = " .";
852
11
    }
853
168
    else {
854
168
        period = ".";
855
168
    }
856
179
    APPEND_STR(period);
857
858
179
    return PyUnicodeWriter_WriteStr(writer, e->v.Attribute.attr);
859
179
}
860
861
static int
862
append_ast_slice(PyUnicodeWriter *writer, expr_ty e)
863
338
{
864
338
    if (e->v.Slice.lower) {
865
57
        APPEND_EXPR(e->v.Slice.lower, PR_TEST);
866
57
    }
867
868
338
    APPEND_CHAR(':');
869
870
338
    if (e->v.Slice.upper) {
871
260
        APPEND_EXPR(e->v.Slice.upper, PR_TEST);
872
260
    }
873
874
338
    if (e->v.Slice.step) {
875
72
        APPEND_CHAR(':');
876
72
        APPEND_EXPR(e->v.Slice.step, PR_TEST);
877
72
    }
878
338
    return 0;
879
338
}
880
881
static int
882
append_ast_subscript(PyUnicodeWriter *writer, expr_ty e)
883
302
{
884
302
    APPEND_EXPR(e->v.Subscript.value, PR_ATOM);
885
302
    APPEND_CHAR('[');
886
302
    APPEND_EXPR(e->v.Subscript.slice, PR_TUPLE);
887
302
    APPEND_CHAR_FINISH(']');
888
302
}
889
890
static int
891
append_ast_starred(PyUnicodeWriter *writer, expr_ty e)
892
264
{
893
264
    APPEND_CHAR('*');
894
264
    APPEND_EXPR(e->v.Starred.value, PR_EXPR);
895
264
    return 0;
896
264
}
897
898
static int
899
append_ast_yield(PyUnicodeWriter *writer, expr_ty e)
900
0
{
901
0
    if (!e->v.Yield.value) {
902
0
        APPEND_STR_FINISH("(yield)");
903
0
    }
904
905
0
    APPEND_STR("(yield ");
906
0
    APPEND_EXPR(e->v.Yield.value, PR_TEST);
907
0
    APPEND_CHAR_FINISH(')');
908
0
}
909
910
static int
911
append_ast_yield_from(PyUnicodeWriter *writer, expr_ty e)
912
0
{
913
0
    APPEND_STR("(yield from ");
914
0
    APPEND_EXPR(e->v.YieldFrom.value, PR_TEST);
915
0
    APPEND_CHAR_FINISH(')');
916
0
}
917
918
static int
919
append_ast_await(PyUnicodeWriter *writer, expr_ty e, int level)
920
0
{
921
0
    APPEND_STR_IF(level > PR_AWAIT, "(");
922
0
    APPEND_STR("await ");
923
0
    APPEND_EXPR(e->v.Await.value, PR_ATOM);
924
0
    APPEND_STR_IF(level > PR_AWAIT, ")");
925
0
    return 0;
926
0
}
927
928
static int
929
append_named_expr(PyUnicodeWriter *writer, expr_ty e, int level)
930
0
{
931
0
    APPEND_STR_IF(level > PR_TUPLE, "(");
932
0
    APPEND_EXPR(e->v.NamedExpr.target, PR_ATOM);
933
0
    APPEND_STR(" := ");
934
0
    APPEND_EXPR(e->v.NamedExpr.value, PR_ATOM);
935
0
    APPEND_STR_IF(level > PR_TUPLE, ")");
936
0
    return 0;
937
0
}
938
939
static int
940
append_ast_expr(PyUnicodeWriter *writer, expr_ty e, int level)
941
246k
{
942
246k
    switch (e->kind) {
943
346
    case BoolOp_kind:
944
346
        return append_ast_boolop(writer, e, level);
945
101k
    case BinOp_kind:
946
101k
        return append_ast_binop(writer, e, level);
947
18.3k
    case UnaryOp_kind:
948
18.3k
        return append_ast_unaryop(writer, e, level);
949
221
    case Lambda_kind:
950
221
        return append_ast_lambda(writer, e, level);
951
648
    case IfExp_kind:
952
648
        return append_ast_ifexp(writer, e, level);
953
44
    case Dict_kind:
954
44
        return append_ast_dict(writer, e);
955
307
    case Set_kind:
956
307
        return append_ast_set(writer, e);
957
0
    case GeneratorExp_kind:
958
0
        return append_ast_genexp(writer, e);
959
0
    case ListComp_kind:
960
0
        return append_ast_listcomp(writer, e);
961
25
    case SetComp_kind:
962
25
        return append_ast_setcomp(writer, e);
963
1
    case DictComp_kind:
964
1
        return append_ast_dictcomp(writer, e);
965
0
    case Yield_kind:
966
0
        return append_ast_yield(writer, e);
967
0
    case YieldFrom_kind:
968
0
        return append_ast_yield_from(writer, e);
969
0
    case Await_kind:
970
0
        return append_ast_await(writer, e, level);
971
1.81k
    case Compare_kind:
972
1.81k
        return append_ast_compare(writer, e, level);
973
263
    case Call_kind:
974
263
        return append_ast_call(writer, e);
975
102k
    case Constant_kind:
976
102k
        if (e->v.Constant.value == Py_Ellipsis) {
977
455
            APPEND_STR_FINISH("...");
978
455
        }
979
101k
        if (e->v.Constant.kind != NULL
980
637
            && -1 == PyUnicodeWriter_WriteStr(writer, e->v.Constant.kind)) {
981
0
            return -1;
982
0
        }
983
101k
        return append_ast_constant(writer, e->v.Constant.value);
984
3.83k
    case JoinedStr_kind:
985
3.83k
        return append_joinedstr(writer, e, false);
986
425
    case TemplateStr_kind:
987
425
        return append_templatestr(writer, e);
988
0
    case FormattedValue_kind:
989
0
        return append_formattedvalue(writer, e);
990
0
    case Interpolation_kind:
991
0
        return append_interpolation(writer, e);
992
    /* The following exprs can be assignment targets. */
993
179
    case Attribute_kind:
994
179
        return append_ast_attribute(writer, e);
995
302
    case Subscript_kind:
996
302
        return append_ast_subscript(writer, e);
997
264
    case Starred_kind:
998
264
        return append_ast_starred(writer, e);
999
338
    case Slice_kind:
1000
338
        return append_ast_slice(writer, e);
1001
14.0k
    case Name_kind:
1002
14.0k
        return PyUnicodeWriter_WriteStr(writer, e->v.Name.id);
1003
26
    case List_kind:
1004
26
        return append_ast_list(writer, e);
1005
720
    case Tuple_kind:
1006
720
        return append_ast_tuple(writer, e, level);
1007
0
    case NamedExpr_kind:
1008
0
        return append_named_expr(writer, e, level);
1009
    // No default so compiler emits a warning for unhandled cases
1010
246k
    }
1011
0
    PyErr_SetString(PyExc_SystemError,
1012
0
                    "unknown expression kind");
1013
0
    return -1;
1014
246k
}
1015
1016
static PyObject *
1017
expr_as_unicode(expr_ty e, int level)
1018
9.41k
{
1019
9.41k
    PyUnicodeWriter *writer = PyUnicodeWriter_Create(256);
1020
9.41k
    if (writer == NULL) {
1021
0
        return NULL;
1022
0
    }
1023
1024
9.41k
    if (-1 == append_ast_expr(writer, e, level)) {
1025
0
        PyUnicodeWriter_Discard(writer);
1026
0
        return NULL;
1027
0
    }
1028
9.41k
    return PyUnicodeWriter_Finish(writer);
1029
9.41k
}
1030
1031
PyObject *
1032
_PyAST_ExprAsUnicode(expr_ty e)
1033
5.21k
{
1034
5.21k
    return expr_as_unicode(e, PR_TEST);
1035
5.21k
}