]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issue #12705: Raise SyntaxError when compiling multiple statements as single interact...
authorMeador Inge <meadori@gmail.com>
Thu, 19 Jan 2012 07:08:41 +0000 (01:08 -0600)
committerMeador Inge <meadori@gmail.com>
Thu, 19 Jan 2012 07:08:41 +0000 (01:08 -0600)
Include/errcode.h
Lib/test/test_compile.py
Misc/NEWS
Parser/parsetok.c
Python/pythonrun.c

index 6bb3cc1e5f7a961961cb6174c0145b4ce99561c9..5946686c659b5416074868d442060a77a5812156 100644 (file)
@@ -30,6 +30,7 @@ extern "C" {
 #define E_EOLS         24      /* EOL in single-quoted string */
 #define E_LINECONT     25      /* Unexpected characters after a line continuation */
 #define E_IDENTIFIER    26      /* Invalid characters in identifier */
+#define E_BADSINGLE    27      /* Ill-formed single statement input */
 
 #ifdef __cplusplus
 }
index c5f9189fcc0f38483776e51d12d2d028179760b7..7089872ee24f06e8a89ffd7beb7f6c5f951c0e7f 100644 (file)
@@ -6,6 +6,12 @@ from test import support
 
 class TestSpecifics(unittest.TestCase):
 
+    def compile_single(self, source):
+        compile(source, "<single>", "single")
+
+    def assertInvalidSingle(self, source):
+        self.assertRaises(SyntaxError, self.compile_single, source)
+
     def test_no_ending_newline(self):
         compile("hi", "<test>", "exec")
         compile("hi\r", "<test>", "exec")
@@ -442,6 +448,28 @@ if 1:
             if isinstance(obj, types.CodeType):
                 self.assertIs(obj.co_filename, c.co_filename)
 
+    def test_single_statement(self):
+        self.compile_single("1 + 2")
+        self.compile_single("\n1 + 2")
+        self.compile_single("1 + 2\n")
+        self.compile_single("1 + 2\n\n")
+        self.compile_single("1 + 2\t\t\n")
+        self.compile_single("1 + 2\t\t\n        ")
+        self.compile_single("1 + 2 # one plus two")
+        self.compile_single("1; 2")
+        self.compile_single("import sys; sys")
+        self.compile_single("def f():\n   pass")
+        self.compile_single("while False:\n   pass")
+        self.compile_single("if x:\n   f(x)")
+        self.compile_single("if x:\n   f(x)\nelse:\n   g(x)")
+        self.compile_single("class T:\n   pass")
+
+    def test_bad_single_statement(self):
+        self.assertInvalidSingle('1\n2')
+        self.assertInvalidSingle('def f(): pass')
+        self.assertInvalidSingle('a = 13\nb = 187')
+        self.assertInvalidSingle('del x\ndel y')
+        self.assertInvalidSingle('f()\ng()')
 
 def test_main():
     support.run_unittest(TestSpecifics)
index d7daba433ca21ee0b18a8996ab30b2fe3df21912..22244a8e76c01db2e7d1425d37e592da5894a3b4 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ What's New in Python 3.3 Alpha 1?
 Core and Builtins
 -----------------
 
+- Issue #12705: A SyntaxError exception is now raised when attempting to
+  compile multiple statements as a single interactive statement.
+
 - Fix the builtin module initialization code to store the init function for
   future reinitialization.
 
index f22ac67254c50dd66813a8b9b054a9de4fbf6a2d..9b2d7306ff6bce4ee80b8bfc729d7ad6492cbc00 100644 (file)
@@ -224,6 +224,23 @@ parsetok(struct tok_state *tok, grammar *g, int start, perrdetail *err_ret,
     if (err_ret->error == E_DONE) {
         n = ps->p_tree;
         ps->p_tree = NULL;
+
+        /* Check that the source for a single input statement really
+           is a single statement by looking at what is left in the
+           buffer after parsing.  Trailing whitespace and comments
+           are OK.  */
+        if (start == single_input) {
+            char *cur = tok->cur;
+            char c = *tok->cur;
+
+            while (c == ' ' || c == '\t' || c == '\n' || c == '\014')
+                c = *++cur;
+
+            if (c && c != '#') {
+                err_ret->error = E_BADSINGLE;
+                n = NULL;
+            }
+        }
     }
     else
         n = NULL;
index bff04de5993549cff9aa336f53a0993a1b76cb5b..44b817f5468b3f2cc54d52498bfd4fdc2093f673 100644 (file)
@@ -2129,6 +2129,9 @@ err_input(perrdetail *err)
     case E_IDENTIFIER:
         msg = "invalid character in identifier";
         break;
+    case E_BADSINGLE:
+        msg = "multiple statements found while compiling a single statement";
+        break;
     default:
         fprintf(stderr, "error=%d\n", err->error);
         msg = "unknown parsing error";