SF patch #1007189, multi-line imports, for instance:

"from blah import (foo, bar
baz, bongo)"
This commit is contained in:
Anthony Baxter 2004-08-31 10:07:13 +00:00
parent 876032e570
commit 1a4ddaecc7
14 changed files with 1394 additions and 1181 deletions

View File

@ -623,6 +623,9 @@ It continues with the next cycle of the nearest enclosing loop.
\productioncont{| "from" \token{module} "import" \token{identifier} \productioncont{| "from" \token{module} "import" \token{identifier}
["as" \token{name}]} ["as" \token{name}]}
\productioncont{ ( "," \token{identifier} ["as" \token{name}] )*} \productioncont{ ( "," \token{identifier} ["as" \token{name}] )*}
\productioncont{| "from" \token{module} "import" "(" \token{identifier}
["as" \token{name}]}
\productioncont{ ( "," \token{identifier} ["as" \token{name}] )* [","] ")"}
\productioncont{| "from" \token{module} "import" "*"} \productioncont{| "from" \token{module} "import" "*"}
\production{module} \production{module}
{(\token{identifier} ".")* \token{identifier}} {(\token{identifier} ".")* \token{identifier}}
@ -744,8 +747,8 @@ before the release in which the feature becomes standard.
\begin{productionlist}[*] \begin{productionlist}[*]
\production{future_statement} \production{future_statement}
{"from" "__future__" "import" feature ["as" name]} {"from" "__future__" "import" feature ["as" name] ("," feature ["as" name])*}
\productioncont{("," feature ["as" name])*} \productioncont{| "from" "__future__" "import" "(" feature ["as" name] ("," feature ["as" name])* [","] ")"}
\production{feature}{identifier} \production{feature}{identifier}
\production{name}{identifier} \production{name}{identifier}
\end{productionlist} \end{productionlist}

View File

@ -51,9 +51,13 @@ continue_stmt: 'continue'
return_stmt: 'return' [testlist] return_stmt: 'return' [testlist]
yield_stmt: 'yield' testlist yield_stmt: 'yield' testlist
raise_stmt: 'raise' [test [',' test [',' test]]] raise_stmt: 'raise' [test [',' test [',' test]]]
import_stmt: 'import' dotted_as_name (',' dotted_as_name)* | 'from' dotted_name 'import' ('*' | import_as_name (',' import_as_name)*) 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_as_name: NAME [NAME NAME] import_as_name: NAME [NAME NAME]
dotted_as_name: dotted_name [NAME NAME] dotted_as_name: dotted_name [NAME NAME]
import_as_names: import_as_name (',' import_as_name)* [',']
dotted_as_names: dotted_as_name (',' dotted_as_name)*
dotted_name: NAME ('.' NAME)* dotted_name: NAME ('.' NAME)*
global_stmt: 'global' NAME (',' NAME)* global_stmt: 'global' NAME (',' NAME)*
exec_stmt: 'exec' expr ['in' test [',' test]] exec_stmt: 'exec' expr ['in' test [',' test]]

View File

@ -23,52 +23,56 @@
#define yield_stmt 278 #define yield_stmt 278
#define raise_stmt 279 #define raise_stmt 279
#define import_stmt 280 #define import_stmt 280
#define import_as_name 281 #define import_name 281
#define dotted_as_name 282 #define import_from 282
#define dotted_name 283 #define import_as_name 283
#define global_stmt 284 #define dotted_as_name 284
#define exec_stmt 285 #define import_as_names 285
#define assert_stmt 286 #define dotted_as_names 286
#define compound_stmt 287 #define dotted_name 287
#define if_stmt 288 #define global_stmt 288
#define while_stmt 289 #define exec_stmt 289
#define for_stmt 290 #define assert_stmt 290
#define try_stmt 291 #define compound_stmt 291
#define except_clause 292 #define if_stmt 292
#define suite 293 #define while_stmt 293
#define test 294 #define for_stmt 294
#define and_test 295 #define try_stmt 295
#define not_test 296 #define except_clause 296
#define comparison 297 #define suite 297
#define comp_op 298 #define test 298
#define expr 299 #define and_test 299
#define xor_expr 300 #define not_test 300
#define and_expr 301 #define comparison 301
#define shift_expr 302 #define comp_op 302
#define arith_expr 303 #define expr 303
#define term 304 #define xor_expr 304
#define factor 305 #define and_expr 305
#define power 306 #define shift_expr 306
#define atom 307 #define arith_expr 307
#define listmaker 308 #define term 308
#define testlist_gexp 309 #define factor 309
#define lambdef 310 #define power 310
#define trailer 311 #define atom 311
#define subscriptlist 312 #define listmaker 312
#define subscript 313 #define testlist_gexp 313
#define sliceop 314 #define lambdef 314
#define exprlist 315 #define trailer 315
#define testlist 316 #define subscriptlist 316
#define testlist_safe 317 #define subscript 317
#define dictmaker 318 #define sliceop 318
#define classdef 319 #define exprlist 319
#define arglist 320 #define testlist 320
#define argument 321 #define testlist_safe 321
#define list_iter 322 #define dictmaker 322
#define list_for 323 #define classdef 323
#define list_if 324 #define arglist 324
#define gen_iter 325 #define argument 325
#define gen_for 326 #define list_iter 326
#define gen_if 327 #define list_for 327
#define testlist1 328 #define list_if 328
#define encoding_decl 329 #define gen_iter 329
#define gen_for 330
#define gen_if 331
#define testlist1 332
#define encoding_decl 333

View File

@ -438,28 +438,28 @@ class Transformer:
return n return n
def import_stmt(self, nodelist): def import_stmt(self, nodelist):
# import_stmt: 'import' dotted_as_name (',' dotted_as_name)* | # import_stmt: import_name | import_from
# from: 'from' dotted_name 'import' assert len(nodelist) == 1
# ('*' | import_as_name (',' import_as_name)*) return self.com_node(nodelist[0])
if nodelist[0][1] == 'from':
names = [] def import_name(self, nodelist):
if nodelist[3][0] == token.NAME: # import_name: 'import' dotted_as_names
for i in range(3, len(nodelist), 2): n = Import(self.com_dotted_as_names(nodelist[1]))
names.append((nodelist[i][1], None))
else:
for i in range(3, len(nodelist), 2):
names.append(self.com_import_as_name(nodelist[i]))
n = From(self.com_dotted_name(nodelist[1]), names)
n.lineno = nodelist[0][2] n.lineno = nodelist[0][2]
return n return n
if nodelist[1][0] == symbol.dotted_name: def import_from(self, nodelist):
names = [(self.com_dotted_name(nodelist[1][1:]), None)] # import_from: 'from' dotted_name 'import' ('*' |
# '(' import_as_names ')' | import_as_names)
assert nodelist[0][1] == 'from'
assert nodelist[1][0] == symbol.dotted_name
assert nodelist[2][1] == 'import'
fromname = self.com_dotted_name(nodelist[1])
if nodelist[3][0] == token.STAR:
n = From(fromname, [('*', None)])
else: else:
names = [] node = nodelist[3 + (nodelist[3][0] == token.LPAR)]
for i in range(1, len(nodelist), 2): n = From(fromname, self.com_import_as_names(node))
names.append(self.com_dotted_as_name(nodelist[i]))
n = Import(names)
n.lineno = nodelist[0][2] n.lineno = nodelist[0][2]
return n return n
@ -895,29 +895,41 @@ class Transformer:
return name[:-1] return name[:-1]
def com_dotted_as_name(self, node): def com_dotted_as_name(self, node):
dot = self.com_dotted_name(node[1]) assert node[0] == symbol.dotted_as_name
if len(node) <= 2: node = node[1:]
dot = self.com_dotted_name(node[0][1:])
if len(node) == 1:
return dot, None return dot, None
if node[0] == symbol.dotted_name: assert node[1][1] == 'as'
pass assert node[2][0] == token.NAME
else: return dot, node[2][1]
assert node[2][1] == 'as'
assert node[3][0] == token.NAME def com_dotted_as_names(self, node):
return dot, node[3][1] assert node[0] == symbol.dotted_as_names
node = node[1:]
names = [self.com_dotted_as_name(node[0])]
for i in range(2, len(node), 2):
names.append(self.com_dotted_as_name(node[i]))
return names
def com_import_as_name(self, node): def com_import_as_name(self, node):
if node[0] == token.STAR:
return '*', None
assert node[0] == symbol.import_as_name assert node[0] == symbol.import_as_name
node = node[1:] node = node[1:]
if len(node) == 1:
assert node[0][0] == token.NAME assert node[0][0] == token.NAME
if len(node) == 1:
return node[0][1], None return node[0][1], None
assert node[1][1] == 'as', node assert node[1][1] == 'as', node
assert node[2][0] == token.NAME assert node[2][0] == token.NAME
return node[0][1], node[2][1] return node[0][1], node[2][1]
def com_import_as_names(self, node):
assert node[0] == symbol.import_as_names
node = node[1:]
names = [self.com_import_as_name(node[0])]
for i in range(2, len(node), 2):
names.append(self.com_import_as_name(node[i]))
return names
def com_bases(self, node): def com_bases(self, node):
bases = [] bases = []
for i in range(1, len(node), 2): for i in range(1, len(node), 2):

View File

@ -35,55 +35,59 @@ return_stmt = 277
yield_stmt = 278 yield_stmt = 278
raise_stmt = 279 raise_stmt = 279
import_stmt = 280 import_stmt = 280
import_as_name = 281 import_name = 281
dotted_as_name = 282 import_from = 282
dotted_name = 283 import_as_name = 283
global_stmt = 284 dotted_as_name = 284
exec_stmt = 285 import_as_names = 285
assert_stmt = 286 dotted_as_names = 286
compound_stmt = 287 dotted_name = 287
if_stmt = 288 global_stmt = 288
while_stmt = 289 exec_stmt = 289
for_stmt = 290 assert_stmt = 290
try_stmt = 291 compound_stmt = 291
except_clause = 292 if_stmt = 292
suite = 293 while_stmt = 293
test = 294 for_stmt = 294
and_test = 295 try_stmt = 295
not_test = 296 except_clause = 296
comparison = 297 suite = 297
comp_op = 298 test = 298
expr = 299 and_test = 299
xor_expr = 300 not_test = 300
and_expr = 301 comparison = 301
shift_expr = 302 comp_op = 302
arith_expr = 303 expr = 303
term = 304 xor_expr = 304
factor = 305 and_expr = 305
power = 306 shift_expr = 306
atom = 307 arith_expr = 307
listmaker = 308 term = 308
testlist_gexp = 309 factor = 309
lambdef = 310 power = 310
trailer = 311 atom = 311
subscriptlist = 312 listmaker = 312
subscript = 313 testlist_gexp = 313
sliceop = 314 lambdef = 314
exprlist = 315 trailer = 315
testlist = 316 subscriptlist = 316
testlist_safe = 317 subscript = 317
dictmaker = 318 sliceop = 318
classdef = 319 exprlist = 319
arglist = 320 testlist = 320
argument = 321 testlist_safe = 321
list_iter = 322 dictmaker = 322
list_for = 323 classdef = 323
list_if = 324 arglist = 324
gen_iter = 325 argument = 325
gen_for = 326 list_iter = 326
gen_if = 327 list_for = 327
testlist1 = 328 list_if = 328
encoding_decl = 329 gen_iter = 329
gen_for = 330
gen_if = 331
testlist1 = 332
encoding_decl = 333
#--end constants-- #--end constants--
sym_name = {} sym_name = {}

View File

@ -35,7 +35,8 @@ continue + try/finally ok
testing continue and break in try/except in loop testing continue and break in try/except in loop
return_stmt return_stmt
raise_stmt raise_stmt
import_stmt import_name
import_from
global_stmt global_stmt
exec_stmt exec_stmt
assert_stmt assert_stmt

View File

@ -211,6 +211,47 @@ if 1:
self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'single') self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'single')
self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec') self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec')
def test_import(self):
succeed = [
'import sys',
'import os, sys',
'from __future__ import nested_scopes, generators',
'from __future__ import (nested_scopes,\ngenerators)',
'from __future__ import (nested_scopes,\ngenerators,)',
'from sys import stdin, stderr, stdout',
'from sys import (stdin, stderr,\nstdout)',
'from sys import (stdin, stderr,\nstdout,)',
'from sys import (stdin\n, stderr, stdout)',
'from sys import (stdin\n, stderr, stdout,)',
'from sys import stdin as si, stdout as so, stderr as se',
'from sys import (stdin as si, stdout as so, stderr as se)',
'from sys import (stdin as si, stdout as so, stderr as se,)',
]
fail = [
'import (os, sys)',
'import (os), (sys)',
'import ((os), (sys))',
'import (sys',
'import sys)',
'import (os,)',
'from (sys) import stdin',
'from __future__ import (nested_scopes',
'from __future__ import nested_scopes)',
'from __future__ import nested_scopes,\ngenerators',
'from sys import (stdin',
'from sys import stdin)',
'from sys import stdin, stdout,\nstderr',
'from sys import stdin si',
'from sys import stdin,'
'from sys import (*)',
'from sys import (stdin,, stdout, stderr)',
'from sys import (stdin, stdout),',
]
for stmt in succeed:
compile(stmt, 'tmp', 'exec')
for stmt in fail:
self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec')
def test_main(): def test_main():
test_support.run_unittest(TestSpecifics) test_support.run_unittest(TestSpecifics)

View File

@ -417,12 +417,16 @@ except RuntimeError: pass
try: raise KeyboardInterrupt try: raise KeyboardInterrupt
except KeyboardInterrupt: pass except KeyboardInterrupt: pass
print 'import_stmt' # 'import' NAME (',' NAME)* | 'from' NAME 'import' ('*' | NAME (',' NAME)*) print 'import_name' # 'import' dotted_as_names
import sys import sys
import time, sys import time, sys
print 'import_from' # 'from' dotted_name 'import' ('*' | '(' import_as_names ')' | import_as_names)
from time import time from time import time
from time import (time)
from sys import * from sys import *
from sys import path, argv from sys import path, argv
from sys import (path, argv)
from sys import (path, argv,)
print 'global_stmt' # 'global' NAME (',' NAME)* print 'global_stmt' # 'global' NAME (',' NAME)*
def f(): def f():

View File

@ -130,12 +130,26 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase):
def test_import_from_statement(self): def test_import_from_statement(self):
self.check_suite("from sys.path import *") self.check_suite("from sys.path import *")
self.check_suite("from sys.path import dirname") self.check_suite("from sys.path import dirname")
self.check_suite("from sys.path import (dirname)")
self.check_suite("from sys.path import (dirname,)")
self.check_suite("from sys.path import dirname as my_dirname") self.check_suite("from sys.path import dirname as my_dirname")
self.check_suite("from sys.path import (dirname as my_dirname)")
self.check_suite("from sys.path import (dirname as my_dirname,)")
self.check_suite("from sys.path import dirname, basename") self.check_suite("from sys.path import dirname, basename")
self.check_suite("from sys.path import (dirname, basename)")
self.check_suite("from sys.path import (dirname, basename,)")
self.check_suite( self.check_suite(
"from sys.path import dirname as my_dirname, basename") "from sys.path import dirname as my_dirname, basename")
self.check_suite(
"from sys.path import (dirname as my_dirname, basename)")
self.check_suite(
"from sys.path import (dirname as my_dirname, basename,)")
self.check_suite( self.check_suite(
"from sys.path import dirname, basename as my_basename") "from sys.path import dirname, basename as my_basename")
self.check_suite(
"from sys.path import (dirname, basename as my_basename)")
self.check_suite(
"from sys.path import (dirname, basename as my_basename,)")
def test_basic_import_statement(self): def test_basic_import_statement(self):
self.check_suite("import sys") self.check_suite("import sys")

View File

@ -12,6 +12,9 @@ What's New in Python 2.4 alpha 3?
Core and builtins Core and builtins
----------------- -----------------
- SF patch #1007189: ``from ... import ...`` statements now allow the name
list to be surrounded by parentheses.
- Some speedups for long arithmetic, thanks to Trevor Perrin. Gradeschool - Some speedups for long arithmetic, thanks to Trevor Perrin. Gradeschool
multiplication was sped a little by optimizing the C code. Gradeschool multiplication was sped a little by optimizing the C code. Gradeschool
squaring was sped by about a factor of 2, by exploiting that about half squaring was sped by about a factor of 2, by exploiting that about half
@ -889,7 +892,7 @@ Library
API matches math.log(). API matches math.log().
- Bug #957381: distutils bdist_rpm no longer fails on recent RPM versions - Bug #957381: distutils bdist_rpm no longer fails on recent RPM versions
that generate a *-debuginfo.rpm. that generate a -debuginfo.rpm
- os.path.devnull has been added for all supported platforms. - os.path.devnull has been added for all supported platforms.

View File

@ -839,6 +839,7 @@ VALIDATER(expr_stmt); VALIDATER(power);
VALIDATER(print_stmt); VALIDATER(del_stmt); VALIDATER(print_stmt); VALIDATER(del_stmt);
VALIDATER(return_stmt); VALIDATER(list_iter); VALIDATER(return_stmt); VALIDATER(list_iter);
VALIDATER(raise_stmt); VALIDATER(import_stmt); VALIDATER(raise_stmt); VALIDATER(import_stmt);
VALIDATER(import_name); VALIDATER(import_from);
VALIDATER(global_stmt); VALIDATER(list_if); VALIDATER(global_stmt); VALIDATER(list_if);
VALIDATER(assert_stmt); VALIDATER(list_for); VALIDATER(assert_stmt); VALIDATER(list_for);
VALIDATER(exec_stmt); VALIDATER(compound_stmt); VALIDATER(exec_stmt); VALIDATER(compound_stmt);
@ -1714,55 +1715,100 @@ validate_dotted_as_name(node *tree)
} }
/* import_stmt: /* dotted_as_name (',' dotted_as_name)* */
* static int
* 'import' dotted_as_name (',' dotted_as_name)* validate_dotted_as_names(node *tree)
* | 'from' dotted_name 'import' ('*' | import_as_name (',' import_as_name)*) {
int nch = NCH(tree);
int res = is_odd(nch) && validate_dotted_as_name(CHILD(tree, 0));
int i;
for (i = 1; res && (i < nch); i += 2)
res = (validate_comma(CHILD(tree, i))
&& validate_dotted_as_name(CHILD(tree, i + 1)));
return (res);
}
/* import_as_name (',' import_as_name)* [','] */
static int
validate_import_as_names(node *tree)
{
int nch = NCH(tree);
int res = validate_import_as_name(CHILD(tree, 0));
int i;
for (i = 1; res && (i + 1 < nch); i += 2)
res = (validate_comma(CHILD(tree, i))
&& validate_import_as_name(CHILD(tree, i + 1)));
return (res);
}
/* 'import' dotted_as_names */
static int
validate_import_name(node *tree)
{
return (validate_ntype(tree, import_name)
&& validate_numnodes(tree, 2, "import_name")
&& validate_name(CHILD(tree, 0), "import")
&& validate_dotted_as_names(CHILD(tree, 1)));
}
/* 'from' dotted_name 'import' ('*' | '(' import_as_names ')' |
* import_as_names
*/ */
static int static int
validate_import_from(node *tree)
{
int nch = NCH(tree);
int res = validate_ntype(tree, import_from)
&& (nch >= 4)
&& validate_name(CHILD(tree, 0), "from")
&& validate_dotted_name(CHILD(tree, 1))
&& validate_name(CHILD(tree, 2), "import");
if (res && TYPE(CHILD(tree, 3)) == LPAR)
res = ((nch == 6)
&& validate_lparen(CHILD(tree, 3))
&& validate_import_as_names(CHILD(tree, 4))
&& validate_rparen(CHILD(tree, 5)));
else if (res && TYPE(CHILD(tree, 3)) != STAR)
res = validate_import_as_names(CHILD(tree, 3));
return (res);
}
/* import_stmt: import_name | import_from */
static int
validate_import_stmt(node *tree) validate_import_stmt(node *tree)
{ {
int nch = NCH(tree); int nch = NCH(tree);
int res = (validate_ntype(tree, import_stmt) int res = validate_numnodes(tree, 1, "import_stmt");
&& (nch >= 2) && is_even(nch)
&& validate_ntype(CHILD(tree, 0), NAME));
if (res && (strcmp(STR(CHILD(tree, 0)), "import") == 0)) { if (res) {
int j; int ntype = TYPE(CHILD(tree, 0));
res = validate_dotted_as_name(CHILD(tree, 1)); if (ntype == import_name || ntype == import_from)
for (j = 2; res && (j < nch); j += 2) res = validate_node(CHILD(tree, 0));
res = (validate_comma(CHILD(tree, j))
&& validate_dotted_as_name(CHILD(tree, j + 1)));
}
else if (res && (res = validate_name(CHILD(tree, 0), "from"))) {
res = ((nch >= 4) && is_even(nch)
&& validate_dotted_name(CHILD(tree, 1))
&& validate_name(CHILD(tree, 2), "import"));
if (nch == 4) {
if (TYPE(CHILD(tree, 3)) == import_as_name)
res = validate_import_as_name(CHILD(tree, 3));
else
res = validate_star(CHILD(tree, 3));
}
else { else {
/* 'from' dotted_name 'import' import_as_name
* (',' import_as_name)+
*/
int j;
res = validate_import_as_name(CHILD(tree, 3));
for (j = 4; res && (j < nch); j += 2)
res = (validate_comma(CHILD(tree, j))
&& validate_import_as_name(CHILD(tree, j + 1)));
}
}
else
res = 0; res = 0;
err_string("illegal import_stmt child type");
}
}
else if (nch == 1) {
res = 0;
PyErr_Format(parser_error,
"Unrecognized child node of import_stmt: %d.",
TYPE(CHILD(tree, 0)));
}
return (res); return (res);
} }
static int static int
validate_global_stmt(node *tree) validate_global_stmt(node *tree)
{ {
@ -2823,6 +2869,12 @@ validate_node(node *tree)
case import_stmt: case import_stmt:
res = validate_import_stmt(tree); res = validate_import_stmt(tree);
break; break;
case import_name:
res = validate_import_name(tree);
break;
case import_from:
res = validate_import_from(tree);
break;
case global_stmt: case global_stmt:
res = validate_global_stmt(tree); res = validate_global_stmt(tree);
break; break;

View File

@ -3490,42 +3490,53 @@ com_from_import(struct compiling *c, node *n)
static void static void
com_import_stmt(struct compiling *c, node *n) com_import_stmt(struct compiling *c, node *n)
{ {
node *nn;
int i; int i;
REQ(n, import_stmt); REQ(n, import_stmt);
/* 'import' dotted_name (',' dotted_name)* | n = CHILD(n, 0);
'from' dotted_name 'import' ('*' | NAME (',' NAME)*) */ /* import_stmt: import_name | import_from */
if (STR(CHILD(n, 0))[0] == 'f') { if (TYPE(n) == import_from) {
/* 'from' dotted_name 'import' ('*' |
'(' import_as_names ')' | import_as_names) */
PyObject *tup; PyObject *tup;
/* 'from' dotted_name 'import' ... */
REQ(CHILD(n, 1), dotted_name); REQ(CHILD(n, 1), dotted_name);
nn = CHILD(n, 3 + (TYPE(CHILD(n, 3)) == LPAR));
if (TYPE(CHILD(n, 3)) == STAR) { if (TYPE(nn) == STAR)
tup = Py_BuildValue("(s)", "*"); tup = Py_BuildValue("(s)", "*");
} else { else {
tup = PyTuple_New((NCH(n) - 2)/2); if (TYPE(CHILD(nn, NCH(nn) - 1)) == COMMA &&
for (i = 3; i < NCH(n); i += 2) { TYPE(CHILD(n, 3)) != LPAR) {
PyTuple_SET_ITEM(tup, (i-3)/2, com_error(c, PyExc_SyntaxError,
PyString_FromString(STR( "trailing comma not allowed "
CHILD(CHILD(n, i), 0)))); "without surrounding parentheses");
return;
} }
REQ(nn, import_as_names);
tup = PyTuple_New((NCH(nn) + 1) / 2);
for (i = 0; i < NCH(nn); i += 2)
PyTuple_SET_ITEM(tup, i / 2,
PyString_FromString(STR(
CHILD(CHILD(nn, i), 0))));
} }
com_addoparg(c, LOAD_CONST, com_addconst(c, tup)); com_addoparg(c, LOAD_CONST, com_addconst(c, tup));
Py_DECREF(tup); Py_DECREF(tup);
com_push(c, 1); com_push(c, 1);
com_addopname(c, IMPORT_NAME, CHILD(n, 1)); com_addopname(c, IMPORT_NAME, CHILD(n, 1));
if (TYPE(CHILD(n, 3)) == STAR) if (TYPE(nn) == STAR)
com_addbyte(c, IMPORT_STAR); com_addbyte(c, IMPORT_STAR);
else { else {
for (i = 3; i < NCH(n); i += 2) for (i = 0; i < NCH(nn); i += 2)
com_from_import(c, CHILD(n, i)); com_from_import(c, CHILD(nn, i));
com_addbyte(c, POP_TOP); com_addbyte(c, POP_TOP);
} }
com_pop(c, 1); com_pop(c, 1);
} }
else { else {
/* 'import' ... */ /* 'import' dotted_as_names */
for (i = 1; i < NCH(n); i += 2) { nn = CHILD(n, 1);
node *subn = CHILD(n, i); REQ(nn, dotted_as_names);
for (i = 0; i < NCH(nn); i += 2) {
node *subn = CHILD(nn, i);
REQ(subn, dotted_as_name); REQ(subn, dotted_as_name);
com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None)); com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
com_push(c, 1); com_push(c, 1);
@ -6291,14 +6302,15 @@ symtable_gen_iter(struct symtable *st, node *n)
static void static void
symtable_import(struct symtable *st, node *n) symtable_import(struct symtable *st, node *n)
{ {
node *nn;
int i; int i;
/* import_stmt: 'import' dotted_as_name (',' dotted_as_name)* /* import_stmt: import_name | import_from */
| 'from' dotted_name 'import' n = CHILD(n, 0);
('*' | import_as_name (',' import_as_name)*) if (TYPE(n) == import_from) {
import_as_name: NAME [NAME NAME] /* import_from: 'from' dotted_name 'import' ('*' |
*/ | '(' import_as_names ')' | import_as_names) */
if (STR(CHILD(n, 0))[0] == 'f') { /* from */
node *dotname = CHILD(n, 1); node *dotname = CHILD(n, 1);
REQ(dotname, dotted_name);
if (strcmp(STR(CHILD(dotname, 0)), "__future__") == 0) { if (strcmp(STR(CHILD(dotname, 0)), "__future__") == 0) {
/* check for bogus imports */ /* check for bogus imports */
if (n->n_lineno >= st->st_future->ff_last_lineno) { if (n->n_lineno >= st->st_future->ff_last_lineno) {
@ -6308,7 +6320,8 @@ symtable_import(struct symtable *st, node *n)
return; return;
} }
} }
if (TYPE(CHILD(n, 3)) == STAR) { nn = CHILD(n, 3 + (TYPE(CHILD(n, 3)) == LPAR));
if (TYPE(nn) == STAR) {
if (st->st_cur->ste_type != TYPE_MODULE) { if (st->st_cur->ste_type != TYPE_MODULE) {
if (symtable_warn(st, if (symtable_warn(st,
"import * only allowed at module level") < 0) "import * only allowed at module level") < 0)
@ -6317,8 +6330,9 @@ symtable_import(struct symtable *st, node *n)
st->st_cur->ste_optimized |= OPT_IMPORT_STAR; st->st_cur->ste_optimized |= OPT_IMPORT_STAR;
st->st_cur->ste_opt_lineno = n->n_lineno; st->st_cur->ste_opt_lineno = n->n_lineno;
} else { } else {
for (i = 3; i < NCH(n); i += 2) { REQ(nn, import_as_names);
node *c = CHILD(n, i); for (i = 0; i < NCH(nn); i += 2) {
node *c = CHILD(nn, i);
if (NCH(c) > 1) /* import as */ if (NCH(c) > 1) /* import as */
symtable_assign(st, CHILD(c, 2), symtable_assign(st, CHILD(c, 2),
DEF_IMPORT); DEF_IMPORT);
@ -6328,9 +6342,11 @@ symtable_import(struct symtable *st, node *n)
} }
} }
} else { } else {
for (i = 1; i < NCH(n); i += 2) { /* 'import' dotted_as_names */
symtable_assign(st, CHILD(n, i), DEF_IMPORT); nn = CHILD(n, 1);
} REQ(nn, dotted_as_names);
for (i = 0; i < NCH(nn); i += 2)
symtable_assign(st, CHILD(nn, i), DEF_IMPORT);
} }
} }

View File

@ -18,18 +18,18 @@ future_check_features(PyFutureFeatures *ff, node *n, const char *filename)
{ {
int i; int i;
char *feature; char *feature;
node *ch; node *ch, *nn;
REQ(n, import_stmt); /* must by from __future__ import ... */ REQ(n, import_from);
nn = CHILD(n, 3 + (TYPE(CHILD(n, 3)) == LPAR));
for (i = 3; i < NCH(n); i += 2) { if (TYPE(nn) == STAR) {
ch = CHILD(n, i); PyErr_SetString(PyExc_SyntaxError, FUTURE_IMPORT_STAR);
if (TYPE(ch) == STAR) { PyErr_SyntaxLocation(filename, nn->n_lineno);
PyErr_SetString(PyExc_SyntaxError,
FUTURE_IMPORT_STAR);
PyErr_SyntaxLocation(filename, ch->n_lineno);
return -1; return -1;
} }
REQ(nn, import_as_names);
for (i = 0; i < NCH(nn); i += 2) {
ch = CHILD(nn, i);
REQ(ch, import_as_name); REQ(ch, import_as_name);
feature = STR(CHILD(ch, 0)); feature = STR(CHILD(ch, 0));
if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) { if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
@ -188,7 +188,8 @@ future_parse(PyFutureFeatures *ff, node *n, const char *filename)
case import_stmt: { case import_stmt: {
node *name; node *name;
if (STR(CHILD(n, 0))[0] != 'f') { /* from */ n = CHILD(n, 0);
if (TYPE(n) != import_from) {
ff->ff_last_lineno = n->n_lineno; ff->ff_last_lineno = n->n_lineno;
return 0; return 0;
} }

File diff suppressed because it is too large Load Diff