]> git.madduck.net Git - etc/vim.git/blob - tests/test_black.py

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:

Only return exit code 1 when --check is used
[etc/vim.git] / tests / test_black.py
1 #!/usr/bin/env python3
2 from functools import partial
3 from io import StringIO
4 import os
5 from pathlib import Path
6 import sys
7 from typing import Any, List, Tuple
8 import unittest
9 from unittest.mock import patch
10
11 from click import unstyle
12
13 import black
14
15 ll = 88
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
21
22 def dump_to_stderr(*output: str) -> str:
23     return '\n' + '\n'.join(output) + '\n'
24
25
26 def read_data(name: str) -> Tuple[str, str]:
27     """read_data('test_name') -> 'input', 'output'"""
28     if not name.endswith('.py'):
29         name += '.py'
30     _input: List[str] = []
31     _output: List[str] = []
32     with open(THIS_DIR / name, 'r', encoding='utf8') as test:
33         lines = test.readlines()
34     result = _input
35     for line in lines:
36         if line.rstrip() == '# output':
37             result = _output
38             continue
39
40         result.append(line)
41     if _input and not _output:
42         # If there's no output marker, treat the entire file as already pre-formatted.
43         _output = _input[:]
44     return ''.join(_input).strip() + '\n', ''.join(_output).strip() + '\n'
45
46
47 class BlackTestCase(unittest.TestCase):
48     maxDiff = None
49
50     def assertFormatEqual(self, expected: str, actual: str) -> None:
51         if actual != expected and not os.environ.get('SKIP_AST_PRINT'):
52             bdv: black.DebugVisitor[Any]
53             black.out('Expected tree:', fg='green')
54             try:
55                 exp_node = black.lib2to3_parse(expected)
56                 bdv = black.DebugVisitor()
57                 list(bdv.visit(exp_node))
58             except Exception as ve:
59                 black.err(str(ve))
60             black.out('Actual tree:', fg='red')
61             try:
62                 exp_node = black.lib2to3_parse(actual)
63                 bdv = black.DebugVisitor()
64                 list(bdv.visit(exp_node))
65             except Exception as ve:
66                 black.err(str(ve))
67         self.assertEqual(expected, actual)
68
69     @patch("black.dump_to_file", dump_to_stderr)
70     def test_self(self) -> None:
71         source, expected = read_data('test_black')
72         actual = fs(source)
73         self.assertFormatEqual(expected, actual)
74         black.assert_equivalent(source, actual)
75         black.assert_stable(source, actual, line_length=ll)
76         self.assertFalse(ff(THIS_FILE))
77
78     @patch("black.dump_to_file", dump_to_stderr)
79     def test_black(self) -> None:
80         source, expected = read_data('../black')
81         actual = fs(source)
82         self.assertFormatEqual(expected, actual)
83         black.assert_equivalent(source, actual)
84         black.assert_stable(source, actual, line_length=ll)
85         self.assertFalse(ff(THIS_DIR / '..' / 'black.py'))
86
87     def test_piping(self) -> None:
88         source, expected = read_data('../black')
89         hold_stdin, hold_stdout = sys.stdin, sys.stdout
90         try:
91             sys.stdin, sys.stdout = StringIO(source), StringIO()
92             sys.stdin.name = '<stdin>'
93             black.format_stdin_to_stdout(line_length=ll, fast=True, write_back=True)
94             sys.stdout.seek(0)
95             actual = sys.stdout.read()
96         finally:
97             sys.stdin, sys.stdout = hold_stdin, hold_stdout
98         self.assertFormatEqual(expected, actual)
99         black.assert_equivalent(source, actual)
100         black.assert_stable(source, actual, line_length=ll)
101
102     @patch("black.dump_to_file", dump_to_stderr)
103     def test_setup(self) -> None:
104         source, expected = read_data('../setup')
105         actual = fs(source)
106         self.assertFormatEqual(expected, actual)
107         black.assert_equivalent(source, actual)
108         black.assert_stable(source, actual, line_length=ll)
109         self.assertFalse(ff(THIS_DIR / '..' / 'setup.py'))
110
111     @patch("black.dump_to_file", dump_to_stderr)
112     def test_function(self) -> None:
113         source, expected = read_data('function')
114         actual = fs(source)
115         self.assertFormatEqual(expected, actual)
116         black.assert_equivalent(source, actual)
117         black.assert_stable(source, actual, line_length=ll)
118
119     @patch("black.dump_to_file", dump_to_stderr)
120     def test_expression(self) -> None:
121         source, expected = read_data('expression')
122         actual = fs(source)
123         self.assertFormatEqual(expected, actual)
124         black.assert_equivalent(source, actual)
125         black.assert_stable(source, actual, line_length=ll)
126
127     @patch("black.dump_to_file", dump_to_stderr)
128     def test_fstring(self) -> None:
129         source, expected = read_data('fstring')
130         actual = fs(source)
131         self.assertFormatEqual(expected, actual)
132         black.assert_equivalent(source, actual)
133         black.assert_stable(source, actual, line_length=ll)
134
135     @patch("black.dump_to_file", dump_to_stderr)
136     def test_comments(self) -> None:
137         source, expected = read_data('comments')
138         actual = fs(source)
139         self.assertFormatEqual(expected, actual)
140         black.assert_equivalent(source, actual)
141         black.assert_stable(source, actual, line_length=ll)
142
143     @patch("black.dump_to_file", dump_to_stderr)
144     def test_comments2(self) -> None:
145         source, expected = read_data('comments2')
146         actual = fs(source)
147         self.assertFormatEqual(expected, actual)
148         black.assert_equivalent(source, actual)
149         black.assert_stable(source, actual, line_length=ll)
150
151     @patch("black.dump_to_file", dump_to_stderr)
152     def test_cantfit(self) -> None:
153         source, expected = read_data('cantfit')
154         actual = fs(source)
155         self.assertFormatEqual(expected, actual)
156         black.assert_equivalent(source, actual)
157         black.assert_stable(source, actual, line_length=ll)
158
159     @patch("black.dump_to_file", dump_to_stderr)
160     def test_import_spacing(self) -> None:
161         source, expected = read_data('import_spacing')
162         actual = fs(source)
163         self.assertFormatEqual(expected, actual)
164         black.assert_equivalent(source, actual)
165         black.assert_stable(source, actual, line_length=ll)
166
167     @patch("black.dump_to_file", dump_to_stderr)
168     def test_composition(self) -> None:
169         source, expected = read_data('composition')
170         actual = fs(source)
171         self.assertFormatEqual(expected, actual)
172         black.assert_equivalent(source, actual)
173         black.assert_stable(source, actual, line_length=ll)
174
175     @patch("black.dump_to_file", dump_to_stderr)
176     def test_empty_lines(self) -> None:
177         source, expected = read_data('empty_lines')
178         actual = fs(source)
179         self.assertFormatEqual(expected, actual)
180         black.assert_equivalent(source, actual)
181         black.assert_stable(source, actual, line_length=ll)
182
183     def test_report(self) -> None:
184         report = black.Report()
185         out_lines = []
186         err_lines = []
187
188         def out(msg: str, **kwargs: Any) -> None:
189             out_lines.append(msg)
190
191         def err(msg: str, **kwargs: Any) -> None:
192             err_lines.append(msg)
193
194         with patch("black.out", out), patch("black.err", err):
195             report.done(Path('f1'), changed=False)
196             self.assertEqual(len(out_lines), 1)
197             self.assertEqual(len(err_lines), 0)
198             self.assertEqual(out_lines[-1], 'f1 already well formatted, good job.')
199             self.assertEqual(unstyle(str(report)), '1 file left unchanged.')
200             self.assertEqual(report.return_code, 0)
201             report.done(Path('f2'), changed=True)
202             self.assertEqual(len(out_lines), 2)
203             self.assertEqual(len(err_lines), 0)
204             self.assertEqual(out_lines[-1], 'reformatted f2')
205             self.assertEqual(
206                 unstyle(str(report)), '1 file reformatted, 1 file left unchanged.'
207             )
208             self.assertEqual(report.return_code, 0)
209             report.check = True
210             self.assertEqual(report.return_code, 1)
211             report.check = False
212             report.failed(Path('e1'), 'boom')
213             self.assertEqual(len(out_lines), 2)
214             self.assertEqual(len(err_lines), 1)
215             self.assertEqual(err_lines[-1], 'error: cannot format e1: boom')
216             self.assertEqual(
217                 unstyle(str(report)),
218                 '1 file reformatted, 1 file left unchanged, '
219                 '1 file failed to reformat.',
220             )
221             self.assertEqual(report.return_code, 123)
222             report.done(Path('f3'), changed=True)
223             self.assertEqual(len(out_lines), 3)
224             self.assertEqual(len(err_lines), 1)
225             self.assertEqual(out_lines[-1], 'reformatted f3')
226             self.assertEqual(
227                 unstyle(str(report)),
228                 '2 files reformatted, 1 file left unchanged, '
229                 '1 file failed to reformat.',
230             )
231             self.assertEqual(report.return_code, 123)
232             report.failed(Path('e2'), 'boom')
233             self.assertEqual(len(out_lines), 3)
234             self.assertEqual(len(err_lines), 2)
235             self.assertEqual(err_lines[-1], 'error: cannot format e2: boom')
236             self.assertEqual(
237                 unstyle(str(report)),
238                 '2 files reformatted, 1 file left unchanged, '
239                 '2 files failed to reformat.',
240             )
241             self.assertEqual(report.return_code, 123)
242             report.done(Path('f4'), changed=False)
243             self.assertEqual(len(out_lines), 4)
244             self.assertEqual(len(err_lines), 2)
245             self.assertEqual(out_lines[-1], 'f4 already well formatted, good job.')
246             self.assertEqual(
247                 unstyle(str(report)),
248                 '2 files reformatted, 2 files left unchanged, '
249                 '2 files failed to reformat.',
250             )
251             self.assertEqual(report.return_code, 123)
252             report.check = True
253             self.assertEqual(
254                 unstyle(str(report)),
255                 '2 files would be reformatted, 2 files would be left unchanged, '
256                 '2 files would fail to reformat.',
257             )
258
259     def test_is_python36(self) -> None:
260         node = black.lib2to3_parse("def f(*, arg): ...\n")
261         self.assertFalse(black.is_python36(node))
262         node = black.lib2to3_parse("def f(*, arg,): ...\n")
263         self.assertTrue(black.is_python36(node))
264         node = black.lib2to3_parse("def f(*, arg): f'string'\n")
265         self.assertTrue(black.is_python36(node))
266         source, expected = read_data('function')
267         node = black.lib2to3_parse(source)
268         self.assertTrue(black.is_python36(node))
269         node = black.lib2to3_parse(expected)
270         self.assertTrue(black.is_python36(node))
271         source, expected = read_data('expression')
272         node = black.lib2to3_parse(source)
273         self.assertFalse(black.is_python36(node))
274         node = black.lib2to3_parse(expected)
275         self.assertFalse(black.is_python36(node))
276
277
278 if __name__ == '__main__':
279     unittest.main()