Skip to content

Wrap walrus expressions in parens in as_string output#3045

Open
SAY-5 wants to merge 2 commits into
pylint-dev:mainfrom
SAY-5:fix-2668-walrus-as-string
Open

Wrap walrus expressions in parens in as_string output#3045
SAY-5 wants to merge 2 commits into
pylint-dev:mainfrom
SAY-5:fix-2668-walrus-as-string

Conversation

@SAY-5
Copy link
Copy Markdown
Contributor

@SAY-5 SAY-5 commented May 5, 2026

Type of Changes

Type
🐛 Bug fix

Description

Closes #2668

AsStringVisitor.visit_namedexpr rendered a := value without surrounding parentheses, producing invalid Python whenever the walrus appeared inside another expression. For example, if x != (size := (1, 2, 3)): round-tripped to if x != size := (1, 2, 3):, which is a SyntaxError.

The fix always emits (target := value), matching CPython's ast.unparse behavior. Existing test_assignment_expression was updated to expect the parenthesized form, and a regression test rebuilds the issue's example and asserts the rendered output is valid Python via compile(...).

DanielNoord
DanielNoord previously approved these changes May 5, 2026
Copy link
Copy Markdown
Collaborator

@DanielNoord DanielNoord left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code LGTM, but you'll need to move the import to the top level.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 5, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.42%. Comparing base (53cd224) to head (a2a70a4).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main    #3045   +/-   ##
=======================================
  Coverage   93.42%   93.42%           
=======================================
  Files          92       92           
  Lines       11314    11314           
=======================================
  Hits        10570    10570           
  Misses        744      744           
Flag Coverage Δ
linux 93.29% <100.00%> (ø)
pypy 93.42% <100.00%> (ø)
windows 93.39% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
astroid/nodes/as_string.py 97.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@SAY-5
Copy link
Copy Markdown
Contributor Author

SAY-5 commented May 5, 2026

Moved the import to module-level. Thanks!

@DanielNoord
Copy link
Copy Markdown
Collaborator

@SAY-5 Could you resolve the conflict? :)

@SAY-5 SAY-5 force-pushed the fix-2668-walrus-as-string branch from 23ad24f to 2c99114 Compare May 8, 2026 20:55
@SAY-5
Copy link
Copy Markdown
Contributor Author

SAY-5 commented May 9, 2026

Pushed 35b011b. The follow-up keeps compare output parenthesized while rendering walrus operands bare when the parent node already manages precedence parens, which fixes the extra wrapping caught by the downstream pylint workflow.\n\nLocal checks I reran:\n- PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 python3 -m pytest -q tests/test_nodes.py\n- PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 python3 -m pytest -q tests/test_nodes.py -k 'assignment_expression'\n- in a local pylint checkout with this astroid branch installed: PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 python -m pytest -q tests/test_functional.py -k 'consider_refactoring_into_while_condition_py38'

Comment thread astroid/nodes/as_string.py Outdated
return child.accept(self)

@staticmethod
def _namedexpr_renders_bare(node: nodes.NamedExpr) -> bool:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels quite brittle. Did you explore other ways to compute this condition?

@SAY-5
Copy link
Copy Markdown
Contributor Author

SAY-5 commented May 11, 2026

Switched to unconditional wrapping in visit_namedexpr (matching CPython's ast.unparse) and removed the NamedExpr precedence entry so parents do not double-wrap. The parent-type list is gone; tests still pass. Pushed in e01d829.

@DanielNoord
Copy link
Copy Markdown
Collaborator

@SAY-5 Sorry to ask, but are you AI?

Anyway, the CI shows you're back to the previous failure now.

@SAY-5
Copy link
Copy Markdown
Contributor Author

SAY-5 commented May 12, 2026

Naa! @DanielNoord I've been trying something, due to that the ci failures

@SAY-5 SAY-5 force-pushed the fix-2668-walrus-as-string branch from e01d829 to 7db5c11 Compare May 12, 2026 23:36
@SAY-5
Copy link
Copy Markdown
Contributor Author

SAY-5 commented May 12, 2026

Rebased onto current main (resolved the ChangeLog conflict) and squashed to a single commit: as_string now always parenthesizes the walrus expression, matching CPython's ast.unparse. The pylint-with-astroid-sha job's consider_refactoring_into_while_condition_py38 functional output will need the matching update on the pylint side. Local tests/test_nodes.py walrus/namedexpr tests pass.

target = node.target.accept(self)
value = node.value.accept(self)
return f"{target} := {value}"
if isinstance(getattr(node, "parent", None), nodes.Compare):
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we do this without a getattr?

Copy link
Copy Markdown
Member

@Pierre-Sassoulas Pierre-Sassoulas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with Daniel's comment, otherwise LGTM

@Pierre-Sassoulas Pierre-Sassoulas added this to the 4.2.0 milestone May 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect removal of brackets

3 participants