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}
["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" "*"}
\production{module}
{(\token{identifier} ".")* \token{identifier}}
@ -744,8 +747,8 @@ before the release in which the feature becomes standard.
\begin{productionlist}[*]
\production{future_statement}
{"from" "__future__" "import" feature ["as" name]}
\productioncont{("," feature ["as" name])*}
{"from" "__future__" "import" feature ["as" name] ("," feature ["as" name])*}
\productioncont{| "from" "__future__" "import" "(" feature ["as" name] ("," feature ["as" name])* [","] ")"}
\production{feature}{identifier}
\production{name}{identifier}
\end{productionlist}

View File

@ -51,9 +51,13 @@ continue_stmt: 'continue'
return_stmt: 'return' [testlist]
yield_stmt: 'yield' testlist
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]
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)*
global_stmt: 'global' NAME (',' NAME)*
exec_stmt: 'exec' expr ['in' test [',' test]]

View File

@ -23,52 +23,56 @@
#define yield_stmt 278
#define raise_stmt 279
#define import_stmt 280
#define import_as_name 281
#define dotted_as_name 282
#define dotted_name 283
#define global_stmt 284
#define exec_stmt 285
#define assert_stmt 286
#define compound_stmt 287
#define if_stmt 288
#define while_stmt 289
#define for_stmt 290
#define try_stmt 291
#define except_clause 292
#define suite 293
#define test 294
#define and_test 295
#define not_test 296
#define comparison 297
#define comp_op 298
#define expr 299
#define xor_expr 300
#define and_expr 301
#define shift_expr 302
#define arith_expr 303
#define term 304
#define factor 305
#define power 306
#define atom 307
#define listmaker 308
#define testlist_gexp 309
#define lambdef 310
#define trailer 311
#define subscriptlist 312
#define subscript 313
#define sliceop 314
#define exprlist 315
#define testlist 316
#define testlist_safe 317
#define dictmaker 318
#define classdef 319
#define arglist 320
#define argument 321
#define list_iter 322
#define list_for 323
#define list_if 324
#define gen_iter 325
#define gen_for 326
#define gen_if 327
#define testlist1 328
#define encoding_decl 329
#define import_name 281
#define import_from 282
#define import_as_name 283
#define dotted_as_name 284
#define import_as_names 285
#define dotted_as_names 286
#define dotted_name 287
#define global_stmt 288
#define exec_stmt 289
#define assert_stmt 290
#define compound_stmt 291
#define if_stmt 292
#define while_stmt 293
#define for_stmt 294
#define try_stmt 295
#define except_clause 296
#define suite 297
#define test 298
#define and_test 299
#define not_test 300
#define comparison 301
#define comp_op 302
#define expr 303
#define xor_expr 304
#define and_expr 305
#define shift_expr 306
#define arith_expr 307
#define term 308
#define factor 309
#define power 310
#define atom 311
#define listmaker 312
#define testlist_gexp 313
#define lambdef 314
#define trailer 315
#define subscriptlist 316
#define subscript 317
#define sliceop 318
#define exprlist 319
#define testlist 320
#define testlist_safe 321
#define dictmaker 322
#define classdef 323
#define arglist 324
#define argument 325
#define list_iter 326
#define list_for 327
#define list_if 328
#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
def import_stmt(self, nodelist):
# import_stmt: 'import' dotted_as_name (',' dotted_as_name)* |
# from: 'from' dotted_name 'import'
# ('*' | import_as_name (',' import_as_name)*)
if nodelist[0][1] == 'from':
names = []
if nodelist[3][0] == token.NAME:
for i in range(3, len(nodelist), 2):
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]
return n
# import_stmt: import_name | import_from
assert len(nodelist) == 1
return self.com_node(nodelist[0])
if nodelist[1][0] == symbol.dotted_name:
names = [(self.com_dotted_name(nodelist[1][1:]), None)]
def import_name(self, nodelist):
# import_name: 'import' dotted_as_names
n = Import(self.com_dotted_as_names(nodelist[1]))
n.lineno = nodelist[0][2]
return n
def import_from(self, nodelist):
# 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:
names = []
for i in range(1, len(nodelist), 2):
names.append(self.com_dotted_as_name(nodelist[i]))
n = Import(names)
node = nodelist[3 + (nodelist[3][0] == token.LPAR)]
n = From(fromname, self.com_import_as_names(node))
n.lineno = nodelist[0][2]
return n
@ -895,29 +895,41 @@ class Transformer:
return name[:-1]
def com_dotted_as_name(self, node):
dot = self.com_dotted_name(node[1])
if len(node) <= 2:
assert node[0] == symbol.dotted_as_name
node = node[1:]
dot = self.com_dotted_name(node[0][1:])
if len(node) == 1:
return dot, None
if node[0] == symbol.dotted_name:
pass
else:
assert node[2][1] == 'as'
assert node[3][0] == token.NAME
return dot, node[3][1]
assert node[1][1] == 'as'
assert node[2][0] == token.NAME
return dot, node[2][1]
def com_dotted_as_names(self, node):
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):
if node[0] == token.STAR:
return '*', None
assert node[0] == symbol.import_as_name
node = node[1:]
assert node[0][0] == token.NAME
if len(node) == 1:
assert node[0][0] == token.NAME
return node[0][1], None
assert node[1][1] == 'as', node
assert node[2][0] == token.NAME
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):
bases = []
for i in range(1, len(node), 2):

View File

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

View File

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

View File

@ -211,6 +211,47 @@ if 1:
self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'single')
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():
test_support.run_unittest(TestSpecifics)

View File

@ -417,12 +417,16 @@ except RuntimeError: pass
try: raise KeyboardInterrupt
except KeyboardInterrupt: pass
print 'import_stmt' # 'import' NAME (',' NAME)* | 'from' NAME 'import' ('*' | NAME (',' NAME)*)
print 'import_name' # 'import' dotted_as_names
import 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 sys import *
from sys import path, argv
from sys import (path, argv)
from sys import (path, argv,)
print 'global_stmt' # 'global' NAME (',' NAME)*
def f():

View File

@ -130,12 +130,26 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase):
def test_import_from_statement(self):
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 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 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(
"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):
self.check_suite("import sys")

View File

@ -12,6 +12,9 @@ What's New in Python 2.4 alpha 3?
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
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
@ -889,7 +892,7 @@ Library
API matches math.log().
- 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.

View File

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

View File

@ -3490,42 +3490,53 @@ com_from_import(struct compiling *c, node *n)
static void
com_import_stmt(struct compiling *c, node *n)
{
node *nn;
int i;
REQ(n, import_stmt);
/* 'import' dotted_name (',' dotted_name)* |
'from' dotted_name 'import' ('*' | NAME (',' NAME)*) */
if (STR(CHILD(n, 0))[0] == 'f') {
n = CHILD(n, 0);
/* import_stmt: import_name | import_from */
if (TYPE(n) == import_from) {
/* 'from' dotted_name 'import' ('*' |
'(' import_as_names ')' | import_as_names) */
PyObject *tup;
/* 'from' dotted_name 'import' ... */
REQ(CHILD(n, 1), dotted_name);
if (TYPE(CHILD(n, 3)) == STAR) {
nn = CHILD(n, 3 + (TYPE(CHILD(n, 3)) == LPAR));
if (TYPE(nn) == STAR)
tup = Py_BuildValue("(s)", "*");
} else {
tup = PyTuple_New((NCH(n) - 2)/2);
for (i = 3; i < NCH(n); i += 2) {
PyTuple_SET_ITEM(tup, (i-3)/2,
PyString_FromString(STR(
CHILD(CHILD(n, i), 0))));
else {
if (TYPE(CHILD(nn, NCH(nn) - 1)) == COMMA &&
TYPE(CHILD(n, 3)) != LPAR) {
com_error(c, PyExc_SyntaxError,
"trailing comma not allowed "
"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));
Py_DECREF(tup);
com_push(c, 1);
com_addopname(c, IMPORT_NAME, CHILD(n, 1));
if (TYPE(CHILD(n, 3)) == STAR)
if (TYPE(nn) == STAR)
com_addbyte(c, IMPORT_STAR);
else {
for (i = 3; i < NCH(n); i += 2)
com_from_import(c, CHILD(n, i));
for (i = 0; i < NCH(nn); i += 2)
com_from_import(c, CHILD(nn, i));
com_addbyte(c, POP_TOP);
}
com_pop(c, 1);
}
else {
/* 'import' ... */
for (i = 1; i < NCH(n); i += 2) {
node *subn = CHILD(n, i);
/* 'import' dotted_as_names */
nn = CHILD(n, 1);
REQ(nn, dotted_as_names);
for (i = 0; i < NCH(nn); i += 2) {
node *subn = CHILD(nn, i);
REQ(subn, dotted_as_name);
com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
com_push(c, 1);
@ -6291,14 +6302,15 @@ symtable_gen_iter(struct symtable *st, node *n)
static void
symtable_import(struct symtable *st, node *n)
{
node *nn;
int i;
/* 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]
*/
if (STR(CHILD(n, 0))[0] == 'f') { /* from */
/* import_stmt: import_name | import_from */
n = CHILD(n, 0);
if (TYPE(n) == import_from) {
/* import_from: 'from' dotted_name 'import' ('*' |
| '(' import_as_names ')' | import_as_names) */
node *dotname = CHILD(n, 1);
REQ(dotname, dotted_name);
if (strcmp(STR(CHILD(dotname, 0)), "__future__") == 0) {
/* check for bogus imports */
if (n->n_lineno >= st->st_future->ff_last_lineno) {
@ -6308,7 +6320,8 @@ symtable_import(struct symtable *st, node *n)
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 (symtable_warn(st,
"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_opt_lineno = n->n_lineno;
} else {
for (i = 3; i < NCH(n); i += 2) {
node *c = CHILD(n, i);
REQ(nn, import_as_names);
for (i = 0; i < NCH(nn); i += 2) {
node *c = CHILD(nn, i);
if (NCH(c) > 1) /* import as */
symtable_assign(st, CHILD(c, 2),
DEF_IMPORT);
@ -6328,9 +6342,11 @@ symtable_import(struct symtable *st, node *n)
}
}
} else {
for (i = 1; i < NCH(n); i += 2) {
symtable_assign(st, CHILD(n, i), DEF_IMPORT);
}
/* 'import' dotted_as_names */
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;
char *feature;
node *ch;
node *ch, *nn;
REQ(n, import_stmt); /* must by from __future__ import ... */
for (i = 3; i < NCH(n); i += 2) {
ch = CHILD(n, i);
if (TYPE(ch) == STAR) {
PyErr_SetString(PyExc_SyntaxError,
FUTURE_IMPORT_STAR);
PyErr_SyntaxLocation(filename, ch->n_lineno);
return -1;
}
REQ(n, import_from);
nn = CHILD(n, 3 + (TYPE(CHILD(n, 3)) == LPAR));
if (TYPE(nn) == STAR) {
PyErr_SetString(PyExc_SyntaxError, FUTURE_IMPORT_STAR);
PyErr_SyntaxLocation(filename, nn->n_lineno);
return -1;
}
REQ(nn, import_as_names);
for (i = 0; i < NCH(nn); i += 2) {
ch = CHILD(nn, i);
REQ(ch, import_as_name);
feature = STR(CHILD(ch, 0));
if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
@ -188,7 +188,8 @@ future_parse(PyFutureFeatures *ff, node *n, const char *filename)
case import_stmt: {
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;
return 0;
}

File diff suppressed because it is too large Load Diff