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

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