Skip to content

Commit bdcb65a

Browse files
committed
Emit chunks of lines instead of individual lines
This should allow us to get smaller diff chunks from Black than by diffing and analyzing Black's string output for whole files.
1 parent 74a3544 commit bdcb65a

File tree

4 files changed

+30
-27
lines changed

4 files changed

+30
-27
lines changed

src/darker/black_diff.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
from black.const import DEFAULT_EXCLUDES, DEFAULT_INCLUDES
5050
from black.files import gen_python_files
5151
from black.report import Report
52-
from darker.linewise_black import format_str_to_lines
52+
from darker.linewise_black import format_str_to_chunks
5353

5454
from darker.utils import TextDocument
5555

@@ -181,8 +181,8 @@ def run_black(src_contents: TextDocument, black_config: BlackConfig) -> TextDocu
181181
# https://github.com/psf/black/pull/2484 lands in Black.
182182
contents_for_black = src_contents.string_with_newline("\n")
183183
if contents_for_black.strip():
184-
dst_lines = format_str_to_lines(contents_for_black, mode=Mode(**mode))
185-
dst_contents = "".join(dst_lines)
184+
dst_chunks = format_str_to_chunks(contents_for_black, mode=Mode(**mode))
185+
dst_contents = "".join(line for chunk in dst_chunks for line in chunk)
186186
else:
187187
dst_contents = "\n" if "\n" in src_contents.string else ""
188188
return TextDocument.from_str(

src/darker/linewise_black.py

+20-17
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Re-implementation of :func:`black.format_str` as a line generator"""
22

3-
from typing import Generator
3+
from typing import Generator, List
44
from black import get_future_imports, detect_target_versions, decode_bytes
55
from black.lines import Line, EmptyLineTracker
66
from black.linegen import transform_line, LineGenerator
@@ -10,13 +10,14 @@
1010
from black.parsing import lib2to3_parse
1111

1212

13-
def format_str_to_lines(
13+
def format_str_to_chunks( # pylint: disable=too-many-locals
1414
src_contents: str, *, mode: Mode
15-
) -> Generator[str, None, None]: # pylint: disable=too-many-locals
15+
) -> Generator[List[str], None, None]:
1616
"""Reformat a string and yield each line of new contents
1717
1818
This is a re-implementation of :func:`black.format_str` modified to be a generator
19-
which yields each resulting line instead of concatenating them into a single string.
19+
which yields each resulting chunk as a list of lines instead of concatenating them
20+
into a single string.
2021
2122
"""
2223
src_node = lib2to3_parse(src_contents.lstrip(), mode.target_versions)
@@ -42,20 +43,22 @@ def format_str_to_lines(
4243
}
4344
num_chars = 0
4445
for current_line in lines.visit(src_node):
45-
for _ in range(after):
46-
yield empty_line
47-
num_chars += after * empty_line_len
46+
if after:
47+
yield after * [empty_line]
48+
num_chars += after * empty_line_len
4849
before, after = elt.maybe_empty_lines(current_line)
49-
for _ in range(before):
50-
yield empty_line
51-
num_chars += before * empty_line_len
52-
for line in transform_line(
53-
current_line, mode=mode, features=split_line_features
54-
):
55-
line_str = str(line)
56-
yield line_str
57-
num_chars += len(line_str)
50+
if before:
51+
yield before * [empty_line]
52+
num_chars += before * empty_line_len
53+
lines = [
54+
str(line)
55+
for line in transform_line(
56+
current_line, mode=mode, features=split_line_features
57+
)
58+
]
59+
yield lines
60+
num_chars += sum(len(line) for line in lines)
5861
if not num_chars:
5962
normalized_content, _, newline = decode_bytes(src_contents.encode("utf-8"))
6063
if "\n" in normalized_content:
61-
yield newline
64+
yield [newline]

src/darker/tests/test_black_diff.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -174,12 +174,12 @@ def test_run_black(encoding, newline):
174174
def test_run_black_always_uses_unix_newlines(newline):
175175
"""Content is always passed to Black with Unix newlines"""
176176
src = TextDocument.from_str(f"print ( 'touché' ){newline}")
177-
with patch.object(black_diff, "format_str_to_lines") as format_str_to_lines:
178-
format_str_to_lines.return_value = ['print("touché")\n']
177+
with patch.object(black_diff, "format_str_to_chunks") as format_str_to_chunks:
178+
format_str_to_chunks.return_value = [['print("touché")\n']]
179179

180180
_ = run_black(src, BlackConfig())
181181

182-
format_str_to_lines.assert_called_once_with("print ( 'touché' )\n", mode=ANY)
182+
format_str_to_chunks.assert_called_once_with("print ( 'touché' )\n", mode=ANY)
183183

184184

185185
def test_run_black_ignores_excludes():

src/darker/tests/test_command_line.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -470,9 +470,9 @@ def test_black_options_skip_string_normalization(git_repo, config, options, expe
470470
added_files["main.py"].write_bytes(b"bar")
471471
mode_class_mock = Mock(wraps=black_diff.Mode)
472472
# Speed up tests by mocking `format_str` to skip running Black
473-
format_str_to_lines = Mock(return_value=["bar"])
473+
format_str_to_chunks = Mock(return_value=[["bar"]])
474474
with patch.multiple(
475-
black_diff, Mode=mode_class_mock, format_str_to_lines=format_str_to_lines
475+
black_diff, Mode=mode_class_mock, format_str_to_chunks=format_str_to_chunks
476476
):
477477

478478
main(options + [str(path) for path in added_files.values()])
@@ -498,9 +498,9 @@ def test_black_options_skip_magic_trailing_comma(git_repo, config, options, expe
498498
added_files["main.py"].write_bytes(b"a = [1, 2,]")
499499
mode_class_mock = Mock(wraps=black_diff.Mode)
500500
# Speed up tests by mocking `format_str` to skip running Black
501-
format_str_to_lines = Mock(return_value=["a = [1, 2,]"])
501+
format_str_to_chunks = Mock(return_value=[["a = [1, 2,]"]])
502502
with patch.multiple(
503-
black_diff, Mode=mode_class_mock, format_str_to_lines=format_str_to_lines
503+
black_diff, Mode=mode_class_mock, format_str_to_chunks=format_str_to_chunks
504504
):
505505

506506
main(options + [str(path) for path in added_files.values()])

0 commit comments

Comments
 (0)