#include #include "Python.h" #include "Python-ast.h" static PyObject *_str_open_br; static PyObject *_str_dbl_open_br; static PyObject *_str_close_br; static PyObject *_str_dbl_close_br; /* Forward declarations for recursion via helper functions. */ static PyObject * expr_as_unicode(expr_ty e, bool omit_parens); static int append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens); static int append_joinedstr(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec); static int append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec); static int append_charp(_PyUnicodeWriter *writer, const char *charp) { return _PyUnicodeWriter_WriteASCIIString(writer, charp, -1); } static int append_repr(_PyUnicodeWriter *writer, PyObject *obj) { int ret; PyObject *repr; repr = PyObject_Repr(obj); if (!repr) { return -1; } ret = _PyUnicodeWriter_WriteStr(writer, repr); Py_DECREF(repr); return ret; } static int append_ast_boolop(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) { Py_ssize_t i, value_count; asdl_seq *values; if (!omit_parens && -1 == append_charp(writer, "(")) { return -1; } values = e->v.BoolOp.values; value_count = asdl_seq_LEN(values) - 1; assert(value_count >= 0); if (-1 == append_ast_expr(writer, (expr_ty)asdl_seq_GET(values, 0), false)) { return -1; } const char *op = (e->v.BoolOp.op == And) ? " and " : " or "; for (i = 1; i <= value_count; ++i) { if (-1 == append_charp(writer, op)) { return -1; } if (-1 == append_ast_expr(writer, (expr_ty)asdl_seq_GET(values, i), false)) { return -1; } } return omit_parens ? 0 : append_charp(writer, ")"); } static int append_ast_binop(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) { const char *op; if (!omit_parens && -1 == append_charp(writer, "(")) { return -1; } if (-1 == append_ast_expr(writer, e->v.BinOp.left, false)) { return -1; } switch(e->v.BinOp.op) { case Add: op = " + "; break; case Sub: op = " - "; break; case Mult: op = " * "; break; case MatMult: op = " @ "; break; case Div: op = " / "; break; case Mod: op = " % "; break; case LShift: op = " << "; break; case RShift: op = " >> "; break; case BitOr: op = " | "; break; case BitXor: op = " ^ "; break; case BitAnd: op = " & "; break; case FloorDiv: op = " // "; break; case Pow: op = " ** "; break; } if (-1 == append_charp(writer, op)) { return -1; } if (-1 == append_ast_expr(writer, e->v.BinOp.right, false)) { return -1; } return omit_parens ? 0 : append_charp(writer, ")"); } static int append_ast_unaryop(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) { const char *op; if (!omit_parens && -1 == append_charp(writer, "(")) { return -1; } switch(e->v.UnaryOp.op) { case Invert: op = "~"; break; case Not: op = "not "; break; case UAdd: op = "+"; break; case USub: op = "-"; break; } if (-1 == append_charp(writer, op)) { return -1; } if (-1 == append_ast_expr(writer, e->v.UnaryOp.operand, false)) { return -1; } return omit_parens ? 0 : append_charp(writer, ")"); } static int append_ast_arg(_PyUnicodeWriter *writer, arg_ty arg) { if (-1 == _PyUnicodeWriter_WriteStr(writer, arg->arg)) { return -1; } if (arg->annotation) { if (-1 == append_charp(writer, ": ")) { return -1; } if (-1 == append_ast_expr(writer, arg->annotation, true)) { return -1; } } return 0; } static int append_ast_args(_PyUnicodeWriter *writer, arguments_ty args) { bool first; Py_ssize_t i, di, arg_count, default_count; arg_ty arg; expr_ty default_; first = true; /* positional arguments with defaults */ arg_count = asdl_seq_LEN(args->args); default_count = asdl_seq_LEN(args->defaults); for (i = 0; i < arg_count; i++) { if (first) { first = false; } else if (-1 == append_charp(writer, ", ")) { return -1; } arg = (arg_ty)asdl_seq_GET(args->args, i); if (-1 == append_ast_arg(writer, arg)) { return -1; } di = i - arg_count + default_count; if (di >= 0) { if (-1 == append_charp(writer, "=")) { return -1; } default_ = (expr_ty)asdl_seq_GET(args->defaults, di); if (-1 == append_ast_expr(writer, default_, false)) { return -1; } } } /* vararg, or bare '*' if no varargs but keyword-only arguments present */ if (args->vararg || args->kwonlyargs) { if (first) { first = false; } else if (-1 == append_charp(writer, ", ")) { return -1; } if (-1 == append_charp(writer, "*")) { return -1; } if (args->vararg) { if (-1 == append_ast_arg(writer, args->vararg)) { return -1; } } } /* keyword-only arguments */ arg_count = asdl_seq_LEN(args->kwonlyargs); default_count = asdl_seq_LEN(args->kw_defaults); for (i = 0; i < arg_count; i++) { if (first) { first = false; } else if (-1 == append_charp(writer, ", ")) { return -1; } arg = (arg_ty)asdl_seq_GET(args->kwonlyargs, i); if (-1 == append_ast_arg(writer, arg)) { return -1; } di = i - arg_count + default_count; if (di >= 0) { if (-1 == append_charp(writer, "=")) { return -1; } default_ = (expr_ty)asdl_seq_GET(args->kw_defaults, di); if (-1 == append_ast_expr(writer, default_, false)) { return -1; } } } /* **kwargs */ if (args->kwarg) { if (first) { first = false; } else if (-1 == append_charp(writer, ", ")) { return -1; } if (-1 == append_charp(writer, "**")) { return -1; } if (-1 == append_ast_arg(writer, args->kwarg)) { return -1; } } return 0; } static int append_ast_lambda(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) { if (!omit_parens && -1 == append_charp(writer, "(")) { return -1; } if (-1 == append_charp(writer, "lambda ")) { return -1; } if (-1 == append_ast_args(writer, e->v.Lambda.args)) { return -1; } if (-1 == append_charp(writer, ": ")) { return -1; } if (-1 == append_ast_expr(writer, e->v.Lambda.body, true)) { return -1; } return omit_parens ? 0 : append_charp(writer, ")"); } static int append_ast_ifexp(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) { if (!omit_parens && -1 == append_charp(writer, "(")) { return -1; } if (-1 == append_ast_expr(writer, e->v.IfExp.body, false)) { return -1; } if (-1 == append_charp(writer, " if ")) { return -1; } if (-1 == append_ast_expr(writer, e->v.IfExp.test, false)) { return -1; } if (-1 == append_charp(writer, " else ")) { return -1; } if (-1 == append_ast_expr(writer, e->v.IfExp.orelse, false)) { return -1; } return omit_parens ? 0 : append_charp(writer, ")"); } static int append_ast_dict(_PyUnicodeWriter *writer, expr_ty e) { Py_ssize_t i, value_count; expr_ty key_node, value_node; if (-1 == append_charp(writer, "{")) { return -1; } value_count = asdl_seq_LEN(e->v.Dict.values); for (i = 0; i < value_count; i++) { if (i > 0 && -1 == append_charp(writer, ", ")) { return -1; } key_node = (expr_ty)asdl_seq_GET(e->v.Dict.keys, i); if (key_node != NULL) { if (-1 == append_ast_expr(writer, key_node, false)) { return -1; } if (-1 == append_charp(writer, ": ")) { return -1; } } else if (-1 == append_charp(writer, "**")) { return -1; } value_node = (expr_ty)asdl_seq_GET(e->v.Dict.values, i); if (-1 == append_ast_expr(writer, value_node, false)) { return -1; } } return append_charp(writer, "}"); } static int append_ast_set(_PyUnicodeWriter *writer, expr_ty e) { Py_ssize_t i, elem_count; expr_ty elem_node; if (-1 == append_charp(writer, "{")) { return -1; } elem_count = asdl_seq_LEN(e->v.Set.elts); for (i = 0; i < elem_count; i++) { if (i > 0 && -1 == append_charp(writer, ", ")) { return -1; } elem_node = (expr_ty)asdl_seq_GET(e->v.Set.elts, i); if (-1 == append_ast_expr(writer, elem_node, false)) { return -1; } } return append_charp(writer, "}"); } static int append_ast_list(_PyUnicodeWriter *writer, expr_ty e) { Py_ssize_t i, elem_count; expr_ty elem_node; if (-1 == append_charp(writer, "[")) { return -1; } elem_count = asdl_seq_LEN(e->v.List.elts); for (i = 0; i < elem_count; i++) { if (i > 0 && -1 == append_charp(writer, ", ")) { return -1; } elem_node = (expr_ty)asdl_seq_GET(e->v.List.elts, i); if (-1 == append_ast_expr(writer, elem_node, false)) { return -1; } } return append_charp(writer, "]"); } static int append_ast_tuple(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) { Py_ssize_t i, elem_count; expr_ty elem_node; elem_count = asdl_seq_LEN(e->v.Tuple.elts); if (!omit_parens || elem_count < 2) { if (-1 == append_charp(writer, "(")) { return -1; } } for (i = 0; i < elem_count; i++) { if ((i > 0 || elem_count == 1) && -1 == append_charp(writer, ", ")) { return -1; } elem_node = (expr_ty)asdl_seq_GET(e->v.Tuple.elts, i); if (-1 == append_ast_expr(writer, elem_node, false)) { return -1; } } if (!omit_parens || elem_count < 2) { return append_charp(writer, ")"); } return 0; } static int append_ast_comprehension(_PyUnicodeWriter *writer, comprehension_ty gen) { Py_ssize_t i, if_count; if (-1 == append_charp(writer, gen->is_async ? " async for " : " for ")) { return -1; } if (-1 == append_ast_expr(writer, gen->target, true)) { return -1; } if (-1 == append_charp(writer, " in ")) { return -1; } if (-1 == append_ast_expr(writer, gen->iter, false)) { return -1; } if_count = asdl_seq_LEN(gen->ifs); for (i = 0; i < if_count; i++) { if (-1 == append_charp(writer, " if ")) { return -1; } if (-1 == append_ast_expr(writer, (expr_ty)asdl_seq_GET(gen->ifs, i), false)) { return -1; } } return 0; } static int append_ast_comprehensions(_PyUnicodeWriter *writer, asdl_seq *comprehensions) { Py_ssize_t i, gen_count; comprehension_ty comp_node; gen_count = asdl_seq_LEN(comprehensions); for (i = 0; i < gen_count; i++) { comp_node = (comprehension_ty)asdl_seq_GET(comprehensions, i); if (-1 == append_ast_comprehension(writer, comp_node)) { return -1; } } return 0; } static int append_ast_genexp(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) { if (!omit_parens && -1 == append_charp(writer, "(")) { return -1; } if (-1 == append_ast_expr(writer, e->v.GeneratorExp.elt, false)) { return -1; } if (-1 == append_ast_comprehensions(writer, e->v.GeneratorExp.generators)) { return -1; } return omit_parens ? 0 : append_charp(writer, ")"); } static int append_ast_listcomp(_PyUnicodeWriter *writer, expr_ty e) { if (-1 == append_charp(writer, "[")) { return -1; } if (-1 == append_ast_expr(writer, e->v.ListComp.elt, false)) { return -1; } if (-1 == append_ast_comprehensions(writer, e->v.ListComp.generators)) { return -1; } return append_charp(writer, "]"); } static int append_ast_setcomp(_PyUnicodeWriter *writer, expr_ty e) { if (-1 == append_charp(writer, "{")) { return -1; } if (-1 == append_ast_expr(writer, e->v.SetComp.elt, false)) { return -1; } if (-1 == append_ast_comprehensions(writer, e->v.SetComp.generators)) { return -1; } return append_charp(writer, "}"); } static int append_ast_dictcomp(_PyUnicodeWriter *writer, expr_ty e) { if (-1 == append_charp(writer, "{")) { return -1; } if (-1 == append_ast_expr(writer, e->v.DictComp.key, false)) { return -1; } if (-1 == append_charp(writer, ": ")) { return -1; } if (-1 == append_ast_expr(writer, e->v.DictComp.value, false)) { return -1; } if (-1 == append_ast_comprehensions(writer, e->v.DictComp.generators)) { return -1; } return append_charp(writer, "}"); } static int append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) { const char *op; Py_ssize_t i, comparator_count; asdl_seq *comparators; asdl_int_seq *ops; if (!omit_parens && -1 == append_charp(writer, "(")) { return -1; } comparators = e->v.Compare.comparators; ops = e->v.Compare.ops; comparator_count = asdl_seq_LEN(comparators); assert(comparator_count > 0); assert(comparator_count == asdl_seq_LEN(ops)); if (-1 == append_ast_expr(writer, e->v.Compare.left, false)) { return -1; } for (i = 0; i < comparator_count; i++) { switch ((cmpop_ty)asdl_seq_GET(ops, i)) { case Eq: op = " == "; break; case NotEq: op = " != "; break; case Lt: op = " < "; break; case LtE: op = " <= "; break; case Gt: op = " > "; break; case GtE: op = " >= "; break; case Is: op = " is "; break; case IsNot: op = " is not "; break; case In: op = " in "; break; case NotIn: op = " not in "; break; default: PyErr_SetString(PyExc_SystemError, "unexpected comparison kind"); return -1; } if (-1 == append_charp(writer, op)) { return -1; } if (-1 == append_ast_expr(writer, (expr_ty)asdl_seq_GET(comparators, i), false)) { return -1; } } return omit_parens ? 0 : append_charp(writer, ")"); } static int append_ast_keyword(_PyUnicodeWriter *writer, keyword_ty kw) { if (kw->arg == NULL) { if (-1 == append_charp(writer, "**")) { return -1; } } else { if (-1 == _PyUnicodeWriter_WriteStr(writer, kw->arg)) { return -1; } if (-1 == append_charp(writer, "=")) { return -1; } } return append_ast_expr(writer, kw->value, false); } static int append_ast_call(_PyUnicodeWriter *writer, expr_ty e) { bool first; Py_ssize_t i, arg_count, kw_count; expr_ty expr; keyword_ty kw; if (-1 == append_ast_expr(writer, e->v.Call.func, false)) { return -1; } if (-1 == append_charp(writer, "(")) { return -1; } first = true; arg_count = asdl_seq_LEN(e->v.Call.args); for (i = 0; i < arg_count; i++) { if (first) { first = false; } else if (-1 == append_charp(writer, ", ")) { return -1; } expr = (expr_ty)asdl_seq_GET(e->v.Call.args, i); if (-1 == append_ast_expr(writer, expr, false)) { return -1; } } kw_count = asdl_seq_LEN(e->v.Call.keywords); for (i = 0; i < kw_count; i++) { if (first) { first = false; } else if (-1 == append_charp(writer, ", ")) { return -1; } kw = (keyword_ty)asdl_seq_GET(e->v.Call.keywords, i); if (-1 == append_ast_keyword(writer, kw)) { return -1; } } return append_charp(writer, ")"); } static PyObject * escape_braces(PyObject *orig) { PyObject *temp; PyObject *result; temp = PyUnicode_Replace(orig, _str_open_br, _str_dbl_open_br, -1); if (!temp) { return NULL; } result = PyUnicode_Replace(temp, _str_close_br, _str_dbl_close_br, -1); Py_DECREF(temp); return result; } static int append_fstring_unicode(_PyUnicodeWriter *writer, PyObject *unicode) { PyObject *escaped; int result = -1; escaped = escape_braces(unicode); if (escaped) { result = _PyUnicodeWriter_WriteStr(writer, escaped); Py_DECREF(escaped); } return result; } static int append_fstring_element(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) { switch (e->kind) { case Constant_kind: return append_fstring_unicode(writer, e->v.Constant.value); case Str_kind: return append_fstring_unicode(writer, e->v.Str.s); case JoinedStr_kind: return append_joinedstr(writer, e, is_format_spec); case FormattedValue_kind: return append_formattedvalue(writer, e, is_format_spec); default: PyErr_SetString(PyExc_SystemError, "unknown expression kind inside f-string"); return -1; } } /* Build body separately to enable wrapping the entire stream of Strs, Constants and FormattedValues in one opening and one closing quote. */ static PyObject * build_fstring_body(asdl_seq *values, bool is_format_spec) { Py_ssize_t i, value_count; _PyUnicodeWriter body_writer; _PyUnicodeWriter_Init(&body_writer); body_writer.min_length = 256; body_writer.overallocate = 1; value_count = asdl_seq_LEN(values) - 1; assert(value_count >= 0); for (i = 0; i <= value_count; ++i) { if (-1 == append_fstring_element(&body_writer, (expr_ty)asdl_seq_GET(values, i), is_format_spec )) { _PyUnicodeWriter_Dealloc(&body_writer); return NULL; } } return _PyUnicodeWriter_Finish(&body_writer); } static int append_joinedstr(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) { int result = -1; PyObject *body = build_fstring_body(e->v.JoinedStr.values, is_format_spec); if (!body) { return -1; } if (!is_format_spec) { if (-1 != append_charp(writer, "f") && -1 != append_repr(writer, body)) { result = 0; } } else { result = _PyUnicodeWriter_WriteStr(writer, body); } Py_DECREF(body); return result; } static int append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) { char *conversion; char *outer_brace = "{"; PyObject *temp_fv_str = expr_as_unicode(e->v.FormattedValue.value, true); if (!temp_fv_str) { return -1; } if (PyUnicode_Find(temp_fv_str, _str_open_br, 0, 1, 1) == 0) { /* Expression starts with a brace, split it with a space from the outer one. */ outer_brace = "{ "; } if (-1 == append_charp(writer, outer_brace)) { Py_DECREF(temp_fv_str); return -1; } if (-1 == _PyUnicodeWriter_WriteStr(writer, temp_fv_str)) { Py_DECREF(temp_fv_str); return -1; } Py_DECREF(temp_fv_str); if (e->v.FormattedValue.conversion > 0) { switch (e->v.FormattedValue.conversion) { case 97: conversion = "!a"; break; case 114: conversion = "!r"; break; case 115: conversion = "!s"; break; default: PyErr_SetString(PyExc_SystemError, "unknown f-value conversion kind"); return -1; } if (-1 == append_charp(writer, conversion)) { return -1; } } if (e->v.FormattedValue.format_spec > 0) { if (-1 == _PyUnicodeWriter_WriteASCIIString(writer, ":", 1) || -1 == append_fstring_element(writer, e->v.FormattedValue.format_spec, true )) { return -1; } } return append_charp(writer, "}"); } static int append_ast_attribute(_PyUnicodeWriter *writer, expr_ty e) { const char *period; if (-1 == append_ast_expr(writer, e->v.Attribute.value, false)) { return -1; } /* Special case: integers require a space for attribute access to be unambiguous. Floats and complex numbers don't but work with it, too. */ if (e->v.Attribute.value->kind == Num_kind || e->v.Attribute.value->kind == Constant_kind) { period = " ."; } else { period = "."; } if (-1 == append_charp(writer, period)) { return -1; } return _PyUnicodeWriter_WriteStr(writer, e->v.Attribute.attr); } static int append_ast_simple_slice(_PyUnicodeWriter *writer, slice_ty slice) { if (slice->v.Slice.lower) { if (-1 == append_ast_expr(writer, slice->v.Slice.lower, false)) { return -1; } } if (-1 == append_charp(writer, ":")) { return -1; } if (slice->v.Slice.upper) { if (-1 == append_ast_expr(writer, slice->v.Slice.upper, false)) { return -1; } } if (slice->v.Slice.step) { if (-1 == append_charp(writer, ":")) { return -1; } if (-1 == append_ast_expr(writer, slice->v.Slice.step, false)) { return -1; } } return 0; } static int append_ast_ext_slice(_PyUnicodeWriter *writer, slice_ty slice) { Py_ssize_t i, dims_count; dims_count = asdl_seq_LEN(slice->v.ExtSlice.dims); for (i = 0; i < dims_count; i++) { if (i > 0 && -1 == append_charp(writer, ", ")) { return -1; } if (-1 == append_ast_expr(writer, (expr_ty)asdl_seq_GET(slice->v.ExtSlice.dims, i), false)) { return -1; } } return 0; } static int append_ast_slice(_PyUnicodeWriter *writer, slice_ty slice, bool omit_parens) { switch(slice->kind) { case Slice_kind: return append_ast_simple_slice(writer, slice); case ExtSlice_kind: return append_ast_ext_slice(writer, slice); case Index_kind: return append_ast_expr(writer, slice->v.Index.value, omit_parens); default: PyErr_SetString(PyExc_SystemError, "unexpected slice kind"); return -1; } } static int append_ast_subscript(_PyUnicodeWriter *writer, expr_ty e) { if (-1 == append_ast_expr(writer, e->v.Subscript.value, false)) { return -1; } if (-1 == append_charp(writer, "[")) { return -1; } if (-1 == append_ast_slice(writer, e->v.Subscript.slice, true)) { return -1; } return append_charp(writer, "]"); } static int append_ast_starred(_PyUnicodeWriter *writer, expr_ty e) { if (-1 == append_charp(writer, "*")) { return -1; } return append_ast_expr(writer, e->v.Starred.value, false); } static int append_ast_yield(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) { if (!omit_parens && -1 == append_charp(writer, "(")) { return -1; } if (-1 == append_charp(writer, e->v.Yield.value ? "yield " : "yield")) { return -1; } if (e->v.Yield.value) { if (-1 == append_ast_expr(writer, e->v.Yield.value, false)) { return -1; } } return omit_parens ? 0 : append_charp(writer, ")"); } static int append_ast_yield_from(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) { if (!omit_parens && -1 == append_charp(writer, "(")) { return -1; } if (-1 == append_charp(writer, e->v.YieldFrom.value ? "yield from " : "yield from")) { return -1; } if (e->v.YieldFrom.value) { if (-1 == append_ast_expr(writer, e->v.YieldFrom.value, false)) { return -1; } } return omit_parens ? 0 : append_charp(writer, ")"); } static int append_ast_await(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) { if (!omit_parens && -1 == append_charp(writer, "(")) { return -1; } if (-1 == append_charp(writer, e->v.Await.value ? "await " : "await")) { return -1; } if (e->v.Await.value) { if (-1 == append_ast_expr(writer, e->v.Await.value, false)) { return -1; } } return omit_parens ? 0 : append_charp(writer, ")"); } static int append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) { switch (e->kind) { case BoolOp_kind: return append_ast_boolop(writer, e, omit_parens); case BinOp_kind: return append_ast_binop(writer, e, omit_parens); case UnaryOp_kind: return append_ast_unaryop(writer, e, omit_parens); case Lambda_kind: return append_ast_lambda(writer, e, omit_parens); case IfExp_kind: return append_ast_ifexp(writer, e, omit_parens); case Dict_kind: return append_ast_dict(writer, e); case Set_kind: return append_ast_set(writer, e); case GeneratorExp_kind: return append_ast_genexp(writer, e, omit_parens); case ListComp_kind: return append_ast_listcomp(writer, e); case SetComp_kind: return append_ast_setcomp(writer, e); case DictComp_kind: return append_ast_dictcomp(writer, e); case Yield_kind: return append_ast_yield(writer, e, omit_parens); case YieldFrom_kind: return append_ast_yield_from(writer, e, omit_parens); case Await_kind: return append_ast_await(writer, e, omit_parens); case Compare_kind: return append_ast_compare(writer, e, omit_parens); case Call_kind: return append_ast_call(writer, e); case Constant_kind: return append_repr(writer, e->v.Constant.value); case Num_kind: return append_repr(writer, e->v.Num.n); case Str_kind: return append_repr(writer, e->v.Str.s); case JoinedStr_kind: return append_joinedstr(writer, e, false); case FormattedValue_kind: return append_formattedvalue(writer, e, false); case Bytes_kind: return append_repr(writer, e->v.Bytes.s); case Ellipsis_kind: return append_charp(writer, "..."); case NameConstant_kind: return append_repr(writer, e->v.NameConstant.value); /* The following exprs can be assignment targets. */ case Attribute_kind: return append_ast_attribute(writer, e); case Subscript_kind: return append_ast_subscript(writer, e); case Starred_kind: return append_ast_starred(writer, e); case Name_kind: return _PyUnicodeWriter_WriteStr(writer, e->v.Name.id); /* child nodes of List and Tuple will have expr_context set */ case List_kind: return append_ast_list(writer, e); case Tuple_kind: return append_ast_tuple(writer, e, omit_parens); default: PyErr_SetString(PyExc_SystemError, "unknown expression kind"); return -1; } } static int maybe_init_static_strings() { if (!_str_open_br && !(_str_open_br = PyUnicode_InternFromString("{"))) { return -1; } if (!_str_dbl_open_br && !(_str_dbl_open_br = PyUnicode_InternFromString("{{"))) { return -1; } if (!_str_close_br && !(_str_close_br = PyUnicode_InternFromString("}"))) { return -1; } if (!_str_dbl_close_br && !(_str_dbl_close_br = PyUnicode_InternFromString("}}"))) { return -1; } return 0; } static PyObject * expr_as_unicode(expr_ty e, bool omit_parens) { _PyUnicodeWriter writer; _PyUnicodeWriter_Init(&writer); writer.min_length = 256; writer.overallocate = 1; if (-1 == maybe_init_static_strings() || -1 == append_ast_expr(&writer, e, omit_parens)) { _PyUnicodeWriter_Dealloc(&writer); return NULL; } return _PyUnicodeWriter_Finish(&writer); } PyObject * _PyAST_ExprAsUnicode(expr_ty e, bool omit_parens) { return expr_as_unicode(e, omit_parens); }