]> 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 use trailing commas in function signatures when it's safe
[etc/vim.git] / tests / test_black.py
1 #!/usr/bin/env python3
2 from functools import partial
3 from pathlib import Path
4 from typing import List, Tuple
5 import unittest
6 from unittest.mock import patch
7
8 from click import unstyle
9
10 import black
11
12 ll = 88
13 ff = partial(black.format_file, line_length=ll, fast=True)
14 fs = partial(black.format_str, line_length=ll)
15 THIS_FILE = Path(__file__)
16 THIS_DIR = THIS_FILE.parent
17
18
19 def dump_to_stderr(*output: str) -> str:
20     return '\n' + '\n'.join(output) + '\n'
21
22
23 def read_data(name: str) -> Tuple[str, str]:
24     """read_data('test_name') -> 'input', 'output'"""
25     if not name.endswith('.py'):
26         name += '.py'
27     _input: List[str] = []
28     _output: List[str] = []
29     with open(THIS_DIR / name, 'r', encoding='utf8') as test:
30         lines = test.readlines()
31     result = _input
32     for line in lines:
33         if line.rstrip() == '# output':
34             result = _output
35             continue
36
37         result.append(line)
38     if _input and not _output:
39         # If there's no output marker, treat the entire file as already pre-formatted.
40         _output = _input[:]
41     return ''.join(_input).strip() + '\n', ''.join(_output).strip() + '\n'
42
43
44 class BlackTestCase(unittest.TestCase):
45     maxDiff = None
46
47     def assertFormatEqual(self, expected: str, actual: str) -> None:
48         if actual != expected:
49             black.out('Expected tree:', fg='green')
50             try:
51                 exp_node = black.lib2to3_parse(expected)
52                 bdv = black.DebugVisitor()
53                 list(bdv.visit(exp_node))
54             except Exception as ve:
55                 black.err(str(ve))
56             black.out('Actual tree:', fg='red')
57             try:
58                 exp_node = black.lib2to3_parse(actual)
59                 bdv = black.DebugVisitor()
60                 list(bdv.visit(exp_node))
61             except Exception as ve:
62                 black.err(str(ve))
63         self.assertEqual(expected, actual)
64
65     @patch("black.dump_to_file", dump_to_stderr)
66     def test_self(self) -> None:
67         source, expected = read_data('test_black')
68         actual = fs(source)
69         self.assertFormatEqual(expected, actual)
70         black.assert_equivalent(source, actual)
71         black.assert_stable(source, actual, line_length=ll)
72         with self.assertRaises(black.NothingChanged):
73             ff(THIS_FILE)
74
75     @patch("black.dump_to_file", dump_to_stderr)
76     def test_black(self) -> None:
77         source, expected = read_data('../black')
78         actual = fs(source)
79         self.assertFormatEqual(expected, actual)
80         black.assert_equivalent(source, actual)
81         black.assert_stable(source, actual, line_length=ll)
82         with self.assertRaises(black.NothingChanged):
83             ff(THIS_FILE)
84
85     @patch("black.dump_to_file", dump_to_stderr)
86     def test_setup(self) -> None:
87         source, expected = read_data('../setup')
88         actual = fs(source)
89         self.assertFormatEqual(expected, actual)
90         black.assert_equivalent(source, actual)
91         black.assert_stable(source, actual, line_length=ll)
92         with self.assertRaises(black.NothingChanged):
93             ff(THIS_FILE)
94
95     @patch("black.dump_to_file", dump_to_stderr)
96     def test_function(self) -> None:
97         source, expected = read_data('function')
98         actual = fs(source)
99         self.assertFormatEqual(expected, actual)
100         black.assert_equivalent(source, actual)
101         black.assert_stable(source, actual, line_length=ll)
102
103     @patch("black.dump_to_file", dump_to_stderr)
104     def test_expression(self) -> None:
105         source, expected = read_data('expression')
106         actual = fs(source)
107         self.assertFormatEqual(expected, actual)
108         black.assert_equivalent(source, actual)
109         black.assert_stable(source, actual, line_length=ll)
110
111     @patch("black.dump_to_file", dump_to_stderr)
112     def test_fstring(self) -> None:
113         source, expected = read_data('fstring')
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_comments(self) -> None:
121         source, expected = read_data('comments')
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_comments2(self) -> None:
129         source, expected = read_data('comments2')
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_cantfit(self) -> None:
137         source, expected = read_data('cantfit')
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_import_spacing(self) -> None:
145         source, expected = read_data('import_spacing')
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_composition(self) -> None:
153         source, expected = read_data('composition')
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     def test_report(self) -> None:
160         report = black.Report()
161         out_lines = []
162         err_lines = []
163
164         def out(msg: str, **kwargs):
165             out_lines.append(msg)
166
167         def err(msg: str, **kwargs):
168             err_lines.append(msg)
169
170         with patch("black.out", out), patch("black.err", err):
171             report.done(Path('f1'), changed=False)
172             self.assertEqual(len(out_lines), 1)
173             self.assertEqual(len(err_lines), 0)
174             self.assertEqual(out_lines[-1], 'f1 already well formatted, good job.')
175             self.assertEqual(unstyle(str(report)), '1 file left unchanged.')
176             self.assertEqual(report.return_code, 0)
177             report.done(Path('f2'), changed=True)
178             self.assertEqual(len(out_lines), 2)
179             self.assertEqual(len(err_lines), 0)
180             self.assertEqual(out_lines[-1], 'reformatted f2')
181             self.assertEqual(
182                 unstyle(str(report)), '1 file reformatted, 1 file left unchanged.'
183             )
184             self.assertEqual(report.return_code, 1)
185             report.failed(Path('e1'), 'boom')
186             self.assertEqual(len(out_lines), 2)
187             self.assertEqual(len(err_lines), 1)
188             self.assertEqual(err_lines[-1], 'error: cannot format e1: boom')
189             self.assertEqual(
190                 unstyle(str(report)),
191                 '1 file reformatted, 1 file left unchanged, '
192                 '1 file failed to reformat.',
193             )
194             self.assertEqual(report.return_code, 123)
195             report.done(Path('f3'), changed=True)
196             self.assertEqual(len(out_lines), 3)
197             self.assertEqual(len(err_lines), 1)
198             self.assertEqual(out_lines[-1], 'reformatted f3')
199             self.assertEqual(
200                 unstyle(str(report)),
201                 '2 files reformatted, 1 file left unchanged, '
202                 '1 file failed to reformat.',
203             )
204             self.assertEqual(report.return_code, 123)
205             report.failed(Path('e2'), 'boom')
206             self.assertEqual(len(out_lines), 3)
207             self.assertEqual(len(err_lines), 2)
208             self.assertEqual(err_lines[-1], 'error: cannot format e2: boom')
209             self.assertEqual(
210                 unstyle(str(report)),
211                 '2 files reformatted, 1 file left unchanged, '
212                 '2 files failed to reformat.',
213             )
214             self.assertEqual(report.return_code, 123)
215             report.done(Path('f4'), changed=False)
216             self.assertEqual(len(out_lines), 4)
217             self.assertEqual(len(err_lines), 2)
218             self.assertEqual(out_lines[-1], 'f4 already well formatted, good job.')
219             self.assertEqual(
220                 unstyle(str(report)),
221                 '2 files reformatted, 2 files left unchanged, '
222                 '2 files failed to reformat.',
223             )
224             self.assertEqual(report.return_code, 123)
225
226     def test_is_python36(self):
227         node = black.lib2to3_parse("def f(*, arg): ...\n")
228         self.assertFalse(black.is_python36(node))
229         node = black.lib2to3_parse("def f(*, arg,): ...\n")
230         self.assertTrue(black.is_python36(node))
231         node = black.lib2to3_parse("def f(*, arg): f'string'\n")
232         self.assertTrue(black.is_python36(node))
233         source, expected = read_data('function')
234         node = black.lib2to3_parse(source)
235         self.assertTrue(black.is_python36(node))
236         node = black.lib2to3_parse(expected)
237         self.assertTrue(black.is_python36(node))
238         source, expected = read_data('expression')
239         node = black.lib2to3_parse(source)
240         self.assertFalse(black.is_python36(node))
241         node = black.lib2to3_parse(expected)
242         self.assertFalse(black.is_python36(node))
243
244
245 if __name__ == '__main__':
246     unittest.main()