Skip to content

Commit f671204

Browse files
author
whitequark
committedMay 7, 2015
95% grammar coverage.
To go further it will be necessary to implement true LL(1) lookahead.
1 parent a4ede46 commit f671204

File tree

3 files changed

+361
-58
lines changed

3 files changed

+361
-58
lines changed
 

Diff for: ‎pyparser/ast.py

+23-11
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
from .shim import ast
1616
from .shim.ast import AST
1717

18+
# Location mixins
19+
1820
class commonloc(object):
1921
"""
2022
A mixin common for all nodes.
@@ -61,17 +63,21 @@ class beginendloc(commonloc):
6163
"""
6264
_locs = commonloc._locs + ('begin_loc', 'end_loc')
6365

64-
class alias(commonloc):
66+
# AST nodes
67+
68+
class alias(commonloc, ast.alias):
6569
"""
6670
An import alias, e.g. ``x as y``.
6771
6872
:ivar name: (string) value to import
6973
:ivar asname: (string) name to add to the environment
74+
:ivar name_loc: location of name
7075
:ivar as_loc: location of ``as``
76+
:ivar asname_loc: location of asname
7177
"""
72-
_locs = commonloc._locs + ('as_loc',)
78+
_locs = commonloc._locs + ('name_loc', 'as_loc', 'asname_loc')
7379

74-
class arguments(commonloc):
80+
class arguments(beginendloc, ast.arguments):
7581
"""
7682
Function definition arguments, e.g. in ``def f(x, y=1, *z, **t)``.
7783
@@ -85,6 +91,8 @@ class arguments(commonloc):
8591
:ivar kwarg_loc: location of keyword splat formal argument, if any
8692
:ivar default_equals_locs: locations of ``=``
8793
"""
94+
_locs = beginendloc._locs + ('star_loc', 'vararg_loc', 'dstar_loc',
95+
'vararg_loc', 'kwarg_loc', 'default_equals_locs')
8896

8997
class boolop:
9098
"""
@@ -241,10 +249,10 @@ class Lambda(expr, ast.Lambda):
241249
242250
:ivar args: (:class:`arguments`) arguments
243251
:ivar body: (node) body
244-
:ivar keyword_loc: location of ``lambda``
252+
:ivar lambda_loc: location of ``lambda``
245253
:ivar colon_loc: location of ``:``
246254
"""
247-
_locs = expr._locs + ('keyword_loc', 'colon_loc')
255+
_locs = expr._locs + ('lambda_loc', 'colon_loc')
248256
class List(beginendloc, expr, ast.List):
249257
"""
250258
A list, e.g. ``[x, y]``.
@@ -320,8 +328,9 @@ class Yield(expr, ast.Yield):
320328
A yield expression, e.g. ``(yield x)``.
321329
322330
:ivar value: (node) yielded value
331+
:ivar yield_loc: location of ``yield``
323332
"""
324-
_locs = expr._locs + ('keyword_loc',)
333+
_locs = expr._locs + ('yield_loc',)
325334

326335
# expr_context
327336
# AugLoad
@@ -507,7 +516,7 @@ class FunctionDef(keywordloc, stmt, ast.FunctionDef):
507516
:ivar colon_loc: location of ``:``, if any
508517
:ivar at_locs: locations of decorator ``@``
509518
"""
510-
_locs = keywordloc._locs + ('name_loc', 'colon_loc', 'at_loc')
519+
_locs = keywordloc._locs + ('name_loc', 'colon_loc', 'at_locs')
511520
class Global(keywordloc, stmt, ast.Global):
512521
"""
513522
The ``global x, y`` statement.
@@ -534,9 +543,10 @@ class Import(keywordloc, stmt, ast.Import):
534543
535544
:ivar names: (list of :class:`alias`) names
536545
"""
537-
class ImportFrom(keywordloc, stmt, ast.Import):
546+
class ImportFrom(keywordloc, stmt, ast.ImportFrom):
538547
"""
539-
The ``from ...x import y, z`` or ``from x import *`` statement.
548+
The ``from ...x import y, z`` or ``from x import (y, z)`` or
549+
``from x import *`` statement.
540550
541551
:ivar names: (list of :class:`alias`) names
542552
:ivar module: (string) module name, if any
@@ -545,8 +555,10 @@ class ImportFrom(keywordloc, stmt, ast.Import):
545555
:ivar dots_loc: location of dots, if any
546556
:ivar module_loc: location of module name, if any
547557
:ivar import_loc: location of ``import``
558+
:ivar lparen_loc: location of ``(``, if any
559+
:ivar rparen_loc: location of ``)``, if any
548560
"""
549-
_locs = keywordloc._locs + ('module_loc', 'import_loc')
561+
_locs = keywordloc._locs + ('dots_loc', 'module_loc', 'import_loc', 'lparen_loc', 'rparen_loc')
550562
class Pass(keywordloc, stmt, ast.Pass):
551563
"""The ``pass`` statement."""
552564
class Print(keywordloc, stmt, ast.Print):
@@ -582,7 +594,7 @@ class TryExcept(keywordloc, stmt, ast.TryExcept):
582594
:ivar else_colon_loc: location of ``:`` after ``else``
583595
"""
584596
_locs = keywordloc._locs + ('try_colon_loc', 'else_loc', 'else_colon_loc',)
585-
class TryFinally(keywordloc, stmt, ast.TryExcept):
597+
class TryFinally(keywordloc, stmt, ast.TryFinally):
586598
"""
587599
The ``try:· x·finally:· y`` statement.
588600

Diff for: ‎pyparser/parser.py

+86-44
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,8 @@ def rule(parser, begin_loc, node, end_loc):
280280
if node.loc is None and type(node) in [
281281
ast.List, ast.Dict, ast.Tuple, ast.Repr,
282282
ast.ListComp, ast.GeneratorExp,
283-
ast.Call, ast.Subscript]:
283+
ast.Call, ast.Subscript,
284+
ast.arguments]:
284285
node.begin_loc, node.end_loc, node.loc = \
285286
begin_loc, end_loc, begin_loc.join(end_loc)
286287
return node
@@ -318,8 +319,9 @@ def _assignable(self, node):
318319
return node
319320

320321
def _empty_arguments(self):
321-
# TODO
322-
return None
322+
return ast.arguments(args=[], defaults=[], vararg=None, kwarg=None,
323+
star_loc=None, vararg_loc=None, dstar_loc=None, kwarg_loc=None,
324+
default_equals_locs=[], begin_loc=None, end_loc=None, loc=None)
323325

324326
# Python-specific methods
325327
@action(Alt(Newline(),
@@ -344,13 +346,13 @@ def eval_input(self, expr):
344346

345347
@action(Seq(Loc('@'), Rule('dotted_name'), Opt(BeginEnd('(', Rule('arglist'), ')')),
346348
Loc('newline')))
347-
def decorator(at_loc, dotted_name, call_opt, newline_loc):
349+
def decorator(self, at_loc, dotted_name, call_opt, newline_loc):
348350
"""decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE"""
349351
name_loc, name = dotted_name
350-
expr = ast.Name(id=name, loc=name_loc)
352+
expr = ast.Name(id=name, ctx=None, loc=name_loc)
351353
if call_opt:
352354
call_opt.func = expr
353-
call_opt.loc = name_loc.join(arglist_opt.loc)
355+
call_opt.loc = name_loc.join(call_opt.loc)
354356
expr = call_opt
355357
return at_loc, expr
356358

@@ -361,16 +363,24 @@ def decorator(at_loc, dotted_name, call_opt, newline_loc):
361363
def decorated(self, decorators, classfuncdef):
362364
"""decorated: decorators (classdef | funcdef)"""
363365
classfuncdef.at_locs = list(map(lambda x: x[0], decorators))
364-
classfuncdef.decorator_list = list(map(lambda x: x[0], decorators))
366+
classfuncdef.decorator_list = list(map(lambda x: x[1], decorators))
367+
classfuncdef.loc = classfuncdef.loc.join(decorators[0][0])
365368
return classfuncdef
366369

367370
@action(Seq(Loc('def'), Tok('ident'), Rule('parameters'), Loc(':'), Rule('suite')))
368371
def funcdef(self, def_loc, ident_tok, args, colon_loc, suite):
369372
"""funcdef: 'def' NAME parameters ':' suite"""
370373
return ast.FunctionDef(name=ident_tok.value, args=args, body=suite, decorator_list=[],
371-
keyword_loc=def_loc, name_loc=ident_tok.value, colon_loc=colon_loc)
374+
at_locs=[], keyword_loc=def_loc, name_loc=ident_tok.loc,
375+
colon_loc=colon_loc, loc=def_loc.join(suite[-1].loc))
376+
377+
@action(Opt(Rule('varargslist')))
378+
def parameters_1(self, args):
379+
if args is None:
380+
args = self._empty_arguments()
381+
return args
372382

373-
parameters = BeginEnd('(', Rule('varargslist'), ')')
383+
parameters = BeginEnd('(', parameters_1, ')')
374384
"""parameters: '(' [varargslist] ')'"""
375385

376386
@action(Seq(Loc('**'), Tok('ident')))
@@ -389,7 +399,7 @@ def varargslist_2(self, star_loc, vararg_tok, kwarg_opt):
389399
star_loc=star_loc, vararg_loc=vararg_tok.loc,
390400
dstar_loc=dstar_loc, kwarg_loc=kwarg_loc)
391401

392-
pass
402+
varargslist = Tok('no')
393403
"""varargslist: ((fpdef ['=' test] ',')*
394404
('*' NAME [',' '**' NAME] | '**' NAME) |
395405
fpdef ['=' test] (',' fpdef ['=' test])* [','])"""
@@ -544,7 +554,7 @@ def raise_stmt(self, raise_loc, type_opt):
544554
def import_name(self, import_loc, names):
545555
"""import_name: 'import' dotted_as_names"""
546556
return ast.Import(names=names,
547-
keyword_loc=import_loc, loc=keyword_loc.join(names[-1].loc))
557+
keyword_loc=import_loc, loc=import_loc.join(names[-1].loc))
548558

549559
@action(Seq(Star(Loc('.')), Rule('dotted_name')))
550560
def import_from_1(self, dots, dotted_name):
@@ -556,45 +566,61 @@ def import_from_2(self, dots):
556566

557567
@action(Loc('*'))
558568
def import_from_3(self, star_loc):
559-
return [ast.alias(name='*', asname=None,
560-
name_loc=star_loc, as_loc=None, asname_loc=None, loc=star_loc)]
569+
return None, \
570+
[ast.alias(name='*', asname=None,
571+
name_loc=star_loc, as_loc=None, asname_loc=None, loc=star_loc)], \
572+
None
573+
574+
@action(Rule('import_as_names'))
575+
def import_from_4(self, names):
576+
return None, names, None
561577

562578
@action(Seq(Loc('from'), Alt(import_from_1, import_from_2),
563579
Loc('import'), Alt(import_from_3,
564-
BeginEnd('(', Rule('import_as_names'), ')'),
565-
Rule('import_as_names'))))
580+
Seq(Loc('('), Rule('import_as_names'), Loc(')')),
581+
import_from_4)))
566582
def import_from(self, from_loc, module_name, import_loc, names):
567583
"""import_from: ('from' ('.'* dotted_name | '.'+)
568584
'import' ('*' | '(' import_as_names ')' | import_as_names))"""
569585
dots, (module_loc, module) = module_name
586+
lparen_loc, names, rparen_loc = names
570587
dots_loc = None
571588
if dots != []:
572589
dots_loc = dots[0].join(dots[-1])
590+
loc = from_loc.join(names[-1].loc)
591+
if rparen_loc:
592+
loc = loc.join(rparen_loc)
573593
return ast.ImportFrom(names=names, module=module, level=len(dots),
574594
keyword_loc=from_loc, dots_loc=dots_loc, module_loc=module_loc,
575-
import_loc=import_loc)
595+
import_loc=import_loc, lparen_loc=lparen_loc, rparen_loc=rparen_loc,
596+
loc=loc)
576597

577598
@action(Seq(Tok('ident'), Opt(Seq(Loc('as'), Tok('ident')))))
578-
def import_as_name(self, name, as_name_opt):
599+
def import_as_name(self, name_tok, as_name_opt):
579600
"""import_as_name: NAME ['as' NAME]"""
580-
asname = as_loc = None
581-
loc = name.loc
601+
asname_name = asname_loc = as_loc = None
602+
loc = name_tok.loc
582603
if as_name_opt:
583-
asname, as_loc = as_name_opt
604+
as_loc, asname = as_name_opt
605+
asname_name = asname.value
606+
asname_loc = asname.loc
584607
loc = loc.join(asname.loc)
585-
return ast.alias(name=name.value, asname=asname.value,
586-
loc=loc, as_loc=as_loc)
608+
return ast.alias(name=name_tok.value, asname=asname_name,
609+
loc=loc, name_loc=name_tok.loc, as_loc=as_loc, asname_loc=asname_loc)
587610

588611
@action(Seq(Rule('dotted_name'), Opt(Seq(Loc('as'), Tok('ident')))))
589612
def dotted_as_name(self, dotted_name, as_name_opt):
590613
"""dotted_as_name: dotted_name ['as' NAME]"""
591-
asname = as_loc = None
592-
loc, name = dotted_name
614+
asname_name = asname_loc = as_loc = None
615+
dotted_name_loc, dotted_name_name = dotted_name
616+
loc = dotted_name_loc
593617
if as_name_opt:
594-
asname, as_loc = as_name_opt
618+
as_loc, asname = as_name_opt
619+
asname_name = asname.value
620+
asname_loc = asname.loc
595621
loc = loc.join(asname.loc)
596-
return ast.alias(name=name, asname=asname.value,
597-
loc=loc, as_loc=as_loc)
622+
return ast.alias(name=dotted_name_name, asname=asname_name,
623+
loc=loc, name_loc=dotted_name_loc, as_loc=as_loc, asname_loc=asname_loc)
598624

599625
import_as_names = List(Rule('import_as_name'), ',', trailing=True)
600626
"""import_as_names: import_as_name (',' import_as_name)* [',']"""
@@ -708,25 +734,31 @@ def try_stmt_1(self, clauses, else_opt, finally_opt):
708734
handlers = []
709735
for clause in clauses:
710736
handler, handler.colon_loc, handler.body = clause
737+
handler.loc = handler.loc.join(handler.body[-1].loc)
711738
handlers.append(handler)
712739

713740
else_loc = else_colon_loc = orelse = None
741+
loc = handlers[-1].loc
714742
if else_opt:
715743
else_loc, else_colon_loc, orelse = else_opt
744+
loc = orelse[-1].loc
716745

717-
stmt = ast.TryExcept(handlers=handlers, orelse=orelse,
718-
else_loc=else_loc, else_colon_loc=else_colon_loc)
746+
stmt = ast.TryExcept(body=None, handlers=handlers, orelse=orelse,
747+
else_loc=else_loc, else_colon_loc=else_colon_loc,
748+
loc=loc)
719749
if finally_opt:
720750
finally_loc, finally_colon_loc, finalbody = finally_opt
721751
return ast.TryFinally(body=[stmt], finalbody=finalbody,
722-
finally_loc=finally_loc, finally_colon_loc=finally_colon_loc)
752+
finally_loc=finally_loc, finally_colon_loc=finally_colon_loc,
753+
loc=finalbody[-1].loc)
723754
else:
724755
return stmt
725756

726757
@action(Seq(Loc('finally'), Loc(':'), Rule('suite')))
727758
def try_stmt_2(self, finally_loc, finally_colon_loc, finalbody):
728-
return ast.TryFinally(finalbody=finalbody,
729-
finally_loc=finally_loc, finally_colon_loc=finally_colon_loc)
759+
return ast.TryFinally(body=None, finalbody=finalbody,
760+
finally_loc=finally_loc, finally_colon_loc=finally_colon_loc,
761+
loc=finalbody[-1].loc)
730762

731763
@action(Seq(Loc('try'), Loc(':'), Rule('suite'), Alt(try_stmt_1, try_stmt_2)))
732764
def try_stmt(self, try_loc, try_colon_loc, body, stmt):
@@ -741,7 +773,10 @@ def try_stmt(self, try_loc, try_colon_loc, body, stmt):
741773
if stmt.body is None: # try..finally or try..except
742774
stmt.body = body
743775
else: # try..except..finally
744-
stmt.body.keyword_loc, stmt.body.try_colon_loc = try_loc, try_colon_loc
776+
stmt.body[0].keyword_loc, stmt.body[0].try_colon_loc, stmt.body[0].body = \
777+
try_loc, try_colon_loc, body
778+
stmt.body[0].loc = stmt.body[0].loc.join(try_loc)
779+
stmt.loc = stmt.loc.join(try_loc)
745780
return stmt
746781

747782
@action(Seq(Loc('with'), Rule('test'), Opt(Rule('with_var')), Loc(':'), Rule('suite')))
@@ -763,12 +798,15 @@ def with_stmt(self, with_loc, context, with_var, colon_loc, body):
763798
def except_clause(self, except_loc, exc_opt):
764799
"""except_clause: 'except' [test [('as' | ',') test]]"""
765800
type_ = name = as_loc = None
801+
loc = except_loc
766802
if exc_opt:
767803
type_, name_opt = exc_opt
804+
loc = loc.join(type_.loc)
768805
if name_opt:
769806
as_loc, name = name_opt
807+
loc = loc.join(name.loc)
770808
return ast.ExceptHandler(type=type_, name=name,
771-
except_loc=except_loc, as_loc=as_loc)
809+
except_loc=except_loc, as_loc=as_loc, loc=loc)
772810

773811
@action(Plus(Rule('stmt')))
774812
def suite_1(self, stmts):
@@ -785,13 +823,15 @@ def suite_1(self, stmts):
785823
old_test = Alt(Rule('or_test'), Rule('old_lambdef'))
786824
"""old_test: or_test | old_lambdef"""
787825

788-
@action(Seq(Loc('lambda'), Opt(Rule('varargslist')), Loc(':'), Rule(old_test)))
826+
@action(Seq(Loc('lambda'), Opt(Rule('varargslist')), Loc(':'), Rule('old_test')))
789827
def old_lambdef(self, lambda_loc, args_opt, colon_loc, body):
790828
"""old_lambdef: 'lambda' [varargslist] ':' old_test"""
791-
args = self._empty_arguments() if not args_opt else args_opt
792-
return ast.Lambda(args=args, body=body,
793-
loc=lambda_loc.join(body.loc),
794-
keyword_loc=lambda_loc, colon_loc=colon_loc)
829+
if args_opt is None:
830+
args_opt = self._empty_arguments()
831+
args_opt.loc = colon_loc.begin()
832+
return ast.Lambda(args=args_opt, body=body,
833+
lambda_loc=lambda_loc, colon_loc=colon_loc,
834+
loc=lambda_loc.join(body.loc))
795835
# 2.x-only backwards compatibility end
796836

797837
@action(Seq(Rule('or_test'), Opt(Seq(Loc('if'), Rule('or_test'),
@@ -974,10 +1014,12 @@ def testlist_gexp_2(self, elts):
9741014
@action(Seq(Loc('lambda'), Opt(Rule('varargslist')), Loc(':'), Rule('test')))
9751015
def lambdef(self, lambda_loc, args_opt, colon_loc, body):
9761016
"""lambdef: 'lambda' [varargslist] ':' test"""
977-
args = self._empty_arguments() if not args_opt else args_opt
978-
return ast.Lambda(args=args, body=body,
979-
loc=lambda_loc.join(body.loc),
980-
keyword_loc=lambda_loc, colon_loc=colon_loc)
1017+
if args_opt is None:
1018+
args_opt = self._empty_arguments()
1019+
args_opt.loc = colon_loc.begin()
1020+
return ast.Lambda(args=args_opt, body=body,
1021+
lambda_loc=lambda_loc, colon_loc=colon_loc,
1022+
loc=lambda_loc.join(body.loc))
9811023

9821024
@action(Seq(Loc('.'), Tok('ident')))
9831025
def trailer_1(self, dot_loc, ident_tok):
@@ -1230,7 +1272,7 @@ def compose(comprehensions):
12301272
def yield_expr(self, stmt_loc, exprs):
12311273
"""yield_expr: 'yield' [testlist]"""
12321274
return ast.Yield(value=exprs,
1233-
loc=stmt_loc.join(exprs.loc), keyword_loc=stmt_loc)
1275+
yield_loc=stmt_loc, loc=stmt_loc.join(exprs.loc))
12341276

12351277
def for_code(code, version=(2,7)):
12361278
return Parser(lexer.Lexer(source.Buffer(code), version))

Diff for: ‎pyparser/test/test_parser.py

+252-3
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def flatten_ast(self, node):
5151
flat_node[unicode(field)] = value
5252
return flat_node
5353

54-
_loc_re = re.compile(r"\s*([~^]+)\s+([a-z_0-9.]+)")
54+
_loc_re = re.compile(r"\s*([~^]*)<?\s+([a-z_0-9.]+)")
5555
_path_re = re.compile(r"(([a-z_]+)|([0-9]+))(\.)?")
5656

5757
def match_loc(self, ast, matcher, root=lambda x: x):
@@ -534,7 +534,7 @@ def test_yield_expr(self):
534534
self.assertParsesExpr(
535535
{'ty': 'Yield', 'value': self.ast_1},
536536
"(yield 1)",
537-
" ~~~~~ keyword_loc"
537+
" ~~~~~ yield_loc"
538538
" ~~~~~~~ loc")
539539

540540
def test_if_expr(self):
@@ -545,6 +545,34 @@ def test_if_expr(self):
545545
" ~~~~ else_loc"
546546
"~~~~~~~~~~~~~ loc")
547547

548+
def test_lambda(self):
549+
self.assertParsesExpr(
550+
{'ty': 'Lambda',
551+
'args': {'ty': 'arguments', 'args': [], 'defaults': [],
552+
'kwarg': None, 'vararg': None},
553+
'body': self.ast_x},
554+
"lambda: x",
555+
"~~~~~~ lambda_loc"
556+
" < args.loc"
557+
" ^ colon_loc"
558+
"~~~~~~~~~ loc")
559+
560+
def test_old_lambda(self):
561+
self.assertParsesExpr(
562+
{'ty': 'ListComp', 'elt': self.ast_x, 'generators': [
563+
{'ty': 'comprehension', 'iter': self.ast_z, 'target': self.ast_y,
564+
'ifs': [{'ty': 'Lambda',
565+
'args': {'ty': 'arguments', 'args': [], 'defaults': [],
566+
'kwarg': None, 'vararg': None},
567+
'body': self.ast_t}
568+
]}
569+
]},
570+
"[x for y in z if lambda: t]",
571+
" ~~~~~~ generators.0.ifs.0.lambda_loc"
572+
" < generators.0.ifs.0.args.loc"
573+
" ^ generators.0.ifs.0.colon_loc"
574+
" ~~~~~~~~~ generators.0.ifs.0.loc")
575+
548576
#
549577
# CALLS, ATTRIBUTES AND SUBSCRIPTS
550578
#
@@ -836,7 +864,7 @@ def test_yield(self):
836864
self.assertParsesSuite(
837865
[{'ty': 'Expr', 'value': {'ty': 'Yield', 'value': self.ast_x}}],
838866
"yield x",
839-
"~~~~~ 0.value.keyword_loc"
867+
"~~~~~ 0.value.yield_loc"
840868
"~~~~~~~ 0.value.loc"
841869
"~~~~~~~ 0.loc")
842870

@@ -865,6 +893,103 @@ def test_raise(self):
865893
"~~~~~ 0.keyword_loc"
866894
"~~~~~~~~~~~~~ 0.loc")
867895

896+
def test_import(self):
897+
self.assertParsesSuite(
898+
[{'ty': 'Import', 'names': [
899+
{'ty': 'alias', 'name': 'foo', 'asname': None}
900+
]}],
901+
"import foo",
902+
"~~~~~~ 0.keyword_loc"
903+
" ~~~ 0.names.0.name_loc"
904+
" ~~~ 0.names.0.loc"
905+
"~~~~~~~~~~ 0.loc")
906+
907+
self.assertParsesSuite(
908+
[{'ty': 'Import', 'names': [
909+
{'ty': 'alias', 'name': 'foo.bar', 'asname': None}
910+
]}],
911+
"import foo. bar",
912+
"~~~~~~ 0.keyword_loc"
913+
" ~~~~~~~~ 0.names.0.name_loc"
914+
" ~~~~~~~~ 0.names.0.loc"
915+
"~~~~~~~~~~~~~~~ 0.loc")
916+
917+
self.assertParsesSuite(
918+
[{'ty': 'Import', 'names': [
919+
{'ty': 'alias', 'name': 'foo', 'asname': 'bar'}
920+
]}],
921+
"import foo as bar",
922+
"~~~~~~ 0.keyword_loc"
923+
" ~~~ 0.names.0.name_loc"
924+
" ~~ 0.names.0.as_loc"
925+
" ~~~ 0.names.0.asname_loc"
926+
" ~~~~~~~~~~ 0.names.0.loc"
927+
"~~~~~~~~~~~~~~~~~ 0.loc")
928+
929+
def test_from(self):
930+
self.assertParsesSuite(
931+
[{'ty': 'ImportFrom', 'names': [
932+
{'ty': 'alias', 'name': 'foo', 'asname': None}
933+
], 'module': 'bar', 'level': 0}],
934+
"from bar import foo",
935+
"~~~~ 0.keyword_loc"
936+
" ~~~ 0.module_loc"
937+
" ~~~~~~ 0.import_loc"
938+
" ~~~ 0.names.0.name_loc"
939+
" ~~~ 0.names.0.loc"
940+
"~~~~~~~~~~~~~~~~~~~ 0.loc")
941+
942+
self.assertParsesSuite(
943+
[{'ty': 'ImportFrom', 'names': [
944+
{'ty': 'alias', 'name': 'foo', 'asname': None}
945+
], 'module': 'bar', 'level': 2}],
946+
"from ..bar import foo",
947+
"~~~~ 0.keyword_loc"
948+
" ~~ 0.dots_loc"
949+
" ~~~ 0.module_loc"
950+
" ~~~~~~ 0.import_loc"
951+
" ~~~ 0.names.0.name_loc"
952+
" ~~~ 0.names.0.loc"
953+
"~~~~~~~~~~~~~~~~~~~~~ 0.loc")
954+
955+
self.assertParsesSuite(
956+
[{'ty': 'ImportFrom', 'names': [
957+
{'ty': 'alias', 'name': 'foo', 'asname': 'bar'}
958+
], 'module': 'bar', 'level': 2}],
959+
"from ..bar import foo as bar",
960+
" ~~~ 0.names.0.name_loc"
961+
" ~~ 0.names.0.as_loc"
962+
" ~~~ 0.names.0.asname_loc"
963+
" ~~~~~~~~~~ 0.names.0.loc"
964+
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0.loc")
965+
966+
self.assertParsesSuite(
967+
[{'ty': 'ImportFrom', 'names': [
968+
{'ty': 'alias', 'name': 'foo', 'asname': None}
969+
], 'module': 'bar', 'level': 2}],
970+
"from ..bar import (foo)",
971+
" ^ 0.lparen_loc"
972+
" ~~~ 0.names.0.loc"
973+
" ^ 0.rparen_loc"
974+
"~~~~~~~~~~~~~~~~~~~~~~~ 0.loc")
975+
976+
self.assertParsesSuite(
977+
[{'ty': 'ImportFrom', 'names': [
978+
{'ty': 'alias', 'name': '*', 'asname': None}
979+
], 'module': 'bar', 'level': 0}],
980+
"from bar import *",
981+
" ^ 0.names.0.name_loc"
982+
" ^ 0.names.0.loc"
983+
"~~~~~~~~~~~~~~~~~ 0.loc")
984+
985+
# self.assertParsesSuite(
986+
# [{'ty': 'ImportFrom', 'names': [
987+
# {'ty': 'alias', 'name': 'foo', 'asname': None}
988+
# ], 'module': None, 'level': 2}],
989+
# "from .. import foo",
990+
# " ~~ 0.dots_loc"
991+
# "~~~~~~~~~~~~~~~~~~ 0.loc")
992+
868993
def test_global(self):
869994
self.assertParsesSuite(
870995
[{'ty': 'Global', 'names': ['x', 'y']}],
@@ -981,6 +1106,86 @@ def test_for(self):
9811106
" ^ 0.else_colon_loc"
9821107
"~~~~~~~~~~~~~~~~~~~~~~~~~ 0.loc")
9831108

1109+
def test_try(self):
1110+
self.assertParsesSuite(
1111+
[{'ty': 'TryExcept', 'body': [self.ast_expr_1], 'orelse': None,
1112+
'handlers': [
1113+
{'ty': 'ExceptHandler', 'type': None, 'name': None,
1114+
'body': [self.ast_expr_2]}
1115+
]}],
1116+
"try:· 1·except:· 2",
1117+
"~~~ 0.keyword_loc"
1118+
" ^ 0.try_colon_loc"
1119+
" ~~~~~~ 0.handlers.0.except_loc"
1120+
" ^ 0.handlers.0.colon_loc"
1121+
" ~~~~~~~~~~~ 0.handlers.0.loc"
1122+
"~~~~~~~~~~~~~~~~~~~~ 0.loc")
1123+
1124+
self.assertParsesSuite(
1125+
[{'ty': 'TryExcept', 'body': [self.ast_expr_1], 'orelse': None,
1126+
'handlers': [
1127+
{'ty': 'ExceptHandler', 'type': self.ast_y, 'name': None,
1128+
'body': [self.ast_expr_2]}
1129+
]}],
1130+
"try:· 1·except y:· 2",
1131+
"")
1132+
1133+
self.assertParsesSuite(
1134+
[{'ty': 'TryExcept', 'body': [self.ast_expr_1], 'orelse': None,
1135+
'handlers': [
1136+
{'ty': 'ExceptHandler', 'type': self.ast_y, 'name': self.ast_t,
1137+
'body': [self.ast_expr_2]}
1138+
]}],
1139+
"try:· 1·except y as t:· 2",
1140+
" ~~ 0.handlers.0.as_loc")
1141+
1142+
self.assertParsesSuite(
1143+
[{'ty': 'TryExcept', 'body': [self.ast_expr_1], 'orelse': None,
1144+
'handlers': [
1145+
{'ty': 'ExceptHandler', 'type': self.ast_y, 'name': self.ast_t,
1146+
'body': [self.ast_expr_2]}
1147+
]}],
1148+
"try:· 1·except y, t:· 2",
1149+
" ^ 0.handlers.0.as_loc")
1150+
1151+
self.assertParsesSuite(
1152+
[{'ty': 'TryExcept', 'body': [self.ast_expr_1], 'orelse': [self.ast_expr_3],
1153+
'handlers': [
1154+
{'ty': 'ExceptHandler', 'type': None, 'name': None,
1155+
'body': [self.ast_expr_2]}
1156+
]}],
1157+
"try:· 1·except:· 2·else:· 3",
1158+
" ~~~~ 0.else_loc"
1159+
" ^ 0.else_colon_loc"
1160+
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0.loc")
1161+
1162+
def test_finally(self):
1163+
self.assertParsesSuite(
1164+
[{'ty': 'TryFinally', 'body': [self.ast_expr_1], 'finalbody': [self.ast_expr_2]}],
1165+
"try:· 1·finally:· 2",
1166+
"~~~ 0.keyword_loc"
1167+
" ^ 0.try_colon_loc"
1168+
" ~~~~~~~ 0.finally_loc"
1169+
" ^ 0.finally_colon_loc"
1170+
"~~~~~~~~~~~~~~~~~~~~~ 0.loc")
1171+
1172+
self.assertParsesSuite(
1173+
[{'ty': 'TryFinally', 'finalbody': [self.ast_expr_3], 'body': [
1174+
{'ty': 'TryExcept', 'body': [self.ast_expr_1], 'orelse': None, 'handlers': [
1175+
{'ty': 'ExceptHandler', 'type': None, 'name': None,
1176+
'body': [self.ast_expr_2]}
1177+
]}
1178+
]}],
1179+
"try:· 1·except:· 2·finally:· 3",
1180+
"~~~ 0.keyword_loc"
1181+
" ^ 0.try_colon_loc"
1182+
"~~~ 0.body.0.keyword_loc"
1183+
" ^ 0.body.0.try_colon_loc"
1184+
"~~~~~~~~~~~~~~~~~~~~ 0.body.0.loc"
1185+
" ~~~~~~~ 0.finally_loc"
1186+
" ^ 0.finally_colon_loc"
1187+
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0.loc")
1188+
9841189
def test_with(self):
9851190
self.assertParsesSuite(
9861191
[{'ty': 'With', 'context_expr': self.ast_x, 'optional_vars': None,
@@ -1015,6 +1220,50 @@ def test_class(self):
10151220
" ^ 0.rparen_loc"
10161221
"~~~~~~~~~~~~~~~~~~~~~ 0.loc")
10171222

1223+
def test_func(self):
1224+
self.assertParsesSuite(
1225+
[{'ty': 'FunctionDef', 'name': 'foo',
1226+
'args': {'ty': 'arguments', 'args': [], 'defaults': [],
1227+
'kwarg': None, 'vararg': None},
1228+
'body': [{'ty': 'Pass'}], 'decorator_list': []}],
1229+
"def foo():· pass",
1230+
"~~~ 0.keyword_loc"
1231+
" ~~~ 0.name_loc"
1232+
" ^ 0.args.begin_loc"
1233+
" ^ 0.args.end_loc"
1234+
" ^ 0.colon_loc"
1235+
"~~~~~~~~~~~~~~~~~ 0.loc")
1236+
1237+
def test_decorated(self):
1238+
self.assertParsesSuite(
1239+
[{'ty': 'ClassDef', 'name': 'x', 'bases': [],
1240+
'body': [{'ty': 'Pass'}], 'decorator_list': [self.ast_x]}],
1241+
"@x·class x:· pass",
1242+
"^ 0.at_locs.0"
1243+
" ^ 0.decorator_list.0.loc"
1244+
"~~~~~~~~~~~~~~~~~~ 0.loc")
1245+
1246+
self.assertParsesSuite(
1247+
[{'ty': 'ClassDef', 'name': 'x', 'bases': [],
1248+
'body': [{'ty': 'Pass'}], 'decorator_list': [
1249+
{'ty': 'Call', 'func': self.ast_x,
1250+
'args': [self.ast_1], 'keywords': [], 'kwargs': None, 'starargs': None}
1251+
]}],
1252+
"@x(1)·class x:· pass",
1253+
"^ 0.at_locs.0"
1254+
" ~~~~ 0.decorator_list.0.loc"
1255+
"~~~~~~~~~~~~~~~~~~~~~ 0.loc")
1256+
1257+
self.assertParsesSuite(
1258+
[{'ty': 'FunctionDef', 'name': 'x',
1259+
'args': {'ty': 'arguments', 'args': [], 'defaults': [],
1260+
'kwarg': None, 'vararg': None},
1261+
'body': [{'ty': 'Pass'}], 'decorator_list': [self.ast_x]}],
1262+
"@x·def x():· pass",
1263+
"^ 0.at_locs.0"
1264+
" ^ 0.decorator_list.0.loc"
1265+
"~~~~~~~~~~~~~~~~~~ 0.loc")
1266+
10181267
#
10191268
# PARSING MODES
10201269
#

0 commit comments

Comments
 (0)
Please sign in to comment.