diff --git a/parso/python/errors.py b/parso/python/errors.py index 422234b..364f72e 100644 --- a/parso/python/errors.py +++ b/parso/python/errors.py @@ -753,6 +753,16 @@ class _StarExprRule(SyntaxRule): return False return False + if self._normalizer.version >= (3, 9): + ancestor = node.parent + else: + ancestor = _skip_parens_bottom_up(node) + # starred expression not in tuple/list/set + if ancestor.type not in (*_STAR_EXPR_PARENTS, 'dictorsetmaker') \ + and not (ancestor.type == 'atom' and ancestor.children[0] != '('): + self.add_issue(node, message="can't use starred expression here") + return + if check_delete_starred(node): if self._normalizer.version >= (3, 9): self.add_issue(node, message="cannot delete starred") @@ -764,12 +774,6 @@ class _StarExprRule(SyntaxRule): # [*[] for a in [1]] if node.parent.children[1].type in _COMP_FOR_TYPES: self.add_issue(node, message=self.message_iterable_unpacking) - return - - ancestor = _skip_parens_bottom_up(node) - # starred expression not in tuple/list/set - if ancestor.type not in (*_STAR_EXPR_PARENTS, 'dictorsetmaker', 'atom'): - self.add_issue(node, message="can't use starred expression here") @ErrorFinder.register_rule(types=_STAR_EXPR_PARENTS) @@ -1107,7 +1111,10 @@ class _CheckAssignmentRule(SyntaxRule): else: self.add_issue(node, message="can't use starred expression here") else: - ancestor = _skip_parens_bottom_up(node) + if self._normalizer.version >= (3, 9): + ancestor = node.parent + else: + ancestor = _skip_parens_bottom_up(node) if ancestor.type not in _STAR_EXPR_PARENTS and not is_aug_assign \ and not (ancestor.type == 'atom' and ancestor.children[0] == '['): message = "starred assignment target must be in a list or tuple" diff --git a/test/test_python_errors.py b/test/test_python_errors.py index 490b103..270cd44 100644 --- a/test/test_python_errors.py +++ b/test/test_python_errors.py @@ -425,10 +425,6 @@ def test_unparenthesized_genexp(source, no_errors): ('a, *b = 1', True), ('a, *b, c', True), ('a, *b, c = 1', True), - ('a, (*b), c', True), - ('a, (*b), c = 1', True), - ('a, ((*b)), c', True), - ('a, ((*b)), c = 1', True), ('a, (*b, c), d', True), ('a, (*b, c), d = 1', True), ('*a.b,', True), @@ -455,6 +451,19 @@ def test_starred_expr(source, no_errors): assert bool(_get_error_list(source, version="3")) ^ no_errors +@pytest.mark.parametrize( + 'code', [ + 'a, (*b), c', + 'a, (*b), c = 1', + 'a, ((*b)), c', + 'a, ((*b)), c = 1', + ] +) +def test_parenthesized_single_starred_expr(code): + assert not _get_error_list(code, version='3.8') + assert _get_error_list(code, version='3.9') + + @pytest.mark.parametrize( 'code', [ '() = ()',