Index: Lib/test/test_parser.py =================================================================== --- Lib/test/test_parser.py (revision 82408) +++ Lib/test/test_parser.py (working copy) @@ -213,6 +213,12 @@ self.check_suite("import sys as system, math") self.check_suite("import sys, math as my_math") + def test_relative_imports(self): + self.check_suite("from . import name") + self.check_suite("from .. import name") + self.check_suite("from .pkg import name") + self.check_suite("from ..pkg import name") + def test_pep263(self): self.check_suite("# -*- coding: iso-8859-1 -*-\n" "pass\n") @@ -511,7 +517,21 @@ (0, '')) self.check_bad_tree(tree, "malformed global ast") + def test_missing_import_source(self): + # from import a + tree = \ + (257, + (267, + (268, + (269, + (281, + (283, (1, 'from'), (1, 'import'), + (286, (284, (1, 'fred')))))), + (4, ''))), + (4, ''), (0, '')) + self.check_bad_tree(tree, "from import a") + class CompileTestCase(unittest.TestCase): # These tests are very minimal. :-( Index: Modules/parsermodule.c =================================================================== --- Modules/parsermodule.c (revision 82408) +++ Modules/parsermodule.c (working copy) @@ -1886,8 +1886,8 @@ return i-1; } -/* 'from' ('.'* dotted_name | '.') 'import' ('*' | '(' import_as_names ')' | - * import_as_names +/* import_from: ('from' ('.'* dotted_name | '.'+) + * 'import' ('*' | '(' import_as_names ')' | import_as_names)) */ static int validate_import_from(node *tree) @@ -1897,7 +1897,8 @@ int havename = (TYPE(CHILD(tree, ndots + 1)) == dotted_name); int offset = ndots + havename; int res = validate_ntype(tree, import_from) - && (nch >= 4 + ndots) + && (offset >= 1) + && (nch >= 3 + offset) && validate_name(CHILD(tree, 0), "from") && (!havename || validate_dotted_name(CHILD(tree, ndots + 1))) && validate_name(CHILD(tree, offset + 1), "import");