X-Git-Url: https://git.madduck.net/etc/vim.git/blobdiff_plain/b73b77a9b039d5afa6ab32202bff2b2232258d45..d4a85643a465f5fae2113d07d22d021d4af4795a:/tests/test_black.py?ds=sidebyside diff --git a/tests/test_black.py b/tests/test_black.py index 9256698..dda1055 100644 --- a/tests/test_black.py +++ b/tests/test_black.py @@ -25,6 +25,7 @@ from typing import ( List, Optional, Sequence, + Type, TypeVar, Union, ) @@ -153,6 +154,34 @@ class BlackTestCase(BlackBaseTestCase): os.unlink(tmp_file) self.assertFormatEqual(expected, actual) + @patch("black.dump_to_file", dump_to_stderr) + def test_one_empty_line(self) -> None: + mode = black.Mode(preview=True) + for nl in ["\n", "\r\n"]: + source = expected = nl + assert_format(source, expected, mode=mode) + + def test_one_empty_line_ff(self) -> None: + mode = black.Mode(preview=True) + for nl in ["\n", "\r\n"]: + expected = nl + tmp_file = Path(black.dump_to_file(nl)) + if system() == "Windows": + # Writing files in text mode automatically uses the system newline, + # but in this case we don't want this for testing reasons. See: + # https://github.com/psf/black/pull/3348 + with open(tmp_file, "wb") as f: + f.write(nl.encode("utf-8")) + try: + self.assertFalse( + ff(tmp_file, mode=mode, write_back=black.WriteBack.YES) + ) + with open(tmp_file, "rb") as f: + actual = f.read().decode("utf8") + finally: + os.unlink(tmp_file) + self.assertFormatEqual(expected, actual) + def test_experimental_string_processing_warns(self) -> None: self.assertWarns( black.mode.Deprecated, black.Mode, experimental_string_processing=True @@ -971,8 +1000,8 @@ class BlackTestCase(BlackBaseTestCase): ) def test_format_file_contents(self) -> None: - empty = "" mode = DEFAULT_MODE + empty = "" with self.assertRaises(black.NothingChanged): black.format_file_contents(empty, mode=mode, fast=False) just_nl = "\n" @@ -990,6 +1019,17 @@ class BlackTestCase(BlackBaseTestCase): black.format_file_contents(invalid, mode=mode, fast=False) self.assertEqual(str(e.exception), "Cannot parse: 1:7: return if you can") + mode = black.Mode(preview=True) + just_crlf = "\r\n" + with self.assertRaises(black.NothingChanged): + black.format_file_contents(just_crlf, mode=mode, fast=False) + just_whitespace_nl = "\n\t\n \n\t \n \t\n\n" + actual = black.format_file_contents(just_whitespace_nl, mode=mode, fast=False) + self.assertEqual("\n", actual) + just_whitespace_crlf = "\r\n\t\r\n \r\n\t \r\n \t\r\n\r\n" + actual = black.format_file_contents(just_whitespace_crlf, mode=mode, fast=False) + self.assertEqual("\r\n", actual) + def test_endmarker(self) -> None: n = black.lib2to3_parse("\n") self.assertEqual(n.type, black.syms.file_input) @@ -1281,8 +1321,51 @@ class BlackTestCase(BlackBaseTestCase): report.done.assert_called_with(expected, black.Changed.YES) def test_reformat_one_with_stdin_empty(self) -> None: + cases = [ + ("", ""), + ("\n", "\n"), + ("\r\n", "\r\n"), + (" \t", ""), + (" \t\n\t ", "\n"), + (" \t\r\n\t ", "\r\n"), + ] + + def _new_wrapper( + output: io.StringIO, io_TextIOWrapper: Type[io.TextIOWrapper] + ) -> Callable[[Any, Any], io.TextIOWrapper]: + def get_output(*args: Any, **kwargs: Any) -> io.TextIOWrapper: + if args == (sys.stdout.buffer,): + # It's `format_stdin_to_stdout()` calling `io.TextIOWrapper()`, + # return our mock object. + return output + # It's something else (i.e. `decode_bytes()`) calling + # `io.TextIOWrapper()`, pass through to the original implementation. + # See discussion in https://github.com/psf/black/pull/2489 + return io_TextIOWrapper(*args, **kwargs) + + return get_output + + mode = black.Mode(preview=True) + for content, expected in cases: + output = io.StringIO() + io_TextIOWrapper = io.TextIOWrapper + + with patch("io.TextIOWrapper", _new_wrapper(output, io_TextIOWrapper)): + try: + black.format_stdin_to_stdout( + fast=True, + content=content, + write_back=black.WriteBack.YES, + mode=mode, + ) + except io.UnsupportedOperation: + pass # StringIO does not support detach + assert output.getvalue() == expected + + # An empty string is the only test case for `preview=False` output = io.StringIO() - with patch("io.TextIOWrapper", lambda *args, **kwargs: output): + io_TextIOWrapper = io.TextIOWrapper + with patch("io.TextIOWrapper", _new_wrapper(output, io_TextIOWrapper)): try: black.format_stdin_to_stdout( fast=True, @@ -1998,6 +2081,17 @@ class TestFileCollection: ctx.obj["root"] = base assert_collected_sources(src, expected, ctx=ctx, extend_exclude=r"/exclude/") + def test_gitignore_used_on_multiple_sources(self) -> None: + root = Path(DATA_DIR / "gitignore_used_on_multiple_sources") + expected = [ + root / "dir1" / "b.py", + root / "dir2" / "b.py", + ] + ctx = FakeContext() + ctx.obj["root"] = root + src = [root / "dir1", root / "dir2"] + assert_collected_sources(src, expected, ctx=ctx) + @patch("black.find_project_root", lambda *args: (THIS_DIR.resolve(), None)) def test_exclude_for_issue_1572(self) -> None: # Exclude shouldn't touch files that were explicitly given to Black through the @@ -2031,7 +2125,7 @@ class TestFileCollection: None, None, report, - gitignore, + {path: gitignore}, verbose=False, quiet=False, ) @@ -2060,7 +2154,7 @@ class TestFileCollection: None, None, report, - root_gitignore, + {path: root_gitignore}, verbose=False, quiet=False, ) @@ -2098,6 +2192,32 @@ class TestFileCollection: gitignore = path / "a" / ".gitignore" assert f"Could not parse {gitignore}" in result.stderr_bytes.decode() + def test_gitignore_that_ignores_subfolders(self) -> None: + # If gitignore with */* is in root + root = Path(DATA_DIR / "ignore_subfolders_gitignore_tests" / "subdir") + expected = [root / "b.py"] + ctx = FakeContext() + ctx.obj["root"] = root + assert_collected_sources([root], expected, ctx=ctx) + + # If .gitignore with */* is nested + root = Path(DATA_DIR / "ignore_subfolders_gitignore_tests") + expected = [ + root / "a.py", + root / "subdir" / "b.py", + ] + ctx = FakeContext() + ctx.obj["root"] = root + assert_collected_sources([root], expected, ctx=ctx) + + # If command is executed from outer dir + root = Path(DATA_DIR / "ignore_subfolders_gitignore_tests") + target = root / "subdir" + expected = [target / "b.py"] + ctx = FakeContext() + ctx.obj["root"] = root + assert_collected_sources([target], expected, ctx=ctx) + def test_empty_include(self) -> None: path = DATA_DIR / "include_exclude_tests" src = [path] @@ -2152,7 +2272,7 @@ class TestFileCollection: None, None, report, - gitignore, + {path: gitignore}, verbose=False, quiet=False, )