]> 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:

Add flake8 to CI, too
[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 Any, 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             bdv: black.DebugVisitor[Any]
50             black.out('Expected tree:', fg='green')
51             try:
52                 exp_node = black.lib2to3_parse(expected)
53                 bdv = black.DebugVisitor()
54                 list(bdv.visit(exp_node))
55             except Exception as ve:
56                 black.err(str(ve))
57             black.out('Actual tree:', fg='red')
58             try:
59                 exp_node = black.lib2to3_parse(actual)
60                 bdv = black.DebugVisitor()
61                 list(bdv.visit(exp_node))
62             except Exception as ve:
63                 black.err(str(ve))
64         self.assertEqual(expected, actual)
65
66     @patch("black.dump_to_file", dump_to_stderr)
67     def test_self(self) -> None:
68         source, expected = read_data('test_black')
69         actual = fs(source)
70         self.assertFormatEqual(expected, actual)
71         black.assert_equivalent(source, actual)
72         black.assert_stable(source, actual, line_length=ll)
73         with self.assertRaises(black.NothingChanged):
74             ff(THIS_FILE)
75
76     @patch("black.dump_to_file", dump_to_stderr)
77     def test_black(self) -> None:
78         source, expected = read_data('../black')
79         actual = fs(source)
80         self.assertFormatEqual(expected, actual)
81         black.assert_equivalent(source, actual)
82         black.assert_stable(source, actual, line_length=ll)
83         with self.assertRaises(black.NothingChanged):
84             ff(THIS_FILE)
85
86     @patch("black.dump_to_file", dump_to_stderr)
87     def test_setup(self) -> None:
88         source, expected = read_data('../setup')
89         actual = fs(source)
90         self.assertFormatEqual(expected, actual)
91         black.assert_equivalent(source, actual)
92         black.assert_stable(source, actual, line_length=ll)
93         with self.assertRaises(black.NothingChanged):
94             ff(THIS_FILE)
95
96     @patch("black.dump_to_file", dump_to_stderr)
97     def test_function(self) -> None:
98         source, expected = read_data('function')
99         actual = fs(source)
100         self.assertFormatEqual(expected, actual)
101         black.assert_equivalent(source, actual)
102         black.assert_stable(source, actual, line_length=ll)
103
104     @patch("black.dump_to_file", dump_to_stderr)
105     def test_expression(self) -> None:
106         source, expected = read_data('expression')
107         actual = fs(source)
108         self.assertFormatEqual(expected, actual)
109         black.assert_equivalent(source, actual)
110         black.assert_stable(source, actual, line_length=ll)
111
112     @patch("black.dump_to_file", dump_to_stderr)
113     def test_fstring(self) -> None:
114         source, expected = read_data('fstring')
115         actual = fs(source)
116         self.assertFormatEqual(expected, actual)
117         black.assert_equivalent(source, actual)
118         black.assert_stable(source, actual, line_length=ll)
119
120     @patch("black.dump_to_file", dump_to_stderr)
121     def test_comments(self) -> None:
122         source, expected = read_data('comments')
123         actual = fs(source)
124         self.assertFormatEqual(expected, actual)
125         black.assert_equivalent(source, actual)
126         black.assert_stable(source, actual, line_length=ll)
127
128     @patch("black.dump_to_file", dump_to_stderr)
129     def test_comments2(self) -> None:
130         source, expected = read_data('comments2')
131         actual = fs(source)
132         self.assertFormatEqual(expected, actual)
133         black.assert_equivalent(source, actual)
134         black.assert_stable(source, actual, line_length=ll)
135
136     @patch("black.dump_to_file", dump_to_stderr)
137     def test_cantfit(self) -> None:
138         source, expected = read_data('cantfit')
139         actual = fs(source)
140         self.assertFormatEqual(expected, actual)
141         black.assert_equivalent(source, actual)
142         black.assert_stable(source, actual, line_length=ll)
143
144     @patch("black.dump_to_file", dump_to_stderr)
145     def test_import_spacing(self) -> None:
146         source, expected = read_data('import_spacing')
147         actual = fs(source)
148         self.assertFormatEqual(expected, actual)
149         black.assert_equivalent(source, actual)
150         black.assert_stable(source, actual, line_length=ll)
151
152     @patch("black.dump_to_file", dump_to_stderr)
153     def test_composition(self) -> None:
154         source, expected = read_data('composition')
155         actual = fs(source)
156         self.assertFormatEqual(expected, actual)
157         black.assert_equivalent(source, actual)
158         black.assert_stable(source, actual, line_length=ll)
159
160     def test_report(self) -> None:
161         report = black.Report()
162         out_lines = []
163         err_lines = []
164
165         def out(msg: str, **kwargs: Any) -> None:
166             out_lines.append(msg)
167
168         def err(msg: str, **kwargs: Any) -> None:
169             err_lines.append(msg)
170
171         with patch("black.out", out), patch("black.err", err):
172             report.done(Path('f1'), changed=False)
173             self.assertEqual(len(out_lines), 1)
174             self.assertEqual(len(err_lines), 0)
175             self.assertEqual(out_lines[-1], 'f1 already well formatted, good job.')
176             self.assertEqual(unstyle(str(report)), '1 file left unchanged.')
177             self.assertEqual(report.return_code, 0)
178             report.done(Path('f2'), changed=True)
179             self.assertEqual(len(out_lines), 2)
180             self.assertEqual(len(err_lines), 0)
181             self.assertEqual(out_lines[-1], 'reformatted f2')
182             self.assertEqual(
183                 unstyle(str(report)), '1 file reformatted, 1 file left unchanged.'
184             )
185             self.assertEqual(report.return_code, 1)
186             report.failed(Path('e1'), 'boom')
187             self.assertEqual(len(out_lines), 2)
188             self.assertEqual(len(err_lines), 1)
189             self.assertEqual(err_lines[-1], 'error: cannot format e1: boom')
190             self.assertEqual(
191                 unstyle(str(report)),
192                 '1 file reformatted, 1 file left unchanged, '
193                 '1 file failed to reformat.',
194             )
195             self.assertEqual(report.return_code, 123)
196             report.done(Path('f3'), changed=True)
197             self.assertEqual(len(out_lines), 3)
198             self.assertEqual(len(err_lines), 1)
199             self.assertEqual(out_lines[-1], 'reformatted f3')
200             self.assertEqual(
201                 unstyle(str(report)),
202                 '2 files reformatted, 1 file left unchanged, '
203                 '1 file failed to reformat.',
204             )
205             self.assertEqual(report.return_code, 123)
206             report.failed(Path('e2'), 'boom')
207             self.assertEqual(len(out_lines), 3)
208             self.assertEqual(len(err_lines), 2)
209             self.assertEqual(err_lines[-1], 'error: cannot format e2: boom')
210             self.assertEqual(
211                 unstyle(str(report)),
212                 '2 files reformatted, 1 file left unchanged, '
213                 '2 files failed to reformat.',
214             )
215             self.assertEqual(report.return_code, 123)
216             report.done(Path('f4'), changed=False)
217             self.assertEqual(len(out_lines), 4)
218             self.assertEqual(len(err_lines), 2)
219             self.assertEqual(out_lines[-1], 'f4 already well formatted, good job.')
220             self.assertEqual(
221                 unstyle(str(report)),
222                 '2 files reformatted, 2 files left unchanged, '
223                 '2 files failed to reformat.',
224             )
225             self.assertEqual(report.return_code, 123)
226
227     def test_is_python36(self) -> None:
228         node = black.lib2to3_parse("def f(*, arg): ...\n")
229         self.assertFalse(black.is_python36(node))
230         node = black.lib2to3_parse("def f(*, arg,): ...\n")
231         self.assertTrue(black.is_python36(node))
232         node = black.lib2to3_parse("def f(*, arg): f'string'\n")
233         self.assertTrue(black.is_python36(node))
234         source, expected = read_data('function')
235         node = black.lib2to3_parse(source)
236         self.assertTrue(black.is_python36(node))
237         node = black.lib2to3_parse(expected)
238         self.assertTrue(black.is_python36(node))
239         source, expected = read_data('expression')
240         node = black.lib2to3_parse(source)
241         self.assertFalse(black.is_python36(node))
242         node = black.lib2to3_parse(expected)
243         self.assertFalse(black.is_python36(node))
244
245
246 if __name__ == '__main__':
247     unittest.main()