]> crepu.dev Git - config.git/blob - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/yapf/yapflib/style.py
Archivo de configuraciĆ³n de la terminal
[config.git] / djavu-asus / elpy / rpc-venv / lib / python3.11 / site-packages / yapf / yapflib / style.py
1 # Copyright 2015 Google Inc. All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 """Python formatting style settings."""
15
16 import os
17 import re
18 import textwrap
19 from configparser import ConfigParser
20
21 from yapf.yapflib import errors
22
23
24 class StyleConfigError(errors.YapfError):
25 """Raised when there's a problem reading the style configuration."""
26 pass
27
28
29 def Get(setting_name):
30 """Get a style setting."""
31 return _style[setting_name]
32
33
34 def GetOrDefault(setting_name, default_value):
35 """Get a style setting or default value if the setting does not exist."""
36 return _style.get(setting_name, default_value)
37
38
39 def Help():
40 """Return dict mapping style names to help strings."""
41 return _STYLE_HELP
42
43
44 def SetGlobalStyle(style):
45 """Set a style dict."""
46 global _style
47 global _GLOBAL_STYLE_FACTORY
48 factory = _GetStyleFactory(style)
49 if factory:
50 _GLOBAL_STYLE_FACTORY = factory
51 _style = style
52
53
54 _STYLE_HELP = dict(
55 # BASED_ON_STYLE='Which predefined style this style is based on',
56 ALIGN_CLOSING_BRACKET_WITH_VISUAL_INDENT=textwrap.dedent("""\
57 Align closing bracket with visual indentation.
58 """),
59 ALLOW_MULTILINE_DICTIONARY_KEYS=textwrap.dedent("""\
60 Allow dictionary keys to exist on multiple lines. For example:
61
62 x = {
63 ('this is the first element of a tuple',
64 'this is the second element of a tuple'):
65 value,
66 }
67 """),
68 ALLOW_MULTILINE_LAMBDAS=textwrap.dedent("""\
69 Allow lambdas to be formatted on more than one line.
70 """),
71 ALLOW_SPLIT_BEFORE_DEFAULT_OR_NAMED_ASSIGNS=textwrap.dedent("""\
72 Allow splitting before a default / named assignment in an argument list.
73 """),
74 ALLOW_SPLIT_BEFORE_DICT_VALUE=textwrap.dedent("""\
75 Allow splits before the dictionary value.
76 """),
77 ARITHMETIC_PRECEDENCE_INDICATION=textwrap.dedent("""\
78 Let spacing indicate operator precedence. For example:
79
80 a = 1 * 2 + 3 / 4
81 b = 1 / 2 - 3 * 4
82 c = (1 + 2) * (3 - 4)
83 d = (1 - 2) / (3 + 4)
84 e = 1 * 2 - 3
85 f = 1 + 2 + 3 + 4
86
87 will be formatted as follows to indicate precedence:
88
89 a = 1*2 + 3/4
90 b = 1/2 - 3*4
91 c = (1+2) * (3-4)
92 d = (1-2) / (3+4)
93 e = 1*2 - 3
94 f = 1 + 2 + 3 + 4
95
96 """),
97 BLANK_LINE_BEFORE_CLASS_DOCSTRING=textwrap.dedent("""\
98 Insert a blank line before a class-level docstring.
99 """),
100 BLANK_LINE_BEFORE_MODULE_DOCSTRING=textwrap.dedent("""\
101 Insert a blank line before a module docstring.
102 """),
103 BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF=textwrap.dedent("""\
104 Insert a blank line before a 'def' or 'class' immediately nested
105 within another 'def' or 'class'. For example:
106
107 class Foo:
108 # <------ this blank line
109 def method():
110 pass
111 """),
112 BLANK_LINES_AROUND_TOP_LEVEL_DEFINITION=textwrap.dedent("""\
113 Number of blank lines surrounding top-level function and class
114 definitions.
115 """),
116 BLANK_LINES_BETWEEN_TOP_LEVEL_IMPORTS_AND_VARIABLES=textwrap.dedent("""\
117 Number of blank lines between top-level imports and variable
118 definitions.
119 """),
120 COALESCE_BRACKETS=textwrap.dedent("""\
121 Do not split consecutive brackets. Only relevant when
122 dedent_closing_brackets is set. For example:
123
124 call_func_that_takes_a_dict(
125 {
126 'key1': 'value1',
127 'key2': 'value2',
128 }
129 )
130
131 would reformat to:
132
133 call_func_that_takes_a_dict({
134 'key1': 'value1',
135 'key2': 'value2',
136 })
137 """),
138 COLUMN_LIMIT=textwrap.dedent("""\
139 The column limit.
140 """),
141 CONTINUATION_ALIGN_STYLE=textwrap.dedent("""\
142 The style for continuation alignment. Possible values are:
143
144 - SPACE: Use spaces for continuation alignment. This is default behavior.
145 - FIXED: Use fixed number (CONTINUATION_INDENT_WIDTH) of columns
146 (ie: CONTINUATION_INDENT_WIDTH/INDENT_WIDTH tabs or
147 CONTINUATION_INDENT_WIDTH spaces) for continuation alignment.
148 - VALIGN-RIGHT: Vertically align continuation lines to multiple of
149 INDENT_WIDTH columns. Slightly right (one tab or a few spaces) if
150 cannot vertically align continuation lines with indent characters.
151 """),
152 CONTINUATION_INDENT_WIDTH=textwrap.dedent("""\
153 Indent width used for line continuations.
154 """),
155 DEDENT_CLOSING_BRACKETS=textwrap.dedent("""\
156 Put closing brackets on a separate line, dedented, if the bracketed
157 expression can't fit in a single line. Applies to all kinds of brackets,
158 including function definitions and calls. For example:
159
160 config = {
161 'key1': 'value1',
162 'key2': 'value2',
163 } # <--- this bracket is dedented and on a separate line
164
165 time_series = self.remote_client.query_entity_counters(
166 entity='dev3246.region1',
167 key='dns.query_latency_tcp',
168 transform=Transformation.AVERAGE(window=timedelta(seconds=60)),
169 start_ts=now()-timedelta(days=3),
170 end_ts=now(),
171 ) # <--- this bracket is dedented and on a separate line
172 """),
173 DISABLE_ENDING_COMMA_HEURISTIC=textwrap.dedent("""\
174 Disable the heuristic which places each list element on a separate line
175 if the list is comma-terminated.
176 """),
177 EACH_DICT_ENTRY_ON_SEPARATE_LINE=textwrap.dedent("""\
178 Place each dictionary entry onto its own line.
179 """),
180 FORCE_MULTILINE_DICT=textwrap.dedent("""\
181 Require multiline dictionary even if it would normally fit on one line.
182 For example:
183
184 config = {
185 'key1': 'value1'
186 }
187 """),
188 I18N_COMMENT=textwrap.dedent("""\
189 The regex for an i18n comment. The presence of this comment stops
190 reformatting of that line, because the comments are required to be
191 next to the string they translate.
192 """),
193 I18N_FUNCTION_CALL=textwrap.dedent("""\
194 The i18n function call names. The presence of this function stops
195 reformattting on that line, because the string it has cannot be moved
196 away from the i18n comment.
197 """),
198 INDENT_CLOSING_BRACKETS=textwrap.dedent("""\
199 Put closing brackets on a separate line, indented, if the bracketed
200 expression can't fit in a single line. Applies to all kinds of brackets,
201 including function definitions and calls. For example:
202
203 config = {
204 'key1': 'value1',
205 'key2': 'value2',
206 } # <--- this bracket is indented and on a separate line
207
208 time_series = self.remote_client.query_entity_counters(
209 entity='dev3246.region1',
210 key='dns.query_latency_tcp',
211 transform=Transformation.AVERAGE(window=timedelta(seconds=60)),
212 start_ts=now()-timedelta(days=3),
213 end_ts=now(),
214 ) # <--- this bracket is indented and on a separate line
215 """),
216 INDENT_DICTIONARY_VALUE=textwrap.dedent("""\
217 Indent the dictionary value if it cannot fit on the same line as the
218 dictionary key. For example:
219
220 config = {
221 'key1':
222 'value1',
223 'key2': value1 +
224 value2,
225 }
226 """),
227 INDENT_BLANK_LINES=textwrap.dedent("""\
228 Indent blank lines.
229 """),
230 INDENT_WIDTH=textwrap.dedent("""\
231 The number of columns to use for indentation.
232 """),
233 JOIN_MULTIPLE_LINES=textwrap.dedent("""\
234 Join short lines into one line. E.g., single line 'if' statements.
235 """),
236 NO_SPACES_AROUND_SELECTED_BINARY_OPERATORS=textwrap.dedent("""\
237 Do not include spaces around selected binary operators. For example:
238
239 1 + 2 * 3 - 4 / 5
240
241 will be formatted as follows when configured with "*,/":
242
243 1 + 2*3 - 4/5
244 """),
245 SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET=textwrap.dedent("""\
246 Insert a space between the ending comma and closing bracket of a list,
247 etc.
248 """),
249 SPACE_INSIDE_BRACKETS=textwrap.dedent("""\
250 Use spaces inside brackets, braces, and parentheses. For example:
251
252 method_call( 1 )
253 my_dict[ 3 ][ 1 ][ get_index( *args, **kwargs ) ]
254 my_set = { 1, 2, 3 }
255 """),
256 SPACES_AROUND_DEFAULT_OR_NAMED_ASSIGN=textwrap.dedent("""\
257 Use spaces around default or named assigns.
258 """),
259 SPACES_AROUND_DICT_DELIMITERS=textwrap.dedent("""\
260 Adds a space after the opening '{' and before the ending '}' dict
261 delimiters.
262
263 {1: 2}
264
265 will be formatted as:
266
267 { 1: 2 }
268 """),
269 SPACES_AROUND_LIST_DELIMITERS=textwrap.dedent("""\
270 Adds a space after the opening '[' and before the ending ']' list
271 delimiters.
272
273 [1, 2]
274
275 will be formatted as:
276
277 [ 1, 2 ]
278 """),
279 SPACES_AROUND_POWER_OPERATOR=textwrap.dedent("""\
280 Use spaces around the power operator.
281 """),
282 SPACES_AROUND_SUBSCRIPT_COLON=textwrap.dedent("""\
283 Use spaces around the subscript / slice operator. For example:
284
285 my_list[1 : 10 : 2]
286 """),
287 SPACES_AROUND_TUPLE_DELIMITERS=textwrap.dedent("""\
288 Adds a space after the opening '(' and before the ending ')' tuple
289 delimiters.
290
291 (1, 2, 3)
292
293 will be formatted as:
294
295 ( 1, 2, 3 )
296 """),
297 SPACES_BEFORE_COMMENT=textwrap.dedent("""\
298 The number of spaces required before a trailing comment.
299 This can be a single value (representing the number of spaces
300 before each trailing comment) or list of values (representing
301 alignment column values; trailing comments within a block will
302 be aligned to the first column value that is greater than the maximum
303 line length within the block). For example:
304
305 With spaces_before_comment=5:
306
307 1 + 1 # Adding values
308
309 will be formatted as:
310
311 1 + 1 # Adding values <-- 5 spaces between the end of the
312 # statement and comment
313
314 With spaces_before_comment=15, 20:
315
316 1 + 1 # Adding values
317 two + two # More adding
318
319 longer_statement # This is a longer statement
320 short # This is a shorter statement
321
322 a_very_long_statement_that_extends_beyond_the_final_column # Comment
323 short # This is a shorter statement
324
325 will be formatted as:
326
327 1 + 1 # Adding values <-- end of line comments in block
328 # aligned to col 15
329 two + two # More adding
330
331 longer_statement # This is a longer statement <-- end of line
332 # comments in block aligned to col 20
333 short # This is a shorter statement
334
335 a_very_long_statement_that_extends_beyond_the_final_column # Comment <-- the end of line comments are aligned based on the line length
336 short # This is a shorter statement
337
338 """), # noqa
339 SPLIT_ALL_COMMA_SEPARATED_VALUES=textwrap.dedent("""\
340 Split before arguments.
341 """),
342 SPLIT_ALL_TOP_LEVEL_COMMA_SEPARATED_VALUES=textwrap.dedent("""\
343 Split before arguments, but do not split all subexpressions recursively
344 (unless needed).
345 """),
346 SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED=textwrap.dedent("""\
347 Split before arguments if the argument list is terminated by a
348 comma.
349 """),
350 SPLIT_BEFORE_ARITHMETIC_OPERATOR=textwrap.dedent("""\
351 Set to True to prefer splitting before '+', '-', '*', '/', '//', or '@'
352 rather than after.
353 """),
354 SPLIT_BEFORE_BITWISE_OPERATOR=textwrap.dedent("""\
355 Set to True to prefer splitting before '&', '|' or '^' rather than
356 after.
357 """),
358 SPLIT_BEFORE_CLOSING_BRACKET=textwrap.dedent("""\
359 Split before the closing bracket if a list or dict literal doesn't fit on
360 a single line.
361 """),
362 SPLIT_BEFORE_DICT_SET_GENERATOR=textwrap.dedent("""\
363 Split before a dictionary or set generator (comp_for). For example, note
364 the split before the 'for':
365
366 foo = {
367 variable: 'Hello world, have a nice day!'
368 for variable in bar if variable != 42
369 }
370 """),
371 SPLIT_BEFORE_DOT=textwrap.dedent("""\
372 Split before the '.' if we need to split a longer expression:
373
374 foo = ('This is a really long string: {}, {}, {}, {}'.format(a, b, c, d))
375
376 would reformat to something like:
377
378 foo = ('This is a really long string: {}, {}, {}, {}'
379 .format(a, b, c, d))
380 """), # noqa
381 SPLIT_BEFORE_EXPRESSION_AFTER_OPENING_PAREN=textwrap.dedent("""\
382 Split after the opening paren which surrounds an expression if it doesn't
383 fit on a single line.
384 """),
385 SPLIT_BEFORE_FIRST_ARGUMENT=textwrap.dedent("""\
386 If an argument / parameter list is going to be split, then split before
387 the first argument.
388 """),
389 SPLIT_BEFORE_LOGICAL_OPERATOR=textwrap.dedent("""\
390 Set to True to prefer splitting before 'and' or 'or' rather than
391 after.
392 """),
393 SPLIT_BEFORE_NAMED_ASSIGNS=textwrap.dedent("""\
394 Split named assignments onto individual lines.
395 """),
396 SPLIT_COMPLEX_COMPREHENSION=textwrap.dedent("""\
397 Set to True to split list comprehensions and generators that have
398 non-trivial expressions and multiple clauses before each of these
399 clauses. For example:
400
401 result = [
402 a_long_var + 100 for a_long_var in xrange(1000)
403 if a_long_var % 10]
404
405 would reformat to something like:
406
407 result = [
408 a_long_var + 100
409 for a_long_var in xrange(1000)
410 if a_long_var % 10]
411 """),
412 SPLIT_PENALTY_AFTER_OPENING_BRACKET=textwrap.dedent("""\
413 The penalty for splitting right after the opening bracket.
414 """),
415 SPLIT_PENALTY_AFTER_UNARY_OPERATOR=textwrap.dedent("""\
416 The penalty for splitting the line after a unary operator.
417 """),
418 SPLIT_PENALTY_ARITHMETIC_OPERATOR=textwrap.dedent("""\
419 The penalty of splitting the line around the '+', '-', '*', '/', '//',
420 `%`, and '@' operators.
421 """),
422 SPLIT_PENALTY_BEFORE_IF_EXPR=textwrap.dedent("""\
423 The penalty for splitting right before an if expression.
424 """),
425 SPLIT_PENALTY_BITWISE_OPERATOR=textwrap.dedent("""\
426 The penalty of splitting the line around the '&', '|', and '^' operators.
427 """),
428 SPLIT_PENALTY_COMPREHENSION=textwrap.dedent("""\
429 The penalty for splitting a list comprehension or generator
430 expression.
431 """),
432 SPLIT_PENALTY_EXCESS_CHARACTER=textwrap.dedent("""\
433 The penalty for characters over the column limit.
434 """),
435 SPLIT_PENALTY_FOR_ADDED_LINE_SPLIT=textwrap.dedent("""\
436 The penalty incurred by adding a line split to the logical line. The
437 more line splits added the higher the penalty.
438 """),
439 SPLIT_PENALTY_IMPORT_NAMES=textwrap.dedent("""\
440 The penalty of splitting a list of "import as" names. For example:
441
442 from a_very_long_or_indented_module_name_yada_yad import (long_argument_1,
443 long_argument_2,
444 long_argument_3)
445
446 would reformat to something like:
447
448 from a_very_long_or_indented_module_name_yada_yad import (
449 long_argument_1, long_argument_2, long_argument_3)
450 """), # noqa
451 SPLIT_PENALTY_LOGICAL_OPERATOR=textwrap.dedent("""\
452 The penalty of splitting the line around the 'and' and 'or' operators.
453 """),
454 USE_TABS=textwrap.dedent("""\
455 Use the Tab character for indentation.
456 """),
457 )
458
459
460 def CreatePEP8Style():
461 """Create the PEP8 formatting style."""
462 return dict(
463 ALIGN_CLOSING_BRACKET_WITH_VISUAL_INDENT=True,
464 ALLOW_MULTILINE_DICTIONARY_KEYS=False,
465 ALLOW_MULTILINE_LAMBDAS=False,
466 ALLOW_SPLIT_BEFORE_DEFAULT_OR_NAMED_ASSIGNS=True,
467 ALLOW_SPLIT_BEFORE_DICT_VALUE=True,
468 ARITHMETIC_PRECEDENCE_INDICATION=False,
469 BLANK_LINE_BEFORE_CLASS_DOCSTRING=False,
470 BLANK_LINE_BEFORE_MODULE_DOCSTRING=False,
471 BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF=True,
472 BLANK_LINES_AROUND_TOP_LEVEL_DEFINITION=2,
473 BLANK_LINES_BETWEEN_TOP_LEVEL_IMPORTS_AND_VARIABLES=1,
474 COALESCE_BRACKETS=False,
475 COLUMN_LIMIT=79,
476 CONTINUATION_ALIGN_STYLE='SPACE',
477 CONTINUATION_INDENT_WIDTH=4,
478 DEDENT_CLOSING_BRACKETS=False,
479 DISABLE_ENDING_COMMA_HEURISTIC=False,
480 EACH_DICT_ENTRY_ON_SEPARATE_LINE=True,
481 FORCE_MULTILINE_DICT=False,
482 I18N_COMMENT='',
483 I18N_FUNCTION_CALL='',
484 INDENT_CLOSING_BRACKETS=False,
485 INDENT_DICTIONARY_VALUE=False,
486 INDENT_WIDTH=4,
487 INDENT_BLANK_LINES=False,
488 JOIN_MULTIPLE_LINES=True,
489 NO_SPACES_AROUND_SELECTED_BINARY_OPERATORS=set(),
490 SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET=True,
491 SPACE_INSIDE_BRACKETS=False,
492 SPACES_AROUND_DEFAULT_OR_NAMED_ASSIGN=False,
493 SPACES_AROUND_DICT_DELIMITERS=False,
494 SPACES_AROUND_LIST_DELIMITERS=False,
495 SPACES_AROUND_POWER_OPERATOR=False,
496 SPACES_AROUND_SUBSCRIPT_COLON=False,
497 SPACES_AROUND_TUPLE_DELIMITERS=False,
498 SPACES_BEFORE_COMMENT=2,
499 SPLIT_ALL_COMMA_SEPARATED_VALUES=False,
500 SPLIT_ALL_TOP_LEVEL_COMMA_SEPARATED_VALUES=False,
501 SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED=False,
502 SPLIT_BEFORE_ARITHMETIC_OPERATOR=False,
503 SPLIT_BEFORE_BITWISE_OPERATOR=True,
504 SPLIT_BEFORE_CLOSING_BRACKET=True,
505 SPLIT_BEFORE_DICT_SET_GENERATOR=True,
506 SPLIT_BEFORE_DOT=False,
507 SPLIT_BEFORE_EXPRESSION_AFTER_OPENING_PAREN=False,
508 SPLIT_BEFORE_FIRST_ARGUMENT=False,
509 SPLIT_BEFORE_LOGICAL_OPERATOR=True,
510 SPLIT_BEFORE_NAMED_ASSIGNS=True,
511 SPLIT_COMPLEX_COMPREHENSION=False,
512 SPLIT_PENALTY_AFTER_OPENING_BRACKET=300,
513 SPLIT_PENALTY_AFTER_UNARY_OPERATOR=10000,
514 SPLIT_PENALTY_ARITHMETIC_OPERATOR=300,
515 SPLIT_PENALTY_BEFORE_IF_EXPR=0,
516 SPLIT_PENALTY_BITWISE_OPERATOR=300,
517 SPLIT_PENALTY_COMPREHENSION=80,
518 SPLIT_PENALTY_EXCESS_CHARACTER=7000,
519 SPLIT_PENALTY_FOR_ADDED_LINE_SPLIT=30,
520 SPLIT_PENALTY_IMPORT_NAMES=0,
521 SPLIT_PENALTY_LOGICAL_OPERATOR=300,
522 USE_TABS=False,
523 )
524
525
526 def CreateGoogleStyle():
527 """Create the Google formatting style."""
528 style = CreatePEP8Style()
529 style['ALIGN_CLOSING_BRACKET_WITH_VISUAL_INDENT'] = False
530 style['COLUMN_LIMIT'] = 80
531 style['INDENT_DICTIONARY_VALUE'] = True
532 style['INDENT_WIDTH'] = 4
533 style['I18N_COMMENT'] = r'#\..*'
534 style['I18N_FUNCTION_CALL'] = ['N_', '_']
535 style['JOIN_MULTIPLE_LINES'] = False
536 style['SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET'] = False
537 style['SPLIT_BEFORE_BITWISE_OPERATOR'] = False
538 style['SPLIT_BEFORE_DICT_SET_GENERATOR'] = False
539 style['SPLIT_BEFORE_LOGICAL_OPERATOR'] = False
540 style['SPLIT_COMPLEX_COMPREHENSION'] = True
541 style['SPLIT_PENALTY_COMPREHENSION'] = 2100
542 return style
543
544
545 def CreateYapfStyle():
546 """Create the YAPF formatting style."""
547 style = CreateGoogleStyle()
548 style['ALLOW_MULTILINE_DICTIONARY_KEYS'] = True
549 style['ALLOW_SPLIT_BEFORE_DEFAULT_OR_NAMED_ASSIGNS'] = False
550 style['INDENT_WIDTH'] = 2
551 style['SPLIT_BEFORE_BITWISE_OPERATOR'] = True
552 style['SPLIT_BEFORE_DOT'] = True
553 style['SPLIT_BEFORE_EXPRESSION_AFTER_OPENING_PAREN'] = True
554 return style
555
556
557 def CreateFacebookStyle():
558 """Create the Facebook formatting style."""
559 style = CreatePEP8Style()
560 style['ALIGN_CLOSING_BRACKET_WITH_VISUAL_INDENT'] = False
561 style['BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF'] = False
562 style['COLUMN_LIMIT'] = 80
563 style['DEDENT_CLOSING_BRACKETS'] = True
564 style['INDENT_CLOSING_BRACKETS'] = False
565 style['INDENT_DICTIONARY_VALUE'] = True
566 style['JOIN_MULTIPLE_LINES'] = False
567 style['SPACES_BEFORE_COMMENT'] = 2
568 style['SPLIT_PENALTY_AFTER_OPENING_BRACKET'] = 0
569 style['SPLIT_PENALTY_BEFORE_IF_EXPR'] = 30
570 style['SPLIT_PENALTY_FOR_ADDED_LINE_SPLIT'] = 30
571 style['SPLIT_BEFORE_BITWISE_OPERATOR'] = False
572 style['SPLIT_BEFORE_LOGICAL_OPERATOR'] = False
573 return style
574
575
576 _STYLE_NAME_TO_FACTORY = dict(
577 facebook=CreateFacebookStyle,
578 google=CreateGoogleStyle,
579 pep8=CreatePEP8Style,
580 yapf=CreateYapfStyle,
581 )
582
583 _DEFAULT_STYLE_TO_FACTORY = [
584 (CreateFacebookStyle(), CreateFacebookStyle),
585 (CreateGoogleStyle(), CreateGoogleStyle),
586 (CreatePEP8Style(), CreatePEP8Style),
587 (CreateYapfStyle(), CreateYapfStyle),
588 ]
589
590
591 def _GetStyleFactory(style):
592 for def_style, factory in _DEFAULT_STYLE_TO_FACTORY:
593 if style == def_style:
594 return factory
595 return None
596
597
598 def _ContinuationAlignStyleStringConverter(s):
599 """Option value converter for a continuation align style string."""
600 accepted_styles = ('SPACE', 'FIXED', 'VALIGN-RIGHT')
601 if s:
602 r = s.strip('"\'').replace('_', '-').upper()
603 if r not in accepted_styles:
604 raise ValueError('unknown continuation align style: %r' % (s,))
605 else:
606 r = accepted_styles[0]
607 return r
608
609
610 def _StringListConverter(s):
611 """Option value converter for a comma-separated list of strings."""
612 return [part.strip() for part in s.split(',')]
613
614
615 def _StringSetConverter(s):
616 """Option value converter for a comma-separated set of strings."""
617 if len(s) > 2 and s[0] in '"\'':
618 s = s[1:-1]
619 return {part.strip() for part in s.split(',')}
620
621
622 def _BoolConverter(s):
623 """Option value converter for a boolean."""
624 return ConfigParser.BOOLEAN_STATES[s.lower()]
625
626
627 def _IntListConverter(s):
628 """Option value converter for a comma-separated list of integers."""
629 s = s.strip()
630 if s.startswith('[') and s.endswith(']'):
631 s = s[1:-1]
632
633 return [int(part.strip()) for part in s.split(',') if part.strip()]
634
635
636 def _IntOrIntListConverter(s):
637 """Option value converter for an integer or list of integers."""
638 if len(s) > 2 and s[0] in '"\'':
639 s = s[1:-1]
640 return _IntListConverter(s) if ',' in s else int(s)
641
642
643 # Different style options need to have their values interpreted differently when
644 # read from the config file. This dict maps an option name to a "converter"
645 # function that accepts the string read for the option's value from the file and
646 # returns it wrapper in actual Python type that's going to be meaningful to
647 # yapf.
648 #
649 # Note: this dict has to map all the supported style options.
650 _STYLE_OPTION_VALUE_CONVERTER = dict(
651 ALIGN_CLOSING_BRACKET_WITH_VISUAL_INDENT=_BoolConverter,
652 ALLOW_MULTILINE_DICTIONARY_KEYS=_BoolConverter,
653 ALLOW_MULTILINE_LAMBDAS=_BoolConverter,
654 ALLOW_SPLIT_BEFORE_DEFAULT_OR_NAMED_ASSIGNS=_BoolConverter,
655 ALLOW_SPLIT_BEFORE_DICT_VALUE=_BoolConverter,
656 ARITHMETIC_PRECEDENCE_INDICATION=_BoolConverter,
657 BLANK_LINE_BEFORE_CLASS_DOCSTRING=_BoolConverter,
658 BLANK_LINE_BEFORE_MODULE_DOCSTRING=_BoolConverter,
659 BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF=_BoolConverter,
660 BLANK_LINES_AROUND_TOP_LEVEL_DEFINITION=int,
661 BLANK_LINES_BETWEEN_TOP_LEVEL_IMPORTS_AND_VARIABLES=int,
662 COALESCE_BRACKETS=_BoolConverter,
663 COLUMN_LIMIT=int,
664 CONTINUATION_ALIGN_STYLE=_ContinuationAlignStyleStringConverter,
665 CONTINUATION_INDENT_WIDTH=int,
666 DEDENT_CLOSING_BRACKETS=_BoolConverter,
667 DISABLE_ENDING_COMMA_HEURISTIC=_BoolConverter,
668 EACH_DICT_ENTRY_ON_SEPARATE_LINE=_BoolConverter,
669 FORCE_MULTILINE_DICT=_BoolConverter,
670 I18N_COMMENT=str,
671 I18N_FUNCTION_CALL=_StringListConverter,
672 INDENT_BLANK_LINES=_BoolConverter,
673 INDENT_CLOSING_BRACKETS=_BoolConverter,
674 INDENT_DICTIONARY_VALUE=_BoolConverter,
675 INDENT_WIDTH=int,
676 JOIN_MULTIPLE_LINES=_BoolConverter,
677 NO_SPACES_AROUND_SELECTED_BINARY_OPERATORS=_StringSetConverter,
678 SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET=_BoolConverter,
679 SPACE_INSIDE_BRACKETS=_BoolConverter,
680 SPACES_AROUND_DEFAULT_OR_NAMED_ASSIGN=_BoolConverter,
681 SPACES_AROUND_DICT_DELIMITERS=_BoolConverter,
682 SPACES_AROUND_LIST_DELIMITERS=_BoolConverter,
683 SPACES_AROUND_POWER_OPERATOR=_BoolConverter,
684 SPACES_AROUND_SUBSCRIPT_COLON=_BoolConverter,
685 SPACES_AROUND_TUPLE_DELIMITERS=_BoolConverter,
686 SPACES_BEFORE_COMMENT=_IntOrIntListConverter,
687 SPLIT_ALL_COMMA_SEPARATED_VALUES=_BoolConverter,
688 SPLIT_ALL_TOP_LEVEL_COMMA_SEPARATED_VALUES=_BoolConverter,
689 SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED=_BoolConverter,
690 SPLIT_BEFORE_ARITHMETIC_OPERATOR=_BoolConverter,
691 SPLIT_BEFORE_BITWISE_OPERATOR=_BoolConverter,
692 SPLIT_BEFORE_CLOSING_BRACKET=_BoolConverter,
693 SPLIT_BEFORE_DICT_SET_GENERATOR=_BoolConverter,
694 SPLIT_BEFORE_DOT=_BoolConverter,
695 SPLIT_BEFORE_EXPRESSION_AFTER_OPENING_PAREN=_BoolConverter,
696 SPLIT_BEFORE_FIRST_ARGUMENT=_BoolConverter,
697 SPLIT_BEFORE_LOGICAL_OPERATOR=_BoolConverter,
698 SPLIT_BEFORE_NAMED_ASSIGNS=_BoolConverter,
699 SPLIT_COMPLEX_COMPREHENSION=_BoolConverter,
700 SPLIT_PENALTY_AFTER_OPENING_BRACKET=int,
701 SPLIT_PENALTY_AFTER_UNARY_OPERATOR=int,
702 SPLIT_PENALTY_ARITHMETIC_OPERATOR=int,
703 SPLIT_PENALTY_BEFORE_IF_EXPR=int,
704 SPLIT_PENALTY_BITWISE_OPERATOR=int,
705 SPLIT_PENALTY_COMPREHENSION=int,
706 SPLIT_PENALTY_EXCESS_CHARACTER=int,
707 SPLIT_PENALTY_FOR_ADDED_LINE_SPLIT=int,
708 SPLIT_PENALTY_IMPORT_NAMES=int,
709 SPLIT_PENALTY_LOGICAL_OPERATOR=int,
710 USE_TABS=_BoolConverter,
711 )
712
713
714 def CreateStyleFromConfig(style_config):
715 """Create a style dict from the given config.
716
717 Arguments:
718 style_config: either a style name or a file name. The file is expected to
719 contain settings. It can have a special BASED_ON_STYLE setting naming the
720 style which it derives from. If no such setting is found, it derives from
721 the default style. When style_config is None, the _GLOBAL_STYLE_FACTORY
722 config is created.
723
724 Returns:
725 A style dict.
726
727 Raises:
728 StyleConfigError: if an unknown style option was encountered.
729 """
730
731 def GlobalStyles():
732 for style, _ in _DEFAULT_STYLE_TO_FACTORY:
733 yield style
734
735 def_style = False
736 if style_config is None:
737 for style in GlobalStyles():
738 if _style == style:
739 def_style = True
740 break
741 if not def_style:
742 return _style
743 return _GLOBAL_STYLE_FACTORY()
744
745 if isinstance(style_config, dict):
746 config = _CreateConfigParserFromConfigDict(style_config)
747 elif isinstance(style_config, str):
748 style_factory = _STYLE_NAME_TO_FACTORY.get(style_config.lower())
749 if style_factory is not None:
750 return style_factory()
751 if style_config.startswith('{'):
752 # Most likely a style specification from the command line.
753 config = _CreateConfigParserFromConfigString(style_config)
754 else:
755 # Unknown config name: assume it's a file name then.
756 config = _CreateConfigParserFromConfigFile(style_config)
757 return _CreateStyleFromConfigParser(config)
758
759
760 def _CreateConfigParserFromConfigDict(config_dict):
761 config = ConfigParser()
762 config.add_section('style')
763 for key, value in config_dict.items():
764 config.set('style', key, str(value))
765 return config
766
767
768 def _CreateConfigParserFromConfigString(config_string):
769 """Given a config string from the command line, return a config parser."""
770 if config_string[0] != '{' or config_string[-1] != '}':
771 raise StyleConfigError(
772 "Invalid style dict syntax: '{}'.".format(config_string))
773 config = ConfigParser()
774 config.add_section('style')
775 for key, value, _ in re.findall(
776 r'([a-zA-Z0-9_]+)\s*[:=]\s*'
777 r'(?:'
778 r'((?P<quote>[\'"]).*?(?P=quote)|'
779 r'[a-zA-Z0-9_]+)'
780 r')', config_string): # yapf: disable
781 config.set('style', key, value)
782 return config
783
784
785 def _CreateConfigParserFromConfigFile(config_filename):
786 """Read the file and return a ConfigParser object."""
787 if not os.path.exists(config_filename):
788 # Provide a more meaningful error here.
789 raise StyleConfigError(
790 '"{0}" is not a valid style or file path'.format(config_filename))
791 config = ConfigParser()
792
793 if config_filename.endswith(PYPROJECT_TOML):
794 try:
795 import tomli as tomllib
796 except ImportError:
797 raise errors.YapfError(
798 'tomli package is needed for using pyproject.toml as a '
799 'configuration file')
800
801 with open(config_filename, 'rb') as style_file:
802 pyproject_toml = tomllib.load(style_file)
803 style_dict = pyproject_toml.get('tool', {}).get('yapf', None)
804 if style_dict is None:
805 raise StyleConfigError(
806 'Unable to find section [tool.yapf] in {0}'.format(config_filename))
807 config.add_section('style')
808 for k, v in style_dict.items():
809 config.set('style', k, str(v))
810 return config
811
812 with open(config_filename) as style_file:
813 config.read_file(style_file)
814
815 if config_filename.endswith(SETUP_CONFIG):
816 if not config.has_section('yapf'):
817 raise StyleConfigError(
818 'Unable to find section [yapf] in {0}'.format(config_filename))
819 return config
820
821 if config_filename.endswith(LOCAL_STYLE):
822 if not config.has_section('style'):
823 raise StyleConfigError(
824 'Unable to find section [style] in {0}'.format(config_filename))
825 return config
826
827 if not config.has_section('style'):
828 raise StyleConfigError(
829 'Unable to find section [style] in {0}'.format(config_filename))
830 return config
831
832
833 def _CreateStyleFromConfigParser(config):
834 """Create a style dict from a configuration file.
835
836 Arguments:
837 config: a ConfigParser object.
838
839 Returns:
840 A style dict.
841
842 Raises:
843 StyleConfigError: if an unknown style option was encountered.
844 """
845 # Initialize the base style.
846 section = 'yapf' if config.has_section('yapf') else 'style'
847 if config.has_option('style', 'based_on_style'):
848 based_on = config.get('style', 'based_on_style').lower()
849 base_style = _STYLE_NAME_TO_FACTORY[based_on]()
850 elif config.has_option('yapf', 'based_on_style'):
851 based_on = config.get('yapf', 'based_on_style').lower()
852 base_style = _STYLE_NAME_TO_FACTORY[based_on]()
853 else:
854 base_style = _GLOBAL_STYLE_FACTORY()
855
856 # Read all options specified in the file and update the style.
857 for option, value in config.items(section):
858 if option.lower() == 'based_on_style':
859 # Now skip this one - we've already handled it and it's not one of the
860 # recognized style options.
861 continue
862 option = option.upper()
863 if option not in _STYLE_OPTION_VALUE_CONVERTER:
864 raise StyleConfigError('Unknown style option "{0}"'.format(option))
865 try:
866 base_style[option] = _STYLE_OPTION_VALUE_CONVERTER[option](value)
867 except ValueError:
868 raise StyleConfigError("'{}' is not a valid setting for {}.".format(
869 value, option))
870 return base_style
871
872
873 # The default style - used if yapf is not invoked without specifically
874 # requesting a formatting style.
875 DEFAULT_STYLE = 'pep8'
876 DEFAULT_STYLE_FACTORY = CreatePEP8Style
877 _GLOBAL_STYLE_FACTORY = CreatePEP8Style
878
879 # The name of the file to use for global style definition.
880 GLOBAL_STYLE = (
881 os.path.join(
882 os.getenv('XDG_CONFIG_HOME') or os.path.expanduser('~/.config'), 'yapf',
883 'style'))
884
885 # The name of the file to use for directory-local style definition.
886 LOCAL_STYLE = '.style.yapf'
887
888 # Alternative place for directory-local style definition. Style should be
889 # specified in the '[yapf]' section.
890 SETUP_CONFIG = 'setup.cfg'
891
892 # Style definition by local pyproject.toml file. Style should be specified
893 # in the '[tool.yapf]' section.
894 PYPROJECT_TOML = 'pyproject.toml'
895
896 # TODO(eliben): For now we're preserving the global presence of a style dict.
897 # Refactor this so that the style is passed around through yapf rather than
898 # being global.
899 _style = None
900 SetGlobalStyle(_GLOBAL_STYLE_FACTORY())