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.
1 """Data structures configuring Black behavior.
3 Mostly around Python language feature support per version and Black configuration
8 from dataclasses import dataclass, field
9 from enum import Enum, auto
10 from hashlib import sha256
11 from operator import attrgetter
12 from typing import Dict, Set
13 from warnings import warn
15 if sys.version_info < (3, 8):
16 from typing_extensions import Final
18 from typing import Final
20 from black.const import DEFAULT_LINE_LENGTH
23 class TargetVersion(Enum):
38 NUMERIC_UNDERSCORES = 3
39 TRAILING_COMMA_IN_CALL = 4
40 TRAILING_COMMA_IN_DEF = 5
41 # The following two feature-flags are mutually exclusive, and exactly one should be
42 # set for every version of python.
45 ASSIGNMENT_EXPRESSIONS = 8
46 POS_ONLY_ARGUMENTS = 9
47 RELAXED_DECORATORS = 10
49 UNPACKING_ON_FLOW = 12
50 ANN_ASSIGN_EXTENDED_RHS = 13
52 VARIADIC_GENERICS = 15
54 PARENTHESIZED_CONTEXT_MANAGERS = 17
56 FORCE_OPTIONAL_PARENTHESES = 50
59 FUTURE_ANNOTATIONS = 51
62 FUTURE_FLAG_TO_FEATURE: Final = {
63 "annotations": Feature.FUTURE_ANNOTATIONS,
67 VERSION_TO_FEATURES: Dict[TargetVersion, Set[Feature]] = {
68 TargetVersion.PY33: {Feature.ASYNC_IDENTIFIERS},
69 TargetVersion.PY34: {Feature.ASYNC_IDENTIFIERS},
70 TargetVersion.PY35: {Feature.TRAILING_COMMA_IN_CALL, Feature.ASYNC_IDENTIFIERS},
73 Feature.NUMERIC_UNDERSCORES,
74 Feature.TRAILING_COMMA_IN_CALL,
75 Feature.TRAILING_COMMA_IN_DEF,
76 Feature.ASYNC_IDENTIFIERS,
80 Feature.NUMERIC_UNDERSCORES,
81 Feature.TRAILING_COMMA_IN_CALL,
82 Feature.TRAILING_COMMA_IN_DEF,
83 Feature.ASYNC_KEYWORDS,
84 Feature.FUTURE_ANNOTATIONS,
88 Feature.DEBUG_F_STRINGS,
89 Feature.NUMERIC_UNDERSCORES,
90 Feature.TRAILING_COMMA_IN_CALL,
91 Feature.TRAILING_COMMA_IN_DEF,
92 Feature.ASYNC_KEYWORDS,
93 Feature.FUTURE_ANNOTATIONS,
94 Feature.ASSIGNMENT_EXPRESSIONS,
95 Feature.POS_ONLY_ARGUMENTS,
96 Feature.UNPACKING_ON_FLOW,
97 Feature.ANN_ASSIGN_EXTENDED_RHS,
101 Feature.DEBUG_F_STRINGS,
102 Feature.NUMERIC_UNDERSCORES,
103 Feature.TRAILING_COMMA_IN_CALL,
104 Feature.TRAILING_COMMA_IN_DEF,
105 Feature.ASYNC_KEYWORDS,
106 Feature.FUTURE_ANNOTATIONS,
107 Feature.ASSIGNMENT_EXPRESSIONS,
108 Feature.RELAXED_DECORATORS,
109 Feature.POS_ONLY_ARGUMENTS,
110 Feature.UNPACKING_ON_FLOW,
111 Feature.ANN_ASSIGN_EXTENDED_RHS,
112 Feature.PARENTHESIZED_CONTEXT_MANAGERS,
114 TargetVersion.PY310: {
116 Feature.DEBUG_F_STRINGS,
117 Feature.NUMERIC_UNDERSCORES,
118 Feature.TRAILING_COMMA_IN_CALL,
119 Feature.TRAILING_COMMA_IN_DEF,
120 Feature.ASYNC_KEYWORDS,
121 Feature.FUTURE_ANNOTATIONS,
122 Feature.ASSIGNMENT_EXPRESSIONS,
123 Feature.RELAXED_DECORATORS,
124 Feature.POS_ONLY_ARGUMENTS,
125 Feature.UNPACKING_ON_FLOW,
126 Feature.ANN_ASSIGN_EXTENDED_RHS,
127 Feature.PARENTHESIZED_CONTEXT_MANAGERS,
128 Feature.PATTERN_MATCHING,
130 TargetVersion.PY311: {
132 Feature.DEBUG_F_STRINGS,
133 Feature.NUMERIC_UNDERSCORES,
134 Feature.TRAILING_COMMA_IN_CALL,
135 Feature.TRAILING_COMMA_IN_DEF,
136 Feature.ASYNC_KEYWORDS,
137 Feature.FUTURE_ANNOTATIONS,
138 Feature.ASSIGNMENT_EXPRESSIONS,
139 Feature.RELAXED_DECORATORS,
140 Feature.POS_ONLY_ARGUMENTS,
141 Feature.UNPACKING_ON_FLOW,
142 Feature.ANN_ASSIGN_EXTENDED_RHS,
143 Feature.PARENTHESIZED_CONTEXT_MANAGERS,
144 Feature.PATTERN_MATCHING,
146 Feature.VARIADIC_GENERICS,
148 TargetVersion.PY312: {
150 Feature.DEBUG_F_STRINGS,
151 Feature.NUMERIC_UNDERSCORES,
152 Feature.TRAILING_COMMA_IN_CALL,
153 Feature.TRAILING_COMMA_IN_DEF,
154 Feature.ASYNC_KEYWORDS,
155 Feature.FUTURE_ANNOTATIONS,
156 Feature.ASSIGNMENT_EXPRESSIONS,
157 Feature.RELAXED_DECORATORS,
158 Feature.POS_ONLY_ARGUMENTS,
159 Feature.UNPACKING_ON_FLOW,
160 Feature.ANN_ASSIGN_EXTENDED_RHS,
161 Feature.PARENTHESIZED_CONTEXT_MANAGERS,
162 Feature.PATTERN_MATCHING,
164 Feature.VARIADIC_GENERICS,
170 def supports_feature(target_versions: Set[TargetVersion], feature: Feature) -> bool:
171 return all(feature in VERSION_TO_FEATURES[version] for version in target_versions)
175 """Individual preview style features."""
177 add_trailing_comma_consistently = auto()
178 blank_line_after_nested_stub_class = auto()
179 hex_codes_in_unicode_sequences = auto()
180 improved_async_statements_handling = auto()
181 multiline_string_handling = auto()
182 no_blank_line_before_class_docstring = auto()
183 prefer_splitting_right_hand_side_of_assignments = auto()
184 # NOTE: string_processing requires wrap_long_dict_values_in_parens
185 # for https://github.com/psf/black/issues/3117 to be fixed.
186 string_processing = auto()
187 parenthesize_conditional_expressions = auto()
188 skip_magic_trailing_comma_in_subscript = auto()
189 wrap_long_dict_values_in_parens = auto()
190 wrap_multiple_context_managers_in_parens = auto()
193 class Deprecated(UserWarning):
194 """Visible deprecation warning."""
199 target_versions: Set[TargetVersion] = field(default_factory=set)
200 line_length: int = DEFAULT_LINE_LENGTH
201 string_normalization: bool = True
203 is_ipynb: bool = False
204 skip_source_first_line: bool = False
205 magic_trailing_comma: bool = True
206 experimental_string_processing: bool = False
207 python_cell_magics: Set[str] = field(default_factory=set)
208 preview: bool = False
210 def __post_init__(self) -> None:
211 if self.experimental_string_processing:
213 "`experimental string processing` has been included in `preview`"
214 " and deprecated. Use `preview` instead.",
218 def __contains__(self, feature: Preview) -> bool:
220 Provide `Preview.FEATURE in Mode` syntax that mirrors the ``preview`` flag.
222 The argument is not checked and features are not differentiated.
223 They only exist to make development easier by clarifying intent.
225 if feature is Preview.string_processing:
226 return self.preview or self.experimental_string_processing
229 def get_cache_key(self) -> str:
230 if self.target_versions:
231 version_str = ",".join(
233 for version in sorted(self.target_versions, key=attrgetter("value"))
239 str(self.line_length),
240 str(int(self.string_normalization)),
241 str(int(self.is_pyi)),
242 str(int(self.is_ipynb)),
243 str(int(self.skip_source_first_line)),
244 str(int(self.magic_trailing_comma)),
245 str(int(self.experimental_string_processing)),
246 str(int(self.preview)),
247 sha256((",".join(sorted(self.python_cell_magics))).encode()).hexdigest(),
249 return ".".join(parts)