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
9 from dataclasses import dataclass, field
10 from enum import Enum, auto
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):
36 NUMERIC_UNDERSCORES = 3
37 TRAILING_COMMA_IN_CALL = 4
38 TRAILING_COMMA_IN_DEF = 5
39 # The following two feature-flags are mutually exclusive, and exactly one should be
40 # set for every version of python.
43 ASSIGNMENT_EXPRESSIONS = 8
44 POS_ONLY_ARGUMENTS = 9
45 RELAXED_DECORATORS = 10
47 UNPACKING_ON_FLOW = 12
48 ANN_ASSIGN_EXTENDED_RHS = 13
49 FORCE_OPTIONAL_PARENTHESES = 50
52 FUTURE_ANNOTATIONS = 51
55 FUTURE_FLAG_TO_FEATURE: Final = {
56 "annotations": Feature.FUTURE_ANNOTATIONS,
60 VERSION_TO_FEATURES: Dict[TargetVersion, Set[Feature]] = {
61 TargetVersion.PY33: {Feature.ASYNC_IDENTIFIERS},
62 TargetVersion.PY34: {Feature.ASYNC_IDENTIFIERS},
63 TargetVersion.PY35: {Feature.TRAILING_COMMA_IN_CALL, Feature.ASYNC_IDENTIFIERS},
66 Feature.NUMERIC_UNDERSCORES,
67 Feature.TRAILING_COMMA_IN_CALL,
68 Feature.TRAILING_COMMA_IN_DEF,
69 Feature.ASYNC_IDENTIFIERS,
73 Feature.NUMERIC_UNDERSCORES,
74 Feature.TRAILING_COMMA_IN_CALL,
75 Feature.TRAILING_COMMA_IN_DEF,
76 Feature.ASYNC_KEYWORDS,
77 Feature.FUTURE_ANNOTATIONS,
81 Feature.NUMERIC_UNDERSCORES,
82 Feature.TRAILING_COMMA_IN_CALL,
83 Feature.TRAILING_COMMA_IN_DEF,
84 Feature.ASYNC_KEYWORDS,
85 Feature.FUTURE_ANNOTATIONS,
86 Feature.ASSIGNMENT_EXPRESSIONS,
87 Feature.POS_ONLY_ARGUMENTS,
88 Feature.UNPACKING_ON_FLOW,
89 Feature.ANN_ASSIGN_EXTENDED_RHS,
93 Feature.NUMERIC_UNDERSCORES,
94 Feature.TRAILING_COMMA_IN_CALL,
95 Feature.TRAILING_COMMA_IN_DEF,
96 Feature.ASYNC_KEYWORDS,
97 Feature.FUTURE_ANNOTATIONS,
98 Feature.ASSIGNMENT_EXPRESSIONS,
99 Feature.RELAXED_DECORATORS,
100 Feature.POS_ONLY_ARGUMENTS,
101 Feature.UNPACKING_ON_FLOW,
102 Feature.ANN_ASSIGN_EXTENDED_RHS,
104 TargetVersion.PY310: {
106 Feature.NUMERIC_UNDERSCORES,
107 Feature.TRAILING_COMMA_IN_CALL,
108 Feature.TRAILING_COMMA_IN_DEF,
109 Feature.ASYNC_KEYWORDS,
110 Feature.FUTURE_ANNOTATIONS,
111 Feature.ASSIGNMENT_EXPRESSIONS,
112 Feature.RELAXED_DECORATORS,
113 Feature.POS_ONLY_ARGUMENTS,
114 Feature.UNPACKING_ON_FLOW,
115 Feature.ANN_ASSIGN_EXTENDED_RHS,
116 Feature.PATTERN_MATCHING,
121 def supports_feature(target_versions: Set[TargetVersion], feature: Feature) -> bool:
122 return all(feature in VERSION_TO_FEATURES[version] for version in target_versions)
126 """Individual preview style features."""
128 string_processing = auto()
129 hug_simple_powers = auto()
132 class Deprecated(UserWarning):
133 """Visible deprecation warning."""
138 target_versions: Set[TargetVersion] = field(default_factory=set)
139 line_length: int = DEFAULT_LINE_LENGTH
140 string_normalization: bool = True
142 is_ipynb: bool = False
143 magic_trailing_comma: bool = True
144 experimental_string_processing: bool = False
145 preview: bool = False
147 def __post_init__(self) -> None:
148 if self.experimental_string_processing:
150 "`experimental string processing` has been included in `preview`"
151 " and deprecated. Use `preview` instead.",
155 def __contains__(self, feature: Preview) -> bool:
157 Provide `Preview.FEATURE in Mode` syntax that mirrors the ``preview`` flag.
159 The argument is not checked and features are not differentiated.
160 They only exist to make development easier by clarifying intent.
162 if feature is Preview.string_processing:
163 return self.preview or self.experimental_string_processing
166 def get_cache_key(self) -> str:
167 if self.target_versions:
168 version_str = ",".join(
170 for version in sorted(self.target_versions, key=attrgetter("value"))
176 str(self.line_length),
177 str(int(self.string_normalization)),
178 str(int(self.is_pyi)),
179 str(int(self.is_ipynb)),
180 str(int(self.magic_trailing_comma)),
181 str(int(self.experimental_string_processing)),
182 str(int(self.preview)),
184 return ".".join(parts)