mirror of
https://github.com/python/cpython.git
synced 2025-10-09 16:34:44 +00:00
Issue #28739: f-string expressions no longer accepted as docstrings and
by ast.literal_eval() even if they do not include subexpressions.
This commit is contained in:
parent
8114f21668
commit
4cc30ae313
4 changed files with 20 additions and 17 deletions
|
@ -70,18 +70,18 @@ f'{a * x()}'"""
|
||||||
# Make sure x was called.
|
# Make sure x was called.
|
||||||
self.assertTrue(x.called)
|
self.assertTrue(x.called)
|
||||||
|
|
||||||
|
def test_docstring(self):
|
||||||
|
def f():
|
||||||
|
f'''Not a docstring'''
|
||||||
|
self.assertIsNone(f.__doc__)
|
||||||
|
def g():
|
||||||
|
'''Not a docstring''' \
|
||||||
|
f''
|
||||||
|
self.assertIsNone(g.__doc__)
|
||||||
|
|
||||||
def test_literal_eval(self):
|
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'):
|
with self.assertRaisesRegex(ValueError, 'malformed node or string'):
|
||||||
ast.literal_eval("f'x{3}'")
|
ast.literal_eval("f'x'")
|
||||||
|
|
||||||
# As should this, which uses a different ast node
|
|
||||||
with self.assertRaisesRegex(ValueError, 'malformed node or string'):
|
|
||||||
ast.literal_eval("f'{3}'")
|
|
||||||
|
|
||||||
def test_ast_compile_time_concat(self):
|
def test_ast_compile_time_concat(self):
|
||||||
x = ['']
|
x = ['']
|
||||||
|
|
|
@ -10,6 +10,9 @@ What's New in Python 3.6.1 release candidate 1
|
||||||
Core and Builtins
|
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
|
- Issue #28512: Fixed setting the offset attribute of SyntaxError by
|
||||||
PyErr_SyntaxLocationEx() and PyErr_SyntaxLocationObject().
|
PyErr_SyntaxLocationEx() and PyErr_SyntaxLocationObject().
|
||||||
|
|
||||||
|
|
11
Python/ast.c
11
Python/ast.c
|
@ -4789,6 +4789,7 @@ ExprList_Finish(ExprList *l, PyArena *arena)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject *last_str;
|
PyObject *last_str;
|
||||||
ExprList expr_list;
|
ExprList expr_list;
|
||||||
|
int fmode;
|
||||||
} FstringParser;
|
} FstringParser;
|
||||||
|
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
|
@ -4807,6 +4808,7 @@ static void
|
||||||
FstringParser_Init(FstringParser *state)
|
FstringParser_Init(FstringParser *state)
|
||||||
{
|
{
|
||||||
state->last_str = NULL;
|
state->last_str = NULL;
|
||||||
|
state->fmode = 0;
|
||||||
ExprList_Init(&state->expr_list);
|
ExprList_Init(&state->expr_list);
|
||||||
FstringParser_check_invariants(state);
|
FstringParser_check_invariants(state);
|
||||||
}
|
}
|
||||||
|
@ -4869,6 +4871,7 @@ FstringParser_ConcatFstring(FstringParser *state, const char **str,
|
||||||
struct compiling *c, const node *n)
|
struct compiling *c, const node *n)
|
||||||
{
|
{
|
||||||
FstringParser_check_invariants(state);
|
FstringParser_check_invariants(state);
|
||||||
|
state->fmode = 1;
|
||||||
|
|
||||||
/* Parse the f-string. */
|
/* Parse the f-string. */
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -4960,7 +4963,8 @@ FstringParser_Finish(FstringParser *state, struct compiling *c,
|
||||||
|
|
||||||
/* If we're just a constant string with no expressions, return
|
/* If we're just a constant string with no expressions, return
|
||||||
that. */
|
that. */
|
||||||
if(state->expr_list.size == 0) {
|
if (!state->fmode) {
|
||||||
|
assert(!state->expr_list.size);
|
||||||
if (!state->last_str) {
|
if (!state->last_str) {
|
||||||
/* Create a zero length string. */
|
/* Create a zero length string. */
|
||||||
state->last_str = PyUnicode_FromStringAndSize(NULL, 0);
|
state->last_str = PyUnicode_FromStringAndSize(NULL, 0);
|
||||||
|
@ -4984,11 +4988,6 @@ FstringParser_Finish(FstringParser *state, struct compiling *c,
|
||||||
if (!seq)
|
if (!seq)
|
||||||
goto error;
|
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);
|
return JoinedStr(seq, LINENO(n), n->n_col_offset, c->c_arena);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
|
|
@ -3415,7 +3415,8 @@ static int
|
||||||
compiler_joined_str(struct compiler *c, expr_ty e)
|
compiler_joined_str(struct compiler *c, expr_ty e)
|
||||||
{
|
{
|
||||||
VISIT_SEQ(c, expr, e->v.JoinedStr.values);
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue