Skip to content

Prefer splitting whole boolean conditions - #5252

Open
zhangli091011 wants to merge 5 commits into
psf:mainfrom
zhangli091011:fix/parenthesize-whole-condition
Open

Prefer splitting whole boolean conditions#5252
zhangli091011 wants to merge 5 commits into
psf:mainfrom
zhangli091011:fix/parenthesize-whole-condition

Conversation

@zhangli091011

Copy link
Copy Markdown

Description

When an if, elif, or while condition contains top-level boolean operators and function calls, prefer splitting the condition's optional outer parentheses before splitting an inner call. This adds a narrowly scoped preview-style RHS candidate and falls back to the existing split order if that candidate does not fit.

The stable style is unchanged.

Fixes #3629.

Tests

  • python -m pytest tests/test_format.py -q (229 passed)
  • python -m tox -e py (475 passed, 1 skipped; 73 Jupyter tests passed; 94% coverage)
  • pre-commit hooks: isort, flake8, mypy, repository checks, end-of-file-fixer, trailing-whitespace
  • npx prettier@3.9.6 --check CHANGES.md docs/the_black_code_style/future_style.md
  • explicit stable/preview output-isolation check

AI disclosure

This contribution was developed with assistance from OpenAI GPT-5.6-sol. I reviewed and tested all changes.

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

diff-shades results comparing this PR (4e84fe7) to main (c7801d9):

--preview style (View full diff):
╭────────────────────────── Summary ───────────────────────────╮
│ 20 projects & 497 files changed / 8030 changes [+4969/-3061] │
│                                                              │
│ ... out of 3 011 072 lines, 14 020 files & 22 projects       │
╰──────────────────────────────────────────────────────────────╯

Differences found.

--stable style: no changes


What is this? | Workflow run | diff-shades documentation

@zhangli091011

Copy link
Copy Markdown
Author

The branch is now updated to the latest main (311f9b399a). The new fork workflow runs are awaiting maintainer approval, so the previous self-format failures cannot yet be re-evaluated against the updated baseline. Could a maintainer please approve the latest Actions runs?

@cobaltt7 cobaltt7 left a comment

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.

Thanks! I personally really like this change, and the diff-shades changes don't seem to include anything bad. However, this is a pretty intrusive change in the sense that it affects a lot of code that would need reformatting, and it's always a net increase in LOC.

As such, Black needs to be run on this repository to fix failing tests!

Would appreciate input from other maintainers!

Comment on lines +34 to +35
# The split preference is limited to conditional statements.
result = check_very_very_very_very_very_long_expression(first) and check_very_very_very_very_very_long_expression(second)

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.

IMO it should apply everywhere. Part of the point of a code formatter is consistency. Was there specific reasoning behind this?
Similarly, does this only affect Boolean operators, or does it affect math operators too? I could see that one going either way (don't make this change without discussion and a consensus! 😅)

On the other hand, this does make it even more intrusive than it already is...

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The current scope is intentional. Issue #3629 is accepted specifically for parenthesizing whole conditional expressions, and its accepted examples are conditional headers. The implementation therefore adds a candidate only for if/elif/while statement conditions, and only when the optional outer parentheses contain top-level and/or delimiters. That gives the requested whole-condition split before the existing RHS call split, while retaining the existing fallback when it does not fit. Applying this everywhere would require a broader policy for expression contexts such as assignments and returns, and extending it to arithmetic would also change operator-precedence and style behavior well beyond the accepted issue. I have not made either semantic expansion without maintainer consensus. If the intended decision is to broaden the accepted scope, I am happy to follow that direction in a subsequent revision, but I think that decision should be explicit first.

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.

I agree math operators doesn't make as much sense. But for boolean operators I think it should apply everywhere, if we are to implement this.
Right now it sounds like the main question is whether or not this style is a good change in general, so you can hold off on making that change until we decide to move forward with this PR, and until other maintainers have a chance to discuss whether it should apply outside if/elif/while conditions.

@zhangli091011

Copy link
Copy Markdown
Author

Updated to current main and ran this PR's Black over the repository as requested. The resulting 15-file self-format change is committed separately, and the piping test now explicitly uses preview to match the repository style. Local self-format, lint, full format fixtures, no-Jupyter, and Jupyter suites pass. I also replied to the open scope thread without expanding semantics pending maintainer consensus. Ready for re-review.

@JelleZijlstra

Copy link
Copy Markdown
Collaborator

I like this in many cases but it's a very disruptive change; it would probably require a ton of reformatting for users of Black. I'm also not sure I like it in all cases; sometimes the extra lines make the code harder to see at once.

@cobaltt7

cobaltt7 commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

I personally find that the cases where it can decrease visibility are mostly changes such as this:
image
(here the trailing comma can be manually removed to condense the second term into one line, which IMO looks best overall)

            if (
                cache is not None
                and write_back not in (WriteBack.DIFF, WriteBack.COLOR_DIFF)
            ):

Or cases where one of the terms is just too long and has to stay split anyway:
image

One possible way to handle that is to not have Black split before the boolean and retain previous behavior if one of the terms is still split across multiple lines with this style. That could also help slightly decrease the scope.

See also the similar #5259, which also made a similar change to exclude arrays that split across multiple lines, and it significantly decreased scope while significantly increasing readability.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Parenthesize whole conditional expression with function calls rather than wrap the last function call

3 participants