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
11 from operator import attrgetter
12 from typing import Dict, Set
14 if sys.version_info < (3, 8):
15 from typing_extensions import Final
17 from typing import Final
19 from black.const import DEFAULT_LINE_LENGTH
22 class TargetVersion(Enum):
33 def is_python2(self) -> bool:
34 return self is TargetVersion.PY27
38 # All string literals are unicode
41 NUMERIC_UNDERSCORES = 3
42 TRAILING_COMMA_IN_CALL = 4
43 TRAILING_COMMA_IN_DEF = 5
44 # The following two feature-flags are mutually exclusive, and exactly one should be
45 # set for every version of python.
48 ASSIGNMENT_EXPRESSIONS = 8
49 POS_ONLY_ARGUMENTS = 9
50 RELAXED_DECORATORS = 10
52 UNPACKING_ON_FLOW = 12
53 ANN_ASSIGN_EXTENDED_RHS = 13
54 FORCE_OPTIONAL_PARENTHESES = 50
57 FUTURE_ANNOTATIONS = 51
59 # temporary for Python 2 deprecation
62 AUTOMATIC_PARAMETER_UNPACKING = 202
63 COMMA_STYLE_EXCEPT = 203
64 COMMA_STYLE_RAISE = 204
65 LONG_INT_LITERAL = 205
66 OCTAL_INT_LITERAL = 206
70 FUTURE_FLAG_TO_FEATURE: Final = {
71 "annotations": Feature.FUTURE_ANNOTATIONS,
75 VERSION_TO_FEATURES: Dict[TargetVersion, Set[Feature]] = {
77 Feature.ASYNC_IDENTIFIERS,
80 Feature.AUTOMATIC_PARAMETER_UNPACKING,
81 Feature.COMMA_STYLE_EXCEPT,
82 Feature.COMMA_STYLE_RAISE,
83 Feature.LONG_INT_LITERAL,
84 Feature.OCTAL_INT_LITERAL,
85 Feature.BACKQUOTE_REPR,
87 TargetVersion.PY33: {Feature.UNICODE_LITERALS, Feature.ASYNC_IDENTIFIERS},
88 TargetVersion.PY34: {Feature.UNICODE_LITERALS, Feature.ASYNC_IDENTIFIERS},
90 Feature.UNICODE_LITERALS,
91 Feature.TRAILING_COMMA_IN_CALL,
92 Feature.ASYNC_IDENTIFIERS,
95 Feature.UNICODE_LITERALS,
97 Feature.NUMERIC_UNDERSCORES,
98 Feature.TRAILING_COMMA_IN_CALL,
99 Feature.TRAILING_COMMA_IN_DEF,
100 Feature.ASYNC_IDENTIFIERS,
102 TargetVersion.PY37: {
103 Feature.UNICODE_LITERALS,
105 Feature.NUMERIC_UNDERSCORES,
106 Feature.TRAILING_COMMA_IN_CALL,
107 Feature.TRAILING_COMMA_IN_DEF,
108 Feature.ASYNC_KEYWORDS,
109 Feature.FUTURE_ANNOTATIONS,
111 TargetVersion.PY38: {
112 Feature.UNICODE_LITERALS,
114 Feature.NUMERIC_UNDERSCORES,
115 Feature.TRAILING_COMMA_IN_CALL,
116 Feature.TRAILING_COMMA_IN_DEF,
117 Feature.ASYNC_KEYWORDS,
118 Feature.FUTURE_ANNOTATIONS,
119 Feature.ASSIGNMENT_EXPRESSIONS,
120 Feature.POS_ONLY_ARGUMENTS,
121 Feature.UNPACKING_ON_FLOW,
122 Feature.ANN_ASSIGN_EXTENDED_RHS,
124 TargetVersion.PY39: {
125 Feature.UNICODE_LITERALS,
127 Feature.NUMERIC_UNDERSCORES,
128 Feature.TRAILING_COMMA_IN_CALL,
129 Feature.TRAILING_COMMA_IN_DEF,
130 Feature.ASYNC_KEYWORDS,
131 Feature.FUTURE_ANNOTATIONS,
132 Feature.ASSIGNMENT_EXPRESSIONS,
133 Feature.RELAXED_DECORATORS,
134 Feature.POS_ONLY_ARGUMENTS,
135 Feature.UNPACKING_ON_FLOW,
136 Feature.ANN_ASSIGN_EXTENDED_RHS,
138 TargetVersion.PY310: {
139 Feature.UNICODE_LITERALS,
141 Feature.NUMERIC_UNDERSCORES,
142 Feature.TRAILING_COMMA_IN_CALL,
143 Feature.TRAILING_COMMA_IN_DEF,
144 Feature.ASYNC_KEYWORDS,
145 Feature.FUTURE_ANNOTATIONS,
146 Feature.ASSIGNMENT_EXPRESSIONS,
147 Feature.RELAXED_DECORATORS,
148 Feature.POS_ONLY_ARGUMENTS,
149 Feature.UNPACKING_ON_FLOW,
150 Feature.ANN_ASSIGN_EXTENDED_RHS,
151 Feature.PATTERN_MATCHING,
156 def supports_feature(target_versions: Set[TargetVersion], feature: Feature) -> bool:
157 return all(feature in VERSION_TO_FEATURES[version] for version in target_versions)
162 target_versions: Set[TargetVersion] = field(default_factory=set)
163 line_length: int = DEFAULT_LINE_LENGTH
164 string_normalization: bool = True
166 is_ipynb: bool = False
167 magic_trailing_comma: bool = True
168 experimental_string_processing: bool = False
170 def get_cache_key(self) -> str:
171 if self.target_versions:
172 version_str = ",".join(
174 for version in sorted(self.target_versions, key=attrgetter("value"))
180 str(self.line_length),
181 str(int(self.string_normalization)),
182 str(int(self.is_pyi)),
183 str(int(self.is_ipynb)),
184 str(int(self.magic_trailing_comma)),
185 str(int(self.experimental_string_processing)),
187 return ".".join(parts)