Skip to content

Commit

Permalink
Merge branch 'main' into sth/include-absolute-path
Browse files Browse the repository at this point in the history
  • Loading branch information
hauntsaninja authored Oct 27, 2023
2 parents 639b819 + 7bfa35c commit 3cb0639
Show file tree
Hide file tree
Showing 13 changed files with 411 additions and 37 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/diff_shades.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: "*"
python-version: "3.11"

- name: Install diff-shades and support dependencies
run: |
Expand Down Expand Up @@ -59,7 +59,7 @@ jobs:

- uses: actions/setup-python@v4
with:
python-version: "*"
python-version: "3.11"

- name: Install diff-shades and support dependencies
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/doc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
- name: Set up latest Python
uses: actions/setup-python@v4
with:
python-version: "*"
python-version: "3.11"

- name: Install dependencies
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
- name: Set up latest Python
uses: actions/setup-python@v4
with:
python-version: "*"
python-version: "3.11"

- name: Install dependencies
run: |
Expand Down
7 changes: 4 additions & 3 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@

### Preview style

<!-- Changes that affect Black's preview style -->
- Multiline dictionaries and lists that are the sole argument to a function are now
indented less (#3964)

### Configuration

<!-- Changes to how Black can be configured -->
- Add support for single line format skip with other comments on the same line (#3959)

- Fix a bug in the matching of absolute path names in `--include` (#3976)

Expand Down Expand Up @@ -53,7 +54,7 @@

### Highlights

- Maintanence release to get a fix out for GitHub Action edge case (#3957)
- Maintenance release to get a fix out for GitHub Action edge case (#3957)

### Preview style

Expand Down
12 changes: 7 additions & 5 deletions docs/the_black_code_style/current_style.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ 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 end with
_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: 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.
`# 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
Expand Down
26 changes: 26 additions & 0 deletions docs/the_black_code_style/future_style.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,32 @@ my_dict = {
}
```

### Improved multiline dictionary and list indentation for sole function parameter

For better readability and less verticality, _Black_ now pairs parentheses ("(", ")")
with braces ("{", "}") and square brackets ("[", "]") on the same line for single
parameter function calls. For example:

```python
foo(
[
1,
2,
3,
]
)
```

will be changed to:

```python
foo([
1,
2,
3,
])
```

### Improved multiline string handling

_Black_ is smarter when formatting multiline strings, especially in function arguments,
Expand Down
2 changes: 1 addition & 1 deletion src/black/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1099,7 +1099,7 @@ def _format_str_once(src_contents: str, *, mode: Mode) -> str:
for feature in {Feature.PARENTHESIZED_CONTEXT_MANAGERS}
if supports_feature(versions, feature)
}
normalize_fmt_off(src_node)
normalize_fmt_off(src_node, mode)
lines = LineGenerator(mode=mode, features=context_manager_features)
elt = EmptyLineTracker(mode=mode)
split_line_features = {
Expand Down
63 changes: 51 additions & 12 deletions src/black/comments.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from functools import lru_cache
from typing import Final, Iterator, List, Optional, Union

from black.mode import Mode, Preview
from black.nodes import (
CLOSING_BRACKETS,
STANDALONE_COMMENT,
Expand All @@ -20,10 +21,11 @@

FMT_OFF: Final = {"# fmt: off", "# fmt:off", "# yapf: disable"}
FMT_SKIP: Final = {"# fmt: skip", "# fmt:skip"}
FMT_PASS: Final = {*FMT_OFF, *FMT_SKIP}
FMT_ON: Final = {"# fmt: on", "# fmt:on", "# yapf: enable"}

COMMENT_EXCEPTIONS = " !:#'"
_COMMENT_PREFIX = "# "
_COMMENT_LIST_SEPARATOR = ";"


@dataclass
Expand Down Expand Up @@ -130,36 +132,42 @@ def make_comment(content: str) -> str:
return "#" + content


def normalize_fmt_off(node: Node) -> None:
def normalize_fmt_off(node: Node, mode: Mode) -> 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)
try_again = convert_one_fmt_off_pair(node, mode)


def convert_one_fmt_off_pair(node: Node) -> bool:
def convert_one_fmt_off_pair(node: Node, mode: Mode) -> bool:
"""Convert content of a single `# fmt: off`/`# fmt: on` into a standalone comment.
Returns True if a pair was converted.
"""
for leaf in node.leaves():
previous_consumed = 0
for comment in list_comments(leaf.prefix, is_endmarker=False):
if comment.value not in FMT_PASS:
should_pass_fmt = comment.value in FMT_OFF or _contains_fmt_skip_comment(
comment.value, mode
)
if not should_pass_fmt:
previous_consumed = comment.consumed
continue
# We only want standalone comments. If there's no previous leaf or
# the previous leaf is indentation, it's a standalone comment in
# disguise.
if comment.value in FMT_PASS and comment.type != STANDALONE_COMMENT:
if should_pass_fmt and comment.type != STANDALONE_COMMENT:
prev = preceding_leaf(leaf)
if prev:
if comment.value in FMT_OFF and prev.type not in WHITESPACE:
continue
if comment.value in FMT_SKIP and prev.type in WHITESPACE:
if (
_contains_fmt_skip_comment(comment.value, mode)
and prev.type in WHITESPACE
):
continue

ignored_nodes = list(generate_ignored_nodes(leaf, comment))
ignored_nodes = list(generate_ignored_nodes(leaf, comment, mode))
if not ignored_nodes:
continue

Expand All @@ -168,7 +176,7 @@ def convert_one_fmt_off_pair(node: Node) -> bool:
prefix = first.prefix
if comment.value in FMT_OFF:
first.prefix = prefix[comment.consumed :]
if comment.value in FMT_SKIP:
if _contains_fmt_skip_comment(comment.value, mode):
first.prefix = ""
standalone_comment_prefix = prefix
else:
Expand All @@ -178,7 +186,7 @@ def convert_one_fmt_off_pair(node: Node) -> bool:
hidden_value = "".join(str(n) for n in ignored_nodes)
if comment.value in FMT_OFF:
hidden_value = comment.value + "\n" + hidden_value
if comment.value in FMT_SKIP:
if _contains_fmt_skip_comment(comment.value, mode):
hidden_value += " " + comment.value
if hidden_value.endswith("\n"):
# That happens when one of the `ignored_nodes` ended with a NEWLINE
Expand All @@ -205,13 +213,15 @@ def convert_one_fmt_off_pair(node: Node) -> bool:
return False


def generate_ignored_nodes(leaf: Leaf, comment: ProtoComment) -> Iterator[LN]:
def generate_ignored_nodes(
leaf: Leaf, comment: ProtoComment, mode: Mode
) -> Iterator[LN]:
"""Starting from the container of `leaf`, generate all leaves until `# fmt: on`.
If comment is skip, returns leaf only.
Stops at the end of the block.
"""
if comment.value in FMT_SKIP:
if _contains_fmt_skip_comment(comment.value, mode):
yield from _generate_ignored_nodes_from_fmt_skip(leaf, comment)
return
container: Optional[LN] = container_of(leaf)
Expand Down Expand Up @@ -327,3 +337,32 @@ def contains_pragma_comment(comment_list: List[Leaf]) -> bool:
return True

return False


def _contains_fmt_skip_comment(comment_line: str, mode: Mode) -> bool:
"""
Checks if the given comment contains FMT_SKIP alone or paired with other comments.
Matching styles:
# fmt:skip <-- single comment
# noqa:XXX # fmt:skip # a nice line <-- multiple comments (Preview)
# pylint:XXX; fmt:skip <-- list of comments (; separated, Preview)
"""
semantic_comment_blocks = (
[
comment_line,
*[
_COMMENT_PREFIX + comment.strip()
for comment in comment_line.split(_COMMENT_PREFIX)[1:]
],
*[
_COMMENT_PREFIX + comment.strip()
for comment in comment_line.strip(_COMMENT_PREFIX).split(
_COMMENT_LIST_SEPARATOR
)
],
]
if Preview.single_line_format_skip_with_multiple_comments in mode
else [comment_line]
)

return any(comment in FMT_SKIP for comment in semantic_comment_blocks)
13 changes: 13 additions & 0 deletions src/black/linegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,19 @@ def _first_right_hand_split(
tail_leaves.reverse()
body_leaves.reverse()
head_leaves.reverse()

if Preview.hug_parens_with_braces_and_square_brackets in line.mode:
if (
tail_leaves[0].type == token.RPAR
and tail_leaves[0].value
and tail_leaves[0].opening_bracket is head_leaves[-1]
and body_leaves[-1].type in [token.RBRACE, token.RSQB]
and body_leaves[-1].opening_bracket is body_leaves[0]
):
head_leaves = head_leaves + body_leaves[:1]
tail_leaves = body_leaves[-1:] + tail_leaves
body_leaves = body_leaves[1:-1]

head = bracket_split_build_line(
head_leaves, line, opening_bracket, component=_BracketSplitComponent.head
)
Expand Down
2 changes: 2 additions & 0 deletions src/black/mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,9 @@ class Preview(Enum):
module_docstring_newlines = auto()
accept_raw_docstrings = auto()
fix_power_op_line_length = auto()
hug_parens_with_braces_and_square_brackets = auto()
allow_empty_first_line_before_new_block_or_comment = auto()
single_line_format_skip_with_multiple_comments = auto()


class Deprecated(UserWarning):
Expand Down
Loading

0 comments on commit 3cb0639

Please sign in to comment.