Mercurial > cpython-lru_cache-weakref
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'",
