Skip to content

Commit 1a4ddae

Browse files
committed
SF patch #1007189, multi-line imports, for instance:
"from blah import (foo, bar baz, bongo)"
1 parent 876032e commit 1a4ddae

14 files changed

Lines changed: 1211 additions & 998 deletions

File tree

Doc/ref/ref6.tex

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,9 @@ \section{The \keyword{import} statement \label{import}}
623623
\productioncont{| "from" \token{module} "import" \token{identifier}
624624
["as" \token{name}]}
625625
\productioncont{ ( "," \token{identifier} ["as" \token{name}] )*}
626+
\productioncont{| "from" \token{module} "import" "(" \token{identifier}
627+
["as" \token{name}]}
628+
\productioncont{ ( "," \token{identifier} ["as" \token{name}] )* [","] ")"}
626629
\productioncont{| "from" \token{module} "import" "*"}
627630
\production{module}
628631
{(\token{identifier} ".")* \token{identifier}}
@@ -744,8 +747,8 @@ \subsection{Future statements \label{future}}
744747
745748
\begin{productionlist}[*]
746749
\production{future_statement}
747-
{"from" "__future__" "import" feature ["as" name]}
748-
\productioncont{("," feature ["as" name])*}
750+
{"from" "__future__" "import" feature ["as" name] ("," feature ["as" name])*}
751+
\productioncont{| "from" "__future__" "import" "(" feature ["as" name] ("," feature ["as" name])* [","] ")"}
749752
\production{feature}{identifier}
750753
\production{name}{identifier}
751754
\end{productionlist}

Grammar/Grammar

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,13 @@ continue_stmt: 'continue'
5151
return_stmt: 'return' [testlist]
5252
yield_stmt: 'yield' testlist
5353
raise_stmt: 'raise' [test [',' test [',' test]]]
54-
import_stmt: 'import' dotted_as_name (',' dotted_as_name)* | 'from' dotted_name 'import' ('*' | import_as_name (',' import_as_name)*)
54+
import_stmt: import_name | import_from
55+
import_name: 'import' dotted_as_names
56+
import_from: 'from' dotted_name 'import' ('*' | '(' import_as_names ')' | import_as_names)
5557
import_as_name: NAME [NAME NAME]
5658
dotted_as_name: dotted_name [NAME NAME]
59+
import_as_names: import_as_name (',' import_as_name)* [',']
60+
dotted_as_names: dotted_as_name (',' dotted_as_name)*
5761
dotted_name: NAME ('.' NAME)*
5862
global_stmt: 'global' NAME (',' NAME)*
5963
exec_stmt: 'exec' expr ['in' test [',' test]]

Include/graminit.h

Lines changed: 53 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -23,52 +23,56 @@
2323
#define yield_stmt 278
2424
#define raise_stmt 279
2525
#define import_stmt 280
26-
#define import_as_name 281
27-
#define dotted_as_name 282
28-
#define dotted_name 283
29-
#define global_stmt 284
30-
#define exec_stmt 285
31-
#define assert_stmt 286
32-
#define compound_stmt 287
33-
#define if_stmt 288
34-
#define while_stmt 289
35-
#define for_stmt 290
36-
#define try_stmt 291
37-
#define except_clause 292
38-
#define suite 293
39-
#define test 294
40-
#define and_test 295
41-
#define not_test 296
42-
#define comparison 297
43-
#define comp_op 298
44-
#define expr 299
45-
#define xor_expr 300
46-
#define and_expr 301
47-
#define shift_expr 302
48-
#define arith_expr 303
49-
#define term 304
50-
#define factor 305
51-
#define power 306
52-
#define atom 307
53-
#define listmaker 308
54-
#define testlist_gexp 309
55-
#define lambdef 310
56-
#define trailer 311
57-
#define subscriptlist 312
58-
#define subscript 313
59-
#define sliceop 314
60-
#define exprlist 315
61-
#define testlist 316
62-
#define testlist_safe 317
63-
#define dictmaker 318
64-
#define classdef 319
65-
#define arglist 320
66-
#define argument 321
67-
#define list_iter 322
68-
#define list_for 323
69-
#define list_if 324
70-
#define gen_iter 325
71-
#define gen_for 326
72-
#define gen_if 327
73-
#define testlist1 328
74-
#define encoding_decl 329
26+
#define import_name 281
27+
#define import_from 282
28+
#define import_as_name 283
29+
#define dotted_as_name 284
30+
#define import_as_names 285
31+
#define dotted_as_names 286
32+
#define dotted_name 287
33+
#define global_stmt 288
34+
#define exec_stmt 289
35+
#define assert_stmt 290
36+
#define compound_stmt 291
37+
#define if_stmt 292
38+
#define while_stmt 293
39+
#define for_stmt 294
40+
#define try_stmt 295
41+
#define except_clause 296
42+
#define suite 297
43+
#define test 298
44+
#define and_test 299
45+
#define not_test 300
46+
#define comparison 301
47+
#define comp_op 302
48+
#define expr 303
49+
#define xor_expr 304
50+
#define and_expr 305
51+
#define shift_expr 306
52+
#define arith_expr 307
53+
#define term 308
54+
#define factor 309
55+
#define power 310
56+
#define atom 311
57+
#define listmaker 312
58+
#define testlist_gexp 313
59+
#define lambdef 314
60+
#define trailer 315
61+
#define subscriptlist 316
62+
#define subscript 317
63+
#define sliceop 318
64+
#define exprlist 319
65+
#define testlist 320
66+
#define testlist_safe 321
67+
#define dictmaker 322
68+
#define classdef 323
69+
#define arglist 324
70+
#define argument 325
71+
#define list_iter 326
72+
#define list_for 327
73+
#define list_if 328
74+
#define gen_iter 329
75+
#define gen_for 330
76+
#define gen_if 331
77+
#define testlist1 332
78+
#define encoding_decl 333

Lib/compiler/transformer.py

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -438,28 +438,28 @@ def raise_stmt(self, nodelist):
438438
return n
439439

440440
def import_stmt(self, nodelist):
441-
# import_stmt: 'import' dotted_as_name (',' dotted_as_name)* |
442-
# from: 'from' dotted_name 'import'
443-
# ('*' | import_as_name (',' import_as_name)*)
444-
if nodelist[0][1] == 'from':
445-
names = []
446-
if nodelist[3][0] == token.NAME:
447-
for i in range(3, len(nodelist), 2):
448-
names.append((nodelist[i][1], None))
449-
else:
450-
for i in range(3, len(nodelist), 2):
451-
names.append(self.com_import_as_name(nodelist[i]))
452-
n = From(self.com_dotted_name(nodelist[1]), names)
453-
n.lineno = nodelist[0][2]
454-
return n
441+
# import_stmt: import_name | import_from
442+
assert len(nodelist) == 1
443+
return self.com_node(nodelist[0])
455444

456-
if nodelist[1][0] == symbol.dotted_name:
457-
names = [(self.com_dotted_name(nodelist[1][1:]), None)]
445+
def import_name(self, nodelist):
446+
# import_name: 'import' dotted_as_names
447+
n = Import(self.com_dotted_as_names(nodelist[1]))
448+
n.lineno = nodelist[0][2]
449+
return n
450+
451+
def import_from(self, nodelist):
452+
# import_from: 'from' dotted_name 'import' ('*' |
453+
# '(' import_as_names ')' | import_as_names)
454+
assert nodelist[0][1] == 'from'
455+
assert nodelist[1][0] == symbol.dotted_name
456+
assert nodelist[2][1] == 'import'
457+
fromname = self.com_dotted_name(nodelist[1])
458+
if nodelist[3][0] == token.STAR:
459+
n = From(fromname, [('*', None)])
458460
else:
459-
names = []
460-
for i in range(1, len(nodelist), 2):
461-
names.append(self.com_dotted_as_name(nodelist[i]))
462-
n = Import(names)
461+
node = nodelist[3 + (nodelist[3][0] == token.LPAR)]
462+
n = From(fromname, self.com_import_as_names(node))
463463
n.lineno = nodelist[0][2]
464464
return n
465465

@@ -895,29 +895,41 @@ def com_dotted_name(self, node):
895895
return name[:-1]
896896

897897
def com_dotted_as_name(self, node):
898-
dot = self.com_dotted_name(node[1])
899-
if len(node) <= 2:
898+
assert node[0] == symbol.dotted_as_name
899+
node = node[1:]
900+
dot = self.com_dotted_name(node[0][1:])
901+
if len(node) == 1:
900902
return dot, None
901-
if node[0] == symbol.dotted_name:
902-
pass
903-
else:
904-
assert node[2][1] == 'as'
905-
assert node[3][0] == token.NAME
906-
return dot, node[3][1]
903+
assert node[1][1] == 'as'
904+
assert node[2][0] == token.NAME
905+
return dot, node[2][1]
906+
907+
def com_dotted_as_names(self, node):
908+
assert node[0] == symbol.dotted_as_names
909+
node = node[1:]
910+
names = [self.com_dotted_as_name(node[0])]
911+
for i in range(2, len(node), 2):
912+
names.append(self.com_dotted_as_name(node[i]))
913+
return names
907914

908915
def com_import_as_name(self, node):
909-
if node[0] == token.STAR:
910-
return '*', None
911916
assert node[0] == symbol.import_as_name
912917
node = node[1:]
918+
assert node[0][0] == token.NAME
913919
if len(node) == 1:
914-
assert node[0][0] == token.NAME
915920
return node[0][1], None
916-
917921
assert node[1][1] == 'as', node
918922
assert node[2][0] == token.NAME
919923
return node[0][1], node[2][1]
920924

925+
def com_import_as_names(self, node):
926+
assert node[0] == symbol.import_as_names
927+
node = node[1:]
928+
names = [self.com_import_as_name(node[0])]
929+
for i in range(2, len(node), 2):
930+
names.append(self.com_import_as_name(node[i]))
931+
return names
932+
921933
def com_bases(self, node):
922934
bases = []
923935
for i in range(1, len(node), 2):

Lib/symbol.py

Lines changed: 53 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -35,55 +35,59 @@
3535
yield_stmt = 278
3636
raise_stmt = 279
3737
import_stmt = 280
38-
import_as_name = 281
39-
dotted_as_name = 282
40-
dotted_name = 283
41-
global_stmt = 284
42-
exec_stmt = 285
43-
assert_stmt = 286
44-
compound_stmt = 287
45-
if_stmt = 288
46-
while_stmt = 289
47-
for_stmt = 290
48-
try_stmt = 291
49-
except_clause = 292
50-
suite = 293
51-
test = 294
52-
and_test = 295
53-
not_test = 296
54-
comparison = 297
55-
comp_op = 298
56-
expr = 299
57-
xor_expr = 300
58-
and_expr = 301
59-
shift_expr = 302
60-
arith_expr = 303
61-
term = 304
62-
factor = 305
63-
power = 306
64-
atom = 307
65-
listmaker = 308
66-
testlist_gexp = 309
67-
lambdef = 310
68-
trailer = 311
69-
subscriptlist = 312
70-
subscript = 313
71-
sliceop = 314
72-
exprlist = 315
73-
testlist = 316
74-
testlist_safe = 317
75-
dictmaker = 318
76-
classdef = 319
77-
arglist = 320
78-
argument = 321
79-
list_iter = 322
80-
list_for = 323
81-
list_if = 324
82-
gen_iter = 325
83-
gen_for = 326
84-
gen_if = 327
85-
testlist1 = 328
86-
encoding_decl = 329
38+
import_name = 281
39+
import_from = 282
40+
import_as_name = 283
41+
dotted_as_name = 284
42+
import_as_names = 285
43+
dotted_as_names = 286
44+
dotted_name = 287
45+
global_stmt = 288
46+
exec_stmt = 289
47+
assert_stmt = 290
48+
compound_stmt = 291
49+
if_stmt = 292
50+
while_stmt = 293
51+
for_stmt = 294
52+
try_stmt = 295
53+
except_clause = 296
54+
suite = 297
55+
test = 298
56+
and_test = 299
57+
not_test = 300
58+
comparison = 301
59+
comp_op = 302
60+
expr = 303
61+
xor_expr = 304
62+
and_expr = 305
63+
shift_expr = 306
64+
arith_expr = 307
65+
term = 308
66+
factor = 309
67+
power = 310
68+
atom = 311
69+
listmaker = 312
70+
testlist_gexp = 313
71+
lambdef = 314
72+
trailer = 315
73+
subscriptlist = 316
74+
subscript = 317
75+
sliceop = 318
76+
exprlist = 319
77+
testlist = 320
78+
testlist_safe = 321
79+
dictmaker = 322
80+
classdef = 323
81+
arglist = 324
82+
argument = 325
83+
list_iter = 326
84+
list_for = 327
85+
list_if = 328
86+
gen_iter = 329
87+
gen_for = 330
88+
gen_if = 331
89+
testlist1 = 332
90+
encoding_decl = 333
8791
#--end constants--
8892

8993
sym_name = {}

Lib/test/output/test_grammar

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ continue + try/finally ok
3535
testing continue and break in try/except in loop
3636
return_stmt
3737
raise_stmt
38-
import_stmt
38+
import_name
39+
import_from
3940
global_stmt
4041
exec_stmt
4142
assert_stmt

0 commit comments

Comments
 (0)