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

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