Skip to content

Preserve prefixes outside --line-ranges - #5175

Open
cyphercodes wants to merge 3 commits into
psf:mainfrom
cyphercodes:fix-line-ranges-preserve-outside-prefix
Open

Preserve prefixes outside --line-ranges#5175
cyphercodes wants to merge 3 commits into
psf:mainfrom
cyphercodes:fix-line-ranges-preserve-outside-prefix

Conversation

@cyphercodes

Copy link
Copy Markdown
Contributor

Description

Preserves comments and blank lines that are outside the requested --line-ranges instead of normalizing them while unchanged code is converted to standalone-comment leaves for range formatting.

This keeps the issue repro constrained to the requested lines: comments and separation before unchanged statements are preserved when the selected range ends immediately before them.

Fixes #4430.

Checklist - did you ...

  • Implement any code style changes under the --preview style, following the stability policy?
  • Add an entry in CHANGES.md if necessary?
  • Add / update tests if necessary?
  • Add new / update outdated documentation?

Verification

  • python -m black --check src/black/comments.py src/black/linegen.py src/black/lines.py src/black/ranges.py tests/test_ranges.py
  • python -m pytest tests/test_ranges.py tests/test_format.py -q
  • git diff --check

@cyphercodes
cyphercodes force-pushed the fix-line-ranges-preserve-outside-prefix branch from 84afab8 to 682d265 Compare June 12, 2026 03:49
@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

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

--preview style: no changes

--stable style: no changes


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

@cyphercodes
cyphercodes force-pushed the fix-line-ranges-preserve-outside-prefix branch from 682d265 to 392adbf Compare June 12, 2026 04:05
@cobaltt7

Copy link
Copy Markdown
Collaborator

Thanks - this fixes issues where whitespace at the beginning of lines before comments is stripped when using --line-ranges. However, this doesn't address trailing whitespace on prefix lines, which I think was the main issue #4430 was implying.

As an example:

   #  format whitespace   
print( "format me" )   
      

   #  don't format whitespace   
print("don't format me"  )     
      

Output with --line-ranges 1-3:

#  format whitespace
print("format me")


   #  don't format whitespace
print("don't format me"  )     
[empty line at EOF]

Expected output:

#  format whitespace
print( "format me" )


   #  don't format whitespace   
print("don't format me"  )     
      

@cobaltt7

Copy link
Copy Markdown
Collaborator

I also found an edge case where this fix doesn't seem to be applied. Example with --line-ranges 1-2:

print( "format me" )
   #  format whitespace

print("don't format me"  )

The spaces before the comment are retained, but they should be removed here. They are removed when running Black on the whole file.

@cobaltt7

Copy link
Copy Markdown
Collaborator

@cyphercodes are you still updating this?

@cyphercodes

Copy link
Copy Markdown
Contributor Author

Updated — merged current main and resolved the src/black/ranges.py conflict by preserving the upstream batched replacement logic plus the PR's line-range conversion marker.

Verification:

  • python -m pytest tests/test_black.py -k 'line_ranges or preserve_outside_prefix' -q
  • git diff --check

@cobaltt7

Copy link
Copy Markdown
Collaborator

@cyphercodes Please resolve my two review comments above.

@cyphercodes

Copy link
Copy Markdown
Contributor Author

Updated — addressed both line-ranges prefix cases from the review:

  • unselected prefix comment lines now keep their original leading/trailing whitespace
  • prefix comments that fall inside the selected --line-ranges are still normalized
  • trailing whitespace-only blank lines outside the selected ranges are preserved

Verification:

  • .venv/bin/python -m black src/black/__init__.py src/black/comments.py src/black/linegen.py src/black/ranges.py src/blib2to3/pytree.py tests/test_black.py
  • .venv/bin/python -m pytest tests/test_black.py -k 'line_ranges or preserve_outside_prefix' -q
  • .venv/bin/python -m pytest tests/test_format.py -k line_ranges -q
  • git diff --check

Comment thread tests/test_black.py
""")
assert expected == formatted

def test_line_ranges_preserves_unselected_prefix_trailing_whitespace(self) -> None:

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.

Is there a reason these aren't their own test case files? They should be if possible.

Comment thread src/blib2to3/pytree.py
Comment on lines +487 to +490
# True when this Leaf is converted from unchanged code for --line-ranges.
line_ranges_converted: bool = False
line_ranges_first_lineno: int = 0
line_ranges_selected: Optional[set[int]] = None

@cobaltt7 cobaltt7 Aug 5, 2026

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.

Wouldn't line_ranges_first_lineno != 0 or line_ranges_selected is not None always be equal to line_ranges_converted? Could we replace line_ranges_converted with one of those?

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.

Also, when I first read through, I assumed that min(line_ranges_selected) would be the same as line_ranges_first_lineno, but I don't think that's always the case after reading through the code. It may be worth adding comments describing the use of both and the differences.

Comment thread src/black/__init__.py
Comment on lines +1289 to +1291
selected: set[int] = set()
for start, end in lines:
selected.update(range(start, end + 1))

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.

Could we use comparison operators (<=/>=) instead of creating a set and checking inclusion?

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.

--line-ranges formats lines outside of range

2 participants