diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index eac42d3feb4..89850f69e2d 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -152,6 +152,10 @@ class AST_Tests(unittest.TestCase): self.assertIsNone(slc.lower) self.assertIsNone(slc.step) + def test_from_import(self): + im = ast.parse("from . import y").body[0] + self.assertIsNone(im.module) + def test_nodeclasses(self): x = ast.BinOp(1, 2, 3, lineno=0) self.assertEquals(x.left, 1) diff --git a/Misc/NEWS b/Misc/NEWS index 18976c03be1..8af99144941 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,9 @@ What's New in Python 2.7 alpha 1 Core and Builtins ----------------- +- When no module is given in a relative import, the module field of the + ImportFrom AST node is now None instead of an empty string. + - Assignment to None using import statements now raises a SyntaxError. - In the slice AST type, the step field will always be None if a step expression diff --git a/Parser/Python.asdl b/Parser/Python.asdl index a4394c9adfc..f7917097574 100644 --- a/Parser/Python.asdl +++ b/Parser/Python.asdl @@ -34,7 +34,7 @@ module Python version "$Revision$" | Assert(expr test, expr? msg) | Import(alias* names) - | ImportFrom(identifier module, alias* names, int? level) + | ImportFrom(identifier? module, alias* names, int? level) -- Doesn't capture requirement that locals must be -- defined if globals is diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 4a999d12f4c..23cb7f35bec 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -1330,11 +1330,6 @@ ImportFrom(identifier module, asdl_seq * names, int level, int lineno, int col_offset, PyArena *arena) { stmt_ty p; - if (!module) { - PyErr_SetString(PyExc_ValueError, - "field module is required for ImportFrom"); - return NULL; - } p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); if (!p) return NULL; @@ -4273,8 +4268,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) Py_XDECREF(tmp); tmp = NULL; } else { - PyErr_SetString(PyExc_TypeError, "required field \"module\" missing from ImportFrom"); - return 1; + module = NULL; } if (PyObject_HasAttrString(obj, "names")) { int res; diff --git a/Python/ast.c b/Python/ast.c index 4a85164d8cd..6ccd02fc704 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -2440,7 +2440,7 @@ ast_for_import_stmt(struct compiling *c, const node *n) int n_children; int idx, ndots = 0; alias_ty mod = NULL; - identifier modname; + identifier modname = NULL; /* Count the number of dots (for relative imports) and check for the optional module name */ @@ -2504,8 +2504,6 @@ ast_for_import_stmt(struct compiling *c, const node *n) } if (mod != NULL) modname = mod->name; - else - modname = new_identifier("", c->c_arena); return ImportFrom(modname, aliases, ndots, lineno, col_offset, c->c_arena); } diff --git a/Python/compile.c b/Python/compile.c index 00e0462c4d3..0a83bfce319 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1976,6 +1976,13 @@ compiler_from_import(struct compiler *c, stmt_ty s) PyObject *names = PyTuple_New(n); PyObject *level; + static PyObject *empty_string; + + if (!empty_string) { + empty_string = PyString_FromString(""); + if (!empty_string) + return 0; + } if (!names) return 0; @@ -1998,23 +2005,24 @@ compiler_from_import(struct compiler *c, stmt_ty s) PyTuple_SET_ITEM(names, i, alias->name); } - if (s->lineno > c->c_future->ff_lineno) { - if (!strcmp(PyString_AS_STRING(s->v.ImportFrom.module), - "__future__")) { - Py_DECREF(level); - Py_DECREF(names); - return compiler_error(c, - "from __future__ imports must occur " + if (s->lineno > c->c_future->ff_lineno && s->v.ImportFrom.module && + !strcmp(PyString_AS_STRING(s->v.ImportFrom.module), "__future__")) { + Py_DECREF(level); + Py_DECREF(names); + return compiler_error(c, "from __future__ imports must occur " "at the beginning of the file"); - - } } ADDOP_O(c, LOAD_CONST, level, consts); Py_DECREF(level); ADDOP_O(c, LOAD_CONST, names, consts); Py_DECREF(names); - ADDOP_NAME(c, IMPORT_NAME, s->v.ImportFrom.module, names); + if (s->v.ImportFrom.module) { + ADDOP_NAME(c, IMPORT_NAME, s->v.ImportFrom.module, names); + } + else { + ADDOP_NAME(c, IMPORT_NAME, empty_string, names); + } for (i = 0; i < n; i++) { alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, i); identifier store_name;