diff Python/ast.c @ 36712:5c36c222e7ca legacy-trunk

SF patch #1438387, PEP 328: relative and absolute imports. - IMPORT_NAME takes an extra argument from the stack: the relativeness of the import. Only passed to __import__ when it's not -1. - __import__() takes an optional 5th argument for the same thing; it __defaults to -1 (old semantics: try relative, then absolute) - 'from . import name' imports name (be it module or regular attribute) from the current module's *package*. Likewise, 'from .module import name' will import name from a sibling to the current module. - Importing from outside a package is not allowed; 'from . import sys' in a toplevel module will not work, nor will 'from .. import sys' in a (single-level) package. - 'from __future__ import absolute_import' will turn on the new semantics for import and from-import: imports will be absolute, except for from-import with dots. Includes tests for regular imports and importhooks, parser changes and a NEWS item, but no compiler-package changes or documentation changes.
author Thomas Wouters <thomas@python.org>
date Tue, 28 Feb 2006 16:09:29 +0000
parents b6d2f6fd3e11
children 45e6f901902c
line wrap: on
line diff
--- a/Python/ast.c	Tue Feb 28 12:11:57 2006 +0000
+++ b/Python/ast.c	Tue Feb 28 16:09:29 2006 +0000
@@ -2171,9 +2171,8 @@
     /*
       import_stmt: import_name | import_from
       import_name: 'import' dotted_as_names
-      import_from: 'from' dotted_name 'import' ('*' | 
-                                                '(' import_as_names ')' | 
-                                                import_as_names)
+      import_from: 'from' ('.'* dotted_name | '.') 'import'
+                          ('*' | '(' import_as_names ')' | import_as_names)
     */
     int i;
     asdl_seq *aliases;
@@ -2197,24 +2196,41 @@
     else if (TYPE(n) == import_from) {
         int n_children;
 	int lineno = LINENO(n);
-	alias_ty mod = alias_for_import_name(c, CHILD(n, 1));
-	if (!mod)
-            return NULL;
-
-        switch (TYPE(CHILD(n, 3))) {
+	int idx, ndots = 0;
+	alias_ty mod = NULL;
+	identifier modname;
+	
+       /* Count the number of dots (for relative imports) and check for the
+          optional module name */
+	for (idx = 1; idx < NCH(n); idx++) {
+	    if (TYPE(CHILD(n, idx)) == dotted_name) {
+	    	mod = alias_for_import_name(c, CHILD(n, idx));
+	    	idx++;
+	    	break;
+	    } else if (TYPE(CHILD(n, idx)) != DOT) {
+	        break;
+	    }
+	    ndots++;
+	}
+	idx++; /* skip over the 'import' keyword */
+        switch (TYPE(CHILD(n, idx))) {
         case STAR:
             /* from ... import * */
-	    n = CHILD(n, 3);
+	    n = CHILD(n, idx);
 	    n_children = 1;
+	    if (ndots) {
+	        ast_error(n, "'import *' not allowed with 'from .'");
+	        return NULL;
+	    }
 	    break;
 	case LPAR:
 	    /* from ... import (x, y, z) */
-	    n = CHILD(n, 4);
+	    n = CHILD(n, idx + 1);
 	    n_children = NCH(n);
 	    break;
 	case import_as_names:
 	    /* from ... import x, y, z */
-	    n = CHILD(n, 3);
+	    n = CHILD(n, idx);
 	    n_children = NCH(n);
             if (n_children % 2 == 0) {
                 ast_error(n, "trailing comma not allowed without"
@@ -2245,7 +2261,12 @@
                 return NULL;
 	    asdl_seq_APPEND(aliases, import_alias);
         }
-	return ImportFrom(mod->name, aliases, lineno, c->c_arena);
+        if (mod != NULL)
+            modname = mod->name;
+        else
+            modname = new_identifier("", c->c_arena);
+        return ImportFrom(modname, aliases, ndots, lineno,
+                          c->c_arena);
     }
     PyErr_Format(PyExc_SystemError,
                  "unknown import statement: starts with command '%s'",