Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/black/mode.py: 79%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""Data structures configuring Black behavior.
3Mostly around Python language feature support per version and Black configuration
4chosen by the user.
5"""
7from dataclasses import dataclass, field
8from enum import Enum, auto
9from hashlib import sha256
10from operator import attrgetter
11from typing import Final
13from black.const import DEFAULT_LINE_LENGTH
16class TargetVersion(Enum):
17 PY33 = 3
18 PY34 = 4
19 PY35 = 5
20 PY36 = 6
21 PY37 = 7
22 PY38 = 8
23 PY39 = 9
24 PY310 = 10
25 PY311 = 11
26 PY312 = 12
27 PY313 = 13
28 PY314 = 14
30 def pretty(self) -> str:
31 assert self.name[:2] == "PY"
32 return f"Python {self.name[2]}.{self.name[3:]}"
35class Feature(Enum):
36 F_STRINGS = 2
37 NUMERIC_UNDERSCORES = 3
38 TRAILING_COMMA_IN_CALL = 4
39 TRAILING_COMMA_IN_DEF = 5
40 # The following two feature-flags are mutually exclusive, and exactly one should be
41 # set for every version of python.
42 ASYNC_IDENTIFIERS = 6
43 ASYNC_KEYWORDS = 7
44 ASSIGNMENT_EXPRESSIONS = 8
45 POS_ONLY_ARGUMENTS = 9
46 RELAXED_DECORATORS = 10
47 PATTERN_MATCHING = 11
48 UNPACKING_ON_FLOW = 12
49 ANN_ASSIGN_EXTENDED_RHS = 13
50 EXCEPT_STAR = 14
51 VARIADIC_GENERICS = 15
52 DEBUG_F_STRINGS = 16
53 PARENTHESIZED_CONTEXT_MANAGERS = 17
54 TYPE_PARAMS = 18
55 # FSTRING_PARSING = 19 # unused
56 TYPE_PARAM_DEFAULTS = 20
57 UNPARENTHESIZED_EXCEPT_TYPES = 21
58 T_STRINGS = 22
59 FORCE_OPTIONAL_PARENTHESES = 50
61 # __future__ flags
62 FUTURE_ANNOTATIONS = 51
65FUTURE_FLAG_TO_FEATURE: Final = {
66 "annotations": Feature.FUTURE_ANNOTATIONS,
67}
70VERSION_TO_FEATURES: dict[TargetVersion, set[Feature]] = {
71 TargetVersion.PY33: {Feature.ASYNC_IDENTIFIERS},
72 TargetVersion.PY34: {Feature.ASYNC_IDENTIFIERS},
73 TargetVersion.PY35: {Feature.TRAILING_COMMA_IN_CALL, Feature.ASYNC_IDENTIFIERS},
74 TargetVersion.PY36: {
75 Feature.F_STRINGS,
76 Feature.NUMERIC_UNDERSCORES,
77 Feature.TRAILING_COMMA_IN_CALL,
78 Feature.TRAILING_COMMA_IN_DEF,
79 Feature.ASYNC_IDENTIFIERS,
80 },
81 TargetVersion.PY37: {
82 Feature.F_STRINGS,
83 Feature.NUMERIC_UNDERSCORES,
84 Feature.TRAILING_COMMA_IN_CALL,
85 Feature.TRAILING_COMMA_IN_DEF,
86 Feature.ASYNC_KEYWORDS,
87 Feature.FUTURE_ANNOTATIONS,
88 },
89 TargetVersion.PY38: {
90 Feature.F_STRINGS,
91 Feature.DEBUG_F_STRINGS,
92 Feature.NUMERIC_UNDERSCORES,
93 Feature.TRAILING_COMMA_IN_CALL,
94 Feature.TRAILING_COMMA_IN_DEF,
95 Feature.ASYNC_KEYWORDS,
96 Feature.FUTURE_ANNOTATIONS,
97 Feature.ASSIGNMENT_EXPRESSIONS,
98 Feature.POS_ONLY_ARGUMENTS,
99 Feature.UNPACKING_ON_FLOW,
100 Feature.ANN_ASSIGN_EXTENDED_RHS,
101 },
102 TargetVersion.PY39: {
103 Feature.F_STRINGS,
104 Feature.DEBUG_F_STRINGS,
105 Feature.NUMERIC_UNDERSCORES,
106 Feature.TRAILING_COMMA_IN_CALL,
107 Feature.TRAILING_COMMA_IN_DEF,
108 Feature.ASYNC_KEYWORDS,
109 Feature.FUTURE_ANNOTATIONS,
110 Feature.ASSIGNMENT_EXPRESSIONS,
111 Feature.RELAXED_DECORATORS,
112 Feature.POS_ONLY_ARGUMENTS,
113 Feature.UNPACKING_ON_FLOW,
114 Feature.ANN_ASSIGN_EXTENDED_RHS,
115 Feature.PARENTHESIZED_CONTEXT_MANAGERS,
116 },
117 TargetVersion.PY310: {
118 Feature.F_STRINGS,
119 Feature.DEBUG_F_STRINGS,
120 Feature.NUMERIC_UNDERSCORES,
121 Feature.TRAILING_COMMA_IN_CALL,
122 Feature.TRAILING_COMMA_IN_DEF,
123 Feature.ASYNC_KEYWORDS,
124 Feature.FUTURE_ANNOTATIONS,
125 Feature.ASSIGNMENT_EXPRESSIONS,
126 Feature.RELAXED_DECORATORS,
127 Feature.POS_ONLY_ARGUMENTS,
128 Feature.UNPACKING_ON_FLOW,
129 Feature.ANN_ASSIGN_EXTENDED_RHS,
130 Feature.PARENTHESIZED_CONTEXT_MANAGERS,
131 Feature.PATTERN_MATCHING,
132 },
133 TargetVersion.PY311: {
134 Feature.F_STRINGS,
135 Feature.DEBUG_F_STRINGS,
136 Feature.NUMERIC_UNDERSCORES,
137 Feature.TRAILING_COMMA_IN_CALL,
138 Feature.TRAILING_COMMA_IN_DEF,
139 Feature.ASYNC_KEYWORDS,
140 Feature.FUTURE_ANNOTATIONS,
141 Feature.ASSIGNMENT_EXPRESSIONS,
142 Feature.RELAXED_DECORATORS,
143 Feature.POS_ONLY_ARGUMENTS,
144 Feature.UNPACKING_ON_FLOW,
145 Feature.ANN_ASSIGN_EXTENDED_RHS,
146 Feature.PARENTHESIZED_CONTEXT_MANAGERS,
147 Feature.PATTERN_MATCHING,
148 Feature.EXCEPT_STAR,
149 Feature.VARIADIC_GENERICS,
150 },
151 TargetVersion.PY312: {
152 Feature.F_STRINGS,
153 Feature.DEBUG_F_STRINGS,
154 Feature.NUMERIC_UNDERSCORES,
155 Feature.TRAILING_COMMA_IN_CALL,
156 Feature.TRAILING_COMMA_IN_DEF,
157 Feature.ASYNC_KEYWORDS,
158 Feature.FUTURE_ANNOTATIONS,
159 Feature.ASSIGNMENT_EXPRESSIONS,
160 Feature.RELAXED_DECORATORS,
161 Feature.POS_ONLY_ARGUMENTS,
162 Feature.UNPACKING_ON_FLOW,
163 Feature.ANN_ASSIGN_EXTENDED_RHS,
164 Feature.PARENTHESIZED_CONTEXT_MANAGERS,
165 Feature.PATTERN_MATCHING,
166 Feature.EXCEPT_STAR,
167 Feature.VARIADIC_GENERICS,
168 Feature.TYPE_PARAMS,
169 },
170 TargetVersion.PY313: {
171 Feature.F_STRINGS,
172 Feature.DEBUG_F_STRINGS,
173 Feature.NUMERIC_UNDERSCORES,
174 Feature.TRAILING_COMMA_IN_CALL,
175 Feature.TRAILING_COMMA_IN_DEF,
176 Feature.ASYNC_KEYWORDS,
177 Feature.FUTURE_ANNOTATIONS,
178 Feature.ASSIGNMENT_EXPRESSIONS,
179 Feature.RELAXED_DECORATORS,
180 Feature.POS_ONLY_ARGUMENTS,
181 Feature.UNPACKING_ON_FLOW,
182 Feature.ANN_ASSIGN_EXTENDED_RHS,
183 Feature.PARENTHESIZED_CONTEXT_MANAGERS,
184 Feature.PATTERN_MATCHING,
185 Feature.EXCEPT_STAR,
186 Feature.VARIADIC_GENERICS,
187 Feature.TYPE_PARAMS,
188 Feature.TYPE_PARAM_DEFAULTS,
189 },
190 TargetVersion.PY314: {
191 Feature.F_STRINGS,
192 Feature.DEBUG_F_STRINGS,
193 Feature.NUMERIC_UNDERSCORES,
194 Feature.TRAILING_COMMA_IN_CALL,
195 Feature.TRAILING_COMMA_IN_DEF,
196 Feature.ASYNC_KEYWORDS,
197 Feature.FUTURE_ANNOTATIONS,
198 Feature.ASSIGNMENT_EXPRESSIONS,
199 Feature.RELAXED_DECORATORS,
200 Feature.POS_ONLY_ARGUMENTS,
201 Feature.UNPACKING_ON_FLOW,
202 Feature.ANN_ASSIGN_EXTENDED_RHS,
203 Feature.PARENTHESIZED_CONTEXT_MANAGERS,
204 Feature.PATTERN_MATCHING,
205 Feature.EXCEPT_STAR,
206 Feature.VARIADIC_GENERICS,
207 Feature.TYPE_PARAMS,
208 Feature.TYPE_PARAM_DEFAULTS,
209 Feature.UNPARENTHESIZED_EXCEPT_TYPES,
210 Feature.T_STRINGS,
211 },
212}
215def supports_feature(target_versions: set[TargetVersion], feature: Feature) -> bool:
216 if not target_versions:
217 raise ValueError("target_versions must not be empty")
219 return all(feature in VERSION_TO_FEATURES[version] for version in target_versions)
222class Preview(Enum):
223 """Individual preview style features."""
225 # NOTE: string_processing requires wrap_long_dict_values_in_parens
226 # for https://github.com/psf/black/issues/3117 to be fixed.
227 string_processing = auto()
228 hug_parens_with_braces_and_square_brackets = auto()
229 wrap_long_dict_values_in_parens = auto()
230 multiline_string_handling = auto()
231 always_one_newline_after_import = auto()
232 fix_fmt_skip_in_one_liners = auto()
233 standardize_type_comments = auto()
234 wrap_comprehension_in = auto()
235 # Remove parentheses around multiple exception types in except and
236 # except* without as. See PEP 758 for details.
237 remove_parens_around_except_types = auto()
238 normalize_cr_newlines = auto()
239 fix_module_docstring_detection = auto()
240 fix_type_expansion_split = auto()
243UNSTABLE_FEATURES: set[Preview] = {
244 # Many issues, see summary in https://github.com/psf/black/issues/4042
245 Preview.string_processing,
246 # See issue #4036 (crash), #4098, #4099 (proposed tweaks)
247 Preview.hug_parens_with_braces_and_square_brackets,
248}
251class Deprecated(UserWarning):
252 """Visible deprecation warning."""
255_MAX_CACHE_KEY_PART_LENGTH: Final = 32
258@dataclass
259class Mode:
260 target_versions: set[TargetVersion] = field(default_factory=set)
261 line_length: int = DEFAULT_LINE_LENGTH
262 string_normalization: bool = True
263 is_pyi: bool = False
264 is_ipynb: bool = False
265 skip_source_first_line: bool = False
266 magic_trailing_comma: bool = True
267 python_cell_magics: set[str] = field(default_factory=set)
268 preview: bool = False
269 unstable: bool = False
270 enabled_features: set[Preview] = field(default_factory=set)
272 def __contains__(self, feature: Preview) -> bool:
273 """
274 Provide `Preview.FEATURE in Mode` syntax that mirrors the ``preview`` flag.
276 In unstable mode, all features are enabled. In preview mode, all features
277 except those in UNSTABLE_FEATURES are enabled. Any features in
278 `self.enabled_features` are also enabled.
279 """
280 if self.unstable:
281 return True
282 if feature in self.enabled_features:
283 return True
284 return self.preview and feature not in UNSTABLE_FEATURES
286 def get_cache_key(self) -> str:
287 if self.target_versions:
288 version_str = ",".join(
289 str(version.value)
290 for version in sorted(self.target_versions, key=attrgetter("value"))
291 )
292 else:
293 version_str = "-"
294 if len(version_str) > _MAX_CACHE_KEY_PART_LENGTH:
295 version_str = sha256(version_str.encode()).hexdigest()[
296 :_MAX_CACHE_KEY_PART_LENGTH
297 ]
298 features_and_magics = (
299 ",".join(sorted(f.name for f in self.enabled_features))
300 + "@"
301 + ",".join(sorted(self.python_cell_magics))
302 )
303 if len(features_and_magics) > _MAX_CACHE_KEY_PART_LENGTH:
304 features_and_magics = sha256(features_and_magics.encode()).hexdigest()[
305 :_MAX_CACHE_KEY_PART_LENGTH
306 ]
307 parts = [
308 version_str,
309 str(self.line_length),
310 str(int(self.string_normalization)),
311 str(int(self.is_pyi)),
312 str(int(self.is_ipynb)),
313 str(int(self.skip_source_first_line)),
314 str(int(self.magic_trailing_comma)),
315 str(int(self.preview)),
316 str(int(self.unstable)),
317 features_and_magics,
318 ]
319 return ".".join(parts)
321 def __hash__(self) -> int:
322 return hash((
323 frozenset(self.target_versions),
324 self.line_length,
325 self.string_normalization,
326 self.is_pyi,
327 self.is_ipynb,
328 self.skip_source_first_line,
329 self.magic_trailing_comma,
330 frozenset(self.python_cell_magics),
331 self.preview,
332 self.unstable,
333 frozenset(self.enabled_features),
334 ))