diff --git a/mypy/test/data.py b/mypy/test/data.py index 5b0ad84c0ba7..fab201d7cc59 100644 --- a/mypy/test/data.py +++ b/mypy/test/data.py @@ -445,7 +445,7 @@ def trimmed_newlines(self) -> int: # compensates for strip_list def parse_test_data(raw_data: str, name: str) -> list[TestItem]: - """Parse a list of lines that represent a sequence of test items.""" + """Parse a multi-line text that represents a sequence of test items in a single test case.""" lines = ["", "[case " + name + "]"] + raw_data.split("\n") ret: list[TestItem] = [] diff --git a/mypy/test/meta/test_update_data.py b/mypy/test/meta/test_update_data.py index 820fd359893e..383d8c7b7bbf 100644 --- a/mypy/test/meta/test_update_data.py +++ b/mypy/test/meta/test_update_data.py @@ -21,7 +21,7 @@ def test_update_data(self) -> None: # Note: We test multiple testcases rather than 'test case per test case' # so we could also exercise rewriting multiple testcases at once. result = _run_pytest_update_data( - """ + r""" [case testCorrect] s: str = 42 # E: Incompatible types in assignment (expression has type "int", variable has type "str") @@ -49,11 +49,27 @@ def test_update_data(self) -> None: s: str = 'foo' # W: foo \ # N: bar + [case testIndentationOfMultiline] + s: str = 42; i: int = 'foo' # E: Incompatible types in assignment (expression has type "int", variable has type "str")\ + # E: Incompatible types in assignment (expression has type "int", variable has type "str") + s2: str = 42; i2: int = 'foo' # E: Incompatible types in assignment (expression has type "int", variable has type "str")\ + # E: Incompatible types in assignment (expression has type "int", variable has type "str") + [case testOutCorrect] s: str = 42 [out] main:1: error: Incompatible types in assignment (expression has type "int", variable has type "str") + [case testOutWithMuchTraillingWhitespace] + s: str = 42 + [out] + main:1: error: Incompatible types in assignment (expression has type "int", variable has type "str") + + + + + + [case testOutWrong] s: str = 42 [out] @@ -79,7 +95,7 @@ def test_update_data(self) -> None: # Assert expected = dedent_docstring( - """ + r""" [case testCorrect] s: str = 42 # E: Incompatible types in assignment (expression has type "int", variable has type "str") @@ -93,7 +109,7 @@ def test_update_data(self) -> None: s: str = 42 # E: Incompatible types in assignment (expression has type "int", variable has type "str") [case testMissingMultiline] - s: str = 42; i: int = 'foo' # E: Incompatible types in assignment (expression has type "int", variable has type "str") \\ + s: str = 42; i: int = 'foo' # E: Incompatible types in assignment (expression has type "int", variable has type "str") \ # E: Incompatible types in assignment (expression has type "str", variable has type "int") [case testExtraneous] @@ -105,11 +121,27 @@ def test_update_data(self) -> None: [case testExtraneousMultilineNonError] s: str = 'foo' + [case testIndentationOfMultiline] + s: str = 42; i: int = 'foo' # E: Incompatible types in assignment (expression has type "int", variable has type "str") \ + # E: Incompatible types in assignment (expression has type "str", variable has type "int") + s2: str = 42; i2: int = 'foo' # E: Incompatible types in assignment (expression has type "int", variable has type "str") \ + # E: Incompatible types in assignment (expression has type "str", variable has type "int") + [case testOutCorrect] s: str = 42 [out] main:1: error: Incompatible types in assignment (expression has type "int", variable has type "str") + [case testOutWithMuchTraillingWhitespace] + s: str = 42 + [out] + main:1: error: Incompatible types in assignment (expression has type "int", variable has type "str") + + + + + + [case testOutWrong] s: str = 42 [out] diff --git a/mypy/test/update_data.py b/mypy/test/update_data.py index 84b6383b3f0c..c3f02641aae2 100644 --- a/mypy/test/update_data.py +++ b/mypy/test/update_data.py @@ -63,17 +63,19 @@ def _iter_fixes( fix_lines = [] for lineno, source_line in enumerate(source_lines, start=1): - reports = reports_by_line.get((file_path, lineno)) + reports_on_this_line = reports_by_line.get((file_path, lineno)) comment_match = re.search(r"(?P\s+)(?P# [EWN]: .+)$", source_line) if comment_match: source_line = source_line[: comment_match.start("indent")] # strip old comment - if reports: + if reports_on_this_line: indent = comment_match.group("indent") if comment_match else " " - # multiline comments are on the first line and then on subsequent lines empty lines - # with a continuation backslash - for j, (severity, msg) in enumerate(reports): - out_l = source_line if j == 0 else " " * len(source_line) - is_last = j == len(reports) - 1 + # Multiple info reports for the same line are represented in these + # comments with the first on the relevant line, then the subsequent + # ones on subsequent empty (indented) lines + # using continuation backslashes + for i, (severity, msg) in enumerate(reports_on_this_line): + out_l = source_line if i == 0 else " " * len(source_line) + is_last = i == len(reports_on_this_line) - 1 severity_char = severity[0].upper() continuation = "" if is_last else " \\" fix_lines.append(f"{out_l}{indent}# {severity_char}: {msg}{continuation}")