X-Git-Url: https://git.madduck.net/etc/vim.git/blobdiff_plain/4c352ad4be70c72ba9b949d3afb7c242522d058e..affc0ec3f90803e77fbba62376e7be9b71fe0807:/tests/test_black.py?ds=inline diff --git a/tests/test_black.py b/tests/test_black.py index adf5ede..1271290 100644 --- a/tests/test_black.py +++ b/tests/test_black.py @@ -3,21 +3,22 @@ import asyncio from concurrent.futures import ThreadPoolExecutor from contextlib import contextmanager from functools import partial -from io import StringIO +from io import BytesIO, TextIOWrapper import os from pathlib import Path +import re import sys from tempfile import TemporaryDirectory -from typing import Any, List, Tuple, Iterator +from typing import Any, BinaryIO, Generator, List, Tuple, Iterator import unittest from unittest.mock import patch -import re from click import unstyle from click.testing import CliRunner import black + ll = 88 ff = partial(black.format_file_in_place, line_length=ll, fast=True) fs = partial(black.format_str, line_length=ll) @@ -77,6 +78,26 @@ def event_loop(close: bool) -> Iterator[None]: loop.close() +class BlackRunner(CliRunner): + """Modify CliRunner so that stderr is not merged with stdout. + + This is a hack that can be removed once we depend on Click 7.x""" + + def __init__(self, stderrbuf: BinaryIO) -> None: + self.stderrbuf = stderrbuf + super().__init__() + + @contextmanager + def isolation(self, *args: Any, **kwargs: Any) -> Generator[BinaryIO, None, None]: + with super().isolation(*args, **kwargs) as output: + try: + hold_stderr = sys.stderr + sys.stderr = TextIOWrapper(self.stderrbuf, encoding=self.charset) + yield output + finally: + sys.stderr = hold_stderr + + class BlackTestCase(unittest.TestCase): maxDiff = None @@ -99,6 +120,25 @@ class BlackTestCase(unittest.TestCase): black.err(str(ve)) self.assertEqual(expected, actual) + @patch("black.dump_to_file", dump_to_stderr) + def test_empty(self) -> None: + source = expected = "" + actual = fs(source) + self.assertFormatEqual(expected, actual) + black.assert_equivalent(source, actual) + black.assert_stable(source, actual, line_length=ll) + + def test_empty_ff(self) -> None: + expected = "" + tmp_file = Path(black.dump_to_file()) + try: + self.assertFalse(ff(tmp_file, write_back=black.WriteBack.YES)) + with open(tmp_file, encoding="utf8") as f: + actual = f.read() + finally: + os.unlink(tmp_file) + self.assertFormatEqual(expected, actual) + @patch("black.dump_to_file", dump_to_stderr) def test_self(self) -> None: source, expected = read_data("test_black") @@ -119,35 +159,28 @@ class BlackTestCase(unittest.TestCase): def test_piping(self) -> None: source, expected = read_data("../black") - hold_stdin, hold_stdout = sys.stdin, sys.stdout - try: - sys.stdin, sys.stdout = StringIO(source), StringIO() - sys.stdin.name = "" - black.format_stdin_to_stdout( - line_length=ll, fast=True, write_back=black.WriteBack.YES - ) - sys.stdout.seek(0) - actual = sys.stdout.read() - finally: - sys.stdin, sys.stdout = hold_stdin, hold_stdout - self.assertFormatEqual(expected, actual) - black.assert_equivalent(source, actual) - black.assert_stable(source, actual, line_length=ll) + stderrbuf = BytesIO() + result = BlackRunner(stderrbuf).invoke( + black.main, ["-", "--fast", f"--line-length={ll}"], input=source + ) + self.assertEqual(result.exit_code, 0) + self.assertFormatEqual(expected, result.output) + black.assert_equivalent(source, result.output) + black.assert_stable(source, result.output, line_length=ll) def test_piping_diff(self) -> None: + diff_header = re.compile( + rf"(STDIN|STDOUT)\t\d\d\d\d-\d\d-\d\d " + rf"\d\d:\d\d:\d\d\.\d\d\d\d\d\d \+\d\d\d\d" + ) source, _ = read_data("expression.py") expected, _ = read_data("expression.diff") - hold_stdin, hold_stdout = sys.stdin, sys.stdout - try: - sys.stdin, sys.stdout = StringIO(source), StringIO() - sys.stdin.name = "" - black.format_stdin_to_stdout( - line_length=ll, fast=True, write_back=black.WriteBack.DIFF - ) - sys.stdout.seek(0) - actual = sys.stdout.read() - finally: - sys.stdin, sys.stdout = hold_stdin, hold_stdout + stderrbuf = BytesIO() + result = BlackRunner(stderrbuf).invoke( + black.main, ["-", "--fast", f"--line-length={ll}", "--diff"], input=source + ) + self.assertEqual(result.exit_code, 0) + actual = diff_header.sub("[Deterministic header]", result.output) actual = actual.rstrip() + "\n" # the diff output has a trailing space self.assertEqual(expected, actual) @@ -202,16 +235,20 @@ class BlackTestCase(unittest.TestCase): source, _ = read_data("expression.py") expected, _ = read_data("expression.diff") tmp_file = Path(black.dump_to_file(source)) - hold_stdout = sys.stdout + diff_header = re.compile( + rf"{re.escape(str(tmp_file))}\t\d\d\d\d-\d\d-\d\d " + rf"\d\d:\d\d:\d\d\.\d\d\d\d\d\d \+\d\d\d\d" + ) + stderrbuf = BytesIO() try: - sys.stdout = StringIO() - self.assertTrue(ff(tmp_file, write_back=black.WriteBack.DIFF)) - sys.stdout.seek(0) - actual = sys.stdout.read() - actual = actual.replace(str(tmp_file), "") + result = BlackRunner(stderrbuf).invoke( + black.main, ["--diff", str(tmp_file)] + ) + self.assertEqual(result.exit_code, 0) finally: - sys.stdout = hold_stdout 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) @@ -854,10 +891,10 @@ class BlackTestCase(unittest.TestCase): cached_but_changed.touch() cache = {cached: black.get_cache_info(cached), cached_but_changed: (0.0, 0)} todo, done = black.filter_cached( - cache, [uncached, cached, cached_but_changed] + cache, {uncached, cached, cached_but_changed} ) - self.assertEqual(todo, [uncached, cached_but_changed]) - self.assertEqual(done, [cached]) + self.assertEqual(todo, {uncached, cached_but_changed}) + self.assertEqual(done, {cached}) def test_write_cache_creates_directory_if_needed(self) -> None: mode = black.FileMode.AUTO_DETECT @@ -1108,6 +1145,22 @@ class BlackTestCase(unittest.TestCase): result = CliRunner().invoke(black.main, ["-", option, "**()(!!*)"]) self.assertEqual(result.exit_code, 2) + def test_preserves_line_endings(self) -> None: + with TemporaryDirectory() as workspace: + test_file = Path(workspace) / "test.py" + for nl in ["\n", "\r\n"]: + contents = nl.join(["def f( ):", " pass"]) + test_file.write_bytes(contents.encode()) + ff(test_file, write_back=black.WriteBack.YES) + updated_contents: bytes = test_file.read_bytes() + self.assertIn(nl.encode(), updated_contents) # type: ignore + if nl == "\n": + self.assertNotIn(b"\r\n", updated_contents) # type: ignore + + def test_assert_equivalent_different_asts(self) -> None: + with self.assertRaises(AssertionError): + black.assert_equivalent("{}", "None") + if __name__ == "__main__": unittest.main()