Skip to content

Commit

Permalink
Preserve crlf line endings in blackd
Browse files Browse the repository at this point in the history
  • Loading branch information
KotlinIsland committed Sep 12, 2022
1 parent 383b228 commit 14cc0e4
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 1 deletion.
2 changes: 1 addition & 1 deletion CHANGES.md
Expand Up @@ -36,7 +36,7 @@

### _Blackd_

<!-- Changes to blackd -->
- Windows style (CRLF) newlines will be preserved (#3257).

### Integrations

Expand Down
4 changes: 4 additions & 0 deletions docs/the_black_code_style/current_style.md
Expand Up @@ -406,6 +406,10 @@ file that are not enforced yet but might be in a future version of the formatter
- use variable annotations instead of type comments, even for stubs that target older
versions of Python.

### Line endings
_Black_ will normalize line endings (`\n` or `\r\n`) based on the first line ending of
the file.

## Pragmatism

Early versions of _Black_ used to be absolutist in some respects. They took after its
Expand Down
7 changes: 7 additions & 0 deletions src/blackd/__init__.py
Expand Up @@ -133,6 +133,13 @@ async def handle(request: web.Request, executor: Executor) -> web.Response:
executor, partial(black.format_file_contents, req_str, fast=fast, mode=mode)
)

# Preserve CRLF line endings
if req_str[req_str.find("\n") - 1] == "\r":
formatted_str = formatted_str.replace("\n", "\r\n")
# If, after swapping line endings, nothing changed, then say so
if formatted_str == req_str:
raise black.NothingChanged

# Only output the diff in the HTTP response
only_diff = bool(request.headers.get(DIFF_HEADER, False))
if only_diff:
Expand Down
8 changes: 8 additions & 0 deletions tests/test_black.py
Expand Up @@ -1286,6 +1286,14 @@ def test_preserves_line_endings_via_stdin(self) -> None:
if nl == "\n":
self.assertNotIn(b"\r\n", output)

def test_normalize_line_endings(self) -> None:
with TemporaryDirectory() as workspace:
test_file = Path(workspace) / "test.py"
for data, expected in ((b"c\r\nc\n ", b"c\r\nc\r\n"), (b"l\nl\r\n ", b"l\nl\n")):
test_file.write_bytes(data)
ff(test_file, write_back=black.WriteBack.YES)
self.assertEqual(test_file.read_bytes(), expected)

def test_assert_equivalent_different_asts(self) -> None:
with self.assertRaises(AssertionError):
black.assert_equivalent("{}", "None")
Expand Down
17 changes: 17 additions & 0 deletions tests/test_blackd.py
Expand Up @@ -209,3 +209,20 @@ async def test_cors_headers_present(self) -> None:
response = await self.client.post("/", headers={"Origin": "*"})
self.assertIsNotNone(response.headers.get("Access-Control-Allow-Origin"))
self.assertIsNotNone(response.headers.get("Access-Control-Expose-Headers"))

@unittest_run_loop
async def test_preserves_line_endings(self) -> None:
for data in (b"c\r\nc\r\n", b"l\nl\n"):
# test preserved newlines when reformatted
response = await self.client.post("/", data=data + b" ")
self.assertEqual(await response.text(), data.decode())
# test 204 when no change
response = await self.client.post("/", data=data)
self.assertEqual(response.status, 204)

@unittest_run_loop
async def test_normalizes_line_endings(self) -> None:
for data, expected in ((b"c\r\nc\n", "c\r\nc\r\n"), (b"l\nl\r\n", "l\nl\n")):
response = await self.client.post("/", data=data)
self.assertEqual(await response.text(), expected)
self.assertEqual(response.status, 200)

0 comments on commit 14cc0e4

Please sign in to comment.