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

100 statements  

1"""Data structures configuring Black behavior. 

2 

3Mostly around Python language feature support per version and Black configuration 

4chosen by the user. 

5""" 

6 

7from dataclasses import dataclass, field 

8from enum import Enum, auto 

9from hashlib import sha256 

10from operator import attrgetter 

11from typing import Final 

12 

13from black.const import DEFAULT_LINE_LENGTH 

14 

15 

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 

29 

30 def pretty(self) -> str: 

31 assert self.name[:2] == "PY" 

32 return f"Python {self.name[2]}.{self.name[3:]}" 

33 

34 

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 

60 

61 # __future__ flags 

62 FUTURE_ANNOTATIONS = 51 

63 

64 

65FUTURE_FLAG_TO_FEATURE: Final = { 

66 "annotations": Feature.FUTURE_ANNOTATIONS, 

67} 

68 

69 

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} 

213 

214 

215def supports_feature(target_versions: set[TargetVersion], feature: Feature) -> bool: 

216 if not target_versions: 

217 raise ValueError("target_versions must not be empty") 

218 

219 return all(feature in VERSION_TO_FEATURES[version] for version in target_versions) 

220 

221 

222class Preview(Enum): 

223 """Individual preview style features.""" 

224 

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() 

241 

242 

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} 

249 

250 

251class Deprecated(UserWarning): 

252 """Visible deprecation warning.""" 

253 

254 

255_MAX_CACHE_KEY_PART_LENGTH: Final = 32 

256 

257 

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) 

271 

272 def __contains__(self, feature: Preview) -> bool: 

273 """ 

274 Provide `Preview.FEATURE in Mode` syntax that mirrors the ``preview`` flag. 

275 

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 

285 

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) 

320 

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 ))