]> git.madduck.net Git - etc/vim.git/commitdiff

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Indicate that a final newline was added in --diff (#1897) (#1897)
authorPaul "TBBle" Hampson <Paul.Hampson@Pobox.com>
Mon, 22 Feb 2021 06:43:23 +0000 (17:43 +1100)
committerGitHub <noreply@github.com>
Mon, 22 Feb 2021 06:43:23 +0000 (22:43 -0800)
Fixes: #1662
Work-around for https://bugs.python.org/issue2142

The test has to slightly mess with its input data, because the utility
functions default to ensuring the test data has a final newline, which
defeats the point of the test.

Signed-off-by: Paul "TBBle" Hampson <Paul.Hampson@Pobox.com>
CHANGES.md
docs/authors.md
src/black/__init__.py
tests/data/missing_final_newline.diff [new file with mode: 0644]
tests/data/missing_final_newline.py [new file with mode: 0644]
tests/test_black.py

index 5f7ca4f4da7825f4b04794f0c32e40b6dbcae225..3fd7ad40496a929467329e576949065dc27361da 100644 (file)
@@ -28,6 +28,8 @@
 
 - speed up caching by avoiding pathlib (#1950)
 
+- `--diff` correctly indicates when a file doesn't end in a newline (#1662)
+
 #### _Packaging_
 
 - Self-contained native _Black_ binaries are now provided for releases via GitHub
index cdf5046c446310eb5c454b7b09056d999bfaf497..9f2ea0571b9a48d79200b06ef132e788e776d73e 100644 (file)
@@ -132,6 +132,7 @@ Multiple contributions by:
 - [Pablo Galindo](mailto:Pablogsal@gmail.com)
 - [Paul Ganssle](mailto:p.ganssle@gmail.com)
 - [Paul Meinhardt](mailto:mnhrdt@gmail.com)
+- [Paul "TBBle" Hampson](mailto:Paul.Hampson@Pobox.com)
 - [Peter Bengtsson](mailto:mail@peterbe.com)
 - [Peter Grayson](mailto:pete@jpgrayson.net)
 - [Peter Stensmyr](mailto:peter.stensmyr@gmail.com)
index 0b734adca565e507aa3ed1daeec4cf49b1fcb61f..c1907d9b1f10dd47a19d30df5686d9885fda4fdb 100644 (file)
@@ -6425,14 +6425,14 @@ def assert_stable(src: str, dst: str, mode: Mode) -> None:
 
 
 @mypyc_attr(patchable=True)
-def dump_to_file(*output: str) -> str:
+def dump_to_file(*output: str, ensure_final_newline: bool = True) -> str:
     """Dump `output` to a temporary file. Return path to the file."""
     with tempfile.NamedTemporaryFile(
         mode="w", prefix="blk_", suffix=".log", delete=False, encoding="utf8"
     ) as f:
         for lines in output:
             f.write(lines)
-            if lines and lines[-1] != "\n":
+            if ensure_final_newline and lines and lines[-1] != "\n":
                 f.write("\n")
     return f.name
 
@@ -6450,11 +6450,20 @@ def diff(a: str, b: str, a_name: str, b_name: str) -> str:
     """Return a unified diff string between strings `a` and `b`."""
     import difflib
 
-    a_lines = [line + "\n" for line in a.splitlines()]
-    b_lines = [line + "\n" for line in b.splitlines()]
-    return "".join(
-        difflib.unified_diff(a_lines, b_lines, fromfile=a_name, tofile=b_name, n=5)
-    )
+    a_lines = [line for line in a.splitlines(keepends=True)]
+    b_lines = [line for line in b.splitlines(keepends=True)]
+    diff_lines = []
+    for line in difflib.unified_diff(
+        a_lines, b_lines, fromfile=a_name, tofile=b_name, n=5
+    ):
+        # Work around https://bugs.python.org/issue2142
+        # See https://www.gnu.org/software/diffutils/manual/html_node/Incomplete-Lines.html
+        if line[-1] == "\n":
+            diff_lines.append(line)
+        else:
+            diff_lines.append(line + "\n")
+            diff_lines.append("\\ No newline at end of file\n")
+    return "".join(diff_lines)
 
 
 def cancel(tasks: Iterable["asyncio.Task[Any]"]) -> None:
diff --git a/tests/data/missing_final_newline.diff b/tests/data/missing_final_newline.diff
new file mode 100644 (file)
index 0000000..6d991c7
--- /dev/null
@@ -0,0 +1,8 @@
+--- [Deterministic header]
++++ [Deterministic header]
+@@ -1,3 +1,3 @@
+ # A comment-only file, with no final EOL character
+ # This triggers https://bugs.python.org/issue2142
+-# This is the line without the EOL character
+\ No newline at end of file
++# This is the line without the EOL character
diff --git a/tests/data/missing_final_newline.py b/tests/data/missing_final_newline.py
new file mode 100644 (file)
index 0000000..687e136
--- /dev/null
@@ -0,0 +1,3 @@
+# A comment-only file, with no final EOL character
+# This triggers https://bugs.python.org/issue2142
+# This is the line without the EOL character
\ No newline at end of file
index a2efef8242287b4194ce5deed1eab650c113623a..5d14ceda8f49f172c6a34c66747882a6eca070cd 100644 (file)
@@ -300,7 +300,6 @@ class BlackTestCase(BlackBaseTestCase):
             os.unlink(tmp_file)
         actual = result.output
         actual = diff_header.sub(DETERMINISTIC_HEADER, actual)
-        actual = actual.rstrip() + "\n"  # the diff output has a trailing space
         if expected != actual:
             dump = black.dump_to_file(actual)
             msg = (
@@ -1798,6 +1797,28 @@ class BlackTestCase(BlackBaseTestCase):
         output = black.format_str(source, mode=DEFAULT_MODE)
         black.assert_stable(source, output, mode=DEFAULT_MODE)
 
+    def test_bpo_2142_workaround(self) -> None:
+
+        # https://bugs.python.org/issue2142
+
+        source, _ = read_data("missing_final_newline.py")
+        # read_data adds a trailing newline
+        source = source.rstrip()
+        expected, _ = read_data("missing_final_newline.diff")
+        tmp_file = Path(black.dump_to_file(source, ensure_final_newline=False))
+        diff_header = re.compile(
+            rf"{re.escape(str(tmp_file))}\t\d\d\d\d-\d\d-\d\d "
+            r"\d\d:\d\d:\d\d\.\d\d\d\d\d\d \+\d\d\d\d"
+        )
+        try:
+            result = BlackRunner().invoke(black.main, ["--diff", str(tmp_file)])
+            self.assertEqual(result.exit_code, 0)
+        finally:
+            os.unlink(tmp_file)
+        actual = result.output
+        actual = diff_header.sub(DETERMINISTIC_HEADER, actual)
+        self.assertEqual(actual, expected)
+
 
 with open(black.__file__, "r", encoding="utf-8") as _bf:
     black_source_lines = _bf.readlines()