1 # Copyright 2015 Google Inc. All Rights Reserved.
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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."""
19 from configparser
import ConfigParser
21 from yapf
.yapflib
import errors
24 class StyleConfigError(errors
.YapfError
):
25 """Raised when there's a problem reading the style configuration."""
29 def Get(setting_name
):
30 """Get a style setting."""
31 return _style
[setting_name
]
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
)
40 """Return dict mapping style names to help strings."""
44 def SetGlobalStyle(style
):
45 """Set a style dict."""
47 global _GLOBAL_STYLE_FACTORY
48 factory
= _GetStyleFactory(style
)
50 _GLOBAL_STYLE_FACTORY
= factory
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.
59 ALLOW_MULTILINE_DICTIONARY_KEYS
=textwrap
.dedent("""\
60 Allow dictionary keys to exist on multiple lines. For example:
63 ('this is the first element of a tuple',
64 'this is the second element of a tuple'):
68 ALLOW_MULTILINE_LAMBDAS
=textwrap
.dedent("""\
69 Allow lambdas to be formatted on more than one line.
71 ALLOW_SPLIT_BEFORE_DEFAULT_OR_NAMED_ASSIGNS
=textwrap
.dedent("""\
72 Allow splitting before a default / named assignment in an argument list.
74 ALLOW_SPLIT_BEFORE_DICT_VALUE
=textwrap
.dedent("""\
75 Allow splits before the dictionary value.
77 ARITHMETIC_PRECEDENCE_INDICATION
=textwrap
.dedent("""\
78 Let spacing indicate operator precedence. For example:
87 will be formatted as follows to indicate precedence:
97 BLANK_LINE_BEFORE_CLASS_DOCSTRING
=textwrap
.dedent("""\
98 Insert a blank line before a class-level docstring.
100 BLANK_LINE_BEFORE_MODULE_DOCSTRING
=textwrap
.dedent("""\
101 Insert a blank line before a module docstring.
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:
108 # <------ this blank line
112 BLANK_LINES_AROUND_TOP_LEVEL_DEFINITION
=textwrap
.dedent("""\
113 Number of blank lines surrounding top-level function and class
116 BLANK_LINES_BETWEEN_TOP_LEVEL_IMPORTS_AND_VARIABLES
=textwrap
.dedent("""\
117 Number of blank lines between top-level imports and variable
120 COALESCE_BRACKETS
=textwrap
.dedent("""\
121 Do not split consecutive brackets. Only relevant when
122 dedent_closing_brackets is set. For example:
124 call_func_that_takes_a_dict(
133 call_func_that_takes_a_dict({
138 COLUMN_LIMIT
=textwrap
.dedent("""\
141 CONTINUATION_ALIGN_STYLE
=textwrap
.dedent("""\
142 The style for continuation alignment. Possible values are:
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.
152 CONTINUATION_INDENT_WIDTH
=textwrap
.dedent("""\
153 Indent width used for line continuations.
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:
163 } # <--- this bracket is dedented and on a separate line
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),
171 ) # <--- this bracket is dedented and on a separate line
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.
177 EACH_DICT_ENTRY_ON_SEPARATE_LINE
=textwrap
.dedent("""\
178 Place each dictionary entry onto its own line.
180 FORCE_MULTILINE_DICT
=textwrap
.dedent("""\
181 Require multiline dictionary even if it would normally fit on one line.
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.
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.
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:
206 } # <--- this bracket is indented and on a separate line
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),
214 ) # <--- this bracket is indented and on a separate line
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:
227 INDENT_BLANK_LINES
=textwrap
.dedent("""\
230 INDENT_WIDTH
=textwrap
.dedent("""\
231 The number of columns to use for indentation.
233 JOIN_MULTIPLE_LINES
=textwrap
.dedent("""\
234 Join short lines into one line. E.g., single line 'if' statements.
236 NO_SPACES_AROUND_SELECTED_BINARY_OPERATORS
=textwrap
.dedent("""\
237 Do not include spaces around selected binary operators. For example:
241 will be formatted as follows when configured with "*,/":
245 SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET
=textwrap
.dedent("""\
246 Insert a space between the ending comma and closing bracket of a list,
249 SPACE_INSIDE_BRACKETS
=textwrap
.dedent("""\
250 Use spaces inside brackets, braces, and parentheses. For example:
253 my_dict[ 3 ][ 1 ][ get_index( *args, **kwargs ) ]
256 SPACES_AROUND_DEFAULT_OR_NAMED_ASSIGN
=textwrap
.dedent("""\
257 Use spaces around default or named assigns.
259 SPACES_AROUND_DICT_DELIMITERS
=textwrap
.dedent("""\
260 Adds a space after the opening '{' and before the ending '}' dict
265 will be formatted as:
269 SPACES_AROUND_LIST_DELIMITERS
=textwrap
.dedent("""\
270 Adds a space after the opening '[' and before the ending ']' list
275 will be formatted as:
279 SPACES_AROUND_POWER_OPERATOR
=textwrap
.dedent("""\
280 Use spaces around the power operator.
282 SPACES_AROUND_SUBSCRIPT_COLON
=textwrap
.dedent("""\
283 Use spaces around the subscript / slice operator. For example:
287 SPACES_AROUND_TUPLE_DELIMITERS
=textwrap
.dedent("""\
288 Adds a space after the opening '(' and before the ending ')' tuple
293 will be formatted as:
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:
305 With spaces_before_comment=5:
307 1 + 1 # Adding values
309 will be formatted as:
311 1 + 1 # Adding values <-- 5 spaces between the end of the
312 # statement and comment
314 With spaces_before_comment=15, 20:
316 1 + 1 # Adding values
317 two + two # More adding
319 longer_statement # This is a longer statement
320 short # This is a shorter statement
322 a_very_long_statement_that_extends_beyond_the_final_column # Comment
323 short # This is a shorter statement
325 will be formatted as:
327 1 + 1 # Adding values <-- end of line comments in block
329 two + two # More adding
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
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
339 SPLIT_ALL_COMMA_SEPARATED_VALUES
=textwrap
.dedent("""\
340 Split before arguments.
342 SPLIT_ALL_TOP_LEVEL_COMMA_SEPARATED_VALUES
=textwrap
.dedent("""\
343 Split before arguments, but do not split all subexpressions recursively
346 SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED
=textwrap
.dedent("""\
347 Split before arguments if the argument list is terminated by a
350 SPLIT_BEFORE_ARITHMETIC_OPERATOR
=textwrap
.dedent("""\
351 Set to True to prefer splitting before '+', '-', '*', '/', '//', or '@'
354 SPLIT_BEFORE_BITWISE_OPERATOR
=textwrap
.dedent("""\
355 Set to True to prefer splitting before '&', '|' or '^' rather than
358 SPLIT_BEFORE_CLOSING_BRACKET
=textwrap
.dedent("""\
359 Split before the closing bracket if a list or dict literal doesn't fit on
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':
367 variable: 'Hello world, have a nice day!'
368 for variable in bar if variable != 42
371 SPLIT_BEFORE_DOT
=textwrap
.dedent("""\
372 Split before the '.' if we need to split a longer expression:
374 foo = ('This is a really long string: {}, {}, {}, {}'.format(a, b, c, d))
376 would reformat to something like:
378 foo = ('This is a really long string: {}, {}, {}, {}'
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.
385 SPLIT_BEFORE_FIRST_ARGUMENT
=textwrap
.dedent("""\
386 If an argument / parameter list is going to be split, then split before
389 SPLIT_BEFORE_LOGICAL_OPERATOR
=textwrap
.dedent("""\
390 Set to True to prefer splitting before 'and' or 'or' rather than
393 SPLIT_BEFORE_NAMED_ASSIGNS
=textwrap
.dedent("""\
394 Split named assignments onto individual lines.
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:
402 a_long_var + 100 for a_long_var in xrange(1000)
405 would reformat to something like:
409 for a_long_var in xrange(1000)
412 SPLIT_PENALTY_AFTER_OPENING_BRACKET
=textwrap
.dedent("""\
413 The penalty for splitting right after the opening bracket.
415 SPLIT_PENALTY_AFTER_UNARY_OPERATOR
=textwrap
.dedent("""\
416 The penalty for splitting the line after a unary operator.
418 SPLIT_PENALTY_ARITHMETIC_OPERATOR
=textwrap
.dedent("""\
419 The penalty of splitting the line around the '+', '-', '*', '/', '//',
420 `%`, and '@' operators.
422 SPLIT_PENALTY_BEFORE_IF_EXPR
=textwrap
.dedent("""\
423 The penalty for splitting right before an if expression.
425 SPLIT_PENALTY_BITWISE_OPERATOR
=textwrap
.dedent("""\
426 The penalty of splitting the line around the '&', '|', and '^' operators.
428 SPLIT_PENALTY_COMPREHENSION
=textwrap
.dedent("""\
429 The penalty for splitting a list comprehension or generator
432 SPLIT_PENALTY_EXCESS_CHARACTER
=textwrap
.dedent("""\
433 The penalty for characters over the column limit.
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.
439 SPLIT_PENALTY_IMPORT_NAMES
=textwrap
.dedent("""\
440 The penalty of splitting a list of "import as" names. For example:
442 from a_very_long_or_indented_module_name_yada_yad import (long_argument_1,
446 would reformat to something like:
448 from a_very_long_or_indented_module_name_yada_yad import (
449 long_argument_1, long_argument_2, long_argument_3)
451 SPLIT_PENALTY_LOGICAL_OPERATOR
=textwrap
.dedent("""\
452 The penalty of splitting the line around the 'and' and 'or' operators.
454 USE_TABS
=textwrap
.dedent("""\
455 Use the Tab character for indentation.
460 def CreatePEP8Style():
461 """Create the PEP8 formatting style."""
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,
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,
483 I18N_FUNCTION_CALL
='',
484 INDENT_CLOSING_BRACKETS
=False,
485 INDENT_DICTIONARY_VALUE
=False,
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,
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
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
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
576 _STYLE_NAME_TO_FACTORY
= dict(
577 facebook
=CreateFacebookStyle
,
578 google
=CreateGoogleStyle
,
579 pep8
=CreatePEP8Style
,
580 yapf
=CreateYapfStyle
,
583 _DEFAULT_STYLE_TO_FACTORY
= [
584 (CreateFacebookStyle(), CreateFacebookStyle
),
585 (CreateGoogleStyle(), CreateGoogleStyle
),
586 (CreatePEP8Style(), CreatePEP8Style
),
587 (CreateYapfStyle(), CreateYapfStyle
),
591 def _GetStyleFactory(style
):
592 for def_style
, factory
in _DEFAULT_STYLE_TO_FACTORY
:
593 if style
== def_style
:
598 def _ContinuationAlignStyleStringConverter(s
):
599 """Option value converter for a continuation align style string."""
600 accepted_styles
= ('SPACE', 'FIXED', 'VALIGN-RIGHT')
602 r
= s
.strip('"\'').replace('_', '-').upper()
603 if r
not in accepted_styles
:
604 raise ValueError('unknown continuation align style: %r' % (s
,))
606 r
= accepted_styles
[0]
610 def _StringListConverter(s
):
611 """Option value converter for a comma-separated list of strings."""
612 return [part
.strip() for part
in s
.split(',')]
615 def _StringSetConverter(s
):
616 """Option value converter for a comma-separated set of strings."""
617 if len(s
) > 2 and s
[0] in '"\'':
619 return {part
.strip() for part
in s
.split(',')}
622 def _BoolConverter(s
):
623 """Option value converter for a boolean."""
624 return ConfigParser
.BOOLEAN_STATES
[s
.lower()]
627 def _IntListConverter(s
):
628 """Option value converter for a comma-separated list of integers."""
630 if s
.startswith('[') and s
.endswith(']'):
633 return [int(part
.strip()) for part
in s
.split(',') if part
.strip()]
636 def _IntOrIntListConverter(s
):
637 """Option value converter for an integer or list of integers."""
638 if len(s
) > 2 and s
[0] in '"\'':
640 return _IntListConverter(s
) if ',' in s
else int(s
)
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
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
,
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
,
671 I18N_FUNCTION_CALL
=_StringListConverter
,
672 INDENT_BLANK_LINES
=_BoolConverter
,
673 INDENT_CLOSING_BRACKETS
=_BoolConverter
,
674 INDENT_DICTIONARY_VALUE
=_BoolConverter
,
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
,
714 def CreateStyleFromConfig(style_config
):
715 """Create a style dict from the given config.
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
728 StyleConfigError: if an unknown style option was encountered.
732 for style
, _
in _DEFAULT_STYLE_TO_FACTORY
:
736 if style_config
is None:
737 for style
in GlobalStyles():
743 return _GLOBAL_STYLE_FACTORY()
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
)
755 # Unknown config name: assume it's a file name then.
756 config
= _CreateConfigParserFromConfigFile(style_config
)
757 return _CreateStyleFromConfigParser(config
)
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
))
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*'
778 r
'((?P<quote>[\'"]).*?(?P=quote)|'
780 r')', config_string): # yapf: disable
781 config.set('style', key, value)
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()
793 if config_filename.endswith(PYPROJECT_TOML):
795 import tomli as tomllib
797 raise errors.YapfError(
798 'tomli package is needed for using pyproject.toml as a '
799 'configuration file')
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))
812 with open(config_filename) as style_file:
813 config.read_file(style_file)
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))
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))
827 if not config.has_section('style'):
828 raise StyleConfigError(
829 'Unable to find section [style] in {0}'.format(config_filename))
833 def _CreateStyleFromConfigParser(config):
834 """Create a style dict from a configuration file.
837 config: a ConfigParser object.
843 StyleConfigError: if an unknown style option was encountered.
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]()
854 base_style = _GLOBAL_STYLE_FACTORY()
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.
862 option = option.upper()
863 if option not in _STYLE_OPTION_VALUE_CONVERTER:
864 raise StyleConfigError('Unknown style option "{0}
"'.format(option))
866 base_style[option] = _STYLE_OPTION_VALUE_CONVERTER[option](value)
868 raise StyleConfigError("'{}' is not a valid setting
for {}.".format(
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
879 # The name of the file to use for global style definition.
882 os.getenv('XDG_CONFIG_HOME') or os.path.expanduser('~/.config'), 'yapf',
885 # The name of the file to use for directory-local style definition.
886 LOCAL_STYLE = '.style.yapf'
888 # Alternative place for directory-local style definition. Style should be
889 # specified in the '[yapf]' section.
890 SETUP_CONFIG = 'setup.cfg'
892 # Style definition by local pyproject.toml file. Style should be specified
893 # in the '[tool.yapf]' section.
894 PYPROJECT_TOML = 'pyproject.toml'
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
900 SetGlobalStyle(_GLOBAL_STYLE_FACTORY())