| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858 |
- # Copyright 2015 Google Inc. All Rights Reserved.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- """Python formatting style settings."""
- import os
- import re
- import textwrap
- from configparser import ConfigParser
- from yapf.yapflib import errors
- class StyleConfigError(errors.YapfError):
- """Raised when there's a problem reading the style configuration."""
- pass
- def Get(setting_name):
- """Get a style setting."""
- return _style[setting_name]
- def GetOrDefault(setting_name, default_value):
- """Get a style setting or default value if the setting does not exist."""
- return _style.get(setting_name, default_value)
- def Help():
- """Return dict mapping style names to help strings."""
- return _STYLE_HELP
- def SetGlobalStyle(style):
- """Set a style dict."""
- global _style
- global _GLOBAL_STYLE_FACTORY
- factory = _GetStyleFactory(style)
- if factory:
- _GLOBAL_STYLE_FACTORY = factory
- _style = style
- _STYLE_HELP = dict(
- ALIGN_CLOSING_BRACKET_WITH_VISUAL_INDENT=textwrap.dedent("""\
- Align closing bracket with visual indentation."""),
- ALLOW_MULTILINE_LAMBDAS=textwrap.dedent("""\
- Allow lambdas to be formatted on more than one line."""),
- ALLOW_MULTILINE_DICTIONARY_KEYS=textwrap.dedent("""\
- Allow dictionary keys to exist on multiple lines. For example:
- x = {
- ('this is the first element of a tuple',
- 'this is the second element of a tuple'):
- value,
- }"""),
- ALLOW_SPLIT_BEFORE_DEFAULT_OR_NAMED_ASSIGNS=textwrap.dedent("""\
- Allow splitting before a default / named assignment in an argument list.
- """),
- ALLOW_SPLIT_BEFORE_DICT_VALUE=textwrap.dedent("""\
- Allow splits before the dictionary value."""),
- ARITHMETIC_PRECEDENCE_INDICATION=textwrap.dedent("""\
- Let spacing indicate operator precedence. For example:
- a = 1 * 2 + 3 / 4
- b = 1 / 2 - 3 * 4
- c = (1 + 2) * (3 - 4)
- d = (1 - 2) / (3 + 4)
- e = 1 * 2 - 3
- f = 1 + 2 + 3 + 4
- will be formatted as follows to indicate precedence:
- a = 1*2 + 3/4
- b = 1/2 - 3*4
- c = (1+2) * (3-4)
- d = (1-2) / (3+4)
- e = 1*2 - 3
- f = 1 + 2 + 3 + 4
- """),
- BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF=textwrap.dedent("""\
- Insert a blank line before a 'def' or 'class' immediately nested
- within another 'def' or 'class'. For example:
- class Foo:
- # <------ this blank line
- def method():
- ..."""),
- BLANK_LINE_BEFORE_CLASS_DOCSTRING=textwrap.dedent("""\
- Insert a blank line before a class-level docstring."""),
- BLANK_LINE_BEFORE_MODULE_DOCSTRING=textwrap.dedent("""\
- Insert a blank line before a module docstring."""),
- BLANK_LINES_AROUND_TOP_LEVEL_DEFINITION=textwrap.dedent("""\
- Number of blank lines surrounding top-level function and class
- definitions."""),
- BLANK_LINES_BETWEEN_TOP_LEVEL_IMPORTS_AND_VARIABLES=textwrap.dedent("""\
- Number of blank lines between top-level imports and variable
- definitions."""),
- COALESCE_BRACKETS=textwrap.dedent("""\
- Do not split consecutive brackets. Only relevant when
- dedent_closing_brackets is set. For example:
- call_func_that_takes_a_dict(
- {
- 'key1': 'value1',
- 'key2': 'value2',
- }
- )
- would reformat to:
- call_func_that_takes_a_dict({
- 'key1': 'value1',
- 'key2': 'value2',
- })"""),
- COLUMN_LIMIT=textwrap.dedent("""\
- The column limit."""),
- CONTINUATION_ALIGN_STYLE=textwrap.dedent("""\
- The style for continuation alignment. Possible values are:
- - SPACE: Use spaces for continuation alignment. This is default behavior.
- - FIXED: Use fixed number (CONTINUATION_INDENT_WIDTH) of columns
- (ie: CONTINUATION_INDENT_WIDTH/INDENT_WIDTH tabs or
- CONTINUATION_INDENT_WIDTH spaces) for continuation alignment.
- - VALIGN-RIGHT: Vertically align continuation lines to multiple of
- INDENT_WIDTH columns. Slightly right (one tab or a few spaces) if
- cannot vertically align continuation lines with indent characters."""),
- CONTINUATION_INDENT_WIDTH=textwrap.dedent("""\
- Indent width used for line continuations."""),
- DEDENT_CLOSING_BRACKETS=textwrap.dedent("""\
- Put closing brackets on a separate line, dedented, if the bracketed
- expression can't fit in a single line. Applies to all kinds of brackets,
- including function definitions and calls. For example:
- config = {
- 'key1': 'value1',
- 'key2': 'value2',
- } # <--- this bracket is dedented and on a separate line
- time_series = self.remote_client.query_entity_counters(
- entity='dev3246.region1',
- key='dns.query_latency_tcp',
- transform=Transformation.AVERAGE(window=timedelta(seconds=60)),
- start_ts=now()-timedelta(days=3),
- end_ts=now(),
- ) # <--- this bracket is dedented and on a separate line
- """),
- DISABLE_ENDING_COMMA_HEURISTIC=textwrap.dedent("""\
- Disable the heuristic which places each list element on a separate line
- if the list is comma-terminated."""),
- EACH_DICT_ENTRY_ON_SEPARATE_LINE=textwrap.dedent("""\
- Place each dictionary entry onto its own line."""),
- FORCE_MULTILINE_DICT=textwrap.dedent("""\
- Require multiline dictionary even if it would normally fit on one line.
- For example:
- config = {
- 'key1': 'value1'
- }"""),
- I18N_COMMENT=textwrap.dedent("""\
- The regex for an i18n comment. The presence of this comment stops
- reformatting of that line, because the comments are required to be
- next to the string they translate."""),
- I18N_FUNCTION_CALL=textwrap.dedent("""\
- The i18n function call names. The presence of this function stops
- reformattting on that line, because the string it has cannot be moved
- away from the i18n comment."""),
- INDENT_CLOSING_BRACKETS=textwrap.dedent("""\
- Put closing brackets on a separate line, indented, if the bracketed
- expression can't fit in a single line. Applies to all kinds of brackets,
- including function definitions and calls. For example:
- config = {
- 'key1': 'value1',
- 'key2': 'value2',
- } # <--- this bracket is indented and on a separate line
- time_series = self.remote_client.query_entity_counters(
- entity='dev3246.region1',
- key='dns.query_latency_tcp',
- transform=Transformation.AVERAGE(window=timedelta(seconds=60)),
- start_ts=now()-timedelta(days=3),
- end_ts=now(),
- ) # <--- this bracket is indented and on a separate line
- """),
- INDENT_DICTIONARY_VALUE=textwrap.dedent("""\
- Indent the dictionary value if it cannot fit on the same line as the
- dictionary key. For example:
- config = {
- 'key1':
- 'value1',
- 'key2': value1 +
- value2,
- }
- """),
- INDENT_WIDTH=textwrap.dedent("""\
- The number of columns to use for indentation."""),
- INDENT_BLANK_LINES=textwrap.dedent("""\
- Indent blank lines."""),
- JOIN_MULTIPLE_LINES=textwrap.dedent("""\
- Join short lines into one line. E.g., single line 'if' statements."""),
- NO_SPACES_AROUND_SELECTED_BINARY_OPERATORS=textwrap.dedent("""\
- Do not include spaces around selected binary operators. For example:
- 1 + 2 * 3 - 4 / 5
- will be formatted as follows when configured with "*,/":
- 1 + 2*3 - 4/5
- """),
- SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET=textwrap.dedent("""\
- Insert a space between the ending comma and closing bracket of a list,
- etc."""),
- SPACE_INSIDE_BRACKETS=textwrap.dedent("""\
- Use spaces inside brackets, braces, and parentheses. For example:
- method_call( 1 )
- my_dict[ 3 ][ 1 ][ get_index( *args, **kwargs ) ]
- my_set = { 1, 2, 3 }
- """),
- SPACES_AROUND_POWER_OPERATOR=textwrap.dedent("""\
- Use spaces around the power operator."""),
- SPACES_AROUND_DEFAULT_OR_NAMED_ASSIGN=textwrap.dedent("""\
- Use spaces around default or named assigns."""),
- SPACES_AROUND_DICT_DELIMITERS=textwrap.dedent("""\
- Adds a space after the opening '{' and before the ending '}' dict
- delimiters.
- {1: 2}
- will be formatted as:
- { 1: 2 }
- """),
- SPACES_AROUND_LIST_DELIMITERS=textwrap.dedent("""\
- Adds a space after the opening '[' and before the ending ']' list
- delimiters.
- [1, 2]
- will be formatted as:
- [ 1, 2 ]
- """),
- SPACES_AROUND_SUBSCRIPT_COLON=textwrap.dedent("""\
- Use spaces around the subscript / slice operator. For example:
- my_list[1 : 10 : 2]
- """),
- SPACES_AROUND_TUPLE_DELIMITERS=textwrap.dedent("""\
- Adds a space after the opening '(' and before the ending ')' tuple
- delimiters.
- (1, 2, 3)
- will be formatted as:
- ( 1, 2, 3 )
- """),
- SPACES_BEFORE_COMMENT=textwrap.dedent("""\
- The number of spaces required before a trailing comment.
- This can be a single value (representing the number of spaces
- before each trailing comment) or list of values (representing
- alignment column values; trailing comments within a block will
- be aligned to the first column value that is greater than the maximum
- line length within the block). For example:
- With spaces_before_comment=5:
- 1 + 1 # Adding values
- will be formatted as:
- 1 + 1 # Adding values <-- 5 spaces between the end of the
- # statement and comment
- With spaces_before_comment=15, 20:
- 1 + 1 # Adding values
- two + two # More adding
- longer_statement # This is a longer statement
- short # This is a shorter statement
- a_very_long_statement_that_extends_beyond_the_final_column # Comment
- short # This is a shorter statement
- will be formatted as:
- 1 + 1 # Adding values <-- end of line comments in block
- # aligned to col 15
- two + two # More adding
- longer_statement # This is a longer statement <-- end of line
- # comments in block aligned to col 20
- short # This is a shorter statement
- a_very_long_statement_that_extends_beyond_the_final_column # Comment <-- the end of line comments are aligned based on the line length
- short # This is a shorter statement
- """), # noqa
- SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED=textwrap.dedent("""\
- Split before arguments if the argument list is terminated by a
- comma."""),
- SPLIT_ALL_COMMA_SEPARATED_VALUES=textwrap.dedent("""\
- Split before arguments"""),
- SPLIT_ALL_TOP_LEVEL_COMMA_SEPARATED_VALUES=textwrap.dedent("""\
- Split before arguments, but do not split all subexpressions recursively
- (unless needed)."""),
- SPLIT_BEFORE_ARITHMETIC_OPERATOR=textwrap.dedent("""\
- Set to True to prefer splitting before '+', '-', '*', '/', '//', or '@'
- rather than after."""),
- SPLIT_BEFORE_BITWISE_OPERATOR=textwrap.dedent("""\
- Set to True to prefer splitting before '&', '|' or '^' rather than
- after."""),
- SPLIT_BEFORE_CLOSING_BRACKET=textwrap.dedent("""\
- Split before the closing bracket if a list or dict literal doesn't fit on
- a single line."""),
- SPLIT_BEFORE_DICT_SET_GENERATOR=textwrap.dedent("""\
- Split before a dictionary or set generator (comp_for). For example, note
- the split before the 'for':
- foo = {
- variable: 'Hello world, have a nice day!'
- for variable in bar if variable != 42
- }"""),
- SPLIT_BEFORE_DOT=textwrap.dedent("""\
- Split before the '.' if we need to split a longer expression:
- foo = ('This is a really long string: {}, {}, {}, {}'.format(a, b, c, d))
- would reformat to something like:
- foo = ('This is a really long string: {}, {}, {}, {}'
- .format(a, b, c, d))
- """), # noqa
- SPLIT_BEFORE_EXPRESSION_AFTER_OPENING_PAREN=textwrap.dedent("""\
- Split after the opening paren which surrounds an expression if it doesn't
- fit on a single line.
- """),
- SPLIT_BEFORE_FIRST_ARGUMENT=textwrap.dedent("""\
- If an argument / parameter list is going to be split, then split before
- the first argument."""),
- SPLIT_BEFORE_LOGICAL_OPERATOR=textwrap.dedent("""\
- Set to True to prefer splitting before 'and' or 'or' rather than
- after."""),
- SPLIT_BEFORE_NAMED_ASSIGNS=textwrap.dedent("""\
- Split named assignments onto individual lines."""),
- SPLIT_COMPLEX_COMPREHENSION=textwrap.dedent("""\
- Set to True to split list comprehensions and generators that have
- non-trivial expressions and multiple clauses before each of these
- clauses. For example:
- result = [
- a_long_var + 100 for a_long_var in xrange(1000)
- if a_long_var % 10]
- would reformat to something like:
- result = [
- a_long_var + 100
- for a_long_var in xrange(1000)
- if a_long_var % 10]
- """),
- SPLIT_PENALTY_AFTER_OPENING_BRACKET=textwrap.dedent("""\
- The penalty for splitting right after the opening bracket."""),
- SPLIT_PENALTY_AFTER_UNARY_OPERATOR=textwrap.dedent("""\
- The penalty for splitting the line after a unary operator."""),
- SPLIT_PENALTY_ARITHMETIC_OPERATOR=textwrap.dedent("""\
- The penalty of splitting the line around the '+', '-', '*', '/', '//',
- ``%``, and '@' operators."""),
- SPLIT_PENALTY_BEFORE_IF_EXPR=textwrap.dedent("""\
- The penalty for splitting right before an if expression."""),
- SPLIT_PENALTY_BITWISE_OPERATOR=textwrap.dedent("""\
- The penalty of splitting the line around the '&', '|', and '^'
- operators."""),
- SPLIT_PENALTY_COMPREHENSION=textwrap.dedent("""\
- The penalty for splitting a list comprehension or generator
- expression."""),
- SPLIT_PENALTY_EXCESS_CHARACTER=textwrap.dedent("""\
- The penalty for characters over the column limit."""),
- SPLIT_PENALTY_FOR_ADDED_LINE_SPLIT=textwrap.dedent("""\
- The penalty incurred by adding a line split to the logical line. The
- more line splits added the higher the penalty."""),
- SPLIT_PENALTY_IMPORT_NAMES=textwrap.dedent("""\
- The penalty of splitting a list of "import as" names. For example:
- from a_very_long_or_indented_module_name_yada_yad import (long_argument_1,
- long_argument_2,
- long_argument_3)
- would reformat to something like:
- from a_very_long_or_indented_module_name_yada_yad import (
- long_argument_1, long_argument_2, long_argument_3)
- """), # noqa
- SPLIT_PENALTY_LOGICAL_OPERATOR=textwrap.dedent("""\
- The penalty of splitting the line around the 'and' and 'or'
- operators."""),
- USE_TABS=textwrap.dedent("""\
- Use the Tab character for indentation."""),
- # BASED_ON_STYLE='Which predefined style this style is based on',
- )
- def CreatePEP8Style():
- """Create the PEP8 formatting style."""
- return dict(
- ALIGN_CLOSING_BRACKET_WITH_VISUAL_INDENT=True,
- ALLOW_MULTILINE_LAMBDAS=False,
- ALLOW_MULTILINE_DICTIONARY_KEYS=False,
- ALLOW_SPLIT_BEFORE_DEFAULT_OR_NAMED_ASSIGNS=True,
- ALLOW_SPLIT_BEFORE_DICT_VALUE=True,
- ARITHMETIC_PRECEDENCE_INDICATION=False,
- BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF=True,
- BLANK_LINE_BEFORE_CLASS_DOCSTRING=False,
- BLANK_LINE_BEFORE_MODULE_DOCSTRING=False,
- BLANK_LINES_AROUND_TOP_LEVEL_DEFINITION=2,
- BLANK_LINES_BETWEEN_TOP_LEVEL_IMPORTS_AND_VARIABLES=1,
- COALESCE_BRACKETS=False,
- COLUMN_LIMIT=79,
- CONTINUATION_ALIGN_STYLE='SPACE',
- CONTINUATION_INDENT_WIDTH=4,
- DEDENT_CLOSING_BRACKETS=False,
- INDENT_CLOSING_BRACKETS=False,
- DISABLE_ENDING_COMMA_HEURISTIC=False,
- EACH_DICT_ENTRY_ON_SEPARATE_LINE=True,
- FORCE_MULTILINE_DICT=False,
- I18N_COMMENT='',
- I18N_FUNCTION_CALL='',
- INDENT_DICTIONARY_VALUE=False,
- INDENT_WIDTH=4,
- INDENT_BLANK_LINES=False,
- JOIN_MULTIPLE_LINES=True,
- NO_SPACES_AROUND_SELECTED_BINARY_OPERATORS=set(),
- SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET=True,
- SPACE_INSIDE_BRACKETS=False,
- SPACES_AROUND_POWER_OPERATOR=False,
- SPACES_AROUND_DEFAULT_OR_NAMED_ASSIGN=False,
- SPACES_AROUND_DICT_DELIMITERS=False,
- SPACES_AROUND_LIST_DELIMITERS=False,
- SPACES_AROUND_SUBSCRIPT_COLON=False,
- SPACES_AROUND_TUPLE_DELIMITERS=False,
- SPACES_BEFORE_COMMENT=2,
- SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED=False,
- SPLIT_ALL_COMMA_SEPARATED_VALUES=False,
- SPLIT_ALL_TOP_LEVEL_COMMA_SEPARATED_VALUES=False,
- SPLIT_BEFORE_ARITHMETIC_OPERATOR=False,
- SPLIT_BEFORE_BITWISE_OPERATOR=True,
- SPLIT_BEFORE_CLOSING_BRACKET=True,
- SPLIT_BEFORE_DICT_SET_GENERATOR=True,
- SPLIT_BEFORE_DOT=False,
- SPLIT_BEFORE_EXPRESSION_AFTER_OPENING_PAREN=False,
- SPLIT_BEFORE_FIRST_ARGUMENT=False,
- SPLIT_BEFORE_LOGICAL_OPERATOR=True,
- SPLIT_BEFORE_NAMED_ASSIGNS=True,
- SPLIT_COMPLEX_COMPREHENSION=False,
- SPLIT_PENALTY_AFTER_OPENING_BRACKET=300,
- SPLIT_PENALTY_AFTER_UNARY_OPERATOR=10000,
- SPLIT_PENALTY_ARITHMETIC_OPERATOR=300,
- SPLIT_PENALTY_BEFORE_IF_EXPR=0,
- SPLIT_PENALTY_BITWISE_OPERATOR=300,
- SPLIT_PENALTY_COMPREHENSION=80,
- SPLIT_PENALTY_EXCESS_CHARACTER=7000,
- SPLIT_PENALTY_FOR_ADDED_LINE_SPLIT=30,
- SPLIT_PENALTY_IMPORT_NAMES=0,
- SPLIT_PENALTY_LOGICAL_OPERATOR=300,
- USE_TABS=False,
- )
- def CreateGoogleStyle():
- """Create the Google formatting style."""
- style = CreatePEP8Style()
- style['ALIGN_CLOSING_BRACKET_WITH_VISUAL_INDENT'] = False
- style['COLUMN_LIMIT'] = 80
- style['INDENT_DICTIONARY_VALUE'] = True
- style['INDENT_WIDTH'] = 4
- style['I18N_COMMENT'] = r'#\..*'
- style['I18N_FUNCTION_CALL'] = ['N_', '_']
- style['JOIN_MULTIPLE_LINES'] = False
- style['SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET'] = False
- style['SPLIT_BEFORE_BITWISE_OPERATOR'] = False
- style['SPLIT_BEFORE_DICT_SET_GENERATOR'] = False
- style['SPLIT_BEFORE_LOGICAL_OPERATOR'] = False
- style['SPLIT_COMPLEX_COMPREHENSION'] = True
- style['SPLIT_PENALTY_COMPREHENSION'] = 2100
- return style
- def CreateYapfStyle():
- """Create the YAPF formatting style."""
- style = CreateGoogleStyle()
- style['ALLOW_MULTILINE_DICTIONARY_KEYS'] = True
- style['ALLOW_SPLIT_BEFORE_DEFAULT_OR_NAMED_ASSIGNS'] = False
- style['INDENT_WIDTH'] = 2
- style['SPLIT_BEFORE_BITWISE_OPERATOR'] = True
- style['SPLIT_BEFORE_DOT'] = True
- style['SPLIT_BEFORE_EXPRESSION_AFTER_OPENING_PAREN'] = True
- return style
- def CreateFacebookStyle():
- """Create the Facebook formatting style."""
- style = CreatePEP8Style()
- style['ALIGN_CLOSING_BRACKET_WITH_VISUAL_INDENT'] = False
- style['BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF'] = False
- style['COLUMN_LIMIT'] = 80
- style['DEDENT_CLOSING_BRACKETS'] = True
- style['INDENT_CLOSING_BRACKETS'] = False
- style['INDENT_DICTIONARY_VALUE'] = True
- style['JOIN_MULTIPLE_LINES'] = False
- style['SPACES_BEFORE_COMMENT'] = 2
- style['SPLIT_PENALTY_AFTER_OPENING_BRACKET'] = 0
- style['SPLIT_PENALTY_BEFORE_IF_EXPR'] = 30
- style['SPLIT_PENALTY_FOR_ADDED_LINE_SPLIT'] = 30
- style['SPLIT_BEFORE_LOGICAL_OPERATOR'] = False
- style['SPLIT_BEFORE_BITWISE_OPERATOR'] = False
- return style
- _STYLE_NAME_TO_FACTORY = dict(
- pep8=CreatePEP8Style,
- google=CreateGoogleStyle,
- facebook=CreateFacebookStyle,
- yapf=CreateYapfStyle,
- )
- _DEFAULT_STYLE_TO_FACTORY = [
- (CreateFacebookStyle(), CreateFacebookStyle),
- (CreateGoogleStyle(), CreateGoogleStyle),
- (CreatePEP8Style(), CreatePEP8Style),
- (CreateYapfStyle(), CreateYapfStyle),
- ]
- def _GetStyleFactory(style):
- for def_style, factory in _DEFAULT_STYLE_TO_FACTORY:
- if style == def_style:
- return factory
- return None
- def _ContinuationAlignStyleStringConverter(s):
- """Option value converter for a continuation align style string."""
- accepted_styles = ('SPACE', 'FIXED', 'VALIGN-RIGHT')
- if s:
- r = s.strip('"\'').replace('_', '-').upper()
- if r not in accepted_styles:
- raise ValueError('unknown continuation align style: %r' % (s,))
- else:
- r = accepted_styles[0]
- return r
- def _StringListConverter(s):
- """Option value converter for a comma-separated list of strings."""
- return [part.strip() for part in s.split(',')]
- def _StringSetConverter(s):
- """Option value converter for a comma-separated set of strings."""
- if len(s) > 2 and s[0] in '"\'':
- s = s[1:-1]
- return {part.strip() for part in s.split(',')}
- def _BoolConverter(s):
- """Option value converter for a boolean."""
- return ConfigParser.BOOLEAN_STATES[s.lower()]
- def _IntListConverter(s):
- """Option value converter for a comma-separated list of integers."""
- s = s.strip()
- if s.startswith('[') and s.endswith(']'):
- s = s[1:-1]
- return [int(part.strip()) for part in s.split(',') if part.strip()]
- def _IntOrIntListConverter(s):
- """Option value converter for an integer or list of integers."""
- if len(s) > 2 and s[0] in '"\'':
- s = s[1:-1]
- return _IntListConverter(s) if ',' in s else int(s)
- # Different style options need to have their values interpreted differently when
- # read from the config file. This dict maps an option name to a "converter"
- # function that accepts the string read for the option's value from the file and
- # returns it wrapper in actual Python type that's going to be meaningful to
- # yapf.
- #
- # Note: this dict has to map all the supported style options.
- _STYLE_OPTION_VALUE_CONVERTER = dict(
- ALIGN_CLOSING_BRACKET_WITH_VISUAL_INDENT=_BoolConverter,
- ALLOW_MULTILINE_LAMBDAS=_BoolConverter,
- ALLOW_MULTILINE_DICTIONARY_KEYS=_BoolConverter,
- ALLOW_SPLIT_BEFORE_DEFAULT_OR_NAMED_ASSIGNS=_BoolConverter,
- ALLOW_SPLIT_BEFORE_DICT_VALUE=_BoolConverter,
- ARITHMETIC_PRECEDENCE_INDICATION=_BoolConverter,
- BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF=_BoolConverter,
- BLANK_LINE_BEFORE_CLASS_DOCSTRING=_BoolConverter,
- BLANK_LINE_BEFORE_MODULE_DOCSTRING=_BoolConverter,
- BLANK_LINES_AROUND_TOP_LEVEL_DEFINITION=int,
- BLANK_LINES_BETWEEN_TOP_LEVEL_IMPORTS_AND_VARIABLES=int,
- COALESCE_BRACKETS=_BoolConverter,
- COLUMN_LIMIT=int,
- CONTINUATION_ALIGN_STYLE=_ContinuationAlignStyleStringConverter,
- CONTINUATION_INDENT_WIDTH=int,
- DEDENT_CLOSING_BRACKETS=_BoolConverter,
- INDENT_CLOSING_BRACKETS=_BoolConverter,
- DISABLE_ENDING_COMMA_HEURISTIC=_BoolConverter,
- EACH_DICT_ENTRY_ON_SEPARATE_LINE=_BoolConverter,
- FORCE_MULTILINE_DICT=_BoolConverter,
- I18N_COMMENT=str,
- I18N_FUNCTION_CALL=_StringListConverter,
- INDENT_DICTIONARY_VALUE=_BoolConverter,
- INDENT_WIDTH=int,
- INDENT_BLANK_LINES=_BoolConverter,
- JOIN_MULTIPLE_LINES=_BoolConverter,
- NO_SPACES_AROUND_SELECTED_BINARY_OPERATORS=_StringSetConverter,
- SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET=_BoolConverter,
- SPACE_INSIDE_BRACKETS=_BoolConverter,
- SPACES_AROUND_POWER_OPERATOR=_BoolConverter,
- SPACES_AROUND_DEFAULT_OR_NAMED_ASSIGN=_BoolConverter,
- SPACES_AROUND_DICT_DELIMITERS=_BoolConverter,
- SPACES_AROUND_LIST_DELIMITERS=_BoolConverter,
- SPACES_AROUND_SUBSCRIPT_COLON=_BoolConverter,
- SPACES_AROUND_TUPLE_DELIMITERS=_BoolConverter,
- SPACES_BEFORE_COMMENT=_IntOrIntListConverter,
- SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED=_BoolConverter,
- SPLIT_ALL_COMMA_SEPARATED_VALUES=_BoolConverter,
- SPLIT_ALL_TOP_LEVEL_COMMA_SEPARATED_VALUES=_BoolConverter,
- SPLIT_BEFORE_ARITHMETIC_OPERATOR=_BoolConverter,
- SPLIT_BEFORE_BITWISE_OPERATOR=_BoolConverter,
- SPLIT_BEFORE_CLOSING_BRACKET=_BoolConverter,
- SPLIT_BEFORE_DICT_SET_GENERATOR=_BoolConverter,
- SPLIT_BEFORE_DOT=_BoolConverter,
- SPLIT_BEFORE_EXPRESSION_AFTER_OPENING_PAREN=_BoolConverter,
- SPLIT_BEFORE_FIRST_ARGUMENT=_BoolConverter,
- SPLIT_BEFORE_LOGICAL_OPERATOR=_BoolConverter,
- SPLIT_BEFORE_NAMED_ASSIGNS=_BoolConverter,
- SPLIT_COMPLEX_COMPREHENSION=_BoolConverter,
- SPLIT_PENALTY_AFTER_OPENING_BRACKET=int,
- SPLIT_PENALTY_AFTER_UNARY_OPERATOR=int,
- SPLIT_PENALTY_ARITHMETIC_OPERATOR=int,
- SPLIT_PENALTY_BEFORE_IF_EXPR=int,
- SPLIT_PENALTY_BITWISE_OPERATOR=int,
- SPLIT_PENALTY_COMPREHENSION=int,
- SPLIT_PENALTY_EXCESS_CHARACTER=int,
- SPLIT_PENALTY_FOR_ADDED_LINE_SPLIT=int,
- SPLIT_PENALTY_IMPORT_NAMES=int,
- SPLIT_PENALTY_LOGICAL_OPERATOR=int,
- USE_TABS=_BoolConverter,
- )
- def CreateStyleFromConfig(style_config):
- """Create a style dict from the given config.
- Arguments:
- style_config: either a style name or a file name. The file is expected to
- contain settings. It can have a special BASED_ON_STYLE setting naming the
- style which it derives from. If no such setting is found, it derives from
- the default style. When style_config is None, the _GLOBAL_STYLE_FACTORY
- config is created.
- Returns:
- A style dict.
- Raises:
- StyleConfigError: if an unknown style option was encountered.
- """
- def GlobalStyles():
- for style, _ in _DEFAULT_STYLE_TO_FACTORY:
- yield style
- def_style = False
- if style_config is None:
- for style in GlobalStyles():
- if _style == style:
- def_style = True
- break
- if not def_style:
- return _style
- return _GLOBAL_STYLE_FACTORY()
- if isinstance(style_config, dict):
- config = _CreateConfigParserFromConfigDict(style_config)
- elif isinstance(style_config, str):
- style_factory = _STYLE_NAME_TO_FACTORY.get(style_config.lower())
- if style_factory is not None:
- return style_factory()
- if style_config.startswith('{'):
- # Most likely a style specification from the command line.
- config = _CreateConfigParserFromConfigString(style_config)
- else:
- # Unknown config name: assume it's a file name then.
- config = _CreateConfigParserFromConfigFile(style_config)
- return _CreateStyleFromConfigParser(config)
- def _CreateConfigParserFromConfigDict(config_dict):
- config = ConfigParser()
- config.add_section('style')
- for key, value in config_dict.items():
- config.set('style', key, str(value))
- return config
- def _CreateConfigParserFromConfigString(config_string):
- """Given a config string from the command line, return a config parser."""
- if config_string[0] != '{' or config_string[-1] != '}':
- raise StyleConfigError(
- "Invalid style dict syntax: '{}'.".format(config_string))
- config = ConfigParser()
- config.add_section('style')
- for key, value, _ in re.findall(
- r'([a-zA-Z0-9_]+)\s*[:=]\s*'
- r'(?:'
- r'((?P<quote>[\'"]).*?(?P=quote)|'
- r'[a-zA-Z0-9_]+)'
- r')', config_string): # yapf: disable
- config.set('style', key, value)
- return config
- def _CreateConfigParserFromConfigFile(config_filename):
- """Read the file and return a ConfigParser object."""
- if not os.path.exists(config_filename):
- # Provide a more meaningful error here.
- raise StyleConfigError(
- '"{0}" is not a valid style or file path'.format(config_filename))
- config = ConfigParser()
- if config_filename.endswith(PYPROJECT_TOML):
- try:
- import tomli as tomllib
- except ImportError:
- raise errors.YapfError(
- 'tomli package is needed for using pyproject.toml as a '
- 'configuration file')
- with open(config_filename, 'rb') as style_file:
- pyproject_toml = tomllib.load(style_file)
- style_dict = pyproject_toml.get('tool', {}).get('yapf', None)
- if style_dict is None:
- raise StyleConfigError(
- 'Unable to find section [tool.yapf] in {0}'.format(config_filename))
- config.add_section('style')
- for k, v in style_dict.items():
- config.set('style', k, str(v))
- return config
- with open(config_filename) as style_file:
- config.read_file(style_file)
- if config_filename.endswith(SETUP_CONFIG):
- if not config.has_section('yapf'):
- raise StyleConfigError(
- 'Unable to find section [yapf] in {0}'.format(config_filename))
- return config
- if config_filename.endswith(LOCAL_STYLE):
- if not config.has_section('style'):
- raise StyleConfigError(
- 'Unable to find section [style] in {0}'.format(config_filename))
- return config
- if not config.has_section('style'):
- raise StyleConfigError(
- 'Unable to find section [style] in {0}'.format(config_filename))
- return config
- def _CreateStyleFromConfigParser(config):
- """Create a style dict from a configuration file.
- Arguments:
- config: a ConfigParser object.
- Returns:
- A style dict.
- Raises:
- StyleConfigError: if an unknown style option was encountered.
- """
- # Initialize the base style.
- section = 'yapf' if config.has_section('yapf') else 'style'
- if config.has_option('style', 'based_on_style'):
- based_on = config.get('style', 'based_on_style').lower()
- base_style = _STYLE_NAME_TO_FACTORY[based_on]()
- elif config.has_option('yapf', 'based_on_style'):
- based_on = config.get('yapf', 'based_on_style').lower()
- base_style = _STYLE_NAME_TO_FACTORY[based_on]()
- else:
- base_style = _GLOBAL_STYLE_FACTORY()
- # Read all options specified in the file and update the style.
- for option, value in config.items(section):
- if option.lower() == 'based_on_style':
- # Now skip this one - we've already handled it and it's not one of the
- # recognized style options.
- continue
- option = option.upper()
- if option not in _STYLE_OPTION_VALUE_CONVERTER:
- raise StyleConfigError('Unknown style option "{0}"'.format(option))
- try:
- base_style[option] = _STYLE_OPTION_VALUE_CONVERTER[option](value)
- except ValueError:
- raise StyleConfigError("'{}' is not a valid setting for {}.".format(
- value, option))
- return base_style
- # The default style - used if yapf is not invoked without specifically
- # requesting a formatting style.
- DEFAULT_STYLE = 'pep8'
- DEFAULT_STYLE_FACTORY = CreatePEP8Style
- _GLOBAL_STYLE_FACTORY = CreatePEP8Style
- # The name of the file to use for global style definition.
- GLOBAL_STYLE = (
- os.path.join(
- os.getenv('XDG_CONFIG_HOME') or os.path.expanduser('~/.config'), 'yapf',
- 'style'))
- # The name of the file to use for directory-local style definition.
- LOCAL_STYLE = '.style.yapf'
- # Alternative place for directory-local style definition. Style should be
- # specified in the '[yapf]' section.
- SETUP_CONFIG = 'setup.cfg'
- # Style definition by local pyproject.toml file. Style should be specified
- # in the '[tool.yapf]' section.
- PYPROJECT_TOML = 'pyproject.toml'
- # TODO(eliben): For now we're preserving the global presence of a style dict.
- # Refactor this so that the style is passed around through yapf rather than
- # being global.
- _style = None
- SetGlobalStyle(_GLOBAL_STYLE_FACTORY())
|