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

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