mirror of
https://github.com/davidhalter/parso.git
synced 2026-05-25 09:48:53 +08:00
comp_for is now called sync_comp_for for all Python versions to be compatible with the Python 3.8 Grammar
This commit is contained in:
+3
-1
@@ -3,9 +3,11 @@
|
|||||||
Changelog
|
Changelog
|
||||||
---------
|
---------
|
||||||
|
|
||||||
0.4.1 (2019-06-05)
|
0.5.0 (2019-06-05)
|
||||||
++++++++++++++++++
|
++++++++++++++++++
|
||||||
|
|
||||||
|
- **Breaking Change** comp_for is now called sync_comp_for for all Python
|
||||||
|
versions to be compatible with the Python 3.8 Grammar
|
||||||
- Added .pyi stubs for a lot of the parso API
|
- Added .pyi stubs for a lot of the parso API
|
||||||
- Small FileIO changes
|
- Small FileIO changes
|
||||||
|
|
||||||
|
|||||||
+2
-3
@@ -41,8 +41,8 @@ class Normalizer(use_metaclass(_NormalizerMeta)):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
return self.visit_leaf(node)
|
return self.visit_leaf(node)
|
||||||
else:
|
else:
|
||||||
with self.visit_node(node):
|
with self.visit_node(node):
|
||||||
return ''.join(self.visit(child) for child in children)
|
return ''.join(self.visit(child) for child in children)
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def visit_node(self, node):
|
def visit_node(self, node):
|
||||||
@@ -147,7 +147,6 @@ class Issue(object):
|
|||||||
return '<%s: %s>' % (self.__class__.__name__, self.code)
|
return '<%s: %s>' % (self.__class__.__name__, self.code)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Rule(object):
|
class Rule(object):
|
||||||
code = None
|
code = None
|
||||||
message = None
|
message = None
|
||||||
|
|||||||
@@ -953,20 +953,17 @@ class _CheckAssignmentRule(SyntaxRule):
|
|||||||
self.add_issue(node, message=message)
|
self.add_issue(node, message=message)
|
||||||
|
|
||||||
|
|
||||||
@ErrorFinder.register_rule(type='comp_for')
|
|
||||||
@ErrorFinder.register_rule(type='sync_comp_for')
|
@ErrorFinder.register_rule(type='sync_comp_for')
|
||||||
class _CompForRule(_CheckAssignmentRule):
|
class _CompForRule(_CheckAssignmentRule):
|
||||||
message = "asynchronous comprehension outside of an asynchronous function"
|
message = "asynchronous comprehension outside of an asynchronous function"
|
||||||
|
|
||||||
def is_issue(self, node):
|
def is_issue(self, node):
|
||||||
# Some of the nodes here are already used, so no else if
|
expr_list = node.children[1]
|
||||||
if node.type != 'comp_for' or self._normalizer.version < (3, 8):
|
print(expr_list)
|
||||||
# comp_for was replaced by sync_comp_for in Python 3.8.
|
if expr_list.type != 'expr_list': # Already handled.
|
||||||
expr_list = node.children[1 + int(node.children[0] == 'async')]
|
self._check_assignment(expr_list)
|
||||||
if expr_list.type != 'expr_list': # Already handled.
|
|
||||||
self._check_assignment(expr_list)
|
|
||||||
|
|
||||||
return node.children[0] == 'async' \
|
return node.parent.children[0] == 'async' \
|
||||||
and not self._normalizer.context.is_async_funcdef()
|
and not self._normalizer.context.is_async_funcdef()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ atom: ('(' [yield_expr|testlist_comp] ')' |
|
|||||||
NAME | NUMBER | strings)
|
NAME | NUMBER | strings)
|
||||||
strings: STRING+
|
strings: STRING+
|
||||||
listmaker: test ( list_for | (',' test)* [','] )
|
listmaker: test ( list_for | (',' test)* [','] )
|
||||||
testlist_comp: test ( comp_for | (',' test)* [','] )
|
testlist_comp: test ( sync_comp_for | (',' test)* [','] )
|
||||||
lambdef: 'lambda' [varargslist] ':' test
|
lambdef: 'lambda' [varargslist] ':' test
|
||||||
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
|
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
|
||||||
subscriptlist: subscript (',' subscript)* [',']
|
subscriptlist: subscript (',' subscript)* [',']
|
||||||
@@ -115,8 +115,8 @@ subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop]
|
|||||||
sliceop: ':' [test]
|
sliceop: ':' [test]
|
||||||
exprlist: expr (',' expr)* [',']
|
exprlist: expr (',' expr)* [',']
|
||||||
testlist: test (',' test)* [',']
|
testlist: test (',' test)* [',']
|
||||||
dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
|
dictorsetmaker: ( (test ':' test (sync_comp_for | (',' test ':' test)* [','])) |
|
||||||
(test (comp_for | (',' test)* [','])) )
|
(test (sync_comp_for | (',' test)* [','])) )
|
||||||
|
|
||||||
classdef: 'class' NAME ['(' [testlist] ')'] ':' suite
|
classdef: 'class' NAME ['(' [testlist] ')'] ':' suite
|
||||||
|
|
||||||
@@ -125,14 +125,14 @@ arglist: (argument ',')* (argument [',']
|
|||||||
|'**' test)
|
|'**' test)
|
||||||
# The reason that keywords are test nodes instead of NAME is that using NAME
|
# The reason that keywords are test nodes instead of NAME is that using NAME
|
||||||
# results in an ambiguity. ast.c makes sure it's a NAME.
|
# results in an ambiguity. ast.c makes sure it's a NAME.
|
||||||
argument: test [comp_for] | test '=' test
|
argument: test [sync_comp_for] | test '=' test
|
||||||
|
|
||||||
list_iter: list_for | list_if
|
list_iter: list_for | list_if
|
||||||
list_for: 'for' exprlist 'in' testlist_safe [list_iter]
|
list_for: 'for' exprlist 'in' testlist_safe [list_iter]
|
||||||
list_if: 'if' old_test [list_iter]
|
list_if: 'if' old_test [list_iter]
|
||||||
|
|
||||||
comp_iter: comp_for | comp_if
|
comp_iter: sync_comp_for | comp_if
|
||||||
comp_for: 'for' exprlist 'in' or_test [comp_iter]
|
sync_comp_for: 'for' exprlist 'in' or_test [comp_iter]
|
||||||
comp_if: 'if' old_test [comp_iter]
|
comp_if: 'if' old_test [comp_iter]
|
||||||
|
|
||||||
testlist1: test (',' test)*
|
testlist1: test (',' test)*
|
||||||
|
|||||||
@@ -105,15 +105,15 @@ atom: ('(' [yield_expr|testlist_comp] ')' |
|
|||||||
'{' [dictorsetmaker] '}' |
|
'{' [dictorsetmaker] '}' |
|
||||||
NAME | NUMBER | strings | '...' | 'None' | 'True' | 'False')
|
NAME | NUMBER | strings | '...' | 'None' | 'True' | 'False')
|
||||||
strings: STRING+
|
strings: STRING+
|
||||||
testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
|
testlist_comp: (test|star_expr) ( sync_comp_for | (',' (test|star_expr))* [','] )
|
||||||
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
|
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
|
||||||
subscriptlist: subscript (',' subscript)* [',']
|
subscriptlist: subscript (',' subscript)* [',']
|
||||||
subscript: test | [test] ':' [test] [sliceop]
|
subscript: test | [test] ':' [test] [sliceop]
|
||||||
sliceop: ':' [test]
|
sliceop: ':' [test]
|
||||||
exprlist: (expr|star_expr) (',' (expr|star_expr))* [',']
|
exprlist: (expr|star_expr) (',' (expr|star_expr))* [',']
|
||||||
testlist: test (',' test)* [',']
|
testlist: test (',' test)* [',']
|
||||||
dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
|
dictorsetmaker: ( (test ':' test (sync_comp_for | (',' test ':' test)* [','])) |
|
||||||
(test (comp_for | (',' test)* [','])) )
|
(test (sync_comp_for | (',' test)* [','])) )
|
||||||
|
|
||||||
classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
|
classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
|
||||||
|
|
||||||
@@ -122,9 +122,9 @@ arglist: (argument ',')* (argument [',']
|
|||||||
|'**' test)
|
|'**' test)
|
||||||
# The reason that keywords are test nodes instead of NAME is that using NAME
|
# The reason that keywords are test nodes instead of NAME is that using NAME
|
||||||
# results in an ambiguity. ast.c makes sure it's a NAME.
|
# results in an ambiguity. ast.c makes sure it's a NAME.
|
||||||
argument: test [comp_for] | test '=' test # Really [keyword '='] test
|
argument: test [sync_comp_for] | test '=' test # Really [keyword '='] test
|
||||||
comp_iter: comp_for | comp_if
|
comp_iter: sync_comp_for | comp_if
|
||||||
comp_for: 'for' exprlist 'in' or_test [comp_iter]
|
sync_comp_for: 'for' exprlist 'in' or_test [comp_iter]
|
||||||
comp_if: 'if' test_nocond [comp_iter]
|
comp_if: 'if' test_nocond [comp_iter]
|
||||||
|
|
||||||
# not used in grammar, but may appear in "node" passed from Parser to Compiler
|
# not used in grammar, but may appear in "node" passed from Parser to Compiler
|
||||||
|
|||||||
@@ -105,15 +105,15 @@ atom: ('(' [yield_expr|testlist_comp] ')' |
|
|||||||
'{' [dictorsetmaker] '}' |
|
'{' [dictorsetmaker] '}' |
|
||||||
NAME | NUMBER | strings | '...' | 'None' | 'True' | 'False')
|
NAME | NUMBER | strings | '...' | 'None' | 'True' | 'False')
|
||||||
strings: STRING+
|
strings: STRING+
|
||||||
testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
|
testlist_comp: (test|star_expr) ( sync_comp_for | (',' (test|star_expr))* [','] )
|
||||||
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
|
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
|
||||||
subscriptlist: subscript (',' subscript)* [',']
|
subscriptlist: subscript (',' subscript)* [',']
|
||||||
subscript: test | [test] ':' [test] [sliceop]
|
subscript: test | [test] ':' [test] [sliceop]
|
||||||
sliceop: ':' [test]
|
sliceop: ':' [test]
|
||||||
exprlist: (expr|star_expr) (',' (expr|star_expr))* [',']
|
exprlist: (expr|star_expr) (',' (expr|star_expr))* [',']
|
||||||
testlist: test (',' test)* [',']
|
testlist: test (',' test)* [',']
|
||||||
dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
|
dictorsetmaker: ( (test ':' test (sync_comp_for | (',' test ':' test)* [','])) |
|
||||||
(test (comp_for | (',' test)* [','])) )
|
(test (sync_comp_for | (',' test)* [','])) )
|
||||||
|
|
||||||
classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
|
classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
|
||||||
|
|
||||||
@@ -122,9 +122,9 @@ arglist: (argument ',')* (argument [',']
|
|||||||
|'**' test)
|
|'**' test)
|
||||||
# The reason that keywords are test nodes instead of NAME is that using NAME
|
# The reason that keywords are test nodes instead of NAME is that using NAME
|
||||||
# results in an ambiguity. ast.c makes sure it's a NAME.
|
# results in an ambiguity. ast.c makes sure it's a NAME.
|
||||||
argument: test [comp_for] | test '=' test # Really [keyword '='] test
|
argument: test [sync_comp_for] | test '=' test # Really [keyword '='] test
|
||||||
comp_iter: comp_for | comp_if
|
comp_iter: sync_comp_for | comp_if
|
||||||
comp_for: 'for' exprlist 'in' or_test [comp_iter]
|
sync_comp_for: 'for' exprlist 'in' or_test [comp_iter]
|
||||||
comp_if: 'if' test_nocond [comp_iter]
|
comp_if: 'if' test_nocond [comp_iter]
|
||||||
|
|
||||||
# not used in grammar, but may appear in "node" passed from Parser to Compiler
|
# not used in grammar, but may appear in "node" passed from Parser to Compiler
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ atom: ('(' [yield_expr|testlist_comp] ')' |
|
|||||||
'{' [dictorsetmaker] '}' |
|
'{' [dictorsetmaker] '}' |
|
||||||
NAME | NUMBER | strings | '...' | 'None' | 'True' | 'False')
|
NAME | NUMBER | strings | '...' | 'None' | 'True' | 'False')
|
||||||
strings: STRING+
|
strings: STRING+
|
||||||
testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
|
testlist_comp: (test|star_expr) ( sync_comp_for | (',' (test|star_expr))* [','] )
|
||||||
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
|
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
|
||||||
subscriptlist: subscript (',' subscript)* [',']
|
subscriptlist: subscript (',' subscript)* [',']
|
||||||
subscript: test | [test] ':' [test] [sliceop]
|
subscript: test | [test] ':' [test] [sliceop]
|
||||||
@@ -120,9 +120,9 @@ sliceop: ':' [test]
|
|||||||
exprlist: (expr|star_expr) (',' (expr|star_expr))* [',']
|
exprlist: (expr|star_expr) (',' (expr|star_expr))* [',']
|
||||||
testlist: test (',' test)* [',']
|
testlist: test (',' test)* [',']
|
||||||
dictorsetmaker: ( ((test ':' test | '**' expr)
|
dictorsetmaker: ( ((test ':' test | '**' expr)
|
||||||
(comp_for | (',' (test ':' test | '**' expr))* [','])) |
|
(sync_comp_for | (',' (test ':' test | '**' expr))* [','])) |
|
||||||
((test | star_expr)
|
((test | star_expr)
|
||||||
(comp_for | (',' (test | star_expr))* [','])) )
|
(sync_comp_for | (',' (test | star_expr))* [','])) )
|
||||||
|
|
||||||
classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
|
classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
|
||||||
|
|
||||||
@@ -137,13 +137,13 @@ arglist: argument (',' argument)* [',']
|
|||||||
# Illegal combinations and orderings are blocked in ast.c:
|
# Illegal combinations and orderings are blocked in ast.c:
|
||||||
# multiple (test comp_for) arguments are blocked; keyword unpackings
|
# multiple (test comp_for) arguments are blocked; keyword unpackings
|
||||||
# that precede iterable unpackings are blocked; etc.
|
# that precede iterable unpackings are blocked; etc.
|
||||||
argument: ( test [comp_for] |
|
argument: ( test [sync_comp_for] |
|
||||||
test '=' test |
|
test '=' test |
|
||||||
'**' test |
|
'**' test |
|
||||||
'*' test )
|
'*' test )
|
||||||
|
|
||||||
comp_iter: comp_for | comp_if
|
comp_iter: sync_comp_for | comp_if
|
||||||
comp_for: 'for' exprlist 'in' or_test [comp_iter]
|
sync_comp_for: 'for' exprlist 'in' or_test [comp_iter]
|
||||||
comp_if: 'if' test_nocond [comp_iter]
|
comp_if: 'if' test_nocond [comp_iter]
|
||||||
|
|
||||||
# not used in grammar, but may appear in "node" passed from Parser to Compiler
|
# not used in grammar, but may appear in "node" passed from Parser to Compiler
|
||||||
|
|||||||
@@ -140,7 +140,8 @@ argument: ( test [comp_for] |
|
|||||||
'*' test )
|
'*' test )
|
||||||
|
|
||||||
comp_iter: comp_for | comp_if
|
comp_iter: comp_for | comp_if
|
||||||
comp_for: ['async'] 'for' exprlist 'in' or_test [comp_iter]
|
sync_comp_for: 'for' exprlist 'in' or_test [comp_iter]
|
||||||
|
comp_for: ['async'] sync_comp_for
|
||||||
comp_if: 'if' test_nocond [comp_iter]
|
comp_if: 'if' test_nocond [comp_iter]
|
||||||
|
|
||||||
# not used in grammar, but may appear in "node" passed from Parser to Compiler
|
# not used in grammar, but may appear in "node" passed from Parser to Compiler
|
||||||
|
|||||||
@@ -138,7 +138,8 @@ argument: ( test [comp_for] |
|
|||||||
'*' test )
|
'*' test )
|
||||||
|
|
||||||
comp_iter: comp_for | comp_if
|
comp_iter: comp_for | comp_if
|
||||||
comp_for: ['async'] 'for' exprlist 'in' or_test [comp_iter]
|
sync_comp_for: 'for' exprlist 'in' or_test [comp_iter]
|
||||||
|
comp_for: ['async'] sync_comp_for
|
||||||
comp_if: 'if' test_nocond [comp_iter]
|
comp_if: 'if' test_nocond [comp_iter]
|
||||||
|
|
||||||
# not used in grammar, but may appear in "node" passed from Parser to Compiler
|
# not used in grammar, but may appear in "node" passed from Parser to Compiler
|
||||||
|
|||||||
@@ -39,13 +39,13 @@ class Parser(BaseParser):
|
|||||||
'for_stmt': tree.ForStmt,
|
'for_stmt': tree.ForStmt,
|
||||||
'while_stmt': tree.WhileStmt,
|
'while_stmt': tree.WhileStmt,
|
||||||
'try_stmt': tree.TryStmt,
|
'try_stmt': tree.TryStmt,
|
||||||
'comp_for': tree.CompFor,
|
'sync_comp_for': tree.SyncCompFor,
|
||||||
# Not sure if this is the best idea, but IMO it's the easiest way to
|
# Not sure if this is the best idea, but IMO it's the easiest way to
|
||||||
# avoid extreme amounts of work around the subtle difference of 2/3
|
# avoid extreme amounts of work around the subtle difference of 2/3
|
||||||
# grammar in list comoprehensions.
|
# grammar in list comoprehensions.
|
||||||
'list_for': tree.CompFor,
|
'list_for': tree.SyncCompFor,
|
||||||
# Same here. This just exists in Python 2.6.
|
# Same here. This just exists in Python 2.6.
|
||||||
'gen_for': tree.CompFor,
|
'gen_for': tree.SyncCompFor,
|
||||||
'decorator': tree.Decorator,
|
'decorator': tree.Decorator,
|
||||||
'lambdef': tree.Lambda,
|
'lambdef': tree.Lambda,
|
||||||
'old_lambdef': tree.Lambda,
|
'old_lambdef': tree.Lambda,
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ _FLOW_CONTAINERS = set(['if_stmt', 'while_stmt', 'for_stmt', 'try_stmt',
|
|||||||
_RETURN_STMT_CONTAINERS = set(['suite', 'simple_stmt']) | _FLOW_CONTAINERS
|
_RETURN_STMT_CONTAINERS = set(['suite', 'simple_stmt']) | _FLOW_CONTAINERS
|
||||||
_FUNC_CONTAINERS = set(['suite', 'simple_stmt', 'decorated']) | _FLOW_CONTAINERS
|
_FUNC_CONTAINERS = set(['suite', 'simple_stmt', 'decorated']) | _FLOW_CONTAINERS
|
||||||
_GET_DEFINITION_TYPES = set([
|
_GET_DEFINITION_TYPES = set([
|
||||||
'expr_stmt', 'comp_for', 'with_stmt', 'for_stmt', 'import_name',
|
'expr_stmt', 'sync_comp_for', 'with_stmt', 'for_stmt', 'import_name',
|
||||||
'import_from', 'param'
|
'import_from', 'param'
|
||||||
])
|
])
|
||||||
_IMPORTS = set(['import_name', 'import_from'])
|
_IMPORTS = set(['import_name', 'import_from'])
|
||||||
@@ -1192,8 +1192,8 @@ class Param(PythonBaseNode):
|
|||||||
return '<%s: %s>' % (type(self).__name__, str(self._tfpdef()) + default)
|
return '<%s: %s>' % (type(self).__name__, str(self._tfpdef()) + default)
|
||||||
|
|
||||||
|
|
||||||
class CompFor(PythonBaseNode):
|
class SyncCompFor(PythonBaseNode):
|
||||||
type = 'comp_for'
|
type = 'sync_comp_for'
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
|
||||||
def get_defined_names(self):
|
def get_defined_names(self):
|
||||||
@@ -1201,4 +1201,4 @@ class CompFor(PythonBaseNode):
|
|||||||
Returns the a list of `Name` that the comprehension defines.
|
Returns the a list of `Name` that the comprehension defines.
|
||||||
"""
|
"""
|
||||||
# allow async for
|
# allow async for
|
||||||
return _defined_names(self.children[self.children.index('for') + 1])
|
return _defined_names(self.children[1])
|
||||||
|
|||||||
Reference in New Issue
Block a user