aboutsummaryrefslogtreecommitdiff
path: root/README.rst
diff options
context:
space:
mode:
Diffstat (limited to 'README.rst')
-rw-r--r--README.rst433
1 files changed, 371 insertions, 62 deletions
diff --git a/README.rst b/README.rst
index 19ef0c2..12286a9 100644
--- a/README.rst
+++ b/README.rst
@@ -6,12 +6,12 @@ YAPF
:target: https://badge.fury.io/py/yapf
:alt: PyPI version
-.. image:: https://travis-ci.org/google/yapf.svg?branch=master
- :target: https://travis-ci.org/google/yapf
+.. image:: https://github.com/google/yapf/actions/workflows/ci.yml/badge.svg
+ :target: https://github.com/google/yapf/actions
:alt: Build status
-.. image:: https://coveralls.io/repos/google/yapf/badge.svg?branch=master
- :target: https://coveralls.io/r/google/yapf?branch=master
+.. image:: https://coveralls.io/repos/google/yapf/badge.svg?branch=main
+ :target: https://coveralls.io/r/google/yapf?branch=main
:alt: Coverage status
@@ -23,21 +23,20 @@ are made to remove lint errors from code. This has some obvious limitations.
For instance, code that conforms to the PEP 8 guidelines may not be
reformatted. But it doesn't mean that the code looks good.
-YAPF takes a different approach. It's based off of 'clang-format', developed by
-Daniel Jasper. In essence, the algorithm takes the code and reformats it to the
-best formatting that conforms to the style guide, even if the original code
-didn't violate the style guide. The idea is also similar to the 'gofmt' tool for
-the Go programming language: end all holy wars about formatting - if the whole
-codebase of a project is simply piped through YAPF whenever modifications are
-made, the style remains consistent throughout the project and there's no point
-arguing about style in every code review.
+YAPF takes a different approach. It's based off of `'clang-format' <https://cl
+ang.llvm.org/docs/ClangFormat.html>`_, developed by Daniel Jasper. In essence,
+the algorithm takes the code and reformats it to the best formatting that
+conforms to the style guide, even if the original code didn't violate the
+style guide. The idea is also similar to the `'gofmt' <https://golang.org/cmd/
+gofmt/>`_ tool for the Go programming language: end all holy wars about
+formatting - if the whole codebase of a project is simply piped through YAPF
+whenever modifications are made, the style remains consistent throughout the
+project and there's no point arguing about style in every code review.
The ultimate goal is that the code YAPF produces is as good as the code that a
programmer would write if they were following the style guide. It takes away
some of the drudgery of maintaining your code.
-Try out YAPF with this `online demo <https://yapf.now.sh>`_.
-
.. footer::
YAPF is not an official Google product (experimental or otherwise), it is
@@ -114,10 +113,10 @@ Options::
--style STYLE specify formatting style: either a style name (for
example "pep8" or "google"), or the name of a file
with style settings. The default is pep8 unless a
- .style.yapf or setup.cfg file located in the same
- directory as the source or one of its parent
- directories (for stdin, the current directory is
- used).
+ .style.yapf or setup.cfg or pyproject.toml file
+ located in the same directory as the source or one of
+ its parent directories (for stdin, the current
+ directory is used).
--style-help show style settings and exit; this output can be saved
to .style.yapf to make your settings permanent
--no-local-style don't search for local style definition
@@ -136,6 +135,33 @@ If ``--diff`` is supplied, YAPF returns zero when no changes were necessary, non
otherwise (including program error). You can use this in a CI workflow to test that code
has been YAPF-formatted.
+---------------------------------------------
+Excluding files from formatting (.yapfignore or pyproject.toml)
+---------------------------------------------
+
+In addition to exclude patterns provided on commandline, YAPF looks for additional
+patterns specified in a file named ``.yapfignore`` or ``pyproject.toml`` located in the
+working directory from which YAPF is invoked.
+
+``.yapfignore``'s syntax is similar to UNIX's filename pattern matching::
+
+ * matches everything
+ ? matches any single character
+ [seq] matches any character in seq
+ [!seq] matches any character not in seq
+
+Note that no entry should begin with `./`.
+
+If you use ``pyproject.toml``, exclude patterns are specified by ``ignore_pattens`` key
+in ``[tool.yapfignore]`` section. For example:
+
+.. code-block:: ini
+
+ [tool.yapfignore]
+ ignore_patterns = [
+ "temp/**/*.py",
+ "temp2/*.py"
+ ]
Formatting style
================
@@ -159,26 +185,41 @@ with a ``[style]`` heading. For example:
split_before_logical_operator = true
The ``based_on_style`` setting determines which of the predefined styles this
-custom style is based on (think of it like subclassing).
+custom style is based on (think of it like subclassing). Four
+styles are predefined:
+
+- ``pep8`` (default)
+- ``google`` (based off of the `Google Python Style Guide`_)
+- ``yapf`` (for use with Google open source projects)
+- ``facebook``
+
+.. _`Google Python Style Guide`: https://github.com/google/styleguide/blob/gh-pages/pyguide.md
+
+See ``_STYLE_NAME_TO_FACTORY`` in style.py_ for details.
+
+.. _style.py: https://github.com/google/yapf/blob/main/yapf/yapflib/style.py
It's also possible to do the same on the command line with a dictionary. For
example:
.. code-block:: shell
- --style='{based_on_style: chromium, indent_width: 4}'
+ --style='{based_on_style: pep8, indent_width: 2}'
-This will take the ``chromium`` base style and modify it to have four space
+This will take the ``pep8`` base style and modify it to have two space
indentations.
YAPF will search for the formatting style in the following manner:
1. Specified on the command line
-2. In the `[style]` section of a `.style.yapf` file in either the current
+2. In the ``[style]`` section of a ``.style.yapf`` file in either the current
+ directory or one of its parent directories.
+3. In the ``[yapf]`` section of a ``setup.cfg`` file in either the current
directory or one of its parent directories.
-3. In the `[yapf]` section of a `setup.cfg` file in either the current
+4. In the ``[tool.yapf]`` section of a ``pyproject.toml`` file in either the current
directory or one of its parent directories.
-4. In the `~/.config/yapf/style` file in your home directory.
+5. In the ``[style]`` section of a ``~/.config/yapf/style`` file in your home
+ directory.
If none of those files are found, the default style is used (PEP8).
@@ -239,8 +280,11 @@ share several arguments which are described below:
>>> from yapf.yapflib.yapf_api import FormatCode # reformat a string of code
- >>> FormatCode("f ( a = 1, b = 2 )")
+ >>> formatted_code, changed = FormatCode("f ( a = 1, b = 2 )")
+ >>> formatted_code
'f(a=1, b=2)\n'
+ >>> changed
+ True
A ``style_config`` argument: Either a style name or a path to a file that contains
formatting style settings. If None is specified, use the default style
@@ -248,7 +292,7 @@ as set in ``style.DEFAULT_STYLE_FACTORY``.
.. code-block:: python
- >>> FormatCode("def g():\n return True", style_config='pep8')
+ >>> FormatCode("def g():\n return True", style_config='pep8')[0]
'def g():\n return True\n'
A ``lines`` argument: A list of tuples of lines (ints), [start, end],
@@ -258,15 +302,15 @@ than a whole file.
.. code-block:: python
- >>> FormatCode("def g( ):\n a=1\n b = 2\n return a==b", lines=[(1, 1), (2, 3)])
+ >>> FormatCode("def g( ):\n a=1\n b = 2\n return a==b", lines=[(1, 1), (2, 3)])[0]
'def g():\n a = 1\n b = 2\n return a==b\n'
A ``print_diff`` (bool): Instead of returning the reformatted source, return a
-diff that turns the formatted source into reformatter source.
+diff that turns the formatted source into reformatted source.
.. code-block:: python
- >>> print(FormatCode("a==b", filename="foo.py", print_diff=True))
+ >>> print(FormatCode("a==b", filename="foo.py", print_diff=True)[0])
--- foo.py (original)
+++ foo.py (reformatted)
@@ -1 +1 @@
@@ -285,19 +329,61 @@ the diff, the default is ``<unknown>``.
>>> print(open("foo.py").read()) # contents of file
a==b
- >>> FormatFile("foo.py")
- ('a == b\n', 'utf-8')
+ >>> reformatted_code, encoding, changed = FormatFile("foo.py")
+ >>> formatted_code
+ 'a == b\n'
+ >>> encoding
+ 'utf-8'
+ >>> changed
+ True
-The ``in-place`` argument saves the reformatted code back to the file:
+The ``in_place`` argument saves the reformatted code back to the file:
.. code-block:: python
- >>> FormatFile("foo.py", in_place=True)
+ >>> FormatFile("foo.py", in_place=True)[:2]
(None, 'utf-8')
>>> print(open("foo.py").read()) # contents of file (now fixed)
a == b
+Formatting diffs
+================
+
+Options::
+
+ usage: yapf-diff [-h] [-i] [-p NUM] [--regex PATTERN] [--iregex PATTERN][-v]
+ [--style STYLE] [--binary BINARY]
+
+ This script reads input from a unified diff and reformats all the changed
+ lines. This is useful to reformat all the lines touched by a specific patch.
+ Example usage for git/svn users:
+
+ git diff -U0 --no-color --relative HEAD^ | yapf-diff -i
+ svn diff --diff-cmd=diff -x-U0 | yapf-diff -p0 -i
+
+ It should be noted that the filename contained in the diff is used
+ unmodified to determine the source file to update. Users calling this script
+ directly should be careful to ensure that the path in the diff is correct
+ relative to the current working directory.
+
+ optional arguments:
+ -h, --help show this help message and exit
+ -i, --in-place apply edits to files instead of displaying a diff
+ -p NUM, --prefix NUM strip the smallest prefix containing P slashes
+ --regex PATTERN custom pattern selecting file paths to reformat
+ (case sensitive, overrides -iregex)
+ --iregex PATTERN custom pattern selecting file paths to reformat
+ (case insensitive, overridden by -regex)
+ -v, --verbose be more verbose, ineffective without -i
+ --style STYLE specify formatting style: either a style name (for
+ example "pep8" or "google"), or the name of a file
+ with style settings. The default is pep8 unless a
+ .style.yapf or setup.cfg or pyproject.toml file
+ located in the same directory as the source or one of
+ its parent directories (for stdin, the current
+ directory is used).
+ --binary BINARY location of binary to use for yapf
Knobs
=====
@@ -319,9 +405,35 @@ Knobs
value,
}
+``ALLOW_SPLIT_BEFORE_DEFAULT_OR_NAMED_ASSIGNS``
+ Allow splitting before a default / named assignment in an argument list.
+
``ALLOW_SPLIT_BEFORE_DICT_VALUE``
Allow splits before the dictionary value.
+``ARITHMETIC_PRECEDENCE_INDICATION``
+ Let spacing indicate operator precedence. For example:
+
+ .. code-block:: python
+
+ 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:
+
+ .. code-block:: python
+
+ 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``
Insert a blank line before a ``def`` or ``class`` immediately nested within
another ``def`` or ``class``. For example:
@@ -352,9 +464,14 @@ Knobs
class Bar:
pass
+``BLANK_LINES_BETWEEN_TOP_LEVEL_IMPORTS_AND_VARIABLES``
+ Sets the number of desired blank lines between top-level imports and
+ variable definitions. Useful for compatibility with tools like isort.
+
``COALESCE_BRACKETS``
Do not split consecutive brackets. Only relevant when
- ``DEDENT_CLOSING_BRACKETS`` is set. For example:
+ ``DEDENT_CLOSING_BRACKETS`` or ``INDENT_CLOSING_BRACKETS``
+ is set. For example:
.. code-block:: python
@@ -381,16 +498,14 @@ Knobs
``CONTINUATION_ALIGN_STYLE``
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) for continuation
- alignment.
- - VALIGN-RIGHT: Vertically align continuation lines with indent characters.
- Slightly right (one more indent character) if cannot vertically align
- continuation lines with indent characters.
-
- For options ``FIXED``, and ``VALIGN-RIGHT`` are only available when
- ``USE_TABS`` is enabled.
+ - ``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``
Indent width used for line continuations.
@@ -422,6 +537,10 @@ Knobs
``EACH_DICT_ENTRY_ON_SEPARATE_LINE``
Place each dictionary entry onto its own line.
+``FORCE_MULTILINE_DICT``
+ Respect EACH_DICT_ENTRY_ON_SEPARATE_LINE even if the line is shorter than
+ COLUMN_LIMIT.
+
``I18N_COMMENT``
The regex for an internationalization comment. The presence of this comment
stops reformatting of that line, because the comments are required to be
@@ -448,12 +567,32 @@ Knobs
``INDENT_WIDTH``
The number of columns to use for indentation.
+``INDENT_BLANK_LINES``
+ Set to ``True`` to prefer indented blank lines rather than empty
+
+``INDENT_CLOSING_BRACKETS``
+ 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:
+
+ .. code-block:: python
+
+ 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
+
``JOIN_MULTIPLE_LINES``
Join short lines into one line. E.g., single line ``if`` statements.
-``SPACES_AROUND_POWER_OPERATOR``
- Set to ``True`` to prefer using spaces around ``**``.
-
``NO_SPACES_AROUND_SELECTED_BINARY_OPERATORS``
Do not include spaces around selected binary operators. For example:
@@ -461,36 +600,163 @@ Knobs
1 + 2 * 3 - 4 / 5
- will be formatted as follows when configured with ``*,/``:
+ will be formatted as follows when configured with ``*``, ``/``:
.. code-block:: python
1 + 2*3 - 4/5
+``SPACES_AROUND_POWER_OPERATOR``
+ Set to ``True`` to prefer using spaces around ``**``.
+
``SPACES_AROUND_DEFAULT_OR_NAMED_ASSIGN``
Set to ``True`` to prefer spaces around the assignment operator for default
or keyword arguments.
+``SPACES_AROUND_DICT_DELIMITERS``
+ Adds a space after the opening '{' and before the ending '}' dict delimiters.
+
+ .. code-block:: python
+
+ {1: 2}
+
+ will be formatted as:
+
+ .. code-block:: python
+
+ { 1: 2 }
+
+``SPACES_AROUND_LIST_DELIMITERS``
+ Adds a space after the opening '[' and before the ending ']' list delimiters.
+
+ .. code-block:: python
+
+ [1, 2]
+
+ will be formatted as:
+
+ .. code-block:: python
+
+ [ 1, 2 ]
+
+``SPACES_AROUND_SUBSCRIPT_COLON``
+ Use spaces around the subscript / slice operator. For example:
+
+ .. code-block:: python
+
+ my_list[1 : 10 : 2]
+
+``SPACES_AROUND_TUPLE_DELIMITERS``
+ Adds a space after the opening '(' and before the ending ')' tuple delimiters.
+
+ .. code-block:: python
+
+ (1, 2, 3)
+
+ will be formatted as:
+
+ .. code-block:: python
+
+ ( 1, 2, 3 )
+
``SPACES_BEFORE_COMMENT``
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 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``:
+
+ .. code-block:: python
+
+ 1 + 1 # Adding values
+
+ will be formatted as:
+
+ .. code-block:: python
+
+ 1 + 1 # Adding values <-- 5 spaces between the end of the statement and comment
+
+ With ``spaces_before_comment=15, 20``:
+
+ .. code-block:: python
+
+ 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:
+
+ .. code-block:: python
+
+ 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
``SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET``
Insert a space between the ending comma and closing bracket of a list, etc.
+``SPACE_INSIDE_BRACKETS``
+ Use spaces inside brackets, braces, and parentheses. For example:
+
+ .. code-block:: python
+
+ method_call( 1 )
+ my_dict[ 3 ][ 1 ][ get_index( *args, **kwargs ) ]
+ my_set = { 1, 2, 3 }
+
``SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED``
Split before arguments if the argument list is terminated by a comma.
``SPLIT_ALL_COMMA_SEPARATED_VALUES``
- If a comma separated list (dict, list, tuple, or function def) is on a
- line that is too long, split such that all elements are on a single line.
+ If a comma separated list (``dict``, ``list``, ``tuple``, or function
+ ``def``) is on a line that is too long, split such that each element
+ is on a separate line.
+
+``SPLIT_ALL_TOP_LEVEL_COMMA_SEPARATED_VALUES``
+ Variation on ``SPLIT_ALL_COMMA_SEPARATED_VALUES`` in which, if a
+ subexpression with a comma fits in its starting line, then the
+ subexpression is not split. This avoids splits like the one for
+ ``b`` in this code:
+
+ .. code-block:: python
+
+ abcdef(
+ aReallyLongThing: int,
+ b: [Int,
+ Int])
+
+ With the new knob this is split as:
+
+ .. code-block:: python
+
+ abcdef(
+ aReallyLongThing: int,
+ b: [Int, Int])
``SPLIT_BEFORE_BITWISE_OPERATOR``
Set to ``True`` to prefer splitting before ``&``, ``|`` or ``^`` rather
than after.
+``SPLIT_BEFORE_ARITHMETIC_OPERATOR``
+ Set to ``True`` to prefer splitting before ``+``, ``-``, ``*``, ``/``, ``//``,
+ or ``@`` rather than after.
+
``SPLIT_BEFORE_CLOSING_BRACKET``
- Split before the closing bracket if a list or dict literal doesn't fit on
- a single line.
+ Split before the closing bracket if a ``list`` or ``dict`` literal doesn't
+ fit on a single line.
``SPLIT_BEFORE_DICT_SET_GENERATOR``
Split before a dictionary or set generator (comp_for). For example, note
@@ -503,6 +769,20 @@ Knobs
for variable in bar if variable != 42
}
+``SPLIT_BEFORE_DOT``
+ Split before the ``.`` if we need to split a longer expression:
+
+ .. code-block:: python
+
+ foo = ('This is a really long string: {}, {}, {}, {}'.format(a, b, c, d))
+
+ would reformat to something like:
+
+ .. code-block:: python
+
+ foo = ('This is a really long string: {}, {}, {}, {}'
+ .format(a, b, c, d))
+
``SPLIT_BEFORE_EXPRESSION_AFTER_OPENING_PAREN``
Split after the opening paren which surrounds an expression if it doesn't
fit on a single line.
@@ -520,8 +800,8 @@ Knobs
``SPLIT_COMPLEX_COMPREHENSION``
For list comprehensions and generator expressions with multiple clauses
- (e.g multiple "for" calls, "if" filter expressions) and which need to be
- reflowed, split each clause onto its own line. For example:
+ (e.g multiple ``for`` calls, ``if`` filter expressions) and which need to
+ be reflowed, split each clause onto its own line. For example:
.. code-block:: python
@@ -545,6 +825,10 @@ Knobs
``SPLIT_PENALTY_AFTER_UNARY_OPERATOR``
The penalty for splitting the line after a unary operator.
+``SPLIT_PENALTY_ARITHMETIC_OPERATOR``
+ The penalty of splitting the line around the ``+``, ``-``, ``*``, ``/``,
+ ``//``, ``%``, and ``@`` operators.
+
``SPLIT_PENALTY_BEFORE_IF_EXPR``
The penalty for splitting right before an ``if`` expression.
@@ -559,7 +843,7 @@ Knobs
The penalty for characters over the column limit.
``SPLIT_PENALTY_FOR_ADDED_LINE_SPLIT``
- The penalty incurred by adding a line split to the unwrapped line. The more
+ 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``
@@ -645,6 +929,31 @@ Can I Use YAPF In My Program?
Please do! YAPF was designed to be used as a library as well as a command line
tool. This means that a tool or IDE plugin is free to use YAPF.
+-----------------------------------------
+I still get non Pep8 compliant code! Why?
+-----------------------------------------
+
+YAPF tries very hard to be fully PEP 8 compliant. However, it is paramount
+to not risk altering the semantics of your code. Thus, YAPF tries to be as
+safe as possible and does not change the token stream
+(e.g., by adding parentheses).
+All these cases however, can be easily fixed manually. For instance,
+
+.. code-block:: python
+
+ from my_package import my_function_1, my_function_2, my_function_3, my_function_4, my_function_5
+
+ FOO = my_variable_1 + my_variable_2 + my_variable_3 + my_variable_4 + my_variable_5 + my_variable_6 + my_variable_7 + my_variable_8
+
+won't be split, but you can easily get it right by just adding parentheses:
+
+.. code-block:: python
+
+ from my_package import (my_function_1, my_function_2, my_function_3,
+ my_function_4, my_function_5)
+
+ FOO = (my_variable_1 + my_variable_2 + my_variable_3 + my_variable_4 +
+ my_variable_5 + my_variable_6 + my_variable_7 + my_variable_8)
Gory Details
============
@@ -653,15 +962,15 @@ Gory Details
Algorithm Design
----------------
-The main data structure in YAPF is the ``UnwrappedLine`` object. It holds a list
-of ``FormatToken``\s, that we would want to place on a single line if there were
-no column limit. An exception being a comment in the middle of an expression
-statement will force the line to be formatted on more than one line. The
-formatter works on one ``UnwrappedLine`` object at a time.
+The main data structure in YAPF is the ``LogicalLine`` object. It holds a list
+of ``FormatToken``\s, that we would want to place on a single line if there
+were no column limit. An exception being a comment in the middle of an
+expression statement will force the line to be formatted on more than one line.
+The formatter works on one ``LogicalLine`` object at a time.
-An ``UnwrappedLine`` typically won't affect the formatting of lines before or
+An ``LogicalLine`` typically won't affect the formatting of lines before or
after it. There is a part of the algorithm that may join two or more
-``UnwrappedLine``\s into one line. For instance, an if-then statement with a
+``LogicalLine``\s into one line. For instance, an if-then statement with a
short body can be placed on a single line:
.. code-block:: python