diff --git a/CHANGES.md b/CHANGES.md index 13b57e76959..6ebf7c3a8f3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -16,6 +16,7 @@ - Handle `# fmt: skip` followed by a comment at the end of file (#4635) - Fix crash when a tuple appears in the `as` clause of a `with` statement (#4634) - Fix crash when tuple is used as a context manager inside a `with` statement (#4646) +- Fix crash when formatting a `\` followed by a `\r` followed by a comment (#4663) - Fix crash on a `\\r\n` (#4673) - Fix crash on `await ...` (where `...` is a literal `Ellipsis`) (#4676) - Remove support for pre-python 3.7 `await/async` as soft keywords/variable names diff --git a/src/black/comments.py b/src/black/comments.py index 81d3cfd4a35..2b530f2b910 100644 --- a/src/black/comments.py +++ b/src/black/comments.py @@ -88,7 +88,7 @@ def list_comments(prefix: str, *, is_endmarker: bool) -> list[ProtoComment]: nlines = 0 ignored_lines = 0 form_feed = False - for index, full_line in enumerate(re.split("\r?\n", prefix)): + for index, full_line in enumerate(re.split("\r?\n|\r", prefix)): consumed += len(full_line) + 1 # adding the length of the split '\n' match = re.match(r"^(\s*)(\S.*|)$", full_line) assert match diff --git a/tests/test_black.py b/tests/test_black.py index f0a5fc74e1f..98d03652abe 100644 --- a/tests/test_black.py +++ b/tests/test_black.py @@ -2048,10 +2048,20 @@ def test_lines_with_leading_tabs_expanded(self) -> None: assert lines_with_leading_tabs_expanded("\t\tx") == [f"{tab}{tab}x"] assert lines_with_leading_tabs_expanded("\tx\n y") == [f"{tab}x", " y"] - def test_backslash_carriage_return(self) -> None: + def test_carriage_return_edge_cases(self) -> None: # These tests are here instead of in the normal cases because # of git's newline normalization and because it's hard to - # get `\r` vs `\r\n` vs `\n` to display properly in editors + # get `\r` vs `\r\n` vs `\n` to display properly + assert ( + black.format_str( + "try:\\\r# type: ignore\n pass\nfinally:\n pass\n", + mode=black.FileMode(), + ) + == "try: # type: ignore\n pass\nfinally:\n pass\n" + ) + assert black.format_str("{\r}", mode=black.FileMode()) == "{}\n" + assert black.format_str("pass #\r#\n", mode=black.FileMode()) == "pass #\n#\n" + assert black.format_str("x=\\\r\n1", mode=black.FileMode()) == "x = 1\n" assert black.format_str("x=\\\n1", mode=black.FileMode()) == "x = 1\n" assert black.format_str("x=\\\r1", mode=black.FileMode()) == "x = 1\n"