mirror of
https://github.com/davidhalter/parso.git
synced 2025-12-08 13:45:01 +08:00
Handling of star_expr and some async issues.
This commit is contained in:
@@ -3,6 +3,7 @@ from contextlib import contextmanager
|
|||||||
from parso.normalizer import Normalizer, NormalizerConfig, Issue
|
from parso.normalizer import Normalizer, NormalizerConfig, Issue
|
||||||
|
|
||||||
_BLOCK_STMTS = ('if_stmt', 'while_stmt', 'for_stmt', 'try_stmt', 'with_stmt')
|
_BLOCK_STMTS = ('if_stmt', 'while_stmt', 'for_stmt', 'try_stmt', 'with_stmt')
|
||||||
|
_STAR_EXPR_PARENTS = ('testlist_star_expr', 'testlist_comp', 'exprlist')
|
||||||
# This is the maximal block size given by python.
|
# This is the maximal block size given by python.
|
||||||
_MAX_BLOCK_SIZE = 20
|
_MAX_BLOCK_SIZE = 20
|
||||||
|
|
||||||
@@ -95,6 +96,24 @@ class ErrorFinder(Normalizer):
|
|||||||
and is_future_import(node):
|
and is_future_import(node):
|
||||||
message = "from __future__ imports must occur at the beginning of the file"
|
message = "from __future__ imports must occur at the beginning of the file"
|
||||||
self._add_syntax_error(message, node)
|
self._add_syntax_error(message, node)
|
||||||
|
elif node.type in _STAR_EXPR_PARENTS:
|
||||||
|
if node.parent.type == 'del_stmt':
|
||||||
|
self._add_syntax_error("can't use starred expression here", node.parent)
|
||||||
|
else:
|
||||||
|
starred = [c for c in node.children if c.type == 'star_expr']
|
||||||
|
if len(starred) > 1:
|
||||||
|
message = "two starred expressions in assignment"
|
||||||
|
self._add_syntax_error(message, starred[1])
|
||||||
|
"can't use starred expression here"
|
||||||
|
elif node.type == 'star_expr':
|
||||||
|
if node.parent.type not in _STAR_EXPR_PARENTS:
|
||||||
|
message = "starred assignment target must be in a list or tuple"
|
||||||
|
self._add_syntax_error(message, node)
|
||||||
|
elif node.type == 'comp_for':
|
||||||
|
if node.children[0] == 'async' \
|
||||||
|
and not self._context.is_async_funcdef():
|
||||||
|
message = "asynchronous comprehension outside of an asynchronous function"
|
||||||
|
self._add_syntax_error(message, node)
|
||||||
|
|
||||||
yield
|
yield
|
||||||
|
|
||||||
@@ -134,10 +153,14 @@ class ErrorFinder(Normalizer):
|
|||||||
self._add_syntax_error("'break' outside loop", leaf)
|
self._add_syntax_error("'break' outside loop", leaf)
|
||||||
elif leaf.value in ('yield', 'return'):
|
elif leaf.value in ('yield', 'return'):
|
||||||
if self._context.node.type != 'funcdef':
|
if self._context.node.type != 'funcdef':
|
||||||
self._add_syntax_error("'%s' outside function" % leaf.value, leaf)
|
self._add_syntax_error("'%s' outside function" % leaf.value, leaf.parent)
|
||||||
|
elif self._context.is_async_funcdef() and leaf.value == 'return' \
|
||||||
|
and leaf.parent.type == 'return_stmt' \
|
||||||
|
and any(self._context.node.iter_yield_exprs()):
|
||||||
|
self._add_syntax_error("'return' with value in async generator", leaf.parent)
|
||||||
elif leaf.value == 'await':
|
elif leaf.value == 'await':
|
||||||
if not self._context.is_async_funcdef():
|
if not self._context.is_async_funcdef():
|
||||||
self._add_syntax_error("'await' outside async function", leaf)
|
self._add_syntax_error("'await' outside async function", leaf.parent)
|
||||||
elif leaf.value == 'from' and leaf.parent.type == 'yield_arg' \
|
elif leaf.value == 'from' and leaf.parent.type == 'yield_arg' \
|
||||||
and self._context.is_async_funcdef():
|
and self._context.is_async_funcdef():
|
||||||
yield_ = leaf.parent.parent
|
yield_ = leaf.parent.parent
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ async def foo():
|
|||||||
await bar()
|
await bar()
|
||||||
#: E901
|
#: E901
|
||||||
yield from []
|
yield from []
|
||||||
|
return
|
||||||
|
#: E901
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
# With decorator it's a different statement.
|
# With decorator it's a different statement.
|
||||||
@@ -17,3 +20,6 @@ async def foo():
|
|||||||
await bar()
|
await bar()
|
||||||
#: E901
|
#: E901
|
||||||
yield from []
|
yield from []
|
||||||
|
return
|
||||||
|
#: E901
|
||||||
|
return ''
|
||||||
|
|||||||
@@ -99,6 +99,12 @@ def test_python_exception_matches(code):
|
|||||||
('async def bla():\n def x(): await bla()', '3.5'),
|
('async def bla():\n def x(): await bla()', '3.5'),
|
||||||
('yield from []', '3.5'),
|
('yield from []', '3.5'),
|
||||||
('async def foo(): yield from []', '3.5'),
|
('async def foo(): yield from []', '3.5'),
|
||||||
|
('async def foo():\n yield x\n return 1', '3.6'),
|
||||||
|
('async def foo():\n yield x\n return 1', '3.6'),
|
||||||
|
('*a, *b = 3, 3', '3.3'),
|
||||||
|
('*a = 3', '3.5'),
|
||||||
|
('del *a, b', '3.5'),
|
||||||
|
('async def foo():\n def nofoo():[x async for x in []]', '3.6'),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
def test_python_exception_matches_version(code, version):
|
def test_python_exception_matches_version(code, version):
|
||||||
|
|||||||
Reference in New Issue
Block a user