diff --git a/parso/python/errors.py b/parso/python/errors.py index af66d9f..66c276a 100644 --- a/parso/python/errors.py +++ b/parso/python/errors.py @@ -713,13 +713,10 @@ class _FutureImportRule(SyntaxRule): @ErrorFinder.register_rule(type='star_expr') class _StarExprRule(SyntaxRule): - message = "starred assignment target must be in a list or tuple" message_iterable_unpacking = "iterable unpacking cannot be used in comprehension" message_assignment = "can use starred expression only as assignment target" def is_issue(self, node): - if node.parent.type not in _STAR_EXPR_PARENTS: - return True if node.parent.type == 'testlist_comp': # [*[] for a in [1]] if node.parent.children[1].type in _COMP_FOR_TYPES: @@ -1075,6 +1072,9 @@ class _CheckAssignmentRule(SyntaxRule): or type_ in ('term', 'factor')): error = 'operator' elif type_ == "star_expr": + if not search_ancestor(node, *_STAR_EXPR_PARENTS): + self.add_issue(node, message="starred assignment target must be in a list or tuple") + self._check_assignment(node.children[1]) if error is not None: diff --git a/test/test_python_errors.py b/test/test_python_errors.py index 743cb25..999c16e 100644 --- a/test/test_python_errors.py +++ b/test/test_python_errors.py @@ -391,3 +391,26 @@ def test_repeated_kwarg(): ) def test_unparenthesized_genexp(source, no_errors): assert bool(_get_error_list(source)) ^ no_errors + +@pytest.mark.parametrize( + ('source', 'no_errors'), [ + ('*x = 2', False), + ('(*y) = 1', False), + ('((*z)) = 1', False), + ('a, *b = 1', True), + ('a, *b, c = 1', True), + ('a, (*b), c = 1', True), + ('a, ((*b)), c = 1', True), + ('a, (*b, c), d = 1', True), + ('[*(1,2,3)]', True), + ('{*(1,2,3)}', True), + ('[*(1,2,3),]', True), + ('[*(1,2,3), *(4,5,6)]', True), + ('[0, *(1,2,3)]', True), + ('{*(1,2,3),}', True), + ('{*(1,2,3), *(4,5,6)}', True), + ('{0, *(4,5,6)}', True) + ] +) +def test_starred_expr(source, no_errors): + assert bool(_get_error_list(source)) ^ no_errors