Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix crash with walrus + await + with #3473

Merged
merged 5 commits into from Jan 18, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.md
Expand Up @@ -33,6 +33,8 @@
string lambda values are now wrapped in parentheses (#3440)
- Exclude string type annotations from improved string processing; fix crash when the
return type annotation is stringified and spans across multiple lines (#3462)
- Fix several crashes in preview style with walrus operators used in `with` statements
or tuples (#3473)

### Configuration

Expand Down
4 changes: 4 additions & 0 deletions src/black/linegen.py
Expand Up @@ -46,6 +46,7 @@
is_rpar_token,
is_stub_body,
is_stub_suite,
is_tuple_containing_walrus,
is_vararg,
is_walrus_assignment,
is_yield,
Expand Down Expand Up @@ -1259,6 +1260,7 @@ def maybe_make_parens_invisible_in_atom(
not remove_brackets_around_comma
and max_delimiter_priority_in_atom(node) >= COMMA_PRIORITY
)
or is_tuple_containing_walrus(node)
):
return False

Expand All @@ -1270,9 +1272,11 @@ def maybe_make_parens_invisible_in_atom(
syms.return_stmt,
syms.except_clause,
syms.funcdef,
syms.with_stmt,
# these ones aren't useful to end users, but they do please fuzzers
syms.for_stmt,
syms.del_stmt,
syms.for_stmt,
]:
return False

Expand Down
11 changes: 11 additions & 0 deletions src/black/nodes.py
Expand Up @@ -563,6 +563,17 @@ def is_one_tuple(node: LN) -> bool:
)


def is_tuple_containing_walrus(node: LN) -> bool:
"""Return True if `node` holds a tuple that contains a walrus operator."""
if node.type != syms.atom:
return False
gexp = unwrap_singleton_parenthesis(node)
if gexp is None or gexp.type != syms.testlist_gexp:
return False

return any(child.type == syms.namedexpr_test for child in gexp.children)


def is_one_sequence_between(
opening: Leaf,
closing: Leaf,
Expand Down
4 changes: 4 additions & 0 deletions tests/data/fast/pep_572_do_not_remove_parens.py
Expand Up @@ -19,3 +19,7 @@
@(please := stop)
def sigh():
pass


for (x := 3, y := 4) in y:
pass
40 changes: 40 additions & 0 deletions tests/data/py_38/pep_572_remove_parens.py
Expand Up @@ -49,6 +49,26 @@ def a():
def this_is_so_dumb() -> (please := no):
pass

async def await_the_walrus():
with (x := y):
pass

with (x := y) as z, (a := b) as c:
pass

with (x := await y):
pass

with (x := await a, y := await b):
pass

# Ideally we should remove one set of parentheses
with ((x := await a, y := await b)):
pass

with (x := await a), (y := await b):
pass


# output
if foo := 0:
Expand Down Expand Up @@ -103,3 +123,23 @@ def a():
def this_is_so_dumb() -> (please := no):
pass


async def await_the_walrus():
with (x := y):
pass

with (x := y) as z, (a := b) as c:
pass

with (x := await y):
pass

with (x := await a, y := await b):
pass

# Ideally we should remove one set of parentheses
with ((x := await a, y := await b)):
pass
ichard26 marked this conversation as resolved.
Show resolved Hide resolved

with (x := await a), (y := await b):
pass