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

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