diff options
author | Anthony Baxter <anthonybaxter@gmail.com> | 2004-08-31 10:07:13 (GMT) |
---|---|---|
committer | Anthony Baxter <anthonybaxter@gmail.com> | 2004-08-31 10:07:13 (GMT) |
commit | 1a4ddaecc732c207fa69890db87ac4b47da867b8 (patch) | |
tree | 3c0c9c3086bc1c5ac72554e8ce6a03773cdc8770 /Lib | |
parent | 876032e5700f58cec44a357b6d3174be76b40278 (diff) | |
download | cpython-1a4ddaecc732c207fa69890db87ac4b47da867b8.zip cpython-1a4ddaecc732c207fa69890db87ac4b47da867b8.tar.gz cpython-1a4ddaecc732c207fa69890db87ac4b47da867b8.tar.bz2 |
SF patch #1007189, multi-line imports, for instance:
"from blah import (foo, bar
baz, bongo)"
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/compiler/transformer.py | 76 | ||||
-rwxr-xr-x | Lib/symbol.py | 102 | ||||
-rw-r--r-- | Lib/test/output/test_grammar | 3 | ||||
-rw-r--r-- | Lib/test/test_compile.py | 41 | ||||
-rw-r--r-- | Lib/test/test_grammar.py | 6 | ||||
-rw-r--r-- | Lib/test/test_parser.py | 14 |
6 files changed, 159 insertions, 83 deletions
diff --git a/Lib/compiler/transformer.py b/Lib/compiler/transformer.py index cdeb5ff..9fb18c2 100644 --- a/Lib/compiler/transformer.py +++ b/Lib/compiler/transformer.py @@ -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): diff --git a/Lib/symbol.py b/Lib/symbol.py index cb57208..eaf5a25 100755 --- a/Lib/symbol.py +++ b/Lib/symbol.py @@ -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 = {} diff --git a/Lib/test/output/test_grammar b/Lib/test/output/test_grammar index 00fab49..6174e7a 100644 --- a/Lib/test/output/test_grammar +++ b/Lib/test/output/test_grammar @@ -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 diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index b1644cb..5011d03 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -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) diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py index e0d5b74..7f5d10d 100644 --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -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(): diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py index 978ce57..0f8c1d0 100644 --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -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") |