Skip to content

Commit

Permalink
Merge pull request #20 from akaihola/context-extension-fix
Browse files Browse the repository at this point in the history
Context extension fix
  • Loading branch information
akaihola authored Jul 9, 2020
2 parents 88cb031 + 6be809b commit 4a4c423
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 13 deletions.
14 changes: 7 additions & 7 deletions src/darker/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@

logger = logging.getLogger(__name__)

# Maximum `git diff -U<context_lines> value to try with
MAX_CONTEXT_LINES = 1000


def format_edited_parts(
srcs: Iterable[Path],
Expand Down Expand Up @@ -72,16 +69,19 @@ def format_edited_parts(
edited_srcs = worktree_srcs

for src_relative, edited_content in edited_srcs.items():
for context_lines in range(MAX_CONTEXT_LINES + 1):
max_context_lines = len(edited_content)
for context_lines in range(max_context_lines + 1):
src = git_root / src_relative
edited = edited_content.splitlines()
head_lines = head_srcs[src_relative]

# 2. diff HEAD and worktree for all file & dir paths on the command line
# 2. diff HEAD and worktree for the file
edited_opcodes = diff_and_get_opcodes(head_lines, edited)

# 3. extract line numbers in each edited to-file for changed lines
edited_linenums = list(opcodes_to_edit_linenums(edited_opcodes))
edited_linenums = list(
opcodes_to_edit_linenums(edited_opcodes, context_lines)
)
if (
isort
and not edited_linenums
Expand Down Expand Up @@ -123,7 +123,7 @@ def format_edited_parts(
# a partially re-formatted Python file which produces an identical AST.
# Try again with a larger `-U<context_lines>` option for `git diff`,
# or give up if `context_lines` is already very large.
if context_lines == MAX_CONTEXT_LINES:
if context_lines == max_context_lines:
raise
logger.debug(
"AST verification failed. "
Expand Down
16 changes: 13 additions & 3 deletions src/darker/diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,23 @@ def _validate_opcodes(opcodes: List[Tuple[str, int, int, int, int]]) -> None:


def opcodes_to_edit_linenums(
opcodes: List[Tuple[str, int, int, int, int]]
opcodes: List[Tuple[str, int, int, int, int]], context_lines: int
) -> Generator[int, None, None]:
"""Convert diff opcode to line number of edited lines in the destination file"""
"""Convert diff opcodes to line numbers of edited lines in the destination file
:param opcodes: The diff opcodes to convert
:param context_lines: The number of lines before and after an edited line to mark
edited as well
"""
_validate_opcodes(opcodes)
prev_chunk_end = 1
_tag, _i1, _i2, _j1, end = opcodes[-1]
for tag, _i1, _i2, j1, j2 in opcodes:
if tag != "equal":
yield from range(j1 + 1, j2 + 1)
chunk_end = min(j2 + 1 + context_lines, end + 1)
yield from range(max(j1 + 1 - context_lines, prev_chunk_end), chunk_end)
prev_chunk_end = chunk_end


def opcodes_to_chunks(
Expand Down
18 changes: 15 additions & 3 deletions src/darker/tests/test_diff.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from itertools import chain
from textwrap import dedent

import pytest
from black import FileMode, format_str

from darker.diff import (
Expand Down Expand Up @@ -141,7 +143,17 @@ def test_opcodes_to_chunks():
]


def test_opcodes_to_edit_linenums():
edit_linenums = list(opcodes_to_edit_linenums(OPCODES))
@pytest.mark.parametrize(
'context_lines, expect',
[
(0, [1, 4, 5, 13, 14, 17, 20, 22, 23, 27]),
(1, [[1, 6], [12, 24], [26, 28]]),
(2, [[1, 7], [11, 28]]),
],
)
def test_opcodes_to_edit_linenums(context_lines, expect):
edit_linenums = list(opcodes_to_edit_linenums(OPCODES, context_lines))
expect_ranges = [[n, n] if isinstance(n, int) else n for n in expect]
expect_linenums = list(chain(*(range(n[0], n[1] + 1) for n in expect_ranges)))

assert edit_linenums == [1, 4, 5, 13, 14, 17, 20, 22, 23, 27]
assert edit_linenums == expect_linenums

0 comments on commit 4a4c423

Please sign in to comment.