diff --git a/parso/python/grammar310.txt b/parso/python/grammar310.txt index 11697ea..fce8753 100644 --- a/parso/python/grammar310.txt +++ b/parso/python/grammar310.txt @@ -124,14 +124,14 @@ atom: ('(' [yield_expr|testlist_comp] ')' | testlist_comp: (namedexpr_test|star_expr) ( comp_for | (',' (namedexpr_test|star_expr))* [','] ) trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME subscriptlist: subscript (',' subscript)* [','] -subscript: test | [test] ':' [test] [sliceop] +subscript: test [':=' test] | [test] ':' [test] [sliceop] sliceop: ':' [test] exprlist: (expr|star_expr) (',' (expr|star_expr))* [','] testlist: test (',' test)* [','] dictorsetmaker: ( ((test ':' test | '**' expr) (comp_for | (',' (test ':' test | '**' expr))* [','])) | - ((test | star_expr) - (comp_for | (',' (test | star_expr))* [','])) ) + ((test [':=' test] | star_expr) + (comp_for | (',' (test [':=' test] | star_expr))* [','])) ) classdef: 'class' NAME ['(' [arglist] ')'] ':' suite diff --git a/parso/python/grammar39.txt b/parso/python/grammar39.txt index 11697ea..f17eba5 100644 --- a/parso/python/grammar39.txt +++ b/parso/python/grammar39.txt @@ -130,8 +130,8 @@ exprlist: (expr|star_expr) (',' (expr|star_expr))* [','] testlist: test (',' test)* [','] dictorsetmaker: ( ((test ':' test | '**' expr) (comp_for | (',' (test ':' test | '**' expr))* [','])) | - ((test | star_expr) - (comp_for | (',' (test | star_expr))* [','])) ) + ((test [':=' test] | star_expr) + (comp_for | (',' (test [':=' test] | star_expr))* [','])) ) classdef: 'class' NAME ['(' [arglist] ')'] ':' suite diff --git a/test/failing_examples.py b/test/failing_examples.py index c89f1f3..8f2edca 100644 --- a/test/failing_examples.py +++ b/test/failing_examples.py @@ -356,6 +356,10 @@ if sys.version_info[:2] >= (3, 8): '(False := 1)', '(None := 1)', '(__debug__ := 1)', + # Unparenthesized walrus not allowed in dict literals, dict comprehensions and slices + '{a:="a": b:=1}', + '{y:=1: 2 for x in range(5)}', + 'a[b:=0:1:2]', ] # f-string debugging syntax with invalid conversion character FAILING_EXAMPLES += [ diff --git a/test/test_python_errors.py b/test/test_python_errors.py index 02b1d40..fa07d66 100644 --- a/test/test_python_errors.py +++ b/test/test_python_errors.py @@ -289,12 +289,37 @@ def test_valid_fstrings(code): '[total := total + v for v in range(10)]', 'while chunk := file.read(2):\n pass', 'numbers = [y := math.factorial(x), y**2, y**3]', + '{(a:="a"): (b:=1)}', + '{(y:=1): 2 for x in range(5)}', + 'a[(b:=0)]', + 'a[(b:=0, c:=0)]', + 'a[(b:=0):1:2]', ] ) def test_valid_namedexpr(code): assert not _get_error_list(code, version='3.8') +@pytest.mark.parametrize( + 'code', [ + '{x := 1, 2, 3}', + '{x4 := x ** 5 for x in range(7)}', + ] +) +def test_valid_namedexpr_set(code): + assert not _get_error_list(code, version='3.9') + + +@pytest.mark.parametrize( + 'code', [ + 'a[b:=0]', + 'a[b:=0, c:=0]', + ] +) +def test_valid_namedexpr_index(code): + assert not _get_error_list(code, version='3.10') + + @pytest.mark.parametrize( ('code', 'message'), [ ("f'{1+}'", ('invalid syntax')),