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

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