diff options
-rw-r--r-- | Lib/test/test_fstring.py | 20 | ||||
-rw-r--r-- | Misc/NEWS | 3 | ||||
-rw-r--r-- | Python/ast.c | 11 | ||||
-rw-r--r-- | Python/compile.c | 3 |
4 files changed, 20 insertions, 17 deletions
diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py index 8205083..708ed25 100644 --- a/Lib/test/test_fstring.py +++ b/Lib/test/test_fstring.py @@ -70,18 +70,18 @@ f'{a * x()}'""" # Make sure x was called. self.assertTrue(x.called) - def test_literal_eval(self): - # With no expressions, an f-string is okay. - self.assertEqual(ast.literal_eval("f'x'"), 'x') - self.assertEqual(ast.literal_eval("f'x' 'y'"), 'xy') - - # But this should raise an error. - with self.assertRaisesRegex(ValueError, 'malformed node or string'): - ast.literal_eval("f'x{3}'") + def test_docstring(self): + def f(): + f'''Not a docstring''' + self.assertIsNone(f.__doc__) + def g(): + '''Not a docstring''' \ + f'' + self.assertIsNone(g.__doc__) - # As should this, which uses a different ast node + def test_literal_eval(self): with self.assertRaisesRegex(ValueError, 'malformed node or string'): - ast.literal_eval("f'{3}'") + ast.literal_eval("f'x'") def test_ast_compile_time_concat(self): x = [''] @@ -10,6 +10,9 @@ What's New in Python 3.7.0 alpha 1 Core and Builtins ----------------- +- Issue #28739: f-string expressions no longer accepted as docstrings and + by ast.literal_eval() even if they do not include expressions. + - Issue #28512: Fixed setting the offset attribute of SyntaxError by PyErr_SyntaxLocationEx() and PyErr_SyntaxLocationObject(). diff --git a/Python/ast.c b/Python/ast.c index e6786d4..f07bb16 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -4784,6 +4784,7 @@ ExprList_Finish(ExprList *l, PyArena *arena) typedef struct { PyObject *last_str; ExprList expr_list; + int fmode; } FstringParser; #ifdef NDEBUG @@ -4802,6 +4803,7 @@ static void FstringParser_Init(FstringParser *state) { state->last_str = NULL; + state->fmode = 0; ExprList_Init(&state->expr_list); FstringParser_check_invariants(state); } @@ -4864,6 +4866,7 @@ FstringParser_ConcatFstring(FstringParser *state, const char **str, struct compiling *c, const node *n) { FstringParser_check_invariants(state); + state->fmode = 1; /* Parse the f-string. */ while (1) { @@ -4955,7 +4958,8 @@ FstringParser_Finish(FstringParser *state, struct compiling *c, /* If we're just a constant string with no expressions, return that. */ - if(state->expr_list.size == 0) { + if (!state->fmode) { + assert(!state->expr_list.size); if (!state->last_str) { /* Create a zero length string. */ state->last_str = PyUnicode_FromStringAndSize(NULL, 0); @@ -4979,11 +4983,6 @@ FstringParser_Finish(FstringParser *state, struct compiling *c, if (!seq) goto error; - /* If there's only one expression, return it. Otherwise, we need - to join them together. */ - if (seq->size == 1) - return seq->elements[0]; - return JoinedStr(seq, LINENO(n), n->n_col_offset, c->c_arena); error: diff --git a/Python/compile.c b/Python/compile.c index 76f08da..f4edf8f 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3412,7 +3412,8 @@ static int compiler_joined_str(struct compiler *c, expr_ty e) { VISIT_SEQ(c, expr, e->v.JoinedStr.values); - ADDOP_I(c, BUILD_STRING, asdl_seq_LEN(e->v.JoinedStr.values)); + if (asdl_seq_LEN(e->v.JoinedStr.values) != 1) + ADDOP_I(c, BUILD_STRING, asdl_seq_LEN(e->v.JoinedStr.values)); return 1; } |