Apply SF patch #101135, adding 'import module as m' and 'from module import

name as n'. By doing some twists and turns, "as" is not a reserved word.

There is a slight change in semantics for 'from module import name' (it will
now honour the 'global' keyword) but only in cases that are explicitly
undocumented.
This commit is contained in:
Thomas Wouters 2000-08-17 22:55:00 +00:00
parent 1d75a79c00
commit 5215225ea1
12 changed files with 970 additions and 818 deletions

View File

@ -301,6 +301,12 @@ is evaluated, the locals are passed to the class definition.
Returns with TOS to the caller of the function. Returns with TOS to the caller of the function.
\end{opcodedesc} \end{opcodedesc}
\begin{opcodedesc}{IMPORT_STAR}{}
Loads all symbols not starting with '_' directly from the module TOS
to the local namespace. The module is popped after loading all names.
This opcode implements 'from module import *'.
\begin{opcodedesc}
\begin{opcodedesc}{EXEC_STMT}{} \begin{opcodedesc}{EXEC_STMT}{}
Implements \code{exec TOS2,TOS1,TOS}. The compiler fills Implements \code{exec TOS2,TOS1,TOS}. The compiler fills
missing optional parameters with None. missing optional parameters with None.
@ -411,8 +417,9 @@ modifies the name space.
\end{opcodedesc} \end{opcodedesc}
\begin{opcodedesc}{IMPORT_FROM}{namei} \begin{opcodedesc}{IMPORT_FROM}{namei}
Imports the attribute \code{co_names[\var{namei}]}. The module to import Loads the attribute \code{co_names[\var{namei}]} from the module found in
from is found in TOS and left there. TOS. The resulting object is pushed onto the stack, to be subsequently
stored by a \code{STORE_FAST} instruction.
\end{opcodedesc} \end{opcodedesc}
\begin{opcodedesc}{JUMP_FORWARD}{delta} \begin{opcodedesc}{JUMP_FORWARD}{delta}

View File

@ -443,8 +443,9 @@ It continues with the next cycle of the nearest enclosing loop.
\stindex{import} \stindex{import}
\begin{verbatim} \begin{verbatim}
import_stmt: "import" module ("," module)* import_stmt: "import" module ["as" name] ("," module ["as" name] )*
| "from" module "import" identifier ("," identifier)* | "from" module "import" identifier ["as" name]
("," identifier ["as" name] )*
| "from" module "import" "*" | "from" module "import" "*"
module: (identifier ".")* identifier module: (identifier ".")* identifier
\end{verbatim} \end{verbatim}
@ -496,13 +497,16 @@ begin.
The first form of \keyword{import} statement binds the module name in the The first form of \keyword{import} statement binds the module name in the
local namespace to the module object, and then goes on to import the local namespace to the module object, and then goes on to import the
next identifier, if any. The \keyword{from} form does not bind the next identifier, if any. If the module name is followed by \keyword{as},
module name: it goes through the list of identifiers, looks each one the name following \keyword{as} is used as the local name for the module.
of them up in the module found in step (1), and binds the name in the The \keyword{from} form does not bind the module name: it goes through the
local namespace to the object thus found. If a name is not found, list of identifiers, looks each one of them up in the module found in step
(1), and binds the name in the local namespace to the object thus found.
Like with the first form of \keyword{import}, an alternate local name can be
supplied by specifying "\keyword{as} localname". If a name is not found,
\exception{ImportError} is raised. If the list of identifiers is replaced \exception{ImportError} is raised. If the list of identifiers is replaced
by a star (\samp{*}), all names defined in the module are bound, by a star (\samp{*}), all names defined in the module are bound, except
except those beginning with an underscore (\character{_}). those beginning with an underscore (\character{_}).
\indexii{name}{binding} \indexii{name}{binding}
\exindex{ImportError} \exindex{ImportError}

View File

@ -41,7 +41,9 @@ break_stmt: 'break'
continue_stmt: 'continue' continue_stmt: 'continue'
return_stmt: 'return' [testlist] return_stmt: 'return' [testlist]
raise_stmt: 'raise' [test [',' test [',' test]]] raise_stmt: 'raise' [test [',' test [',' test]]]
import_stmt: 'import' dotted_name (',' dotted_name)* | 'from' dotted_name 'import' ('*' | NAME (',' NAME)*) import_stmt: 'import' dotted_as_name (',' dotted_as_name)* | 'from' dotted_name 'import' ('*' | import_as_name (',' import_as_name)*)
import_as_name: NAME [NAME NAME]
dotted_as_name: dotted_name [NAME NAME]
dotted_name: NAME ('.' NAME)* dotted_name: NAME ('.' NAME)*
global_stmt: 'global' NAME (',' NAME)* global_stmt: 'global' NAME (',' NAME)*
#access_stmt: 'access' ('*' | NAME (',' NAME)*) ':' accesstype (',' accesstype)* #access_stmt: 'access' ('*' | NAME (',' NAME)*) ':' accesstype (',' accesstype)*

View File

@ -19,43 +19,45 @@
#define return_stmt 274 #define return_stmt 274
#define raise_stmt 275 #define raise_stmt 275
#define import_stmt 276 #define import_stmt 276
#define dotted_name 277 #define import_as_name 277
#define global_stmt 278 #define dotted_as_name 278
#define exec_stmt 279 #define dotted_name 279
#define assert_stmt 280 #define global_stmt 280
#define compound_stmt 281 #define exec_stmt 281
#define if_stmt 282 #define assert_stmt 282
#define while_stmt 283 #define compound_stmt 283
#define for_stmt 284 #define if_stmt 284
#define try_stmt 285 #define while_stmt 285
#define except_clause 286 #define for_stmt 286
#define suite 287 #define try_stmt 287
#define test 288 #define except_clause 288
#define and_test 289 #define suite 289
#define not_test 290 #define test 290
#define comparison 291 #define and_test 291
#define comp_op 292 #define not_test 292
#define expr 293 #define comparison 293
#define xor_expr 294 #define comp_op 294
#define and_expr 295 #define expr 295
#define shift_expr 296 #define xor_expr 296
#define arith_expr 297 #define and_expr 297
#define term 298 #define shift_expr 298
#define factor 299 #define arith_expr 299
#define power 300 #define term 300
#define atom 301 #define factor 301
#define listmaker 302 #define power 302
#define lambdef 303 #define atom 303
#define trailer 304 #define listmaker 304
#define subscriptlist 305 #define lambdef 305
#define subscript 306 #define trailer 306
#define sliceop 307 #define subscriptlist 307
#define exprlist 308 #define subscript 308
#define testlist 309 #define sliceop 309
#define dictmaker 310 #define exprlist 310
#define classdef 311 #define testlist 311
#define arglist 312 #define dictmaker 312
#define argument 313 #define classdef 313
#define list_iter 314 #define arglist 314
#define list_for 315 #define argument 315
#define list_if 316 #define list_iter 316
#define list_for 317
#define list_if 318

View File

@ -65,7 +65,7 @@ redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#define LOAD_LOCALS 82 #define LOAD_LOCALS 82
#define RETURN_VALUE 83 #define RETURN_VALUE 83
#define IMPORT_STAR 84
#define EXEC_STMT 85 #define EXEC_STMT 85
#define POP_BLOCK 87 #define POP_BLOCK 87

View File

@ -195,7 +195,7 @@ def_op('BREAK_LOOP', 80)
def_op('LOAD_LOCALS', 82) def_op('LOAD_LOCALS', 82)
def_op('RETURN_VALUE', 83) def_op('RETURN_VALUE', 83)
def_op('IMPORT_STAR', 84)
def_op('EXEC_STMT', 85) def_op('EXEC_STMT', 85)
def_op('POP_BLOCK', 87) def_op('POP_BLOCK', 87)

View File

@ -36,3 +36,10 @@ t6.ham loading
t6.eggs loading t6.eggs loading
['__all__', '__builtins__', '__doc__', '__file__', '__name__', '__path__', 'eggs', 'ham', 'spam'] ['__all__', '__builtins__', '__doc__', '__file__', '__name__', '__path__', 'eggs', 'ham', 'spam']
['eggs', 'ham', 'spam', 't6'] ['eggs', 'ham', 'spam', 't6']
running test t7
t7 loading
['__builtins__', '__doc__', '__file__', '__name__', '__path__']
['__builtins__', '__doc__', '__file__', '__name__', '__path__']
t7.sub.subsub loading
['__builtins__', '__doc__', '__file__', '__name__', '__path__', 'spam']
t7.sub.subsub.spam = 1

View File

@ -164,6 +164,33 @@ print dir(t6)
from t6 import * from t6 import *
print dir(t6) print dir(t6)
print dir() print dir()
"""),
("t7", [
("t7.py", "print 'Importing t7.py'"),
("t7", None),
("t7 __init__.py", "print __name__, 'loading'"),
("t7 sub.py", "print 'THIS SHOULD NOT BE PRINTED (sub.py)'"),
("t7 sub", None),
("t7 sub __init__.py", ""),
("t7 sub subsub.py", "print 'THIS SHOULD NOT BE PRINTED (subsub.py)'"),
("t7 sub subsub", None),
("t7 sub subsub __init__.py", "print __name__, 'loading'; spam = 1"),
],
"""
t7, sub, subsub = None, None, None
import t7 as tas
print dir(tas)
assert not t7
from t7 import sub as subpar
print dir(subpar)
assert not t7 and not sub
from t7.sub import subsub as subsubsub
print dir(subsubsub)
assert not t7 and not sub and not subsub
from t7.sub.subsub import spam as ham
print "t7.sub.subsub.spam =", ham
assert not t7 and not sub and not subsub
"""), """),
] ]

View File

@ -66,7 +66,8 @@ static PyObject *apply_slice(PyObject *, PyObject *, PyObject *);
static int assign_slice(PyObject *, PyObject *, static int assign_slice(PyObject *, PyObject *,
PyObject *, PyObject *); PyObject *, PyObject *);
static PyObject *cmp_outcome(int, PyObject *, PyObject *); static PyObject *cmp_outcome(int, PyObject *, PyObject *);
static int import_from(PyObject *, PyObject *, PyObject *); static PyObject *import_from(PyObject *, PyObject *);
static int import_all_from(PyObject *, PyObject *);
static PyObject *build_class(PyObject *, PyObject *, PyObject *); static PyObject *build_class(PyObject *, PyObject *, PyObject *);
static int exec_statement(PyFrameObject *, static int exec_statement(PyFrameObject *,
PyObject *, PyObject *, PyObject *); PyObject *, PyObject *, PyObject *);
@ -1414,20 +1415,28 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
if (x != NULL) continue; if (x != NULL) continue;
break; break;
case IMPORT_FROM: case IMPORT_STAR:
w = GETNAMEV(oparg); v = POP();
v = TOP();
PyFrame_FastToLocals(f); PyFrame_FastToLocals(f);
if ((x = f->f_locals) == NULL) { if ((x = f->f_locals) == NULL) {
PyErr_SetString(PyExc_SystemError, PyErr_SetString(PyExc_SystemError,
"no locals"); "no locals");
break; break;
} }
err = import_from(x, v, w); err = import_all_from(x, v);
PyFrame_LocalsToFast(f, 0); PyFrame_LocalsToFast(f, 0);
Py_DECREF(v);
if (err == 0) continue; if (err == 0) continue;
break; break;
case IMPORT_FROM:
w = GETNAMEV(oparg);
v = TOP();
x = import_from(v, w);
PUSH(x);
if (x != NULL) continue;
break;
case JUMP_FORWARD: case JUMP_FORWARD:
JUMPBY(oparg); JUMPBY(oparg);
continue; continue;
@ -2647,43 +2656,51 @@ cmp_outcome(int op, register PyObject *v, register PyObject *w)
return v; return v;
} }
static int static PyObject *
import_from(PyObject *locals, PyObject *v, PyObject *name) import_from(PyObject *v, PyObject *name)
{ {
PyObject *w, *x; PyObject *w, *x;
if (!PyModule_Check(v)) {
PyErr_SetString(PyExc_TypeError,
"import-from requires module object");
return NULL;
}
w = PyModule_GetDict(v); /* TDB: can this not fail ? */
x = PyDict_GetItem(w, name);
if (x == NULL) {
PyErr_Format(PyExc_ImportError,
"cannot import name %.230s",
PyString_AsString(name));
} else
Py_INCREF(x);
return x;
}
static int
import_all_from(PyObject *locals, PyObject *v)
{
int pos = 0, err;
PyObject *name, *value;
PyObject *w;
if (!PyModule_Check(v)) { if (!PyModule_Check(v)) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"import-from requires module object"); "import-from requires module object");
return -1; return -1;
} }
w = PyModule_GetDict(v); w = PyModule_GetDict(v); /* TBD: can this not fail ? */
if (PyString_AsString(name)[0] == '*') {
int pos, err; while (PyDict_Next(w, &pos, &name, &value)) {
PyObject *name, *value; if (!PyString_Check(name) ||
pos = 0; PyString_AsString(name)[0] == '_')
while (PyDict_Next(w, &pos, &name, &value)) {
if (!PyString_Check(name) ||
PyString_AsString(name)[0] == '_')
continue; continue;
Py_INCREF(value); Py_INCREF(value);
err = PyDict_SetItem(locals, name, value); err = PyDict_SetItem(locals, name, value);
Py_DECREF(value); Py_DECREF(value);
if (err != 0) if (err != 0)
return -1;
}
return 0;
}
else {
x = PyDict_GetItem(w, name);
if (x == NULL) {
PyErr_Format(PyExc_ImportError,
"cannot import name %.230s",
PyString_AsString(name));
return -1; return -1;
}
else
return PyDict_SetItem(locals, name, x);
} }
return 0;
} }
static PyObject * static PyObject *
@ -2825,7 +2842,7 @@ find_from_args(PyFrameObject *f, int nexti)
next_instr += nexti; next_instr += nexti;
opcode = (*next_instr++); opcode = (*next_instr++);
if (opcode != IMPORT_FROM) { if (opcode != IMPORT_FROM && opcode != IMPORT_STAR) {
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
@ -2833,18 +2850,28 @@ find_from_args(PyFrameObject *f, int nexti)
list = PyList_New(0); list = PyList_New(0);
if (list == NULL) if (list == NULL)
return NULL; return NULL;
do { if (opcode == IMPORT_STAR) {
oparg = (next_instr[1]<<8) + next_instr[0]; name = PyString_FromString("*");
next_instr += 2; if (!name)
name = Getnamev(f, oparg);
if (PyList_Append(list, name) < 0) {
Py_DECREF(list); Py_DECREF(list);
break; else {
if (PyList_Append(list, name) < 0)
Py_DECREF(list);
Py_DECREF(name);
} }
opcode = (*next_instr++); } else {
} while (opcode == IMPORT_FROM); do {
oparg = (next_instr[1]<<8) + next_instr[0];
next_instr += 2;
name = Getnamev(f, oparg);
if (PyList_Append(list, name) < 0) {
Py_DECREF(list);
break;
}
opcode = (*next_instr++);
} while (opcode == IMPORT_FROM);
}
return list; return list;
} }

View File

@ -2095,6 +2095,22 @@ com_raise_stmt(struct compiling *c, node *n)
com_pop(c, i); com_pop(c, i);
} }
static void
com_from_import(struct compiling *c, node *n)
{
com_addopname(c, IMPORT_FROM, CHILD(n, 0));
com_push(c, 1);
if (NCH(n) > 1) {
if (strcmp(STR(CHILD(n, 1)), "as") != 0) {
com_error(c, PyExc_SyntaxError, "invalid syntax");
return;
}
com_addopname(c, STORE_NAME, CHILD(n, 2));
} else
com_addopname(c, STORE_NAME, CHILD(n, 0));
com_pop(c, 1);
}
static void static void
com_import_stmt(struct compiling *c, node *n) com_import_stmt(struct compiling *c, node *n)
{ {
@ -2107,18 +2123,32 @@ com_import_stmt(struct compiling *c, node *n)
REQ(CHILD(n, 1), dotted_name); REQ(CHILD(n, 1), dotted_name);
com_addopname(c, IMPORT_NAME, CHILD(n, 1)); com_addopname(c, IMPORT_NAME, CHILD(n, 1));
com_push(c, 1); com_push(c, 1);
for (i = 3; i < NCH(n); i += 2) if (TYPE(CHILD(n, 3)) == STAR)
com_addopname(c, IMPORT_FROM, CHILD(n, i)); com_addbyte(c, IMPORT_STAR);
com_addbyte(c, POP_TOP); else {
for (i = 3; i < NCH(n); i += 2)
com_from_import(c, CHILD(n, i));
com_addbyte(c, POP_TOP);
}
com_pop(c, 1); com_pop(c, 1);
} }
else { else {
/* 'import' ... */ /* 'import' ... */
for (i = 1; i < NCH(n); i += 2) { for (i = 1; i < NCH(n); i += 2) {
REQ(CHILD(n, i), dotted_name); node *subn = CHILD(n, i);
com_addopname(c, IMPORT_NAME, CHILD(n, i)); REQ(subn, dotted_as_name);
com_addopname(c, IMPORT_NAME, CHILD(subn, 0));
com_push(c, 1); com_push(c, 1);
com_addopname(c, STORE_NAME, CHILD(CHILD(n, i), 0)); if (NCH(subn) > 1) {
if (strcmp(STR(CHILD(subn, 1)), "as") != 0) {
com_error(c, PyExc_SyntaxError,
"invalid syntax");
return;
}
com_addopname(c, STORE_NAME, CHILD(subn, 2));
} else
com_addopname(c, STORE_NAME,
CHILD(CHILD(subn, 0),0));
com_pop(c, 1); com_pop(c, 1);
} }
} }
@ -3295,12 +3325,14 @@ optimize(struct compiling *c)
case IMPORT_FROM: case IMPORT_FROM:
com_addlocal_o(c, GETNAMEOBJ(oparg)); com_addlocal_o(c, GETNAMEOBJ(oparg));
break; break;
case IMPORT_STAR:
case EXEC_STMT: case EXEC_STMT:
c->c_flags &= ~CO_OPTIMIZED; c->c_flags &= ~CO_OPTIMIZED;
break; break;
} }
} }
/* TBD: Is this still necessary ? */
if (PyDict_GetItemString(c->c_locals, "*") != NULL) if (PyDict_GetItemString(c->c_locals, "*") != NULL)
c->c_flags &= ~CO_OPTIMIZED; c->c_flags &= ~CO_OPTIMIZED;

File diff suppressed because it is too large Load Diff

View File

@ -66,7 +66,7 @@ extern time_t PyOS_GetLastModificationTime(char *, FILE *);
/* XXX Perhaps the magic number should be frozen and a version field /* XXX Perhaps the magic number should be frozen and a version field
added to the .pyc file header? */ added to the .pyc file header? */
/* New way to come up with the magic number: (YEAR-1995), MONTH, DAY */ /* New way to come up with the magic number: (YEAR-1995), MONTH, DAY */
#define MAGIC (50811 | ((long)'\r'<<16) | ((long)'\n'<<24)) #define MAGIC (50815 | ((long)'\r'<<16) | ((long)'\n'<<24))
/* Magic word as global; note that _PyImport_Init() can change the /* Magic word as global; note that _PyImport_Init() can change the
value of this global to accommodate for alterations of how the value of this global to accommodate for alterations of how the