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

Don't let TokenError bubble up from lib2to3_parse (GH-2343)
[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     "pattern_matching_style",
78     "parenthesized_context_managers",
79 ]
80
81 SOURCES = [
82     "src/black/__init__.py",
83     "src/black/__main__.py",
84     "src/black/brackets.py",
85     "src/black/cache.py",
86     "src/black/comments.py",
87     "src/black/concurrency.py",
88     "src/black/const.py",
89     "src/black/debug.py",
90     "src/black/files.py",
91     "src/black/linegen.py",
92     "src/black/lines.py",
93     "src/black/mode.py",
94     "src/black/nodes.py",
95     "src/black/numerics.py",
96     "src/black/output.py",
97     "src/black/parsing.py",
98     "src/black/report.py",
99     "src/black/rusty.py",
100     "src/black/strings.py",
101     "src/black/trans.py",
102     "src/blackd/__init__.py",
103     "src/black_primer/cli.py",
104     "src/black_primer/lib.py",
105     "src/blib2to3/pygram.py",
106     "src/blib2to3/pytree.py",
107     "src/blib2to3/pgen2/conv.py",
108     "src/blib2to3/pgen2/driver.py",
109     "src/blib2to3/pgen2/grammar.py",
110     "src/blib2to3/pgen2/literals.py",
111     "src/blib2to3/pgen2/parse.py",
112     "src/blib2to3/pgen2/pgen.py",
113     "src/blib2to3/pgen2/tokenize.py",
114     "src/blib2to3/pgen2/token.py",
115     "setup.py",
116     "tests/test_black.py",
117     "tests/test_blackd.py",
118     "tests/test_format.py",
119     "tests/test_primer.py",
120     "tests/optional.py",
121     "tests/util.py",
122     "tests/conftest.py",
123 ]
124
125
126 @pytest.fixture(autouse=True)
127 def patch_dump_to_file(request: Any) -> Iterator[None]:
128     with patch("black.dump_to_file", dump_to_stderr):
129         yield
130
131
132 def check_file(filename: str, mode: black.Mode, *, data: bool = True) -> None:
133     source, expected = read_data(filename, data=data)
134     assert_format(source, expected, mode, fast=False)
135
136
137 @pytest.mark.parametrize("filename", SIMPLE_CASES_PY2)
138 @pytest.mark.python2
139 def test_simple_format_py2(filename: str) -> None:
140     check_file(filename, DEFAULT_MODE)
141
142
143 @pytest.mark.parametrize("filename", SIMPLE_CASES)
144 def test_simple_format(filename: str) -> None:
145     check_file(filename, DEFAULT_MODE)
146
147
148 @pytest.mark.parametrize("filename", EXPERIMENTAL_STRING_PROCESSING_CASES)
149 def test_experimental_format(filename: str) -> None:
150     check_file(filename, black.Mode(experimental_string_processing=True))
151
152
153 @pytest.mark.parametrize("filename", SOURCES)
154 def test_source_is_formatted(filename: str) -> None:
155     path = THIS_DIR.parent / filename
156     check_file(str(path), DEFAULT_MODE, data=False)
157
158
159 # =============== #
160 # Complex cases
161 # ============= #
162
163
164 def test_empty() -> None:
165     source = expected = ""
166     assert_format(source, expected)
167
168
169 def test_pep_572() -> None:
170     source, expected = read_data("pep_572")
171     assert_format(source, expected, minimum_version=(3, 8))
172
173
174 def test_pep_572_remove_parens() -> None:
175     source, expected = read_data("pep_572_remove_parens")
176     assert_format(source, expected, minimum_version=(3, 8))
177
178
179 def test_pep_572_do_not_remove_parens() -> None:
180     source, expected = read_data("pep_572_do_not_remove_parens")
181     # the AST safety checks will fail, but that's expected, just make sure no
182     # parentheses are touched
183     assert_format(source, expected, fast=True)
184
185
186 @pytest.mark.parametrize("major, minor", [(3, 9), (3, 10)])
187 def test_pep_572_newer_syntax(major: int, minor: int) -> None:
188     source, expected = read_data(f"pep_572_py{major}{minor}")
189     assert_format(source, expected, minimum_version=(major, minor))
190
191
192 def test_pep_570() -> None:
193     source, expected = read_data("pep_570")
194     assert_format(source, expected, minimum_version=(3, 8))
195
196
197 @pytest.mark.parametrize("filename", PY310_CASES)
198 def test_python_310(filename: str) -> None:
199     source, expected = read_data(filename)
200     mode = black.Mode(target_versions={black.TargetVersion.PY310})
201     assert_format(source, expected, mode, minimum_version=(3, 10))
202
203
204 def test_patma_invalid() -> None:
205     source, expected = read_data("pattern_matching_invalid")
206     mode = black.Mode(target_versions={black.TargetVersion.PY310})
207     with pytest.raises(black.parsing.InvalidInput) as exc_info:
208         assert_format(source, expected, mode, minimum_version=(3, 10))
209
210     exc_info.match("Cannot parse: 10:11")
211
212
213 def test_docstring_no_string_normalization() -> None:
214     """Like test_docstring but with string normalization off."""
215     source, expected = read_data("docstring_no_string_normalization")
216     mode = replace(DEFAULT_MODE, string_normalization=False)
217     assert_format(source, expected, mode)
218
219
220 def test_long_strings_flag_disabled() -> None:
221     """Tests for turning off the string processing logic."""
222     source, expected = read_data("long_strings_flag_disabled")
223     mode = replace(DEFAULT_MODE, experimental_string_processing=False)
224     assert_format(source, expected, mode)
225
226
227 def test_numeric_literals() -> None:
228     source, expected = read_data("numeric_literals")
229     mode = replace(DEFAULT_MODE, target_versions=PY36_VERSIONS)
230     assert_format(source, expected, mode)
231
232
233 def test_numeric_literals_ignoring_underscores() -> None:
234     source, expected = read_data("numeric_literals_skip_underscores")
235     mode = replace(DEFAULT_MODE, target_versions=PY36_VERSIONS)
236     assert_format(source, expected, mode)
237
238
239 @pytest.mark.python2
240 def test_python2_print_function() -> None:
241     source, expected = read_data("python2_print_function")
242     mode = replace(DEFAULT_MODE, target_versions={black.TargetVersion.PY27})
243     assert_format(source, expected, mode)
244
245
246 def test_stub() -> None:
247     mode = replace(DEFAULT_MODE, is_pyi=True)
248     source, expected = read_data("stub.pyi")
249     assert_format(source, expected, mode)
250
251
252 def test_python38() -> None:
253     source, expected = read_data("python38")
254     assert_format(source, expected, minimum_version=(3, 8))
255
256
257 def test_python39() -> None:
258     source, expected = read_data("python39")
259     assert_format(source, expected, minimum_version=(3, 9))