diff options
author | Benjamin Peterson <benjamin@python.org> | 2013-03-16 09:15:47 -0700 |
---|---|---|
committer | Benjamin Peterson <benjamin@python.org> | 2013-03-16 09:15:47 -0700 |
commit | 2d6acd2ac2399ecc0f163c12c5695f434ba14955 (patch) | |
tree | 0f49c3803c6c58b3ff149e231f81d43ea230a903 | |
parent | 694bafa04ed7af12c86ca28217d143ab74428b2f (diff) | |
download | cpython-git-2d6acd2ac2399ecc0f163c12c5695f434ba14955.tar.gz |
reject non-docs strings between future imports (closes #17434)
-rw-r--r-- | Lib/test/badsyntax_future10.py | 3 | ||||
-rw-r--r-- | Lib/test/test_future.py | 8 | ||||
-rw-r--r-- | Misc/NEWS | 3 | ||||
-rw-r--r-- | Python/future.c | 25 |
4 files changed, 28 insertions, 11 deletions
diff --git a/Lib/test/badsyntax_future10.py b/Lib/test/badsyntax_future10.py new file mode 100644 index 0000000000..fa5ab67a98 --- /dev/null +++ b/Lib/test/badsyntax_future10.py @@ -0,0 +1,3 @@ +from __future__ import absolute_import +"spam, bar, blah" +from __future__ import print_function diff --git a/Lib/test/test_future.py b/Lib/test/test_future.py index a0c156f5f7..beac993e4d 100644 --- a/Lib/test/test_future.py +++ b/Lib/test/test_future.py @@ -82,6 +82,14 @@ class FutureTest(unittest.TestCase): else: self.fail("expected exception didn't occur") + def test_badfuture10(self): + try: + from test import badsyntax_future10 + except SyntaxError as msg: + self.assertEqual(get_error_location(msg), ("badsyntax_future10", '3')) + else: + self.fail("expected exception didn't occur") + def test_parserhack(self): # test that the parser.c::future_hack function works as expected # Note: although this test must pass, it's not testing the original @@ -10,6 +10,9 @@ What's New in Python 3.4.0 Alpha 1? Core and Builtins ----------------- +- Issue #17434: Properly raise a SyntaxError when a string occurs between future + imports. + - Issue #17117: Import and @importlib.util.set_loader now set __loader__ when it has a value of None or the attribute doesn't exist. diff --git a/Python/future.c b/Python/future.c index d24ae416ff..345efb2167 100644 --- a/Python/future.c +++ b/Python/future.c @@ -58,11 +58,14 @@ future_check_features(PyFutureFeatures *ff, stmt_ty s, const char *filename) static int future_parse(PyFutureFeatures *ff, mod_ty mod, const char *filename) { - int i, found_docstring = 0, done = 0, prev_line = 0; + int i, done = 0, prev_line = 0; if (!(mod->kind == Module_kind || mod->kind == Interactive_kind)) return 1; + if (asdl_seq_LEN(mod->v.Module.body) == 0) + return 1; + /* A subsequent pass will detect future imports that don't appear at the beginning of the file. There's one case, however, that is easier to handle here: A series of imports @@ -71,8 +74,13 @@ future_parse(PyFutureFeatures *ff, mod_ty mod, const char *filename) but is preceded by a regular import. */ + i = 0; + stmt_ty first = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i); + if (first->kind == Expr_kind && first->v.Expr.value->kind == Str_kind) + i++; - for (i = 0; i < asdl_seq_LEN(mod->v.Module.body); i++) { + + for (; i < asdl_seq_LEN(mod->v.Module.body); i++) { stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i); if (done && s->lineno > prev_line) @@ -99,18 +107,13 @@ future_parse(PyFutureFeatures *ff, mod_ty mod, const char *filename) return 0; ff->ff_lineno = s->lineno; } - else + else { done = 1; + } } - else if (s->kind == Expr_kind && !found_docstring) { - expr_ty e = s->v.Expr.value; - if (e->kind != Str_kind) - done = 1; - else - found_docstring = 1; - } - else + else { done = 1; + } } return 1; } |