From 64fddc423fcbe90b8088446c63385ec0aaf3077c Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 17 May 2018 06:17:48 +0300 Subject: [PATCH] bpo-33475: Fix and improve converting annotations to strings. (GH-6774) --- Include/ast.h | 4 +- Lib/test/test_future.py | 127 +-- .../2018-05-13-01-26-18.bpo-33475.rI0y1U.rst | 2 + Python/ast_unparse.c | 822 ++++++------------ Python/compile.c | 2 +- 5 files changed, 356 insertions(+), 601 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2018-05-13-01-26-18.bpo-33475.rI0y1U.rst diff --git a/Include/ast.h b/Include/ast.h index 639c4f82325..5bc2b05b3e9 100644 --- a/Include/ast.h +++ b/Include/ast.h @@ -19,9 +19,7 @@ PyAPI_FUNC(mod_ty) PyAST_FromNodeObject( #ifndef Py_LIMITED_API /* _PyAST_ExprAsUnicode is defined in ast_unparse.c */ -PyAPI_FUNC(PyObject *) _PyAST_ExprAsUnicode( - expr_ty e, - int omit_parens); +PyAPI_FUNC(PyObject *) _PyAST_ExprAsUnicode(expr_ty); #endif /* !Py_LIMITED_API */ diff --git a/Lib/test/test_future.py b/Lib/test/test_future.py index 29c4632e7e5..61cd63479d8 100644 --- a/Lib/test/test_future.py +++ b/Lib/test/test_future.py @@ -157,55 +157,76 @@ class AnnotationsFutureTestCase(unittest.TestCase): eq('True or False or None') eq('True and False') eq('True and False and None') - eq('(Name1 and Name2) or Name3') - eq('Name1 or (Name2 and Name3)') - eq('(Name1 and Name2) or (Name3 and Name4)') - eq('Name1 or (Name2 and Name3) or Name4') + eq('Name1 and Name2 or Name3') + eq('Name1 and (Name2 or Name3)') + eq('Name1 or Name2 and Name3') + eq('(Name1 or Name2) and Name3') + eq('Name1 and Name2 or Name3 and Name4') + eq('Name1 or Name2 and Name3 or Name4') + eq('a + b + (c + d)') + eq('a * b * (c * d)') + eq('(a ** b) ** c ** d') eq('v1 << 2') eq('1 >> v2') - eq(r'1 % finished') - eq('((1 + v2) - (v3 * 4)) ^ (((5 ** v6) / 7) // 8)') + eq('1 % finished') + eq('1 + v2 - v3 * 4 ^ 5 ** v6 / 7 // 8') eq('not great') + eq('not not great') eq('~great') eq('+value') + eq('++value') eq('-1') - eq('(~int) and (not ((v1 ^ (123 + v2)) | True))') + eq('~int and not v1 ^ 123 + v2 | True') + eq('a + (not b)') eq('lambda arg: None') eq('lambda a=True: a') eq('lambda a, b, c=True: a') - eq("lambda a, b, c=True, *, d=(1 << v2), e='str': a") - eq("lambda a, b, c=True, *vararg, d=(v1 << 2), e='str', **kwargs: a + b") + eq("lambda a, b, c=True, *, d=1 << v2, e='str': a") + eq("lambda a, b, c=True, *vararg, d=v1 << 2, e='str', **kwargs: a + b") + eq('lambda x: lambda y: x + y') eq('1 if True else 2') - eq('(str or None) if True else (str or bytes or None)') - eq('(str or None) if (1 if True else 2) else (str or bytes or None)') - eq("{'2.7': dead, '3.7': (long_live or die_hard)}") - eq("{'2.7': dead, '3.7': (long_live or die_hard), **{'3.6': verygood}}") + eq('str or None if int or True else str or bytes or None') + eq('str or None if (1 if True else 2) else str or bytes or None') + eq("0 if not x else 1 if x > 0 else -1") + eq("(1 if x > 0 else -1) if x else 0") + eq("{'2.7': dead, '3.7': long_live or die_hard}") + eq("{'2.7': dead, '3.7': long_live or die_hard, **{'3.6': verygood}}") eq("{**a, **b, **c}") - eq("{'2.7', '3.6', '3.7', '3.8', '3.9', ('4.0' if gilectomy else '3.10')}") - eq("({'a': 'b'}, (True or False), (+value), 'string', b'bytes') or None") + eq("{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}") + eq("{*a, *b, *c}") + eq("({'a': 'b'}, True or False, +value, 'string', b'bytes') or None") eq("()") - eq("(1,)") - eq("(1, 2)") - eq("(1, 2, 3)") + eq("(a,)") + eq("(a, b)") + eq("(a, b, c)") + eq("(*a, *b, *c)") eq("[]") - eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, (10 or A), (11 or B), (12 or C)]") + eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]") + eq("[*a, *b, *c]") eq("{i for i in (1, 2, 3)}") - eq("{(i ** 2) for i in (1, 2, 3)}") - eq("{(i ** 2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}") - eq("{((i ** 2) + j) for i in (1, 2, 3) for j in (1, 2, 3)}") + eq("{i ** 2 for i in (1, 2, 3)}") + eq("{i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}") + eq("{i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)}") eq("[i for i in (1, 2, 3)]") - eq("[(i ** 2) for i in (1, 2, 3)]") - eq("[(i ** 2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]") - eq("[((i ** 2) + j) for i in (1, 2, 3) for j in (1, 2, 3)]") - eq(r"{i: 0 for i in (1, 2, 3)}") + eq("[i ** 2 for i in (1, 2, 3)]") + eq("[i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]") + eq("[i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)]") + eq("(i for i in (1, 2, 3))") + eq("(i ** 2 for i in (1, 2, 3))") + eq("(i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))") + eq("(i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3))") + eq("{i: 0 for i in (1, 2, 3)}") eq("{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}") + eq("[(x, y) for x, y in (a, b)]") + eq("[(x,) for x, in (a,)]") eq("Python3 > Python2 > COBOL") eq("Life is Life") eq("call()") eq("call(arg)") eq("call(kwarg='hey')") eq("call(arg, kwarg='hey')") - eq("call(arg, another, kwarg='hey', **kwargs)") + eq("call(arg, *args, another, kwarg='hey')") + eq("call(arg, another, kwarg='hey', **kwargs, kwarg2='ho')") eq("lukasz.langa.pl") eq("call.me(maybe)") eq("1 .real") @@ -213,6 +234,7 @@ class AnnotationsFutureTestCase(unittest.TestCase): eq("....__class__") eq("list[str]") eq("dict[str, int]") + eq("set[str,]") eq("tuple[str, ...]") eq("tuple[str, int, float, dict[str, int]]") eq("slice[0]") @@ -222,49 +244,28 @@ class AnnotationsFutureTestCase(unittest.TestCase): eq("slice[:-1]") eq("slice[1:]") eq("slice[::-1]") - eq('(str or None) if (sys.version_info[0] > (3,)) else (str or bytes or None)') + eq("slice[()]") + eq("slice[a, b:c, d:e:f]") + eq("slice[(x for x in a)]") + eq('str or None if sys.version_info[0] > (3,) else str or bytes or None') eq("f'f-string without formatted values is just a string'") eq("f'{{NOT a formatted value}}'") eq("f'some f-string with {a} {few():.2f} {formatted.values!r}'") eq('''f"{f'{nested} inner'} outer"''') eq("f'space between opening braces: { {a for a in (1, 2, 3)}}'") - - def test_annotations_inexact(self): - """Source formatting is not always preserved - - This is due to reconstruction from AST. We *need to* put the parens - in nested expressions because we don't know if the source code - had them in the first place or not. - """ - eq = partial(self.assertAnnotationEqual, drop_parens=True) - eq('Name1 and Name2 or Name3') - eq('Name1 or Name2 and Name3') - eq('Name1 and Name2 or Name3 and Name4') - eq('Name1 or Name2 and Name3 or Name4') - eq('1 + v2 - v3 * 4 ^ v5 ** 6 / 7 // 8') - eq('~int and not v1 ^ 123 + v2 | True') - eq('str or None if True else str or bytes or None') - eq("{'2.7': dead, '3.7': long_live or die_hard}") - eq("{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}") - eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]") - # Consequently, we always drop unnecessary parens if they were given in - # the outer scope: - some_name = self.getActual("(SomeName)") - self.assertEqual(some_name, 'SomeName') - # Interestingly, in the case of tuples (and generator expressions) the - # parens are *required* by the Python syntax in the annotation context. - # But there's no point storing that detail in __annotations__ so we're - # fine with the parens-less form. - eq = partial(self.assertAnnotationEqual, is_tuple=True) - eq("(Good, Bad, Ugly)") - eq("(i for i in (1, 2, 3))") - eq("((i ** 2) for i in (1, 2, 3))") - eq("((i ** 2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))") - eq("(((i ** 2) + j) for i in (1, 2, 3) for j in (1, 2, 3))") - eq("(*starred)") + eq("f'{(lambda x: x)}'") + eq("f'{(None if a else lambda x: x)}'") eq('(yield from outside_of_generator)') eq('(yield)') - eq('(await some.complicated[0].call(with_args=(True or (1 is not 1))))') + eq('(yield a + b)') + eq('await some.complicated[0].call(with_args=True or 1 is not 1)') + eq('[x for x in (a if b else c)]') + eq('[x for x in a if (b if c else d)]') + eq('f(x for x in a)') + eq('f(1, (x for x in a))') + eq('f((x for x in a), 2)') + eq('(((a)))', 'a') + eq('(((a, b)))', '(a, b)') if __name__ == "__main__": diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-13-01-26-18.bpo-33475.rI0y1U.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-13-01-26-18.bpo-33475.rI0y1U.rst new file mode 100644 index 00000000000..cd714b9d1e8 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-05-13-01-26-18.bpo-33475.rI0y1U.rst @@ -0,0 +1,2 @@ +Fixed miscellaneous bugs in converting annotations to strings and optimized +parentheses in the string representation. diff --git a/Python/ast_unparse.c b/Python/ast_unparse.c index 1345271e599..725ce31fe3c 100644 --- a/Python/ast_unparse.c +++ b/Python/ast_unparse.c @@ -9,13 +9,15 @@ static PyObject *_str_dbl_close_br; /* Forward declarations for recursion via helper functions. */ static PyObject * -expr_as_unicode(expr_ty e, bool omit_parens); +expr_as_unicode(expr_ty e, int level); static int -append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens); +append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, int level); 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_ast_slice(_PyUnicodeWriter *writer, slice_ty slice); static int append_charp(_PyUnicodeWriter *writer, const char *charp) @@ -23,6 +25,39 @@ append_charp(_PyUnicodeWriter *writer, const char *charp) return _PyUnicodeWriter_WriteASCIIString(writer, charp, -1); } +#define APPEND_STR_FINISH(str) do { \ + return append_charp(writer, (str)); \ + } while (0) + +#define APPEND_STR(str) do { \ + if (-1 == append_charp(writer, (str))) { \ + return -1; \ + } \ + } while (0) + +#define APPEND_STR_IF(cond, str) do { \ + if ((cond) && -1 == append_charp(writer, (str))) { \ + return -1; \ + } \ + } while (0) + +#define APPEND_STR_IF_NOT_FIRST(str) do { \ + APPEND_STR_IF(!first, (str)); \ + first = false; \ + } while (0) + +#define APPEND_EXPR(expr, pr) do { \ + if (-1 == append_ast_expr(writer, (expr), (pr))) { \ + return -1; \ + } \ + } while (0) + +#define APPEND(type, value) do { \ + if (-1 == append_ast_ ## type(writer, (value))) { \ + return -1; \ + } \ + } while (0) + static int append_repr(_PyUnicodeWriter *writer, PyObject *obj) { @@ -37,111 +72,108 @@ append_repr(_PyUnicodeWriter *writer, PyObject *obj) return ret; } +/* Priority levels */ + +enum { + PR_TUPLE, + PR_TEST, /* 'if'-'else', 'lambda' */ + PR_OR, /* 'or' */ + PR_AND, /* 'and' */ + PR_NOT, /* 'not' */ + PR_CMP, /* '<', '>', '==', '>=', '<=', '!=', + 'in', 'not in', 'is', 'is not' */ + PR_EXPR, + PR_BOR = PR_EXPR, /* '|' */ + PR_BXOR, /* '^' */ + PR_BAND, /* '&' */ + PR_SHIFT, /* '<<', '>>' */ + PR_ARITH, /* '+', '-' */ + PR_TERM, /* '*', '@', '/', '%', '//' */ + PR_FACTOR, /* unary '+', '-', '~' */ + PR_POWER, /* '**' */ + PR_AWAIT, /* 'await' */ + PR_ATOM, +}; + static int -append_ast_boolop(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_boolop(_PyUnicodeWriter *writer, expr_ty e, int level) { Py_ssize_t i, value_count; asdl_seq *values; + const char *op = (e->v.BoolOp.op == And) ? " and " : " or "; + int pr = (e->v.BoolOp.op == And) ? PR_AND : PR_OR; - if (!omit_parens && -1 == append_charp(writer, "(")) { - return -1; - } + APPEND_STR_IF(level > pr, "("); values = e->v.BoolOp.values; - value_count = asdl_seq_LEN(values) - 1; - assert(value_count >= 0); + value_count = asdl_seq_LEN(values); - if (-1 == append_ast_expr(writer, - (expr_ty)asdl_seq_GET(values, 0), - false)) { - return -1; + for (i = 0; i < value_count; ++i) { + APPEND_STR_IF(i > 0, op); + APPEND_EXPR((expr_ty)asdl_seq_GET(values, i), pr + 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, ")"); + APPEND_STR_IF(level > pr, ")"); + return 0; } static int -append_ast_binop(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_binop(_PyUnicodeWriter *writer, expr_ty e, int level) { const char *op; + int pr; + bool rassoc = false; /* is right-associative? */ - 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; + switch (e->v.BinOp.op) { + case Add: op = " + "; pr = PR_ARITH; break; + case Sub: op = " - "; pr = PR_ARITH; break; + case Mult: op = " * "; pr = PR_TERM; break; + case MatMult: op = " @ "; pr = PR_TERM; break; + case Div: op = " / "; pr = PR_TERM; break; + case Mod: op = " % "; pr = PR_TERM; break; + case LShift: op = " << "; pr = PR_SHIFT; break; + case RShift: op = " >> "; pr = PR_SHIFT; break; + case BitOr: op = " | "; pr = PR_BOR; break; + case BitXor: op = " ^ "; pr = PR_BXOR; break; + case BitAnd: op = " & "; pr = PR_BAND; break; + case FloorDiv: op = " // "; pr = PR_TERM; break; + case Pow: op = " ** "; pr = PR_POWER; rassoc = true; break; default: - Py_UNREACHABLE(); - } - - if (-1 == append_charp(writer, op)) { + PyErr_SetString(PyExc_SystemError, + "unknown binary operator"); return -1; } - if (-1 == append_ast_expr(writer, e->v.BinOp.right, false)) { - return -1; - } - - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR_IF(level > pr, "("); + APPEND_EXPR(e->v.BinOp.left, pr + rassoc); + APPEND_STR(op); + APPEND_EXPR(e->v.BinOp.right, pr + !rassoc); + APPEND_STR_IF(level > pr, ")"); + return 0; } static int -append_ast_unaryop(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_unaryop(_PyUnicodeWriter *writer, expr_ty e, int level) { const char *op; + int pr; - 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; + switch (e->v.UnaryOp.op) { + case Invert: op = "~"; pr = PR_FACTOR; break; + case Not: op = "not "; pr = PR_NOT; break; + case UAdd: op = "+"; pr = PR_FACTOR; break; + case USub: op = "-"; pr = PR_FACTOR; break; default: - Py_UNREACHABLE(); - } - - if (-1 == append_charp(writer, op)) { + PyErr_SetString(PyExc_SystemError, + "unknown unary operator"); return -1; } - if (-1 == append_ast_expr(writer, e->v.UnaryOp.operand, false)) { - return -1; - } - - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR_IF(level > pr, "("); + APPEND_STR(op); + APPEND_EXPR(e->v.UnaryOp.operand, pr); + APPEND_STR_IF(level > pr, ")"); + return 0; } static int @@ -151,12 +183,8 @@ append_ast_arg(_PyUnicodeWriter *writer, arg_ty arg) return -1; } if (arg->annotation) { - if (-1 == append_charp(writer, ": ")) { - return -1; - } - if (-1 == append_ast_expr(writer, arg->annotation, true)) { - return -1; - } + APPEND_STR(": "); + APPEND_EXPR(arg->annotation, PR_TEST); } return 0; } @@ -166,8 +194,6 @@ 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; @@ -175,47 +201,22 @@ append_ast_args(_PyUnicodeWriter *writer, arguments_ty args) 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; - } + APPEND_STR_IF_NOT_FIRST(", "); + APPEND(arg, (arg_ty)asdl_seq_GET(args->args, i)); 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; - } + APPEND_STR("="); + APPEND_EXPR((expr_ty)asdl_seq_GET(args->defaults, di), PR_TEST); } } /* 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; - } - + APPEND_STR_IF_NOT_FIRST(", "); + APPEND_STR("*"); if (args->vararg) { - if (-1 == append_ast_arg(writer, args->vararg)) { - return -1; - } + APPEND(arg, args->vararg); } } @@ -223,223 +224,127 @@ append_ast_args(_PyUnicodeWriter *writer, arguments_ty args) 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; - } + APPEND_STR_IF_NOT_FIRST(", "); + APPEND(arg, (arg_ty)asdl_seq_GET(args->kwonlyargs, i)); 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; - } + APPEND_STR("="); + APPEND_EXPR((expr_ty)asdl_seq_GET(args->kw_defaults, di), PR_TEST); } } /* **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; - } + APPEND_STR_IF_NOT_FIRST(", "); + APPEND_STR("**"); + APPEND(arg, args->kwarg); } return 0; } static int -append_ast_lambda(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_lambda(_PyUnicodeWriter *writer, expr_ty e, int level) { - 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, ")"); + APPEND_STR_IF(level > PR_TEST, "("); + APPEND_STR("lambda "); + APPEND(args, e->v.Lambda.args); + APPEND_STR(": "); + APPEND_EXPR(e->v.Lambda.body, PR_TEST); + APPEND_STR_IF(level > PR_TEST, ")"); + return 0; } static int -append_ast_ifexp(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_ifexp(_PyUnicodeWriter *writer, expr_ty e, int level) { - 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, ")"); + APPEND_STR_IF(level > PR_TEST, "("); + APPEND_EXPR(e->v.IfExp.body, PR_TEST + 1); + APPEND_STR(" if "); + APPEND_EXPR(e->v.IfExp.test, PR_TEST + 1); + APPEND_STR(" else "); + APPEND_EXPR(e->v.IfExp.orelse, PR_TEST); + APPEND_STR_IF(level > PR_TEST, ")"); + return 0; } 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; - } + expr_ty key_node; + APPEND_STR("{"); 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; - } + APPEND_STR_IF(i > 0, ", "); 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; - } + APPEND_EXPR(key_node, PR_TEST); + APPEND_STR(": "); + APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Dict.values, i), PR_TEST); } - 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; + else { + APPEND_STR("**"); + APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Dict.values, i), PR_EXPR); } } - return append_charp(writer, "}"); + APPEND_STR_FINISH("}"); } 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; - } + APPEND_STR("{"); 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; - } + APPEND_STR_IF(i > 0, ", "); + APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Set.elts, i), PR_TEST); } - return append_charp(writer, "}"); + APPEND_STR_FINISH("}"); } 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; - } + APPEND_STR("["); 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; - } + APPEND_STR_IF(i > 0, ", "); + APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.List.elts, i), PR_TEST); } - return append_charp(writer, "]"); + APPEND_STR_FINISH("]"); } static int -append_ast_tuple(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_tuple(_PyUnicodeWriter *writer, expr_ty e, int level) { 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; - } + if (elem_count == 0) { + APPEND_STR_FINISH("()"); } + APPEND_STR_IF(level > PR_TUPLE, "("); + 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, ")"); + APPEND_STR_IF(i > 0, ", "); + APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Tuple.elts, i), PR_TEST); } + APPEND_STR_IF(elem_count == 1, ","); + APPEND_STR_IF(level > PR_TUPLE, ")"); return 0; } @@ -448,33 +353,15 @@ 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; - } + APPEND_STR(gen->is_async ? " async for " : " for "); + APPEND_EXPR(gen->target, PR_TUPLE); + APPEND_STR(" in "); + APPEND_EXPR(gen->iter, PR_TEST + 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; - } + APPEND_STR(" if "); + APPEND_EXPR((expr_ty)asdl_seq_GET(gen->ifs, i), PR_TEST + 1); } return 0; } @@ -483,110 +370,62 @@ 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; - } + APPEND(comprehension, (comprehension_ty)asdl_seq_GET(comprehensions, i)); } return 0; } static int -append_ast_genexp(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_genexp(_PyUnicodeWriter *writer, expr_ty e) { - 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, ")"); + APPEND_STR("("); + APPEND_EXPR(e->v.GeneratorExp.elt, PR_TEST); + APPEND(comprehensions, e->v.GeneratorExp.generators); + APPEND_STR_FINISH(")"); } 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, "]"); + APPEND_STR("["); + APPEND_EXPR(e->v.ListComp.elt, PR_TEST); + APPEND(comprehensions, e->v.ListComp.generators); + APPEND_STR_FINISH("]"); } 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, "}"); + APPEND_STR("{"); + APPEND_EXPR(e->v.SetComp.elt, PR_TEST); + APPEND(comprehensions, e->v.SetComp.generators); + APPEND_STR_FINISH("}"); } 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, "}"); + APPEND_STR("{"); + APPEND_EXPR(e->v.DictComp.key, PR_TEST); + APPEND_STR(": "); + APPEND_EXPR(e->v.DictComp.value, PR_TEST); + APPEND(comprehensions, e->v.DictComp.generators); + APPEND_STR_FINISH("}"); } static int -append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, int level) { 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; - } + APPEND_STR_IF(level > PR_CMP, "("); comparators = e->v.Compare.comparators; ops = e->v.Compare.ops; @@ -594,9 +433,7 @@ append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) assert(comparator_count > 0); assert(comparator_count == asdl_seq_LEN(ops)); - if (-1 == append_ast_expr(writer, e->v.Compare.left, false)) { - return -1; - } + APPEND_EXPR(e->v.Compare.left, PR_CMP + 1); for (i = 0; i < comparator_count; i++) { switch ((cmpop_ty)asdl_seq_GET(ops, i)) { @@ -636,39 +473,30 @@ append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) 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; - } + APPEND_STR(op); + APPEND_EXPR((expr_ty)asdl_seq_GET(comparators, i), PR_CMP + 1); } - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR_IF(level > PR_CMP, ")"); + return 0; } static int append_ast_keyword(_PyUnicodeWriter *writer, keyword_ty kw) { if (kw->arg == NULL) { - if (-1 == append_charp(writer, "**")) { - return -1; - } + APPEND_STR("**"); } else { if (-1 == _PyUnicodeWriter_WriteStr(writer, kw->arg)) { return -1; } - if (-1 == append_charp(writer, "=")) { - return -1; - } + APPEND_STR("="); } - return append_ast_expr(writer, kw->value, false); + APPEND_EXPR(kw->value, PR_TEST); + return 0; } static int @@ -677,48 +505,33 @@ 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; + APPEND_EXPR(e->v.Call.func, PR_ATOM); + + arg_count = asdl_seq_LEN(e->v.Call.args); + kw_count = asdl_seq_LEN(e->v.Call.keywords); + if (arg_count == 1 && kw_count == 0) { + expr = (expr_ty)asdl_seq_GET(e->v.Call.args, 0); + if (expr->kind == GeneratorExp_kind) { + /* Special case: a single generator expression. */ + return append_ast_genexp(writer, expr); + } } - if (-1 == append_charp(writer, "(")) { - return -1; - } + APPEND_STR("("); 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; - } + APPEND_STR_IF_NOT_FIRST(", "); + APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Call.args, i), PR_TEST); } - 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; - } + APPEND_STR_IF_NOT_FIRST(", "); + APPEND(keyword, (keyword_ty)asdl_seq_GET(e->v.Call.keywords, i)); } - return append_charp(writer, ")"); + APPEND_STR_FINISH(")"); } static PyObject * @@ -778,9 +591,8 @@ build_fstring_body(asdl_seq *values, bool is_format_spec) 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) { + value_count = asdl_seq_LEN(values); + for (i = 0; i < value_count; ++i) { if (-1 == append_fstring_element(&body_writer, (expr_ty)asdl_seq_GET(values, i), is_format_spec @@ -819,9 +631,11 @@ append_joinedstr(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) 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); + const char *conversion; + const char *outer_brace = "{"; + /* Grammar allows PR_TUPLE, but use >PR_TEST for adding parenthesis + around a lambda with ':' */ + PyObject *temp_fv_str = expr_as_unicode(e->v.FormattedValue.value, PR_TEST + 1); if (!temp_fv_str) { return -1; } @@ -842,13 +656,13 @@ append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) if (e->v.FormattedValue.conversion > 0) { switch (e->v.FormattedValue.conversion) { - case 97: + case 'a': conversion = "!a"; break; - case 114: + case 'r': conversion = "!r"; break; - case 115: + case 's': conversion = "!s"; break; default: @@ -856,9 +670,7 @@ append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) "unknown f-value conversion kind"); return -1; } - if (-1 == append_charp(writer, conversion)) { - return -1; - } + APPEND_STR(conversion); } if (e->v.FormattedValue.format_spec) { if (-1 == _PyUnicodeWriter_WriteASCIIString(writer, ":", 1) || @@ -870,16 +682,15 @@ append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) return -1; } } - return append_charp(writer, "}"); + + APPEND_STR_FINISH("}"); } 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; - } + APPEND_EXPR(e->v.Attribute.value, PR_ATOM); /* Special case: integers require a space for attribute access to be unambiguous. Floats and complex numbers don't but work with it, too. */ @@ -891,9 +702,7 @@ append_ast_attribute(_PyUnicodeWriter *writer, expr_ty e) else { period = "."; } - if (-1 == append_charp(writer, period)) { - return -1; - } + APPEND_STR(period); return _PyUnicodeWriter_WriteStr(writer, e->v.Attribute.attr); } @@ -902,28 +711,18 @@ 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; - } + APPEND_EXPR(slice->v.Slice.lower, PR_TEST); } - if (-1 == append_charp(writer, ":")) { - return -1; - } + APPEND_STR(":"); if (slice->v.Slice.upper) { - if (-1 == append_ast_expr(writer, slice->v.Slice.upper, false)) { - return -1; - } + APPEND_EXPR(slice->v.Slice.upper, PR_TEST); } 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; - } + APPEND_STR(":"); + APPEND_EXPR(slice->v.Slice.step, PR_TEST); } return 0; } @@ -934,28 +733,23 @@ 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; - } + APPEND_STR_IF(i > 0, ", "); + APPEND(slice, (slice_ty)asdl_seq_GET(slice->v.ExtSlice.dims, i)); } return 0; } static int -append_ast_slice(_PyUnicodeWriter *writer, slice_ty slice, bool omit_parens) +append_ast_slice(_PyUnicodeWriter *writer, slice_ty slice) { - switch(slice->kind) { + 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); + APPEND_EXPR(slice->v.Index.value, PR_TUPLE); + return 0; default: PyErr_SetString(PyExc_SystemError, "unexpected slice kind"); @@ -966,109 +760,70 @@ append_ast_slice(_PyUnicodeWriter *writer, slice_ty slice, bool omit_parens) 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, "]"); + APPEND_EXPR(e->v.Subscript.value, PR_ATOM); + APPEND_STR("["); + APPEND(slice, e->v.Subscript.slice); + APPEND_STR_FINISH("]"); } 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); + APPEND_STR("*"); + APPEND_EXPR(e->v.Starred.value, PR_EXPR); + return 0; } static int -append_ast_yield(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_yield(_PyUnicodeWriter *writer, expr_ty e) { - if (!omit_parens && -1 == append_charp(writer, "(")) { - return -1; + if (!e->v.Yield.value) { + APPEND_STR_FINISH("(yield)"); } - 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, ")"); + APPEND_STR("(yield "); + APPEND_EXPR(e->v.Yield.value, PR_TEST); + APPEND_STR_FINISH(")"); } static int -append_ast_yield_from(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_yield_from(_PyUnicodeWriter *writer, expr_ty e) { - 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, ")"); + APPEND_STR("(yield from "); + APPEND_EXPR(e->v.YieldFrom.value, PR_TEST); + APPEND_STR_FINISH(")"); } static int -append_ast_await(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_await(_PyUnicodeWriter *writer, expr_ty e, int level) { - 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, ")"); + APPEND_STR_IF(level > PR_AWAIT, "("); + APPEND_STR("await "); + APPEND_EXPR(e->v.Await.value, PR_ATOM); + APPEND_STR_IF(level > PR_AWAIT, ")"); + return 0; } static int -append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, int level) { switch (e->kind) { case BoolOp_kind: - return append_ast_boolop(writer, e, omit_parens); + return append_ast_boolop(writer, e, level); case BinOp_kind: - return append_ast_binop(writer, e, omit_parens); + return append_ast_binop(writer, e, level); case UnaryOp_kind: - return append_ast_unaryop(writer, e, omit_parens); + return append_ast_unaryop(writer, e, level); case Lambda_kind: - return append_ast_lambda(writer, e, omit_parens); + return append_ast_lambda(writer, e, level); case IfExp_kind: - return append_ast_ifexp(writer, e, omit_parens); + return append_ast_ifexp(writer, e, level); 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); + return append_ast_genexp(writer, e); case ListComp_kind: return append_ast_listcomp(writer, e); case SetComp_kind: @@ -1076,13 +831,13 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) case DictComp_kind: return append_ast_dictcomp(writer, e); case Yield_kind: - return append_ast_yield(writer, e, omit_parens); + return append_ast_yield(writer, e); case YieldFrom_kind: - return append_ast_yield_from(writer, e, omit_parens); + return append_ast_yield_from(writer, e); case Await_kind: - return append_ast_await(writer, e, omit_parens); + return append_ast_await(writer, e, level); case Compare_kind: - return append_ast_compare(writer, e, omit_parens); + return append_ast_compare(writer, e, level); case Call_kind: return append_ast_call(writer, e); case Constant_kind: @@ -1098,7 +853,7 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) case Bytes_kind: return append_repr(writer, e->v.Bytes.s); case Ellipsis_kind: - return append_charp(writer, "..."); + APPEND_STR_FINISH("..."); case NameConstant_kind: return append_repr(writer, e->v.NameConstant.value); /* The following exprs can be assignment targets. */ @@ -1110,11 +865,10 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) 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); + return append_ast_tuple(writer, e, level); default: PyErr_SetString(PyExc_SystemError, "unknown expression kind"); @@ -1145,14 +899,14 @@ maybe_init_static_strings(void) } static PyObject * -expr_as_unicode(expr_ty e, bool omit_parens) +expr_as_unicode(expr_ty e, int level) { _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)) + -1 == append_ast_expr(&writer, e, level)) { _PyUnicodeWriter_Dealloc(&writer); return NULL; @@ -1161,7 +915,7 @@ expr_as_unicode(expr_ty e, bool omit_parens) } PyObject * -_PyAST_ExprAsUnicode(expr_ty e, bool omit_parens) +_PyAST_ExprAsUnicode(expr_ty e) { - return expr_as_unicode(e, omit_parens); + return expr_as_unicode(e, PR_TEST); } diff --git a/Python/compile.c b/Python/compile.c index 7960f09319e..c3397f0c455 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1822,7 +1822,7 @@ error: static int compiler_visit_annexpr(struct compiler *c, expr_ty annotation) { - ADDOP_LOAD_CONST_NEW(c, _PyAST_ExprAsUnicode(annotation, 1)); + ADDOP_LOAD_CONST_NEW(c, _PyAST_ExprAsUnicode(annotation)); return 1; }