Merge branch 'main' into 241a1really
This commit is contained in:
commit
337a85df22
6
.github/workflows/lint.yml
vendored
6
.github/workflows/lint.yml
vendored
@ -11,11 +11,7 @@ jobs:
|
||||
github.event_name == 'push' || github.event.pull_request.head.repo.full_name !=
|
||||
github.repository
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macOS-latest, windows-latest]
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
2
.github/workflows/pypi_upload.yml
vendored
2
.github/workflows/pypi_upload.yml
vendored
@ -73,7 +73,7 @@ jobs:
|
||||
| pyp 'json.dumps({"only": x, "os": "ubuntu-latest"})'
|
||||
} | pyp 'json.dumps(list(map(json.loads, lines)))' > /tmp/matrix
|
||||
env:
|
||||
CIBW_BUILD: "cp38-* cp311-*"
|
||||
CIBW_BUILD: "cp38-* cp312-*"
|
||||
CIBW_ARCHS_LINUX: x86_64
|
||||
- id: set-matrix
|
||||
run: echo "include=$(cat /tmp/matrix)" | tee -a $GITHUB_OUTPUT
|
||||
|
@ -39,7 +39,7 @@ repos:
|
||||
exclude: ^src/blib2to3/
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v1.6.1
|
||||
rev: v1.7.1
|
||||
hooks:
|
||||
- id: mypy
|
||||
exclude: ^docs/conf.py
|
||||
|
@ -8,15 +8,18 @@
|
||||
|
||||
### Stable style
|
||||
|
||||
<!-- Changes that affect Black's stable style -->
|
||||
- Fix bug where `# fmt: off` automatically dedents when used with the `--line-ranges`
|
||||
option, even when it is not within the specified line range. (#4084)
|
||||
|
||||
### Preview style
|
||||
|
||||
- Prefer more equal signs before a break when splitting chained assignments (#4010)
|
||||
- Standalone form feed characters at the module level are no longer removed (#4021)
|
||||
- Additional cases of immediately nested tuples, lists, and dictionaries are now
|
||||
indented less (#4012)
|
||||
- Allow empty lines at the beginning of all blocks, except immediately before a
|
||||
docstring (#4060)
|
||||
- Fix crash in preview mode when using a short `--line-length` (#4086)
|
||||
|
||||
### Configuration
|
||||
|
||||
@ -27,7 +30,8 @@
|
||||
|
||||
### Packaging
|
||||
|
||||
- Upgrade to mypy 1.6.1 (#4049)
|
||||
- Upgrade to mypy 1.7.1 (#4049) (#4069)
|
||||
- Faster compiled wheels are now available for CPython 3.12 (#4070)
|
||||
|
||||
### Parser
|
||||
|
||||
|
@ -8,18 +8,9 @@ deliberately limited and rarely added. Previous formatting is taken into account
|
||||
little as possible, with rare exceptions like the magic trailing comma. The coding style
|
||||
used by _Black_ can be viewed as a strict subset of PEP 8.
|
||||
|
||||
_Black_ reformats entire files in place. It doesn't reformat lines that contain
|
||||
`# fmt: skip` or blocks that start with `# fmt: off` and end with `# fmt: on`.
|
||||
`# fmt: skip` can be mixed with other pragmas/comments either with multiple comments
|
||||
(e.g. `# fmt: skip # pylint # noqa`) or as a semicolon separated list (e.g.
|
||||
`# fmt: skip; pylint; noqa`). `# fmt: on/off` must be on the same level of indentation
|
||||
and in the same block, meaning no unindents beyond the initial indentation level between
|
||||
them. It also recognizes [YAPF](https://github.com/google/yapf)'s block comments to the
|
||||
same effect, as a courtesy for straddling code.
|
||||
|
||||
The rest of this document describes the current formatting style. If you're interested
|
||||
in trying out where the style is heading, see [future style](./future_style.md) and try
|
||||
running `black --preview`.
|
||||
This document describes the current formatting style. If you're interested in trying out
|
||||
where the style is heading, see [future style](./future_style.md) and try running
|
||||
`black --preview`.
|
||||
|
||||
### How _Black_ wraps lines
|
||||
|
||||
|
@ -12,7 +12,8 @@ _Black_ is a well-behaved Unix-style command-line tool:
|
||||
|
||||
## Usage
|
||||
|
||||
To get started right away with sensible defaults:
|
||||
_Black_ will reformat entire files in place. To get started right away with sensible
|
||||
defaults:
|
||||
|
||||
```sh
|
||||
black {source_file_or_directory}
|
||||
@ -24,6 +25,17 @@ You can run _Black_ as a package if running it as a script doesn't work:
|
||||
python -m black {source_file_or_directory}
|
||||
```
|
||||
|
||||
### Ignoring sections
|
||||
|
||||
Black will not reformat lines that contain `# fmt: skip` or blocks that start with
|
||||
`# fmt: off` and end with `# fmt: on`. `# fmt: skip` can be mixed with other
|
||||
pragmas/comments either with multiple comments (e.g. `# fmt: skip # pylint # noqa`) or
|
||||
as a semicolon separated list (e.g. `# fmt: skip; pylint; noqa`). `# fmt: on/off` must
|
||||
be on the same level of indentation and in the same block, meaning no unindents beyond
|
||||
the initial indentation level between them. Black also recognizes
|
||||
[YAPF](https://github.com/google/yapf)'s block comments to the same effect, as a
|
||||
courtesy for straddling code.
|
||||
|
||||
### Command line options
|
||||
|
||||
The CLI options of _Black_ can be displayed by running `black --help`. All options are
|
||||
@ -35,6 +47,10 @@ are deliberately limited and rarely added.
|
||||
Note that all command-line options listed above can also be configured using a
|
||||
`pyproject.toml` file (more on that below).
|
||||
|
||||
#### `-h`, `--help`
|
||||
|
||||
Show available command-line options and exit.
|
||||
|
||||
#### `-c`, `--code`
|
||||
|
||||
Format the code passed in as a string.
|
||||
@ -109,6 +125,10 @@ useful when piping source on standard input.
|
||||
When processing Jupyter Notebooks, add the given magic to the list of known python-
|
||||
magics. Useful for formatting cells with custom python magics.
|
||||
|
||||
#### `-x, --skip-source-first-line`
|
||||
|
||||
Skip the first line of the source code.
|
||||
|
||||
#### `-S, --skip-string-normalization`
|
||||
|
||||
By default, _Black_ uses double quotes for all strings and normalizes string prefixes,
|
||||
@ -132,7 +152,7 @@ functionality in the next major release. Read more about
|
||||
|
||||
#### `--check`
|
||||
|
||||
Passing `--check` will make _Black_ exit with:
|
||||
Don't write the files back, just return the status. _Black_ will exit with:
|
||||
|
||||
- code 0 if nothing would change;
|
||||
- code 1 if some files would be reformatted; or
|
||||
@ -162,8 +182,8 @@ $ echo $?
|
||||
|
||||
#### `--diff`
|
||||
|
||||
Passing `--diff` will make _Black_ print out diffs that indicate what changes _Black_
|
||||
would've made. They are printed to stdout so capturing them is simple.
|
||||
Don't write the files back, just output a diff to indicate what changes _Black_ would've
|
||||
made. They are printed to stdout so capturing them is simple.
|
||||
|
||||
If you'd like colored diffs, you can enable them with `--color`.
|
||||
|
||||
@ -179,7 +199,11 @@ All done! ✨ 🍰 ✨
|
||||
1 file would be reformatted.
|
||||
```
|
||||
|
||||
### `--line-ranges`
|
||||
#### `--color` / `--no-color`
|
||||
|
||||
Show (or do not show) colored diff. Only applies when `--diff` is given.
|
||||
|
||||
#### `--line-ranges`
|
||||
|
||||
When specified, _Black_ will try its best to only format these lines.
|
||||
|
||||
@ -202,10 +226,6 @@ extra lines outside of the ranges when ther are unformatted lines with the exact
|
||||
content. It also disables _Black_'s formatting stability check in `--safe` mode.
|
||||
```
|
||||
|
||||
#### `--color` / `--no-color`
|
||||
|
||||
Show (or do not show) colored diff. Only applies when `--diff` is given.
|
||||
|
||||
#### `--fast` / `--safe`
|
||||
|
||||
By default, _Black_ performs [an AST safety check](labels/ast-changes) after formatting
|
||||
@ -241,29 +261,22 @@ Because of our [stability policy](../the_black_code_style/index.md), this will g
|
||||
stable formatting, but still allow you to take advantage of improvements that do not
|
||||
affect formatting.
|
||||
|
||||
#### `--include`
|
||||
|
||||
A regular expression that matches files and directories that should be included on
|
||||
recursive searches. An empty value means all files are included regardless of the name.
|
||||
Use forward slashes for directories on all platforms (Windows, too). Exclusions are
|
||||
calculated first, inclusions later.
|
||||
|
||||
#### `--exclude`
|
||||
|
||||
A regular expression that matches files and directories that should be excluded on
|
||||
recursive searches. An empty value means no paths are excluded. Use forward slashes for
|
||||
directories on all platforms (Windows, too). Exclusions are calculated first, inclusions
|
||||
later.
|
||||
directories on all platforms (Windows, too). By default, Black also ignores all paths
|
||||
listed in `.gitignore`. Changing this value will override all default exclusions.
|
||||
|
||||
#### `--extend-exclude`
|
||||
|
||||
Like `--exclude`, but adds additional files and directories on top of the excluded ones.
|
||||
Useful if you simply want to add to the default.
|
||||
Like `--exclude`, but adds additional files and directories on top of the default values
|
||||
instead of overriding them.
|
||||
|
||||
#### `--force-exclude`
|
||||
|
||||
Like `--exclude`, but files and directories matching this regex will be excluded even
|
||||
when they are passed explicitly as arguments. This is useful when invoking _Black_
|
||||
when they are passed explicitly as arguments. This is useful when invoking Black
|
||||
programmatically on changed files, such as in a pre-commit hook or editor plugin.
|
||||
|
||||
#### `--stdin-filename`
|
||||
@ -271,16 +284,23 @@ programmatically on changed files, such as in a pre-commit hook or editor plugin
|
||||
The name of the file when passing it through stdin. Useful to make sure Black will
|
||||
respect the `--force-exclude` option on some editors that rely on using stdin.
|
||||
|
||||
#### `--include`
|
||||
|
||||
A regular expression that matches files and directories that should be included on
|
||||
recursive searches. An empty value means all files are included regardless of the name.
|
||||
Use forward slashes for directories on all platforms (Windows, too). Overrides all
|
||||
exclusions, including from `.gitignore` and command line options.
|
||||
|
||||
#### `-W`, `--workers`
|
||||
|
||||
When _Black_ formats multiple files, it may use a process pool to speed up formatting.
|
||||
This option controls the number of parallel workers. This can also be specified via the
|
||||
`BLACK_NUM_WORKERS` environment variable.
|
||||
`BLACK_NUM_WORKERS` environment variable. Defaults to the number of CPUs in the system.
|
||||
|
||||
#### `-q`, `--quiet`
|
||||
|
||||
Passing `-q` / `--quiet` will cause _Black_ to stop emitting all non-critical output.
|
||||
Error messages will still be emitted (which can silenced by `2>/dev/null`).
|
||||
Stop emitting all non-critical output. Error messages will still be emitted (which can
|
||||
silenced by `2>/dev/null`).
|
||||
|
||||
```console
|
||||
$ black src/ -q
|
||||
@ -289,9 +309,9 @@ error: cannot format src/black_primer/cli.py: Cannot parse: 5:6: mport asyncio
|
||||
|
||||
#### `-v`, `--verbose`
|
||||
|
||||
Passing `-v` / `--verbose` will cause _Black_ to also emit messages about files that
|
||||
were not changed or were ignored due to exclusion patterns. If _Black_ is using a
|
||||
configuration file, a blue message detailing which one it is using will be emitted.
|
||||
Emit messages about files that were not changed or were ignored due to exclusion
|
||||
patterns. If _Black_ is using a configuration file, a message detailing which one it is
|
||||
using will be emitted.
|
||||
|
||||
```console
|
||||
$ black src/ -v
|
||||
@ -321,10 +341,6 @@ black, 23.11.0
|
||||
Read configuration options from a configuration file. See
|
||||
[below](#configuration-via-a-file) for more details on the configuration file.
|
||||
|
||||
#### `-h`, `--help`
|
||||
|
||||
Show available command-line options and exit.
|
||||
|
||||
### Environment variable options
|
||||
|
||||
_Black_ supports the following configuration via environment variables.
|
||||
@ -355,7 +371,7 @@ All done! ✨ 🍰 ✨
|
||||
use `--stdin-filename`. Useful to make sure _Black_ will respect the `--force-exclude`
|
||||
option on some editors that rely on using stdin.
|
||||
|
||||
You can also pass code as a string using the `-c` / `--code` option.
|
||||
You can also pass code as a string using the `--code` option.
|
||||
|
||||
### Writeback and reporting
|
||||
|
||||
@ -435,8 +451,7 @@ refers to the path to your home directory. On Windows, this will be something li
|
||||
You can also explicitly specify the path to a particular file that you want with
|
||||
`--config`. In this situation _Black_ will not look for any other file.
|
||||
|
||||
If you're running with `--verbose`, you will see a blue message if a file was found and
|
||||
used.
|
||||
If you're running with `--verbose`, you will see a message if a file was found and used.
|
||||
|
||||
Please note `blackd` will not use `pyproject.toml` configuration.
|
||||
|
||||
|
@ -121,7 +121,7 @@ macos-max-compat = true
|
||||
enable-by-default = false
|
||||
dependencies = [
|
||||
"hatch-mypyc>=0.16.0",
|
||||
"mypy==1.6.1",
|
||||
"mypy==1.7.1",
|
||||
"click==8.1.3", # avoid https://github.com/pallets/click/issues/2558
|
||||
]
|
||||
require-runtime-dependencies = true
|
||||
@ -150,7 +150,7 @@ build-verbosity = 1
|
||||
# - Architecture (64-bit only): amd64 / x86_64, universal2, and arm64
|
||||
# - OS: Linux (no musl), Windows, and macOS
|
||||
build = "cp3*"
|
||||
skip = ["*-manylinux_i686", "*-musllinux_*", "*-win32", "pp*", "cp312-*"]
|
||||
skip = ["*-manylinux_i686", "*-musllinux_*", "*-win32", "pp*"]
|
||||
# This is the bare minimum needed to run the test suite. Pulling in the full
|
||||
# test_requirements.txt would download a bunch of other packages not necessary
|
||||
# here and would slow down the testing step a fair bit.
|
||||
@ -187,7 +187,7 @@ CC = "clang"
|
||||
build-frontend = { name = "build", args = ["--no-isolation"] }
|
||||
# Unfortunately, hatch doesn't respect MACOSX_DEPLOYMENT_TARGET
|
||||
before-build = [
|
||||
"python -m pip install 'hatchling==1.18.0' hatch-vcs hatch-fancy-pypi-readme 'hatch-mypyc>=0.16.0' 'mypy==1.6.1' 'click==8.1.3'",
|
||||
"python -m pip install 'hatchling==1.18.0' hatch-vcs hatch-fancy-pypi-readme 'hatch-mypyc>=0.16.0' 'mypy==1.7.1' 'click==8.1.3'",
|
||||
"""sed -i '' -e "600,700s/'10_16'/os.environ['MACOSX_DEPLOYMENT_TARGET'].replace('.', '_')/" $(python -c 'import hatchling.builders.wheel as h; print(h.__file__)') """,
|
||||
]
|
||||
|
||||
|
@ -235,25 +235,26 @@ def validate_regex(
|
||||
callback=target_version_option_callback,
|
||||
multiple=True,
|
||||
help=(
|
||||
"Python versions that should be supported by Black's output. By default, Black"
|
||||
" will try to infer this from the project metadata in pyproject.toml. If this"
|
||||
" does not yield conclusive results, Black will use per-file auto-detection."
|
||||
"Python versions that should be supported by Black's output. You should"
|
||||
" include all versions that your code supports. By default, Black will infer"
|
||||
" target versions from the project metadata in pyproject.toml. If this does"
|
||||
" not yield conclusive results, Black will use per-file auto-detection."
|
||||
),
|
||||
)
|
||||
@click.option(
|
||||
"--pyi",
|
||||
is_flag=True,
|
||||
help=(
|
||||
"Format all input files like typing stubs regardless of file extension (useful"
|
||||
" when piping source on standard input)."
|
||||
"Format all input files like typing stubs regardless of file extension. This"
|
||||
" is useful when piping source on standard input."
|
||||
),
|
||||
)
|
||||
@click.option(
|
||||
"--ipynb",
|
||||
is_flag=True,
|
||||
help=(
|
||||
"Format all input files like Jupyter Notebooks regardless of file extension "
|
||||
"(useful when piping source on standard input)."
|
||||
"Format all input files like Jupyter Notebooks regardless of file extension."
|
||||
"This is useful when piping source on standard input."
|
||||
),
|
||||
)
|
||||
@click.option(
|
||||
@ -310,14 +311,22 @@ def validate_regex(
|
||||
@click.option(
|
||||
"--diff",
|
||||
is_flag=True,
|
||||
help="Don't write the files back, just output a diff for each file on stdout.",
|
||||
help=(
|
||||
"Don't write the files back, just output a diff to indicate what changes"
|
||||
" Black would've made. They are printed to stdout so capturing them is simple."
|
||||
),
|
||||
)
|
||||
@click.option(
|
||||
"--color/--no-color",
|
||||
is_flag=True,
|
||||
help="Show (or do not show) colored diff. Only applies when --diff is given.",
|
||||
)
|
||||
@click.option(
|
||||
"--line-ranges",
|
||||
multiple=True,
|
||||
metavar="START-END",
|
||||
help=(
|
||||
"When specified, _Black_ will try its best to only format these lines. This"
|
||||
"When specified, Black will try its best to only format these lines. This"
|
||||
" option can be specified multiple times, and a union of the lines will be"
|
||||
" formatted. Each range must be specified as two integers connected by a `-`:"
|
||||
" `<START>-<END>`. The `<START>` and `<END>` integer indices are 1-based and"
|
||||
@ -325,23 +334,67 @@ def validate_regex(
|
||||
),
|
||||
default=(),
|
||||
)
|
||||
@click.option(
|
||||
"--color/--no-color",
|
||||
is_flag=True,
|
||||
help="Show colored diff. Only applies when `--diff` is given.",
|
||||
)
|
||||
@click.option(
|
||||
"--fast/--safe",
|
||||
is_flag=True,
|
||||
help="If --fast given, skip temporary sanity checks. [default: --safe]",
|
||||
help=(
|
||||
"By default, Black performs an AST safety check after formatting your code."
|
||||
" The --fast flag turns off this check and the --safe flag explicitly enables"
|
||||
" it. [default: --safe]"
|
||||
),
|
||||
)
|
||||
@click.option(
|
||||
"--required-version",
|
||||
type=str,
|
||||
help=(
|
||||
"Require a specific version of Black to be running (useful for unifying results"
|
||||
" across many environments e.g. with a pyproject.toml file). It can be"
|
||||
" either a major version number or an exact version."
|
||||
"Require a specific version of Black to be running. This is useful for"
|
||||
" ensuring that all contributors to your project are using the same"
|
||||
" version, because different versions of Black may format code a little"
|
||||
" differently. This option can be set in a configuration file for consistent"
|
||||
" results across environments."
|
||||
),
|
||||
)
|
||||
@click.option(
|
||||
"--exclude",
|
||||
type=str,
|
||||
callback=validate_regex,
|
||||
help=(
|
||||
"A regular expression that matches files and directories that should be"
|
||||
" excluded on recursive searches. An empty value means no paths are excluded."
|
||||
" Use forward slashes for directories on all platforms (Windows, too)."
|
||||
" By default, Black also ignores all paths listed in .gitignore. Changing this"
|
||||
f" value will override all default exclusions. [default: {DEFAULT_EXCLUDES}]"
|
||||
),
|
||||
show_default=False,
|
||||
)
|
||||
@click.option(
|
||||
"--extend-exclude",
|
||||
type=str,
|
||||
callback=validate_regex,
|
||||
help=(
|
||||
"Like --exclude, but adds additional files and directories on top of the"
|
||||
" default values instead of overriding them."
|
||||
),
|
||||
)
|
||||
@click.option(
|
||||
"--force-exclude",
|
||||
type=str,
|
||||
callback=validate_regex,
|
||||
help=(
|
||||
"Like --exclude, but files and directories matching this regex will be excluded"
|
||||
" even when they are passed explicitly as arguments. This is useful when"
|
||||
" invoking Black programmatically on changed files, such as in a pre-commit"
|
||||
" hook or editor plugin."
|
||||
),
|
||||
)
|
||||
@click.option(
|
||||
"--stdin-filename",
|
||||
type=str,
|
||||
is_eager=True,
|
||||
help=(
|
||||
"The name of the file when passing it through stdin. Useful to make sure Black"
|
||||
" will respect the --force-exclude option on some editors that rely on using"
|
||||
" stdin."
|
||||
),
|
||||
)
|
||||
@click.option(
|
||||
@ -353,59 +406,21 @@ def validate_regex(
|
||||
"A regular expression that matches files and directories that should be"
|
||||
" included on recursive searches. An empty value means all files are included"
|
||||
" regardless of the name. Use forward slashes for directories on all platforms"
|
||||
" (Windows, too). Exclusions are calculated first, inclusions later."
|
||||
" (Windows, too). Overrides all exclusions, including from .gitignore and"
|
||||
" command line options."
|
||||
),
|
||||
show_default=True,
|
||||
)
|
||||
@click.option(
|
||||
"--exclude",
|
||||
type=str,
|
||||
callback=validate_regex,
|
||||
help=(
|
||||
"A regular expression that matches files and directories that should be"
|
||||
" excluded on recursive searches. An empty value means no paths are excluded."
|
||||
" Use forward slashes for directories on all platforms (Windows, too)."
|
||||
" Exclusions are calculated first, inclusions later. [default:"
|
||||
f" {DEFAULT_EXCLUDES}]"
|
||||
),
|
||||
show_default=False,
|
||||
)
|
||||
@click.option(
|
||||
"--extend-exclude",
|
||||
type=str,
|
||||
callback=validate_regex,
|
||||
help=(
|
||||
"Like --exclude, but adds additional files and directories on top of the"
|
||||
" excluded ones. (Useful if you simply want to add to the default)"
|
||||
),
|
||||
)
|
||||
@click.option(
|
||||
"--force-exclude",
|
||||
type=str,
|
||||
callback=validate_regex,
|
||||
help=(
|
||||
"Like --exclude, but files and directories matching this regex will be "
|
||||
"excluded even when they are passed explicitly as arguments."
|
||||
),
|
||||
)
|
||||
@click.option(
|
||||
"--stdin-filename",
|
||||
type=str,
|
||||
is_eager=True,
|
||||
help=(
|
||||
"The name of the file when passing it through stdin. Useful to make "
|
||||
"sure Black will respect --force-exclude option on some "
|
||||
"editors that rely on using stdin."
|
||||
),
|
||||
)
|
||||
@click.option(
|
||||
"-W",
|
||||
"--workers",
|
||||
type=click.IntRange(min=1),
|
||||
default=None,
|
||||
help=(
|
||||
"Number of parallel workers [default: BLACK_NUM_WORKERS environment variable "
|
||||
"or number of CPUs in the system]"
|
||||
"When Black formats multiple files, it may use a process pool to speed up"
|
||||
" formatting. This option controls the number of parallel workers. This can"
|
||||
" also be specified via the BLACK_NUM_WORKERS environment variable. Defaults"
|
||||
" to the number of CPUs in the system."
|
||||
),
|
||||
)
|
||||
@click.option(
|
||||
@ -413,8 +428,8 @@ def validate_regex(
|
||||
"--quiet",
|
||||
is_flag=True,
|
||||
help=(
|
||||
"Don't emit non-error messages to stderr. Errors are still emitted; silence"
|
||||
" those with 2>/dev/null."
|
||||
"Stop emitting all non-critical output. Error messages will still be emitted"
|
||||
" (which can silenced by 2>/dev/null)."
|
||||
),
|
||||
)
|
||||
@click.option(
|
||||
@ -422,8 +437,9 @@ def validate_regex(
|
||||
"--verbose",
|
||||
is_flag=True,
|
||||
help=(
|
||||
"Also emit messages to stderr about files that were not changed or were ignored"
|
||||
" due to exclusion patterns."
|
||||
"Emit messages about files that were not changed or were ignored due to"
|
||||
" exclusion patterns. If Black is using a configuration file, a message"
|
||||
" detailing which one it is using will be emitted."
|
||||
),
|
||||
)
|
||||
@click.version_option(
|
||||
@ -454,7 +470,7 @@ def validate_regex(
|
||||
),
|
||||
is_eager=True,
|
||||
callback=read_pyproject_toml,
|
||||
help="Read configuration from FILE path.",
|
||||
help="Read configuration options from a configuration file.",
|
||||
)
|
||||
@click.pass_context
|
||||
def main( # noqa: C901
|
||||
@ -1180,7 +1196,7 @@ def _format_str_once(
|
||||
for feature in {Feature.PARENTHESIZED_CONTEXT_MANAGERS}
|
||||
if supports_feature(versions, feature)
|
||||
}
|
||||
normalize_fmt_off(src_node, mode)
|
||||
normalize_fmt_off(src_node, mode, lines)
|
||||
if lines:
|
||||
# This should be called after normalize_fmt_off.
|
||||
convert_unchanged_lines(src_node, lines)
|
||||
|
@ -1,7 +1,7 @@
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
from functools import lru_cache
|
||||
from typing import Final, Iterator, List, Optional, Union
|
||||
from typing import Collection, Final, Iterator, List, Optional, Tuple, Union
|
||||
|
||||
from black.mode import Mode, Preview
|
||||
from black.nodes import (
|
||||
@ -161,14 +161,18 @@ def make_comment(content: str) -> str:
|
||||
return "#" + content
|
||||
|
||||
|
||||
def normalize_fmt_off(node: Node, mode: Mode) -> None:
|
||||
def normalize_fmt_off(
|
||||
node: Node, mode: Mode, lines: Collection[Tuple[int, int]]
|
||||
) -> None:
|
||||
"""Convert content between `# fmt: off`/`# fmt: on` into standalone comments."""
|
||||
try_again = True
|
||||
while try_again:
|
||||
try_again = convert_one_fmt_off_pair(node, mode)
|
||||
try_again = convert_one_fmt_off_pair(node, mode, lines)
|
||||
|
||||
|
||||
def convert_one_fmt_off_pair(node: Node, mode: Mode) -> bool:
|
||||
def convert_one_fmt_off_pair(
|
||||
node: Node, mode: Mode, lines: Collection[Tuple[int, int]]
|
||||
) -> bool:
|
||||
"""Convert content of a single `# fmt: off`/`# fmt: on` into a standalone comment.
|
||||
|
||||
Returns True if a pair was converted.
|
||||
@ -213,7 +217,18 @@ def convert_one_fmt_off_pair(node: Node, mode: Mode) -> bool:
|
||||
prefix[:previous_consumed] + "\n" * comment.newlines
|
||||
)
|
||||
hidden_value = "".join(str(n) for n in ignored_nodes)
|
||||
comment_lineno = leaf.lineno - comment.newlines
|
||||
if comment.value in FMT_OFF:
|
||||
fmt_off_prefix = ""
|
||||
if len(lines) > 0 and not any(
|
||||
comment_lineno >= line[0] and comment_lineno <= line[1]
|
||||
for line in lines
|
||||
):
|
||||
# keeping indentation of comment by preserving original whitespaces.
|
||||
fmt_off_prefix = prefix.split(comment.value)[0]
|
||||
if "\n" in fmt_off_prefix:
|
||||
fmt_off_prefix = fmt_off_prefix.split("\n")[-1]
|
||||
standalone_comment_prefix += fmt_off_prefix
|
||||
hidden_value = comment.value + "\n" + hidden_value
|
||||
if _contains_fmt_skip_comment(comment.value, mode):
|
||||
hidden_value += " " + comment.value
|
||||
|
@ -716,7 +716,7 @@ def left_hand_split(
|
||||
if leaf.type in OPENING_BRACKETS:
|
||||
matching_bracket = leaf
|
||||
current_leaves = body_leaves
|
||||
if not matching_bracket:
|
||||
if not matching_bracket or not tail_leaves:
|
||||
raise CannotSplit("No brackets found")
|
||||
|
||||
head = bracket_split_build_line(
|
||||
@ -882,23 +882,28 @@ def _maybe_split_omitting_optional_parens(
|
||||
try:
|
||||
# The RHSResult Omitting Optional Parens.
|
||||
rhs_oop = _first_right_hand_split(line, omit=omit)
|
||||
if not (
|
||||
# the split is right after `=`
|
||||
len(rhs.head.leaves) >= 2
|
||||
and rhs.head.leaves[-2].type == token.EQUAL
|
||||
# the left side of assignment contains brackets
|
||||
and any(leaf.type in BRACKETS for leaf in rhs.head.leaves[:-1])
|
||||
# the left side of assignment is short enough (the -1 is for the ending
|
||||
# optional paren)
|
||||
and is_line_short_enough(
|
||||
rhs.head, mode=replace(mode, line_length=mode.line_length - 1)
|
||||
is_split_right_after_equal = (
|
||||
len(rhs.head.leaves) >= 2 and rhs.head.leaves[-2].type == token.EQUAL
|
||||
)
|
||||
rhs_head_contains_brackets = any(
|
||||
leaf.type in BRACKETS for leaf in rhs.head.leaves[:-1]
|
||||
)
|
||||
# the -1 is for the ending optional paren
|
||||
rhs_head_short_enough = is_line_short_enough(
|
||||
rhs.head, mode=replace(mode, line_length=mode.line_length - 1)
|
||||
)
|
||||
rhs_head_explode_blocked_by_magic_trailing_comma = (
|
||||
rhs.head.magic_trailing_comma is None
|
||||
)
|
||||
if (
|
||||
not (
|
||||
is_split_right_after_equal
|
||||
and rhs_head_contains_brackets
|
||||
and rhs_head_short_enough
|
||||
and rhs_head_explode_blocked_by_magic_trailing_comma
|
||||
)
|
||||
# the left side of assignment won't explode further because of magic
|
||||
# trailing comma
|
||||
and rhs.head.magic_trailing_comma is None
|
||||
# the split by omitting optional parens isn't preferred by some other
|
||||
# reason
|
||||
and not _prefer_split_rhs_oop(rhs_oop, mode)
|
||||
# the omit optional parens split is preferred by some other reason
|
||||
or _prefer_split_rhs_oop_over_rhs(rhs_oop, rhs, mode)
|
||||
):
|
||||
yield from _maybe_split_omitting_optional_parens(
|
||||
rhs_oop, line, mode, features=features, omit=omit
|
||||
@ -906,8 +911,12 @@ def _maybe_split_omitting_optional_parens(
|
||||
return
|
||||
|
||||
except CannotSplit as e:
|
||||
if not (
|
||||
can_be_split(rhs.body) or is_line_short_enough(rhs.body, mode=mode)
|
||||
# For chained assignments we want to use the previous successful split
|
||||
if line.is_chained_assignment:
|
||||
pass
|
||||
|
||||
elif not can_be_split(rhs.body) and not is_line_short_enough(
|
||||
rhs.body, mode=mode
|
||||
):
|
||||
raise CannotSplit(
|
||||
"Splitting failed, body is still too long and can't be split."
|
||||
@ -931,10 +940,22 @@ def _maybe_split_omitting_optional_parens(
|
||||
yield result
|
||||
|
||||
|
||||
def _prefer_split_rhs_oop(rhs_oop: RHSResult, mode: Mode) -> bool:
|
||||
def _prefer_split_rhs_oop_over_rhs(
|
||||
rhs_oop: RHSResult, rhs: RHSResult, mode: Mode
|
||||
) -> bool:
|
||||
"""
|
||||
Returns whether we should prefer the result from a split omitting optional parens.
|
||||
Returns whether we should prefer the result from a split omitting optional parens
|
||||
(rhs_oop) over the original (rhs).
|
||||
"""
|
||||
# If we have multiple targets, we prefer more `=`s on the head vs pushing them to
|
||||
# the body
|
||||
rhs_head_equal_count = [leaf.type for leaf in rhs.head.leaves].count(token.EQUAL)
|
||||
rhs_oop_head_equal_count = [leaf.type for leaf in rhs_oop.head.leaves].count(
|
||||
token.EQUAL
|
||||
)
|
||||
if rhs_head_equal_count > 1 and rhs_head_equal_count > rhs_oop_head_equal_count:
|
||||
return False
|
||||
|
||||
has_closing_bracket_after_assign = False
|
||||
for leaf in reversed(rhs_oop.head.leaves):
|
||||
if leaf.type == token.EQUAL:
|
||||
|
@ -207,6 +207,11 @@ def is_triple_quoted_string(self) -> bool:
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_chained_assignment(self) -> bool:
|
||||
"""Is the line a chained assignment"""
|
||||
return [leaf.type for leaf in self.leaves].count(token.EQUAL) > 1
|
||||
|
||||
@property
|
||||
def opens_block(self) -> bool:
|
||||
"""Does this line open a new level of indentation."""
|
||||
@ -674,11 +679,9 @@ def _maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
|
||||
):
|
||||
return 0, 1
|
||||
|
||||
if (
|
||||
self.previous_line
|
||||
and self.previous_line.opens_block
|
||||
# Always allow blank lines, except right before a function docstring
|
||||
and not (
|
||||
# In preview mode, always allow blank lines, except right before a function
|
||||
# docstring
|
||||
is_empty_first_line_ok = (
|
||||
not is_docstring(current_line.leaves[0])
|
||||
or (
|
||||
self.previous_line
|
||||
@ -686,7 +689,6 @@ def _maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
|
||||
and self.previous_line.leaves[0].parent
|
||||
and not is_funcdef(self.previous_line.leaves[0].parent)
|
||||
)
|
||||
)
|
||||
):
|
||||
return 0, 0
|
||||
return before, 0
|
||||
|
@ -171,6 +171,10 @@ class Preview(Enum):
|
||||
hex_codes_in_unicode_sequences = auto()
|
||||
string_processing = auto()
|
||||
hug_parens_with_braces_and_square_brackets = auto()
|
||||
allow_empty_first_line_in_block = auto()
|
||||
single_line_format_skip_with_multiple_comments = auto()
|
||||
long_case_block_line_splitting = auto()
|
||||
allow_form_feeds = auto()
|
||||
|
||||
|
||||
class Deprecated(UserWarning):
|
||||
|
@ -14,7 +14,7 @@ def format_hex(text: str) -> str:
|
||||
|
||||
|
||||
def format_scientific_notation(text: str) -> str:
|
||||
"""Formats a numeric string utilizing scentific notation"""
|
||||
"""Formats a numeric string utilizing scientific notation"""
|
||||
before, after = text.split("e")
|
||||
sign = ""
|
||||
if after.startswith("-"):
|
||||
|
@ -172,7 +172,7 @@ class _TopLevelStatementsVisitor(Visitor[None]):
|
||||
A node visitor that converts unchanged top-level statements to
|
||||
STANDALONE_COMMENT.
|
||||
|
||||
This is used in addition to _convert_unchanged_lines_by_flatterning, to
|
||||
This is used in addition to _convert_unchanged_line_by_line, to
|
||||
speed up formatting when there are unchanged top-level
|
||||
classes/functions/statements.
|
||||
"""
|
||||
@ -302,7 +302,7 @@ def _convert_node_to_standalone_comment(node: LN) -> None:
|
||||
index = node.remove()
|
||||
if index is not None:
|
||||
# Remove the '\n', as STANDALONE_COMMENT will have '\n' appended when
|
||||
# genearting the formatted code.
|
||||
# generating the formatted code.
|
||||
value = str(node)[:-1]
|
||||
parent.insert_child(
|
||||
index,
|
||||
|
@ -39,7 +39,6 @@
|
||||
Set,
|
||||
Tuple,
|
||||
Union,
|
||||
cast,
|
||||
)
|
||||
|
||||
from blib2to3.pgen2.grammar import Grammar
|
||||
@ -262,11 +261,9 @@ def add_whitespace(self, start: Coord) -> None:
|
||||
def untokenize(self, iterable: Iterable[TokenInfo]) -> str:
|
||||
for t in iterable:
|
||||
if len(t) == 2:
|
||||
self.compat(cast(Tuple[int, str], t), iterable)
|
||||
self.compat(t, iterable)
|
||||
break
|
||||
tok_type, token, start, end, line = cast(
|
||||
Tuple[int, str, Coord, Coord, str], t
|
||||
)
|
||||
tok_type, token, start, end, line = t
|
||||
self.add_whitespace(start)
|
||||
self.tokens.append(token)
|
||||
self.prev_row, self.prev_col = end
|
||||
|
3
tests/data/cases/comment_type_hint.py
Normal file
3
tests/data/cases/comment_type_hint.py
Normal file
@ -0,0 +1,3 @@
|
||||
# flags: --no-preview-line-length-1
|
||||
# split out from comments2 as it does not work with line-length=1, losing the comment
|
||||
a = "type comment with trailing space" # type: str
|
@ -155,8 +155,6 @@ def _init_host(self, parsed) -> None:
|
||||
pass
|
||||
|
||||
|
||||
a = "type comment with trailing space" # type: str
|
||||
|
||||
#######################
|
||||
### SECTION COMMENT ###
|
||||
#######################
|
||||
@ -335,8 +333,6 @@ def _init_host(self, parsed) -> None:
|
||||
pass
|
||||
|
||||
|
||||
a = "type comment with trailing space" # type: str
|
||||
|
||||
#######################
|
||||
### SECTION COMMENT ###
|
||||
#######################
|
||||
|
@ -1,9 +1,12 @@
|
||||
# flags: --no-preview-line-length-1
|
||||
# l2 loses the comment with line-length=1 in preview mode
|
||||
l1 = ["This list should be broken up", "into multiple lines", "because it is way too long"]
|
||||
l2 = ["But this list shouldn't", "even though it also has", "way too many characters in it"] # fmt: skip
|
||||
l3 = ["I have", "trailing comma", "so I should be braked",]
|
||||
|
||||
# output
|
||||
|
||||
# l2 loses the comment with line-length=1 in preview mode
|
||||
l1 = [
|
||||
"This list should be broken up",
|
||||
"into multiple lines",
|
||||
|
@ -1,4 +1,4 @@
|
||||
# flags: --line-ranges=12-12
|
||||
# flags: --line-ranges=12-12 --line-ranges=21-21
|
||||
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
|
||||
# flag above as it's formatting specifically these lines.
|
||||
|
||||
@ -11,9 +11,19 @@ class MyClass:
|
||||
def method():
|
||||
print ( "str" )
|
||||
|
||||
@decor(
|
||||
a=1,
|
||||
# fmt: off
|
||||
b=(2, 3),
|
||||
# fmt: on
|
||||
)
|
||||
def func():
|
||||
pass
|
||||
|
||||
|
||||
# output
|
||||
|
||||
# flags: --line-ranges=12-12
|
||||
# flags: --line-ranges=12-12 --line-ranges=21-21
|
||||
# NOTE: If you need to modify this file, pay special attention to the --line-ranges=
|
||||
# flag above as it's formatting specifically these lines.
|
||||
|
||||
@ -25,3 +35,13 @@ class MyClass:
|
||||
# fmt: on
|
||||
def method():
|
||||
print("str")
|
||||
|
||||
@decor(
|
||||
a=1,
|
||||
# fmt: off
|
||||
b=(2, 3),
|
||||
# fmt: on
|
||||
)
|
||||
def func():
|
||||
pass
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# flags: --minimum-version=3.8
|
||||
# flags: --minimum-version=3.8 --no-preview-line-length-1
|
||||
if (foo := 0):
|
||||
pass
|
||||
|
||||
|
@ -55,6 +55,13 @@ def quux():
|
||||
|
||||
new_line = here
|
||||
|
||||
|
||||
class Cls:
|
||||
|
||||
def method(self):
|
||||
|
||||
pass
|
||||
|
||||
# output
|
||||
|
||||
def foo():
|
||||
@ -113,3 +120,9 @@ def baz():
|
||||
def quux():
|
||||
|
||||
new_line = here
|
||||
|
||||
|
||||
class Cls:
|
||||
def method(self):
|
||||
|
||||
pass
|
||||
|
@ -125,23 +125,6 @@ def foo_square_brackets(request):
|
||||
func([x for x in "long line long line long line long line long line long line long line"])
|
||||
func([x for x in [x for x in "long line long line long line long line long line long line long line"]])
|
||||
|
||||
func({"short line"})
|
||||
func({"long line", "long long line", "long long long line", "long long long long line", "long long long long long line"})
|
||||
func({{"long line", "long long line", "long long long line", "long long long long line", "long long long long long line"}})
|
||||
func(("long line", "long long line", "long long long line", "long long long long line", "long long long long long line"))
|
||||
func((("long line", "long long line", "long long long line", "long long long long line", "long long long long long line")))
|
||||
func([["long line", "long long line", "long long long line", "long long long long line", "long long long long long line"]])
|
||||
|
||||
# Do not hug if the argument fits on a single line.
|
||||
func({"fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"})
|
||||
func(("fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"))
|
||||
func(["fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"])
|
||||
func(**{"fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit---"})
|
||||
func(*("fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit----"))
|
||||
array = [{"fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"}]
|
||||
array = [("fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line")]
|
||||
array = [["fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"]]
|
||||
|
||||
foooooooooooooooooooo(
|
||||
[{c: n + 1 for c in range(256)} for n in range(100)] + [{}], {size}
|
||||
)
|
||||
@ -151,14 +134,11 @@ def foo_square_brackets(request):
|
||||
)
|
||||
|
||||
nested_mapping = {"key": [{"a very long key 1": "with a very long value", "a very long key 2": "with a very long value"}]}
|
||||
nested_array = [[["long line", "long long line", "long long long line", "long long long long line", "long long long long long line"]]]
|
||||
explicit_exploding = [[["short", "line",],],]
|
||||
single_item_do_not_explode = Context({
|
||||
"version": get_docs_version(),
|
||||
})
|
||||
|
||||
foo(*["long long long long long line", "long long long long long line", "long long long long long line"])
|
||||
|
||||
foo(*[str(i) for i in range(100000000000000000000000000000000000000000000000000000000000)])
|
||||
|
||||
foo(
|
||||
@ -310,69 +290,6 @@ def foo_square_brackets(request):
|
||||
]
|
||||
])
|
||||
|
||||
func({"short line"})
|
||||
func({
|
||||
"long line",
|
||||
"long long line",
|
||||
"long long long line",
|
||||
"long long long long line",
|
||||
"long long long long long line",
|
||||
})
|
||||
func({{
|
||||
"long line",
|
||||
"long long line",
|
||||
"long long long line",
|
||||
"long long long long line",
|
||||
"long long long long long line",
|
||||
}})
|
||||
func((
|
||||
"long line",
|
||||
"long long line",
|
||||
"long long long line",
|
||||
"long long long long line",
|
||||
"long long long long long line",
|
||||
))
|
||||
func(((
|
||||
"long line",
|
||||
"long long line",
|
||||
"long long long line",
|
||||
"long long long long line",
|
||||
"long long long long long line",
|
||||
)))
|
||||
func([[
|
||||
"long line",
|
||||
"long long line",
|
||||
"long long long line",
|
||||
"long long long long line",
|
||||
"long long long long long line",
|
||||
]])
|
||||
|
||||
# Do not hug if the argument fits on a single line.
|
||||
func(
|
||||
{"fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"}
|
||||
)
|
||||
func(
|
||||
("fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line")
|
||||
)
|
||||
func(
|
||||
["fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"]
|
||||
)
|
||||
func(
|
||||
**{"fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit---"}
|
||||
)
|
||||
func(
|
||||
*("fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit----")
|
||||
)
|
||||
array = [
|
||||
{"fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"}
|
||||
]
|
||||
array = [
|
||||
("fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line")
|
||||
]
|
||||
array = [
|
||||
["fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"]
|
||||
]
|
||||
|
||||
foooooooooooooooooooo(
|
||||
[{c: n + 1 for c in range(256)} for n in range(100)] + [{}], {size}
|
||||
)
|
||||
@ -387,13 +304,6 @@ def foo_square_brackets(request):
|
||||
"a very long key 2": "with a very long value",
|
||||
}]
|
||||
}
|
||||
nested_array = [[[
|
||||
"long line",
|
||||
"long long line",
|
||||
"long long long line",
|
||||
"long long long long line",
|
||||
"long long long long long line",
|
||||
]]]
|
||||
explicit_exploding = [
|
||||
[
|
||||
[
|
||||
@ -406,12 +316,6 @@ def foo_square_brackets(request):
|
||||
"version": get_docs_version(),
|
||||
})
|
||||
|
||||
foo(*[
|
||||
"long long long long long line",
|
||||
"long long long long long line",
|
||||
"long long long long long line",
|
||||
])
|
||||
|
||||
foo(*[
|
||||
str(i) for i in range(100000000000000000000000000000000000000000000000000000000000)
|
||||
])
|
||||
|
@ -0,0 +1,106 @@
|
||||
# flags: --preview --no-preview-line-length-1
|
||||
# split out from preview_hug_parens_with_brackes_and_square_brackets, as it produces
|
||||
# different code on the second pass with line-length 1 in many cases.
|
||||
# Seems to be about whether the last string in a sequence gets wrapped in parens or not.
|
||||
foo(*["long long long long long line", "long long long long long line", "long long long long long line"])
|
||||
func({"short line"})
|
||||
func({"long line", "long long line", "long long long line", "long long long long line", "long long long long long line"})
|
||||
func({{"long line", "long long line", "long long long line", "long long long long line", "long long long long long line"}})
|
||||
func(("long line", "long long line", "long long long line", "long long long long line", "long long long long long line"))
|
||||
func((("long line", "long long line", "long long long line", "long long long long line", "long long long long long line")))
|
||||
func([["long line", "long long line", "long long long line", "long long long long line", "long long long long long line"]])
|
||||
|
||||
|
||||
# Do not hug if the argument fits on a single line.
|
||||
func({"fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"})
|
||||
func(("fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"))
|
||||
func(["fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"])
|
||||
func(**{"fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit---"})
|
||||
func(*("fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit----"))
|
||||
array = [{"fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"}]
|
||||
array = [("fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line")]
|
||||
array = [["fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"]]
|
||||
|
||||
nested_array = [[["long line", "long long line", "long long long line", "long long long long line", "long long long long long line"]]]
|
||||
|
||||
# output
|
||||
|
||||
# split out from preview_hug_parens_with_brackes_and_square_brackets, as it produces
|
||||
# different code on the second pass with line-length 1 in many cases.
|
||||
# Seems to be about whether the last string in a sequence gets wrapped in parens or not.
|
||||
foo(*[
|
||||
"long long long long long line",
|
||||
"long long long long long line",
|
||||
"long long long long long line",
|
||||
])
|
||||
func({"short line"})
|
||||
func({
|
||||
"long line",
|
||||
"long long line",
|
||||
"long long long line",
|
||||
"long long long long line",
|
||||
"long long long long long line",
|
||||
})
|
||||
func({{
|
||||
"long line",
|
||||
"long long line",
|
||||
"long long long line",
|
||||
"long long long long line",
|
||||
"long long long long long line",
|
||||
}})
|
||||
func((
|
||||
"long line",
|
||||
"long long line",
|
||||
"long long long line",
|
||||
"long long long long line",
|
||||
"long long long long long line",
|
||||
))
|
||||
func(((
|
||||
"long line",
|
||||
"long long line",
|
||||
"long long long line",
|
||||
"long long long long line",
|
||||
"long long long long long line",
|
||||
)))
|
||||
func([[
|
||||
"long line",
|
||||
"long long line",
|
||||
"long long long line",
|
||||
"long long long long line",
|
||||
"long long long long long line",
|
||||
]])
|
||||
|
||||
|
||||
# Do not hug if the argument fits on a single line.
|
||||
func(
|
||||
{"fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"}
|
||||
)
|
||||
func(
|
||||
("fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line")
|
||||
)
|
||||
func(
|
||||
["fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"]
|
||||
)
|
||||
func(
|
||||
**{"fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit---"}
|
||||
)
|
||||
func(
|
||||
*("fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit----")
|
||||
)
|
||||
array = [
|
||||
{"fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"}
|
||||
]
|
||||
array = [
|
||||
("fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line")
|
||||
]
|
||||
array = [
|
||||
["fit line", "fit line", "fit line", "fit line", "fit line", "fit line", "fit line"]
|
||||
]
|
||||
|
||||
nested_array = [[[
|
||||
"long line",
|
||||
"long long line",
|
||||
"long long long line",
|
||||
"long long long long line",
|
||||
"long long long long long line",
|
||||
]]]
|
@ -84,3 +84,24 @@
|
||||
) or (
|
||||
isinstance(some_other_var, BaseClass) and table.something != table.some_other_thing
|
||||
)
|
||||
|
||||
# Multiple targets
|
||||
a = b = (
|
||||
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
)
|
||||
|
||||
a = b = c = d = e = f = g = (
|
||||
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
|
||||
) = i = j = (
|
||||
kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
|
||||
)
|
||||
|
||||
a = (
|
||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
) = c
|
||||
|
||||
a = (
|
||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
) = (
|
||||
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
) = ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
|
||||
|
@ -30,6 +30,7 @@ def check_file(subdir: str, filename: str, *, data: bool = True) -> None:
|
||||
fast=args.fast,
|
||||
minimum_version=args.minimum_version,
|
||||
lines=args.lines,
|
||||
no_preview_line_length_1=args.no_preview_line_length_1,
|
||||
)
|
||||
if args.minimum_version is not None:
|
||||
major, minor = args.minimum_version
|
||||
@ -42,6 +43,7 @@ def check_file(subdir: str, filename: str, *, data: bool = True) -> None:
|
||||
fast=args.fast,
|
||||
minimum_version=args.minimum_version,
|
||||
lines=args.lines,
|
||||
no_preview_line_length_1=args.no_preview_line_length_1,
|
||||
)
|
||||
|
||||
|
||||
|
@ -46,6 +46,7 @@ class TestCaseArgs:
|
||||
fast: bool = False
|
||||
minimum_version: Optional[Tuple[int, int]] = None
|
||||
lines: Collection[Tuple[int, int]] = ()
|
||||
no_preview_line_length_1: bool = False
|
||||
|
||||
|
||||
def _assert_format_equal(expected: str, actual: str) -> None:
|
||||
@ -96,6 +97,7 @@ def assert_format(
|
||||
fast: bool = False,
|
||||
minimum_version: Optional[Tuple[int, int]] = None,
|
||||
lines: Collection[Tuple[int, int]] = (),
|
||||
no_preview_line_length_1: bool = False,
|
||||
) -> None:
|
||||
"""Convenience function to check that Black formats as expected.
|
||||
|
||||
@ -124,21 +126,28 @@ def assert_format(
|
||||
f"Black crashed formatting this case in {text} mode."
|
||||
) from e
|
||||
# Similarly, setting line length to 1 is a good way to catch
|
||||
# stability bugs. But only in non-preview mode because preview mode
|
||||
# currently has a lot of line length 1 bugs.
|
||||
try:
|
||||
_assert_format_inner(
|
||||
source,
|
||||
None,
|
||||
replace(mode, preview=False, line_length=1),
|
||||
fast=fast,
|
||||
minimum_version=minimum_version,
|
||||
lines=lines,
|
||||
)
|
||||
except Exception as e:
|
||||
raise FormatFailure(
|
||||
"Black crashed formatting this case with line-length set to 1."
|
||||
) from e
|
||||
# stability bugs. Some tests are known to be broken in preview mode with line length
|
||||
# of 1 though, and have marked that with a flag --no-preview-line-length-1
|
||||
preview_modes = [False]
|
||||
if not no_preview_line_length_1:
|
||||
preview_modes.append(True)
|
||||
|
||||
for preview_mode in preview_modes:
|
||||
|
||||
try:
|
||||
_assert_format_inner(
|
||||
source,
|
||||
None,
|
||||
replace(mode, preview=preview_mode, line_length=1),
|
||||
fast=fast,
|
||||
minimum_version=minimum_version,
|
||||
lines=lines,
|
||||
)
|
||||
except Exception as e:
|
||||
text = "preview" if preview_mode else "non-preview"
|
||||
raise FormatFailure(
|
||||
f"Black crashed formatting this case in {text} mode with line-length=1."
|
||||
) from e
|
||||
|
||||
|
||||
def _assert_format_inner(
|
||||
@ -246,6 +255,15 @@ def get_flags_parser() -> argparse.ArgumentParser:
|
||||
),
|
||||
)
|
||||
parser.add_argument("--line-ranges", action="append")
|
||||
parser.add_argument(
|
||||
"--no-preview-line-length-1",
|
||||
default=False,
|
||||
action="store_true",
|
||||
help=(
|
||||
"Don't run in preview mode with --line-length=1, as that's known to cause a"
|
||||
" crash"
|
||||
),
|
||||
)
|
||||
return parser
|
||||
|
||||
|
||||
@ -266,7 +284,11 @@ def parse_mode(flags_line: str) -> TestCaseArgs:
|
||||
else:
|
||||
lines = []
|
||||
return TestCaseArgs(
|
||||
mode=mode, fast=args.fast, minimum_version=args.minimum_version, lines=lines
|
||||
mode=mode,
|
||||
fast=args.fast,
|
||||
minimum_version=args.minimum_version,
|
||||
lines=lines,
|
||||
no_preview_line_length_1=args.no_preview_line_length_1,
|
||||
)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user