summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/ast.h4
-rw-r--r--Lib/test/test_future.py127
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2018-05-13-01-26-18.bpo-33475.rI0y1U.rst2
-rw-r--r--Python/ast_unparse.c826
-rw-r--r--Python/compile.c2
5 files changed, 358 insertions, 603 deletions
diff --git a/Include/ast.h b/Include/ast.h
index 639c4f8..5bc2b05 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 29c4632..61cd634 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 0000000..cd714b9
--- /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 1345271..725ce31 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;
}
-static int
-append_ast_boolop(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens)
+/* 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, 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;
- }
-
- 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;
- }
+ for (i = 0; i < value_count; ++i) {
+ APPEND_STR_IF(i > 0, op);
+ APPEND_EXPR((expr_ty)asdl_seq_GET(values, i), pr + 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;
-
- 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;
+ int pr;
+ bool rassoc = false; /* is right-associative? */
+
+ 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)) {
- return -1;
- }
-
- if (-1 == append_ast_expr(writer, e->v.BinOp.right, false)) {
+ PyErr_SetString(PyExc_SystemError,
+ "unknown binary operator");
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)) {
- return -1;
- }
-
- if (-1 == append_ast_expr(writer, e->v.UnaryOp.operand, false)) {
+ PyErr_SetString(PyExc_SystemError,
+ "unknown unary operator");
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;
- }
- }
- else 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);
}
-
- 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("()");
}
- 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;
- }
- }
+ APPEND_STR_IF(level > PR_TUPLE, "(");
- if (!omit_parens || elem_count < 2) {
- return append_charp(writer, ")");
+ for (i = 0; i < elem_count; i++) {
+ 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);
- if (-1 == append_charp(writer, "(")) {
- return -1;
+ 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);
+ }
}
+ 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 (-1 == append_charp(writer, e->v.Yield.value ? "yield " : "yield")) {
- return -1;
+ if (!e->v.Yield.value) {
+ APPEND_STR_FINISH("(yield)");
}
- 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 7960f09..c3397f0 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;
}