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.
2 from functools import partial
3 from io import StringIO
5 from pathlib import Path
7 from typing import Any, List, Tuple
9 from unittest.mock import patch
11 from click import unstyle
16 ff = partial(black.format_file_in_place, line_length=ll, fast=True)
17 fs = partial(black.format_str, line_length=ll)
18 THIS_FILE = Path(__file__)
19 THIS_DIR = THIS_FILE.parent
20 EMPTY_LINE = "# EMPTY LINE WITH WHITESPACE" + " (this comment will be removed)"
23 def dump_to_stderr(*output: str) -> str:
24 return "\n" + "\n".join(output) + "\n"
27 def read_data(name: str) -> Tuple[str, str]:
28 """read_data('test_name') -> 'input', 'output'"""
29 if not name.endswith((".py", ".out")):
31 _input: List[str] = []
32 _output: List[str] = []
33 with open(THIS_DIR / name, "r", encoding="utf8") as test:
34 lines = test.readlines()
37 line = line.replace(EMPTY_LINE, "")
38 if line.rstrip() == "# output":
43 if _input and not _output:
44 # If there's no output marker, treat the entire file as already pre-formatted.
46 return "".join(_input).strip() + "\n", "".join(_output).strip() + "\n"
49 class BlackTestCase(unittest.TestCase):
52 def assertFormatEqual(self, expected: str, actual: str) -> None:
53 if actual != expected and not os.environ.get("SKIP_AST_PRINT"):
54 bdv: black.DebugVisitor[Any]
55 black.out("Expected tree:", fg="green")
57 exp_node = black.lib2to3_parse(expected)
58 bdv = black.DebugVisitor()
59 list(bdv.visit(exp_node))
60 except Exception as ve:
62 black.out("Actual tree:", fg="red")
64 exp_node = black.lib2to3_parse(actual)
65 bdv = black.DebugVisitor()
66 list(bdv.visit(exp_node))
67 except Exception as ve:
69 self.assertEqual(expected, actual)
71 @patch("black.dump_to_file", dump_to_stderr)
72 def test_self(self) -> None:
73 source, expected = read_data("test_black")
75 self.assertFormatEqual(expected, actual)
76 black.assert_equivalent(source, actual)
77 black.assert_stable(source, actual, line_length=ll)
78 self.assertFalse(ff(THIS_FILE))
80 @patch("black.dump_to_file", dump_to_stderr)
81 def test_black(self) -> None:
82 source, expected = read_data("../black")
84 self.assertFormatEqual(expected, actual)
85 black.assert_equivalent(source, actual)
86 black.assert_stable(source, actual, line_length=ll)
87 self.assertFalse(ff(THIS_DIR / ".." / "black.py"))
89 def test_piping(self) -> None:
90 source, expected = read_data("../black")
91 hold_stdin, hold_stdout = sys.stdin, sys.stdout
93 sys.stdin, sys.stdout = StringIO(source), StringIO()
94 sys.stdin.name = "<stdin>"
95 black.format_stdin_to_stdout(line_length=ll, fast=True, write_back=True)
97 actual = sys.stdout.read()
99 sys.stdin, sys.stdout = hold_stdin, hold_stdout
100 self.assertFormatEqual(expected, actual)
101 black.assert_equivalent(source, actual)
102 black.assert_stable(source, actual, line_length=ll)
104 @patch("black.dump_to_file", dump_to_stderr)
105 def test_setup(self) -> None:
106 source, expected = read_data("../setup")
108 self.assertFormatEqual(expected, actual)
109 black.assert_equivalent(source, actual)
110 black.assert_stable(source, actual, line_length=ll)
111 self.assertFalse(ff(THIS_DIR / ".." / "setup.py"))
113 @patch("black.dump_to_file", dump_to_stderr)
114 def test_function(self) -> None:
115 source, expected = read_data("function")
117 self.assertFormatEqual(expected, actual)
118 black.assert_equivalent(source, actual)
119 black.assert_stable(source, actual, line_length=ll)
121 @patch("black.dump_to_file", dump_to_stderr)
122 def test_expression(self) -> None:
123 source, expected = read_data("expression")
125 self.assertFormatEqual(expected, actual)
126 black.assert_equivalent(source, actual)
127 black.assert_stable(source, actual, line_length=ll)
129 @patch("black.dump_to_file", dump_to_stderr)
130 def test_fstring(self) -> None:
131 source, expected = read_data("fstring")
133 self.assertFormatEqual(expected, actual)
134 black.assert_equivalent(source, actual)
135 black.assert_stable(source, actual, line_length=ll)
137 @patch("black.dump_to_file", dump_to_stderr)
138 def test_string_quotes(self) -> None:
139 source, expected = read_data("string_quotes")
141 self.assertFormatEqual(expected, actual)
142 black.assert_equivalent(source, actual)
143 black.assert_stable(source, actual, line_length=ll)
145 @patch("black.dump_to_file", dump_to_stderr)
146 def test_comments(self) -> None:
147 source, expected = read_data("comments")
149 self.assertFormatEqual(expected, actual)
150 black.assert_equivalent(source, actual)
151 black.assert_stable(source, actual, line_length=ll)
153 @patch("black.dump_to_file", dump_to_stderr)
154 def test_comments2(self) -> None:
155 source, expected = read_data("comments2")
157 self.assertFormatEqual(expected, actual)
158 black.assert_equivalent(source, actual)
159 black.assert_stable(source, actual, line_length=ll)
161 @patch("black.dump_to_file", dump_to_stderr)
162 def test_comments3(self) -> None:
163 source, expected = read_data("comments3")
165 self.assertFormatEqual(expected, actual)
166 black.assert_equivalent(source, actual)
167 black.assert_stable(source, actual, line_length=ll)
169 @patch("black.dump_to_file", dump_to_stderr)
170 def test_comments4(self) -> None:
171 source, expected = read_data("comments4")
173 self.assertFormatEqual(expected, actual)
174 black.assert_equivalent(source, actual)
175 black.assert_stable(source, actual, line_length=ll)
177 @patch("black.dump_to_file", dump_to_stderr)
178 def test_cantfit(self) -> None:
179 source, expected = read_data("cantfit")
181 self.assertFormatEqual(expected, actual)
182 black.assert_equivalent(source, actual)
183 black.assert_stable(source, actual, line_length=ll)
185 @patch("black.dump_to_file", dump_to_stderr)
186 def test_import_spacing(self) -> None:
187 source, expected = read_data("import_spacing")
189 self.assertFormatEqual(expected, actual)
190 black.assert_equivalent(source, actual)
191 black.assert_stable(source, actual, line_length=ll)
193 @patch("black.dump_to_file", dump_to_stderr)
194 def test_composition(self) -> None:
195 source, expected = read_data("composition")
197 self.assertFormatEqual(expected, actual)
198 black.assert_equivalent(source, actual)
199 black.assert_stable(source, actual, line_length=ll)
201 @patch("black.dump_to_file", dump_to_stderr)
202 def test_empty_lines(self) -> None:
203 source, expected = read_data("empty_lines")
205 self.assertFormatEqual(expected, actual)
206 black.assert_equivalent(source, actual)
207 black.assert_stable(source, actual, line_length=ll)
209 @patch("black.dump_to_file", dump_to_stderr)
210 def test_python2(self) -> None:
211 source, expected = read_data("python2")
213 self.assertFormatEqual(expected, actual)
214 # black.assert_equivalent(source, actual)
215 black.assert_stable(source, actual, line_length=ll)
217 @patch("black.dump_to_file", dump_to_stderr)
218 def test_fmtonoff(self) -> None:
219 source, expected = read_data("fmtonoff")
221 self.assertFormatEqual(expected, actual)
222 black.assert_equivalent(source, actual)
223 black.assert_stable(source, actual, line_length=ll)
225 def test_report(self) -> None:
226 report = black.Report()
230 def out(msg: str, **kwargs: Any) -> None:
231 out_lines.append(msg)
233 def err(msg: str, **kwargs: Any) -> None:
234 err_lines.append(msg)
236 with patch("black.out", out), patch("black.err", err):
237 report.done(Path("f1"), changed=False)
238 self.assertEqual(len(out_lines), 1)
239 self.assertEqual(len(err_lines), 0)
240 self.assertEqual(out_lines[-1], "f1 already well formatted, good job.")
241 self.assertEqual(unstyle(str(report)), "1 file left unchanged.")
242 self.assertEqual(report.return_code, 0)
243 report.done(Path("f2"), changed=True)
244 self.assertEqual(len(out_lines), 2)
245 self.assertEqual(len(err_lines), 0)
246 self.assertEqual(out_lines[-1], "reformatted f2")
248 unstyle(str(report)), "1 file reformatted, 1 file left unchanged."
250 self.assertEqual(report.return_code, 0)
252 self.assertEqual(report.return_code, 1)
254 report.failed(Path("e1"), "boom")
255 self.assertEqual(len(out_lines), 2)
256 self.assertEqual(len(err_lines), 1)
257 self.assertEqual(err_lines[-1], "error: cannot format e1: boom")
259 unstyle(str(report)),
260 "1 file reformatted, 1 file left unchanged, "
261 "1 file failed to reformat.",
263 self.assertEqual(report.return_code, 123)
264 report.done(Path("f3"), changed=True)
265 self.assertEqual(len(out_lines), 3)
266 self.assertEqual(len(err_lines), 1)
267 self.assertEqual(out_lines[-1], "reformatted f3")
269 unstyle(str(report)),
270 "2 files reformatted, 1 file left unchanged, "
271 "1 file failed to reformat.",
273 self.assertEqual(report.return_code, 123)
274 report.failed(Path("e2"), "boom")
275 self.assertEqual(len(out_lines), 3)
276 self.assertEqual(len(err_lines), 2)
277 self.assertEqual(err_lines[-1], "error: cannot format e2: boom")
279 unstyle(str(report)),
280 "2 files reformatted, 1 file left unchanged, "
281 "2 files failed to reformat.",
283 self.assertEqual(report.return_code, 123)
284 report.done(Path("f4"), changed=False)
285 self.assertEqual(len(out_lines), 4)
286 self.assertEqual(len(err_lines), 2)
287 self.assertEqual(out_lines[-1], "f4 already well formatted, good job.")
289 unstyle(str(report)),
290 "2 files reformatted, 2 files left unchanged, "
291 "2 files failed to reformat.",
293 self.assertEqual(report.return_code, 123)
296 unstyle(str(report)),
297 "2 files would be reformatted, 2 files would be left unchanged, "
298 "2 files would fail to reformat.",
301 def test_is_python36(self) -> None:
302 node = black.lib2to3_parse("def f(*, arg): ...\n")
303 self.assertFalse(black.is_python36(node))
304 node = black.lib2to3_parse("def f(*, arg,): ...\n")
305 self.assertTrue(black.is_python36(node))
306 node = black.lib2to3_parse("def f(*, arg): f'string'\n")
307 self.assertTrue(black.is_python36(node))
308 source, expected = read_data("function")
309 node = black.lib2to3_parse(source)
310 self.assertTrue(black.is_python36(node))
311 node = black.lib2to3_parse(expected)
312 self.assertTrue(black.is_python36(node))
313 source, expected = read_data("expression")
314 node = black.lib2to3_parse(source)
315 self.assertFalse(black.is_python36(node))
316 node = black.lib2to3_parse(expected)
317 self.assertFalse(black.is_python36(node))
319 def test_debug_visitor(self) -> None:
320 source, _ = read_data("debug_visitor.py")
321 expected, _ = read_data("debug_visitor.out")
325 def out(msg: str, **kwargs: Any) -> None:
326 out_lines.append(msg)
328 def err(msg: str, **kwargs: Any) -> None:
329 err_lines.append(msg)
331 with patch("black.out", out), patch("black.err", err):
332 black.DebugVisitor.show(source)
333 actual = "\n".join(out_lines) + "\n"
335 if expected != actual:
336 log_name = black.dump_to_file(*out_lines)
340 f"AST print out is different. Actual version dumped to {log_name}",
344 if __name__ == "__main__":