summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2016-12-11 17:39:36 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2016-12-11 17:39:36 (GMT)
commit0f6373c34f5c0881d6ab2329aea5bce742789b20 (patch)
tree67470506d05cf6bff1d25067fc7068084a601a65
parent26817a84908b831d71dd59de432f75829a5bae33 (diff)
parent4cc30ae31341ba233a861899be7d225519c71830 (diff)
downloadcpython-0f6373c34f5c0881d6ab2329aea5bce742789b20.zip
cpython-0f6373c34f5c0881d6ab2329aea5bce742789b20.tar.gz
cpython-0f6373c34f5c0881d6ab2329aea5bce742789b20.tar.bz2
Issue #28739: f-string expressions no longer accepted as docstrings and
by ast.literal_eval() even if they do not include subexpressions.
-rw-r--r--Lib/test/test_fstring.py20
-rw-r--r--Misc/NEWS3
-rw-r--r--Python/ast.c11
-rw-r--r--Python/compile.c3
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 = ['']
diff --git a/Misc/NEWS b/Misc/NEWS
index 417343a..07f059f 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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;
}