Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix an infinite loop when using #fmt: on/off in the middle of an expression or code block #3158

Merged
merged 9 commits into from Jul 20, 2022
2 changes: 2 additions & 0 deletions CHANGES.md
Expand Up @@ -10,6 +10,8 @@

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

- Fix an infinite loop when using `# fmt: on/off` in the middle of an expression or code
block (#3158)
- Fix incorrect handling of `# fmt: skip` on colon `:` lines. (#3148)
- Comments are no longer deleted when a line had spaces removed around power operators
(#2874)
Expand Down
10 changes: 9 additions & 1 deletion src/black/comments.py
Expand Up @@ -13,7 +13,7 @@
from blib2to3.pgen2 import token

from black.nodes import first_leaf_column, preceding_leaf, container_of
from black.nodes import STANDALONE_COMMENT, WHITESPACE
from black.nodes import CLOSING_BRACKETS, STANDALONE_COMMENT, WHITESPACE

# types
LN = Union[Leaf, Node]
Expand Down Expand Up @@ -227,6 +227,14 @@ def generate_ignored_nodes(
# fix for fmt: on in children
if contains_fmt_on_at_column(container, leaf.column, preview=preview):
for child in container.children:
if isinstance(child, Leaf) and is_fmt_on(child, preview=preview):
if child.type in CLOSING_BRACKETS:
# This means `# fmt: on` is placed at a different bracket level
# than `# fmt: off`. This is an invalid use, but as a courtesy,
# we include this closing bracket in the ignored nodes.
# The alternative is to fail the formatting.
yield child
return
if contains_fmt_on_at_column(child, leaf.column, preview=preview):
return
yield child
Expand Down
36 changes: 36 additions & 0 deletions tests/data/simple_cases/fmtonoff5.py
@@ -0,0 +1,36 @@
# Regression test for https://github.com/psf/black/issues/3129.
setup(
entry_points={
# fmt: off
"console_scripts": [
"foo-bar"
"=foo.bar.:main",
# fmt: on
] # Includes an formatted indentation.
},
)


# Regression test for https://github.com/psf/black/issues/2015.
run(
# fmt: off
[
"ls",
"-la",
]
# fmt: on
+ path,
check=True,
)


# Regression test for https://github.com/psf/black/issues/3026.
def test_func():
# yapf: disable
if unformatted( args ):
return True
# yapf: enable
elif b:
return True

return False