Skip to content

Commit

Permalink
Modify sorted_by_file_and_line to sort only by (filename, line) (#67)
Browse files Browse the repository at this point in the history
Currently, sorted_by_file_and_line uses `(filename, line, content)`.
This means it is not stable within `(filename, line)` and can
incorrectly reorder multiline outputs

Closes #66
  • Loading branch information
zero323 authored Oct 9, 2021
1 parent 639263d commit 97f8b32
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 5 deletions.
33 changes: 33 additions & 0 deletions pytest_mypy_plugins/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
TypecheckAssertionError,
assert_expected_matched_actual,
extract_output_matchers_from_comments,
sorted_by_file_and_line,
)


Expand Down Expand Up @@ -184,3 +185,35 @@ def test_assert_expected_matched_actual_failures(
assert_expected_matched_actual(expected, actual_lines)

assert e.value.error_message.strip() == expected_error_message.strip()


@pytest.mark.parametrize(
"input_lines",
[
[
'''main:12: error: No overload variant of "f" matches argument type "List[int]"''',
"""main:12: note: Possible overload variants:""",
"""main:12: note: def f(x: int) -> int""",
"""main:12: note: def f(x: str) -> str""",
],
[
'''main_a:12: error: No overload variant of "g" matches argument type "List[int]"''',
'''main_b:12: error: No overload variant of "f" matches argument type "List[int]"''',
"""main_b:12: note: Possible overload variants:""",
"""main_a:12: note: def g(b: int) -> int""",
"""main_a:12: note: def g(a: int) -> int""",
"""main_b:12: note: def f(x: int) -> int""",
"""main_b:12: note: def f(x: str) -> str""",
],
],
)
def test_sorted_by_file_and_line_is_stable(input_lines: List[str]) -> None:
def lines_for_file(lines: List[str], fname: str) -> List[str]:
prefix = f"{fname}:"
return [line for line in lines if line.startswith(prefix)]

files = sorted({line.split(":", maxsplit=1)[0] for line in input_lines})
sorted_lines = sorted_by_file_and_line(input_lines)

for f in files:
assert lines_for_file(sorted_lines, f) == lines_for_file(input_lines, f)
10 changes: 5 additions & 5 deletions pytest_mypy_plugins/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,15 +194,15 @@ def remove_empty_lines(lines: List[str]) -> List[str]:


def sorted_by_file_and_line(lines: List[str]) -> List[str]:
def extract_parts_as_tuple(line: str) -> Tuple[str, int, str]:
def extract_parts_as_tuple(line: str) -> Tuple[str, int]:
if len(line.split(":", maxsplit=2)) < 3:
return "", 0, ""
return "", 0

fname, line_number, contents = line.split(":", maxsplit=2)
fname, line_number, _ = line.split(":", maxsplit=2)
try:
return fname, int(line_number), contents
return fname, int(line_number)
except ValueError:
return "", 0, ""
return "", 0

return sorted(lines, key=extract_parts_as_tuple)

Expand Down

0 comments on commit 97f8b32

Please sign in to comment.