Skip to content

Commit

Permalink
Merge branch 'main' into wrap-long-val
Browse files Browse the repository at this point in the history
  • Loading branch information
JelleZijlstra authored Jan 20, 2024
2 parents 90b0c28 + 7f60f3d commit bf616a8
Show file tree
Hide file tree
Showing 15 changed files with 187 additions and 36 deletions.
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ repos:
additional_dependencies: *version_check_dependencies

- repo: https://github.com/pycqa/isort
rev: 5.12.0
rev: 5.13.2
hooks:
- id: isort

Expand All @@ -39,7 +39,7 @@ repos:
exclude: ^src/blib2to3/

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.7.1
rev: v1.8.0
hooks:
- id: mypy
exclude: ^docs/conf.py
Expand All @@ -58,13 +58,13 @@ repos:
- hypothesmith

- repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.0.3
rev: v4.0.0-alpha.8
hooks:
- id: prettier
exclude: \.github/workflows/diff_shades\.yml

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
rev: v4.5.0
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace
Expand Down
2 changes: 0 additions & 2 deletions .pre-commit-hooks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
name: black
description: "Black: The uncompromising Python code formatter"
entry: black
stages: [pre-commit, pre-merge-commit, pre-push, manual]
language: python
minimum_pre_commit_version: 2.9.2
require_serial: true
Expand All @@ -14,7 +13,6 @@
description:
"Black: The uncompromising Python code formatter (with Jupyter Notebook support)"
entry: black
stages: [pre-commit, pre-merge-commit, pre-push, manual]
language: python
minimum_pre_commit_version: 2.9.2
require_serial: true
Expand Down
9 changes: 9 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,15 @@

<!-- Changes that affect Black's preview style -->

- Fix comment handling when parenthesising conditional expressions (#4134)
- Format module docstrings the same as class and function docstrings (#4095)
- Fix bug where spaces were not added around parenthesized walruses in subscripts,
unlike other binary operators (#4109)
- Remove empty lines before docstrings in async functions (#4132)
- Address a missing case in the change to allow empty lines at the beginning of all
blocks, except immediately before a docstring (#4130)
- For stubs, fix logic to enforce empty line after nested classes with bodies (#4141)
- Fix crash when using a walrus in a dictionary (#4155)

### Configuration

Expand Down Expand Up @@ -48,6 +54,9 @@

<!-- For example, Docker, GitHub Actions, pre-commit, editors -->

- Revert the change to run Black's pre-commit integration only on specific git hooks
(#3940) for better compatibility with older versions of pre-commit (#4137)

### Documentation

<!-- Major changes to documentation and policies. Small docs changes
Expand Down
6 changes: 3 additions & 3 deletions docs/guides/using_black_with_other_tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ There are a few deviations that cause incompatibilities with _Black_.

```
max-line-length = 88
extend-ignore = E203
extend-ignore = E203, E704
```

#### Why those options above?
Expand Down Expand Up @@ -184,7 +184,7 @@ extend-ignore = E203, E704
```ini
[flake8]
max-line-length = 88
extend-ignore = E203
extend-ignore = E203, E704
```

</details>
Expand All @@ -195,7 +195,7 @@ extend-ignore = E203
```ini
[flake8]
max-line-length = 88
extend-ignore = E203
extend-ignore = E203, E704
```

</details>
Expand Down
5 changes: 5 additions & 0 deletions docs/usage_and_configuration/the_basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,11 @@ recursive searches. An empty value means no paths are excluded. Use forward slas
directories on all platforms (Windows, too). By default, Black also ignores all paths
listed in `.gitignore`. Changing this value will override all default exclusions.

If the regular expression contains newlines, it is treated as a
[verbose regular expression](https://docs.python.org/3/library/re.html#re.VERBOSE). This
is typically useful when setting these options in a `pyproject.toml` configuration file;
see [Configuration format](#configuration-format) for more information.

#### `--extend-exclude`

Like `--exclude`, but adds additional files and directories on top of the default values
Expand Down
9 changes: 7 additions & 2 deletions src/black/linegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@
is_atom_with_invisible_parens,
is_docstring,
is_empty_tuple,
is_function_or_class,
is_lpar_token,
is_multiline_string,
is_name_token,
is_one_sequence_between,
is_one_tuple,
is_parent_function_or_class,
is_rpar_token,
is_stub_body,
is_stub_suite,
Expand Down Expand Up @@ -170,8 +170,12 @@ def visit_test(self, node: Node) -> Iterator[Line]:
)

if not already_parenthesized:
# Similar to logic in wrap_in_parentheses
lpar = Leaf(token.LPAR, "")
rpar = Leaf(token.RPAR, "")
prefix = node.prefix
node.prefix = ""
lpar.prefix = prefix
node.insert_child(0, lpar)
node.append_child(rpar)

Expand Down Expand Up @@ -241,6 +245,7 @@ def visit_dictsetmaker(self, node: Node) -> Iterator[Line]:
if (
child.type == syms.atom
and child.children[0].type in OPENING_BRACKETS
and not is_walrus_assignment(child)
):
maybe_make_parens_invisible_in_atom(
child,
Expand Down Expand Up @@ -304,7 +309,7 @@ def visit_simple_stmt(self, node: Node) -> Iterator[Line]:

if node.parent and node.parent.type in STATEMENT:
if Preview.dummy_implementations in self.mode:
condition = is_function_or_class(node.parent)
condition = is_parent_function_or_class(node)
else:
condition = self.mode.is_pyi
if condition and is_stub_body(node):
Expand Down
36 changes: 15 additions & 21 deletions src/black/lines.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
TEST_DESCENDANTS,
child_towards,
is_docstring,
is_funcdef,
is_import,
is_multiline_string,
is_one_sequence_between,
Expand Down Expand Up @@ -92,7 +91,7 @@ def append(
if self.mode.magic_trailing_comma:
if self.has_magic_trailing_comma(leaf):
self.magic_trailing_comma = leaf
elif self.has_magic_trailing_comma(leaf, ensure_removable=True):
elif self.has_magic_trailing_comma(leaf):
self.remove_trailing_comma()
if not self.append_comment(leaf):
self.leaves.append(leaf)
Expand Down Expand Up @@ -343,16 +342,11 @@ def contains_unsplittable_type_ignore(self) -> bool:
def contains_multiline_strings(self) -> bool:
return any(is_multiline_string(leaf) for leaf in self.leaves)

def has_magic_trailing_comma(
self, closing: Leaf, ensure_removable: bool = False
) -> bool:
def has_magic_trailing_comma(self, closing: Leaf) -> bool:
"""Return True if we have a magic trailing comma, that is when:
- there's a trailing comma here
- it's not from single-element square bracket indexing
- it's not a one-tuple
- it's not a single-element subscript
Additionally, if ensure_removable:
- it's not from square bracket indexing
(specifically, single-element square bracket indexing)
"""
if not (
closing.type in CLOSING_BRACKETS
Expand All @@ -376,6 +370,8 @@ def has_magic_trailing_comma(
brackets=(token.LSQB, token.RSQB),
)
):
assert closing.prev_sibling is not None
assert closing.prev_sibling.type == syms.subscriptlist
return False

return True
Expand Down Expand Up @@ -644,15 +640,15 @@ def _maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
if previous_def is not None:
assert self.previous_line is not None
if self.mode.is_pyi:
if depth and not current_line.is_def and self.previous_line.is_def:
# Empty lines between attributes and methods should be preserved.
before = 1 if user_had_newline else 0
elif (
if (
Preview.blank_line_after_nested_stub_class in self.mode
and previous_def.is_class
and not previous_def.is_stub_class
):
before = 1
elif depth and not current_line.is_def and self.previous_line.is_def:
# Empty lines between attributes and methods should be preserved.
before = 1 if user_had_newline else 0
elif depth:
before = 0
else:
Expand Down Expand Up @@ -708,13 +704,8 @@ def _maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
is_empty_first_line_ok = (
Preview.allow_empty_first_line_in_block in current_line.mode
and (
not is_docstring(current_line.leaves[0], current_line.mode)
or (
self.previous_line
and self.previous_line.leaves[0]
and self.previous_line.leaves[0].parent
and not is_funcdef(self.previous_line.leaves[0].parent)
)
not current_line.is_docstring
or (self.previous_line and not self.previous_line.is_def)
)
)

Expand Down Expand Up @@ -745,7 +736,10 @@ def _maybe_empty_lines_for_class_or_def( # noqa: C901
if self.previous_line.depth < current_line.depth and (
self.previous_line.is_class or self.previous_line.is_def
):
return 0, 0
if self.mode.is_pyi or not Preview.allow_empty_first_line_in_block:
return 0, 0
else:
return 1 if user_had_newline else 0, 0

comment_to_add_newlines: Optional[LinesBlock] = None
if (
Expand Down
9 changes: 6 additions & 3 deletions src/black/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -742,8 +742,11 @@ def is_multiline_string(leaf: Leaf) -> bool:
return has_triple_quotes(leaf.value) and "\n" in leaf.value


def is_funcdef(node: Node) -> bool:
return node.type == syms.funcdef
def is_parent_function_or_class(node: Node) -> bool:
assert node.type in {syms.suite, syms.simple_stmt}
assert node.parent is not None
# Note this works for suites / simple_stmts in async def as well
return node.parent.type in {syms.funcdef, syms.classdef}


def is_function_or_class(node: Node) -> bool:
Expand All @@ -755,7 +758,7 @@ def is_stub_suite(node: Node, mode: Mode) -> bool:
if (
node.parent is not None
and Preview.dummy_implementations in mode
and not is_function_or_class(node.parent)
and not is_parent_function_or_class(node)
):
return False

Expand Down
1 change: 1 addition & 0 deletions tests/data/cases/class_blank_parentheses.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def test_func(self):


class ClassWithEmptyFunc(object):

def func_with_blank_parentheses():
return 5

Expand Down
42 changes: 42 additions & 0 deletions tests/data/cases/conditional_expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,28 @@ def something():
else ValuesListIterable
)


def foo(wait: bool = True):
# This comment is two
# lines long

# This is only one
time.sleep(1) if wait else None
time.sleep(1) if wait else None

# With newline above
time.sleep(1) if wait else None
# Without newline above
time.sleep(1) if wait else None


a = "".join(
(
"", # comment
"" if True else "",
)
)

# output

long_kwargs_single_line = my_function(
Expand Down Expand Up @@ -159,3 +181,23 @@ def something():
if named
else FlatValuesListIterable if flat else ValuesListIterable
)


def foo(wait: bool = True):
# This comment is two
# lines long

# This is only one
time.sleep(1) if wait else None
time.sleep(1) if wait else None

# With newline above
time.sleep(1) if wait else None
# Without newline above
time.sleep(1) if wait else None


a = "".join((
"", # comment
"" if True else "",
))
27 changes: 26 additions & 1 deletion tests/data/cases/nested_stub.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,18 @@ def function_definition(self): ...
assignment = 1
def f2(self) -> str: ...


class TopLevel:
class Nested1:
foo: int
def bar(self): ...
field = 1

class Nested2:
def bar(self): ...
foo: int
field = 1

# output

import sys
Expand All @@ -41,4 +53,17 @@ def f1(self) -> str: ...
def function_definition(self): ...
assignment = 1

def f2(self) -> str: ...
def f2(self) -> str: ...

class TopLevel:
class Nested1:
foo: int
def bar(self): ...

field = 1

class Nested2:
def bar(self): ...
foo: int

field = 1
Loading

0 comments on commit bf616a8

Please sign in to comment.