mirror of
https://github.com/python/cpython.git
synced 2025-09-09 18:32:22 +00:00
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.
This commit is contained in:
parent
d3188639c3
commit
f7f438ba3b
20 changed files with 270 additions and 73 deletions
45
Python/ast.c
45
Python/ast.c
|
@ -2171,9 +2171,8 @@ ast_for_import_stmt(struct compiling *c, const node *n)
|
|||
/*
|
||||
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 @@ ast_for_import_stmt(struct compiling *c, const node *n)
|
|||
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 @@ ast_for_import_stmt(struct compiling *c, const node *n)
|
|||
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'",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue