]> git.madduck.net Git - etc/vim.git/blob - tests/test_format.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:

f97d7165b1af353278200aa6610e4782a5df35be
[etc/vim.git] / tests / test_format.py
1 from dataclasses import replace
2 from typing import Any, Iterator
3 from unittest.mock import patch
4
5 import pytest
6
7 import black
8 from tests.util import (
9     DEFAULT_MODE,
10     PY36_VERSIONS,
11     THIS_DIR,
12     assert_format,
13     dump_to_stderr,
14     read_data,
15 )
16
17 SIMPLE_CASES = [
18     "beginning_backslash",
19     "bracketmatch",
20     "class_blank_parentheses",
21     "class_methods_new_line",
22     "collections",
23     "comments",
24     "comments2",
25     "comments3",
26     "comments4",
27     "comments5",
28     "comments6",
29     "comments_non_breaking_space",
30     "comment_after_escaped_newline",
31     "composition",
32     "composition_no_trailing_comma",
33     "docstring",
34     "empty_lines",
35     "expression",
36     "fmtonoff",
37     "fmtonoff2",
38     "fmtonoff3",
39     "fmtonoff4",
40     "fmtskip",
41     "fmtskip2",
42     "fmtskip3",
43     "fmtskip4",
44     "fmtskip5",
45     "fmtskip6",
46     "fstring",
47     "function",
48     "function2",
49     "function_trailing_comma",
50     "import_spacing",
51     "remove_parens",
52     "slices",
53     "string_prefixes",
54     "tricky_unicode_symbols",
55     "tupleassign",
56 ]
57
58 SIMPLE_CASES_PY2 = [
59     "numeric_literals_py2",
60     "python2",
61     "python2_unicode_literals",
62 ]
63
64 EXPERIMENTAL_STRING_PROCESSING_CASES = [
65     "cantfit",
66     "comments7",
67     "long_strings",
68     "long_strings__edge_case",
69     "long_strings__regression",
70     "percent_precedence",
71 ]
72
73 PY310_CASES = [
74     "pattern_matching_simple",
75     "pattern_matching_complex",
76     "pattern_matching_extras",
77     "parenthesized_context_managers",
78 ]
79
80 SOURCES = [
81     "src/black/__init__.py",
82     "src/black/__main__.py",
83     "src/black/brackets.py",
84     "src/black/cache.py",
85     "src/black/comments.py",
86     "src/black/concurrency.py",
87     "src/black/const.py",
88     "src/black/debug.py",
89     "src/black/files.py",
90     "src/black/linegen.py",
91     "src/black/lines.py",
92     "src/black/mode.py",
93     "src/black/nodes.py",
94     "src/black/numerics.py",
95     "src/black/output.py",
96     "src/black/parsing.py",
97     "src/black/report.py",
98     "src/black/rusty.py",
99     "src/black/strings.py",
100     "src/black/trans.py",
101     "src/blackd/__init__.py",
102     "src/black_primer/cli.py",
103     "src/black_primer/lib.py",
104     "src/blib2to3/pygram.py",
105     "src/blib2to3/pytree.py",
106     "src/blib2to3/pgen2/conv.py",
107     "src/blib2to3/pgen2/driver.py",
108     "src/blib2to3/pgen2/grammar.py",
109     "src/blib2to3/pgen2/literals.py",
110     "src/blib2to3/pgen2/parse.py",
111     "src/blib2to3/pgen2/pgen.py",
112     "src/blib2to3/pgen2/tokenize.py",
113     "src/blib2to3/pgen2/token.py",
114     "setup.py",
115     "tests/test_black.py",
116     "tests/test_blackd.py",
117     "tests/test_format.py",
118     "tests/test_primer.py",
119     "tests/optional.py",
120     "tests/util.py",
121     "tests/conftest.py",
122 ]
123
124
125 @pytest.fixture(autouse=True)
126 def patch_dump_to_file(request: Any) -> Iterator[None]:
127     with patch("black.dump_to_file", dump_to_stderr):
128         yield
129
130
131 def check_file(filename: str, mode: black.Mode, *, data: bool = True) -> None:
132     source, expected = read_data(filename, data=data)
133     assert_format(source, expected, mode, fast=False)
134
135
136 @pytest.mark.parametrize("filename", SIMPLE_CASES_PY2)
137 @pytest.mark.python2
138 def test_simple_format_py2(filename: str) -> None:
139     check_file(filename, DEFAULT_MODE)
140
141
142 @pytest.mark.parametrize("filename", SIMPLE_CASES)
143 def test_simple_format(filename: str) -> None:
144     check_file(filename, DEFAULT_MODE)
145
146
147 @pytest.mark.parametrize("filename", EXPERIMENTAL_STRING_PROCESSING_CASES)
148 def test_experimental_format(filename: str) -> None:
149     check_file(filename, black.Mode(experimental_string_processing=True))
150
151
152 @pytest.mark.parametrize("filename", SOURCES)
153 def test_source_is_formatted(filename: str) -> None:
154     path = THIS_DIR.parent / filename
155     check_file(str(path), DEFAULT_MODE, data=False)
156
157
158 # =============== #
159 # Complex cases
160 # ============= #
161
162
163 def test_empty() -> None:
164     source = expected = ""
165     assert_format(source, expected)
166
167
168 def test_pep_572() -> None:
169     source, expected = read_data("pep_572")
170     assert_format(source, expected, minimum_version=(3, 8))
171
172
173 def test_pep_572_remove_parens() -> None:
174     source, expected = read_data("pep_572_remove_parens")
175     assert_format(source, expected, minimum_version=(3, 8))
176
177
178 def test_pep_572_do_not_remove_parens() -> None:
179     source, expected = read_data("pep_572_do_not_remove_parens")
180     # the AST safety checks will fail, but that's expected, just make sure no
181     # parentheses are touched
182     assert_format(source, expected, fast=True)
183
184
185 @pytest.mark.parametrize("major, minor", [(3, 9), (3, 10)])
186 def test_pep_572_newer_syntax(major: int, minor: int) -> None:
187     source, expected = read_data(f"pep_572_py{major}{minor}")
188     assert_format(source, expected, minimum_version=(major, minor))
189
190
191 def test_pep_570() -> None:
192     source, expected = read_data("pep_570")
193     assert_format(source, expected, minimum_version=(3, 8))
194
195
196 @pytest.mark.parametrize("filename", PY310_CASES)
197 def test_python_310(filename: str) -> None:
198     source, expected = read_data(filename)
199     mode = black.Mode(target_versions={black.TargetVersion.PY310})
200     assert_format(source, expected, mode, minimum_version=(3, 10))
201
202
203 def test_patma_invalid() -> None:
204     source, expected = read_data("pattern_matching_invalid")
205     mode = black.Mode(target_versions={black.TargetVersion.PY310})
206     with pytest.raises(black.parsing.InvalidInput) as exc_info:
207         assert_format(source, expected, mode, minimum_version=(3, 10))
208
209     exc_info.match("Cannot parse: 10:11")
210
211
212 def test_docstring_no_string_normalization() -> None:
213     """Like test_docstring but with string normalization off."""
214     source, expected = read_data("docstring_no_string_normalization")
215     mode = replace(DEFAULT_MODE, string_normalization=False)
216     assert_format(source, expected, mode)
217
218
219 def test_long_strings_flag_disabled() -> None:
220     """Tests for turning off the string processing logic."""
221     source, expected = read_data("long_strings_flag_disabled")
222     mode = replace(DEFAULT_MODE, experimental_string_processing=False)
223     assert_format(source, expected, mode)
224
225
226 def test_numeric_literals() -> None:
227     source, expected = read_data("numeric_literals")
228     mode = replace(DEFAULT_MODE, target_versions=PY36_VERSIONS)
229     assert_format(source, expected, mode)
230
231
232 def test_numeric_literals_ignoring_underscores() -> None:
233     source, expected = read_data("numeric_literals_skip_underscores")
234     mode = replace(DEFAULT_MODE, target_versions=PY36_VERSIONS)
235     assert_format(source, expected, mode)
236
237
238 @pytest.mark.python2
239 def test_python2_print_function() -> None:
240     source, expected = read_data("python2_print_function")
241     mode = replace(DEFAULT_MODE, target_versions={black.TargetVersion.PY27})
242     assert_format(source, expected, mode)
243
244
245 def test_stub() -> None:
246     mode = replace(DEFAULT_MODE, is_pyi=True)
247     source, expected = read_data("stub.pyi")
248     assert_format(source, expected, mode)
249
250
251 def test_python38() -> None:
252     source, expected = read_data("python38")
253     assert_format(source, expected, minimum_version=(3, 8))
254
255
256 def test_python39() -> None:
257     source, expected = read_data("python39")
258     assert_format(source, expected, minimum_version=(3, 9))