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:
parent
1d75a79c00
commit
5215225ea1
|
@ -301,6 +301,12 @@ is evaluated, the locals are passed to the class definition.
|
|||
Returns with TOS to the caller of the function.
|
||||
\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}{}
|
||||
Implements \code{exec TOS2,TOS1,TOS}. The compiler fills
|
||||
missing optional parameters with None.
|
||||
|
@ -411,8 +417,9 @@ modifies the name space.
|
|||
\end{opcodedesc}
|
||||
|
||||
\begin{opcodedesc}{IMPORT_FROM}{namei}
|
||||
Imports the attribute \code{co_names[\var{namei}]}. The module to import
|
||||
from is found in TOS and left there.
|
||||
Loads the attribute \code{co_names[\var{namei}]} from the module found in
|
||||
TOS. The resulting object is pushed onto the stack, to be subsequently
|
||||
stored by a \code{STORE_FAST} instruction.
|
||||
\end{opcodedesc}
|
||||
|
||||
\begin{opcodedesc}{JUMP_FORWARD}{delta}
|
||||
|
|
|
@ -443,8 +443,9 @@ It continues with the next cycle of the nearest enclosing loop.
|
|||
\stindex{import}
|
||||
|
||||
\begin{verbatim}
|
||||
import_stmt: "import" module ("," module)*
|
||||
| "from" module "import" identifier ("," identifier)*
|
||||
import_stmt: "import" module ["as" name] ("," module ["as" name] )*
|
||||
| "from" module "import" identifier ["as" name]
|
||||
("," identifier ["as" name] )*
|
||||
| "from" module "import" "*"
|
||||
module: (identifier ".")* identifier
|
||||
\end{verbatim}
|
||||
|
@ -496,13 +497,16 @@ begin.
|
|||
|
||||
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
|
||||
next identifier, if any. The \keyword{from} form does not bind the
|
||||
module name: it goes through the 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. If a name is not found,
|
||||
next identifier, if any. If the module name is followed by \keyword{as},
|
||||
the name following \keyword{as} is used as the local name for the module.
|
||||
The \keyword{from} form does not bind the module name: it goes through the
|
||||
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
|
||||
by a star (\samp{*}), all names defined in the module are bound,
|
||||
except those beginning with an underscore (\character{_}).
|
||||
by a star (\samp{*}), all names defined in the module are bound, except
|
||||
those beginning with an underscore (\character{_}).
|
||||
\indexii{name}{binding}
|
||||
\exindex{ImportError}
|
||||
|
||||
|
|
|
@ -41,7 +41,9 @@ break_stmt: 'break'
|
|||
continue_stmt: 'continue'
|
||||
return_stmt: 'return' [testlist]
|
||||
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)*
|
||||
global_stmt: 'global' NAME (',' NAME)*
|
||||
#access_stmt: 'access' ('*' | NAME (',' NAME)*) ':' accesstype (',' accesstype)*
|
||||
|
|
|
@ -19,43 +19,45 @@
|
|||
#define return_stmt 274
|
||||
#define raise_stmt 275
|
||||
#define import_stmt 276
|
||||
#define dotted_name 277
|
||||
#define global_stmt 278
|
||||
#define exec_stmt 279
|
||||
#define assert_stmt 280
|
||||
#define compound_stmt 281
|
||||
#define if_stmt 282
|
||||
#define while_stmt 283
|
||||
#define for_stmt 284
|
||||
#define try_stmt 285
|
||||
#define except_clause 286
|
||||
#define suite 287
|
||||
#define test 288
|
||||
#define and_test 289
|
||||
#define not_test 290
|
||||
#define comparison 291
|
||||
#define comp_op 292
|
||||
#define expr 293
|
||||
#define xor_expr 294
|
||||
#define and_expr 295
|
||||
#define shift_expr 296
|
||||
#define arith_expr 297
|
||||
#define term 298
|
||||
#define factor 299
|
||||
#define power 300
|
||||
#define atom 301
|
||||
#define listmaker 302
|
||||
#define lambdef 303
|
||||
#define trailer 304
|
||||
#define subscriptlist 305
|
||||
#define subscript 306
|
||||
#define sliceop 307
|
||||
#define exprlist 308
|
||||
#define testlist 309
|
||||
#define dictmaker 310
|
||||
#define classdef 311
|
||||
#define arglist 312
|
||||
#define argument 313
|
||||
#define list_iter 314
|
||||
#define list_for 315
|
||||
#define list_if 316
|
||||
#define import_as_name 277
|
||||
#define dotted_as_name 278
|
||||
#define dotted_name 279
|
||||
#define global_stmt 280
|
||||
#define exec_stmt 281
|
||||
#define assert_stmt 282
|
||||
#define compound_stmt 283
|
||||
#define if_stmt 284
|
||||
#define while_stmt 285
|
||||
#define for_stmt 286
|
||||
#define try_stmt 287
|
||||
#define except_clause 288
|
||||
#define suite 289
|
||||
#define test 290
|
||||
#define and_test 291
|
||||
#define not_test 292
|
||||
#define comparison 293
|
||||
#define comp_op 294
|
||||
#define expr 295
|
||||
#define xor_expr 296
|
||||
#define and_expr 297
|
||||
#define shift_expr 298
|
||||
#define arith_expr 299
|
||||
#define term 300
|
||||
#define factor 301
|
||||
#define power 302
|
||||
#define atom 303
|
||||
#define listmaker 304
|
||||
#define lambdef 305
|
||||
#define trailer 306
|
||||
#define subscriptlist 307
|
||||
#define subscript 308
|
||||
#define sliceop 309
|
||||
#define exprlist 310
|
||||
#define testlist 311
|
||||
#define dictmaker 312
|
||||
#define classdef 313
|
||||
#define arglist 314
|
||||
#define argument 315
|
||||
#define list_iter 316
|
||||
#define list_for 317
|
||||
#define list_if 318
|
||||
|
|
|
@ -65,7 +65,7 @@ redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|||
|
||||
#define LOAD_LOCALS 82
|
||||
#define RETURN_VALUE 83
|
||||
|
||||
#define IMPORT_STAR 84
|
||||
#define EXEC_STMT 85
|
||||
|
||||
#define POP_BLOCK 87
|
||||
|
|
|
@ -195,7 +195,7 @@ def_op('BREAK_LOOP', 80)
|
|||
|
||||
def_op('LOAD_LOCALS', 82)
|
||||
def_op('RETURN_VALUE', 83)
|
||||
|
||||
def_op('IMPORT_STAR', 84)
|
||||
def_op('EXEC_STMT', 85)
|
||||
|
||||
def_op('POP_BLOCK', 87)
|
||||
|
|
|
@ -36,3 +36,10 @@ t6.ham loading
|
|||
t6.eggs loading
|
||||
['__all__', '__builtins__', '__doc__', '__file__', '__name__', '__path__', 'eggs', 'ham', 'spam']
|
||||
['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
|
||||
|
|
|
@ -164,6 +164,33 @@ print dir(t6)
|
|||
from t6 import *
|
||||
print dir(t6)
|
||||
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
|
||||
"""),
|
||||
|
||||
]
|
||||
|
|
|
@ -66,7 +66,8 @@ static PyObject *apply_slice(PyObject *, PyObject *, PyObject *);
|
|||
static int assign_slice(PyObject *, PyObject *,
|
||||
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 int exec_statement(PyFrameObject *,
|
||||
PyObject *, PyObject *, PyObject *);
|
||||
|
@ -1414,20 +1415,28 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
|||
if (x != NULL) continue;
|
||||
break;
|
||||
|
||||
case IMPORT_FROM:
|
||||
w = GETNAMEV(oparg);
|
||||
v = TOP();
|
||||
case IMPORT_STAR:
|
||||
v = POP();
|
||||
PyFrame_FastToLocals(f);
|
||||
if ((x = f->f_locals) == NULL) {
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
"no locals");
|
||||
break;
|
||||
}
|
||||
err = import_from(x, v, w);
|
||||
err = import_all_from(x, v);
|
||||
PyFrame_LocalsToFast(f, 0);
|
||||
Py_DECREF(v);
|
||||
if (err == 0) continue;
|
||||
break;
|
||||
|
||||
case IMPORT_FROM:
|
||||
w = GETNAMEV(oparg);
|
||||
v = TOP();
|
||||
x = import_from(v, w);
|
||||
PUSH(x);
|
||||
if (x != NULL) continue;
|
||||
break;
|
||||
|
||||
case JUMP_FORWARD:
|
||||
JUMPBY(oparg);
|
||||
continue;
|
||||
|
@ -2647,20 +2656,40 @@ cmp_outcome(int op, register PyObject *v, register PyObject *w)
|
|||
return v;
|
||||
}
|
||||
|
||||
static int
|
||||
import_from(PyObject *locals, PyObject *v, PyObject *name)
|
||||
static PyObject *
|
||||
import_from(PyObject *v, PyObject *name)
|
||||
{
|
||||
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)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"import-from requires module object");
|
||||
return -1;
|
||||
}
|
||||
w = PyModule_GetDict(v);
|
||||
if (PyString_AsString(name)[0] == '*') {
|
||||
int pos, err;
|
||||
PyObject *name, *value;
|
||||
pos = 0;
|
||||
w = PyModule_GetDict(v); /* TBD: can this not fail ? */
|
||||
|
||||
while (PyDict_Next(w, &pos, &name, &value)) {
|
||||
if (!PyString_Check(name) ||
|
||||
PyString_AsString(name)[0] == '_')
|
||||
|
@ -2673,18 +2702,6 @@ import_from(PyObject *locals, PyObject *v, PyObject *name)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
x = PyDict_GetItem(w, name);
|
||||
if (x == NULL) {
|
||||
PyErr_Format(PyExc_ImportError,
|
||||
"cannot import name %.230s",
|
||||
PyString_AsString(name));
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return PyDict_SetItem(locals, name, x);
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
build_class(PyObject *methods, PyObject *bases, PyObject *name)
|
||||
|
@ -2825,7 +2842,7 @@ find_from_args(PyFrameObject *f, int nexti)
|
|||
next_instr += nexti;
|
||||
|
||||
opcode = (*next_instr++);
|
||||
if (opcode != IMPORT_FROM) {
|
||||
if (opcode != IMPORT_FROM && opcode != IMPORT_STAR) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
@ -2834,6 +2851,16 @@ find_from_args(PyFrameObject *f, int nexti)
|
|||
if (list == NULL)
|
||||
return NULL;
|
||||
|
||||
if (opcode == IMPORT_STAR) {
|
||||
name = PyString_FromString("*");
|
||||
if (!name)
|
||||
Py_DECREF(list);
|
||||
else {
|
||||
if (PyList_Append(list, name) < 0)
|
||||
Py_DECREF(list);
|
||||
Py_DECREF(name);
|
||||
}
|
||||
} else {
|
||||
do {
|
||||
oparg = (next_instr[1]<<8) + next_instr[0];
|
||||
next_instr += 2;
|
||||
|
@ -2844,7 +2871,7 @@ find_from_args(PyFrameObject *f, int nexti)
|
|||
}
|
||||
opcode = (*next_instr++);
|
||||
} while (opcode == IMPORT_FROM);
|
||||
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
|
|
@ -2095,6 +2095,22 @@ com_raise_stmt(struct compiling *c, node *n)
|
|||
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
|
||||
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);
|
||||
com_addopname(c, IMPORT_NAME, CHILD(n, 1));
|
||||
com_push(c, 1);
|
||||
if (TYPE(CHILD(n, 3)) == STAR)
|
||||
com_addbyte(c, IMPORT_STAR);
|
||||
else {
|
||||
for (i = 3; i < NCH(n); i += 2)
|
||||
com_addopname(c, IMPORT_FROM, CHILD(n, i));
|
||||
com_from_import(c, CHILD(n, i));
|
||||
com_addbyte(c, POP_TOP);
|
||||
}
|
||||
com_pop(c, 1);
|
||||
}
|
||||
else {
|
||||
/* 'import' ... */
|
||||
for (i = 1; i < NCH(n); i += 2) {
|
||||
REQ(CHILD(n, i), dotted_name);
|
||||
com_addopname(c, IMPORT_NAME, CHILD(n, i));
|
||||
node *subn = CHILD(n, i);
|
||||
REQ(subn, dotted_as_name);
|
||||
com_addopname(c, IMPORT_NAME, CHILD(subn, 0));
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -3295,12 +3325,14 @@ optimize(struct compiling *c)
|
|||
case IMPORT_FROM:
|
||||
com_addlocal_o(c, GETNAMEOBJ(oparg));
|
||||
break;
|
||||
case IMPORT_STAR:
|
||||
case EXEC_STMT:
|
||||
c->c_flags &= ~CO_OPTIMIZED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* TBD: Is this still necessary ? */
|
||||
if (PyDict_GetItemString(c->c_locals, "*") != NULL)
|
||||
c->c_flags &= ~CO_OPTIMIZED;
|
||||
|
||||
|
|
1474
Python/graminit.c
1474
Python/graminit.c
File diff suppressed because it is too large
Load Diff
|
@ -66,7 +66,7 @@ extern time_t PyOS_GetLastModificationTime(char *, FILE *);
|
|||
/* XXX Perhaps the magic number should be frozen and a version field
|
||||
added to the .pyc file header? */
|
||||
/* 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
|
||||
value of this global to accommodate for alterations of how the
|
||||
|
|
Loading…
Reference in New Issue