]> granicus.if.org Git - python/commitdiff
Issue #28739: f-string expressions no longer accepted as docstrings and
authorSerhiy Storchaka <storchaka@gmail.com>
Sun, 11 Dec 2016 17:37:19 +0000 (19:37 +0200)
committerSerhiy Storchaka <storchaka@gmail.com>
Sun, 11 Dec 2016 17:37:19 +0000 (19:37 +0200)
by ast.literal_eval() even if they do not include subexpressions.

Lib/test/test_fstring.py
Misc/NEWS
Python/ast.c
Python/compile.c

index 82050835f6aee401d942e2a487111869616c255d..708ed25b526b743c10e12cfc4dba98ef8cac26d0 100644 (file)
@@ -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 = ['']
index 8db9170158ba8f50a94afa33eafaa396b2f2093f..446b9f937e26be2805881c6bc522a0b6e1f82820 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ What's New in Python 3.6.1 release candidate 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().
 
index 82f4529bf91ec5181bf943577024d3e811f4c39f..217ea14bf310be55432bfdd7978e1e58b631622c 100644 (file)
@@ -4789,6 +4789,7 @@ ExprList_Finish(ExprList *l, PyArena *arena)
 typedef struct {
     PyObject *last_str;
     ExprList expr_list;
+    int fmode;
 } FstringParser;
 
 #ifdef NDEBUG
@@ -4807,6 +4808,7 @@ static void
 FstringParser_Init(FstringParser *state)
 {
     state->last_str = NULL;
+    state->fmode = 0;
     ExprList_Init(&state->expr_list);
     FstringParser_check_invariants(state);
 }
@@ -4869,6 +4871,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) {
@@ -4960,7 +4963,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);
@@ -4984,11 +4988,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:
index 35151cdd590784dfa962ed6d7da7b68dec1528df..0e1607585245b9e52283f964bd24a2f1223322bd 100644 (file)
@@ -3415,7 +3415,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;
 }