Author: Armin Rigo <[email protected]>
Branch: py3.5-fstring-pep498
Changeset: r89699:3cc879e93827
Date: 2017-01-22 23:30 +0100
http://bitbucket.org/pypy/pypy/changeset/3cc879e93827/

Log:    better error checking; and found a more reasonable way to forbid
        comments than CPython uses

diff --git a/pypy/interpreter/astcompiler/astbuilder.py 
b/pypy/interpreter/astcompiler/astbuilder.py
--- a/pypy/interpreter/astcompiler/astbuilder.py
+++ b/pypy/interpreter/astcompiler/astbuilder.py
@@ -1218,14 +1218,22 @@
         # or even tokenized together with the rest of the source code!
         from pypy.interpreter.pyparser import pyparse
 
+        # complain if 'source' is only whitespace or an empty string
+        for c in source:
+            if c not in ' \t\n\r\v\f':
+                break
+        else:
+            self.error("f-string: empty expression not allowed", atom_node)
+
         if self.recursive_parser is None:
             self.error("internal error: parser not available for parsing "
                        "the expressions inside the f-string", atom_node)
-        source = source.encode('utf-8')
+        source = '(%s)' % source.encode('utf-8')
 
         info = pyparse.CompileInfo("<fstring>", "eval",
                                    consts.PyCF_SOURCE_IS_UTF8 |
-                                   consts.PyCF_IGNORE_COOKIE,
+                                   consts.PyCF_IGNORE_COOKIE |
+                                   consts.PyCF_REFUSE_COMMENTS,
                                    optimize=self.compile_info.optimize)
         parse_tree = self.recursive_parser.parse_source(source, info)
         return ast_from_node(self.space, parse_tree, info)
@@ -1247,7 +1255,6 @@
                 if ch == u'!' and p < len(u) and u[p] == u'=':
                     continue
                 break     # normal way out of this loop
-            # XXX forbid comment, but how?
         else:
             ch = u'\x00'
         #
diff --git a/pypy/interpreter/astcompiler/consts.py 
b/pypy/interpreter/astcompiler/consts.py
--- a/pypy/interpreter/astcompiler/consts.py
+++ b/pypy/interpreter/astcompiler/consts.py
@@ -33,6 +33,7 @@
 PyCF_IGNORE_COOKIE = 0x0800
 PyCF_ACCEPT_NULL_BYTES = 0x10000000   # PyPy only, for compile()
 PyCF_FOUND_ENCODING = 0x20000000      # PyPy only, for pytokenizer
+PyCF_REFUSE_COMMENTS = 0x40000000     # PyPy only, for f-strings
 
 # Masks and values used by FORMAT_VALUE opcode
 FVC_MASK      = 0x3
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py 
b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -1174,6 +1174,15 @@
         yield self.st, """x = 'hi'; z = f'{x!r}'""", 'z', "'hi'"
         yield self.st, """x = 'hi'; z = f'{x!a}'""", 'z', "'hi'"
 
+        yield self.st, """x = 'hi'; z = f'''{\nx}'''""", 'z', 'hi'
+
+    def test_fstring_error(self):
+        raises(SyntaxError, self.run, "f'{}'")
+        raises(SyntaxError, self.run, "f'{   \t   }'")
+        raises(SyntaxError, self.run, "f'{5#}'")
+        raises(SyntaxError, self.run, "f'{5)#}'")
+        raises(SyntaxError, self.run, "f'''{5)\n#}'''")
+
 
 class AppTestCompiler:
 
diff --git a/pypy/interpreter/pyparser/pytokenizer.py 
b/pypy/interpreter/pyparser/pytokenizer.py
--- a/pypy/interpreter/pyparser/pytokenizer.py
+++ b/pypy/interpreter/pyparser/pytokenizer.py
@@ -187,6 +187,9 @@
                 continue
             if line[pos] == '#':
                 # skip full-line comment, but still check that it is valid 
utf-8
+                if flags & consts.PyCF_REFUSE_COMMENTS:
+                    raise TokenError("comments not allowed here",
+                                     line, lnum, pos, token_list)
                 if not verify_utf8(line):
                     raise bad_utf8("comment",
                                    line, lnum, pos, token_list, flags)
@@ -257,6 +260,9 @@
                     last_comment = ''
                 elif initial == '#':
                     # skip comment, but still check that it is valid utf-8
+                    if flags & consts.PyCF_REFUSE_COMMENTS:
+                        raise TokenError("comments not allowed here",
+                                         line, lnum, start, token_list)
                     if not verify_utf8(token):
                         raise bad_utf8("comment",
                                        line, lnum, start, token_list, flags)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to