Skip to content

Commit efad911

Browse files
HWKDSpre-commit-ci[bot]cobaltt7
authored
Fix comments being removed before fmt:off/on blocks (#4845)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: cobalt <[email protected]>
1 parent 0c3d2ac commit efad911

File tree

4 files changed

+71
-4
lines changed

4 files changed

+71
-4
lines changed

CHANGES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515

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

18+
- Fix bug where comments preceding `# fmt: off`/`# fmt: on` blocks were incorrectly
19+
removed, particularly affecting Jupytext's `# %% [markdown]` comments (#4845)
20+
1821
### Preview style
1922

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

src/black/comments.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,9 +281,18 @@ def _handle_comment_only_fmt_block(
281281
if hidden_value.endswith("\n"):
282282
hidden_value = hidden_value[:-1]
283283

284-
# Build the standalone comment prefix
284+
# Build the standalone comment prefix - preserve all content before fmt:off
285+
# including any comments that precede it
286+
if fmt_off_idx == 0:
287+
# No comments before fmt:off, use previous_consumed
288+
pre_fmt_off_consumed = previous_consumed
289+
else:
290+
# Use the consumed position of the last comment before fmt:off
291+
# This preserves all comments and content before the fmt:off directive
292+
pre_fmt_off_consumed = all_comments[fmt_off_idx - 1].consumed
293+
285294
standalone_comment_prefix = (
286-
original_prefix[:previous_consumed] + "\n" * comment.newlines
295+
original_prefix[:pre_fmt_off_consumed] + "\n" * comment.newlines
287296
)
288297

289298
fmt_off_prefix = original_prefix.split(comment.value)[0]
@@ -326,6 +335,15 @@ def convert_one_fmt_off_pair(
326335
Returns True if a pair was converted.
327336
"""
328337
for leaf in node.leaves():
338+
# Skip STANDALONE_COMMENT nodes that were created by fmt:off/on processing
339+
# to avoid reprocessing them in subsequent iterations
340+
if (
341+
leaf.type == STANDALONE_COMMENT
342+
and hasattr(leaf, "fmt_pass_converted_first_leaf")
343+
and leaf.fmt_pass_converted_first_leaf is None
344+
):
345+
continue
346+
329347
previous_consumed = 0
330348
for comment in list_comments(leaf.prefix, is_endmarker=False, mode=mode):
331349
should_process, is_fmt_off, is_fmt_skip = _should_process_fmt_comment(

src/black/linegen.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,13 @@
1717
get_leaves_inside_matching_brackets,
1818
max_delimiter_priority_in_atom,
1919
)
20-
from black.comments import FMT_OFF, FMT_ON, generate_comments, list_comments
20+
from black.comments import (
21+
FMT_OFF,
22+
FMT_ON,
23+
_contains_fmt_directive,
24+
generate_comments,
25+
list_comments,
26+
)
2127
from black.lines import (
2228
Line,
2329
RHSResult,
@@ -405,7 +411,23 @@ def visit_STANDALONE_COMMENT(self, leaf: Leaf) -> Iterator[Line]:
405411
else:
406412
is_fmt_off_block = False
407413
if is_fmt_off_block:
408-
# This is a fmt:off/on block from normalize_fmt_off - append directly
414+
# This is a fmt:off/on block from normalize_fmt_off - we still need
415+
# to process any prefix comments (like markdown comments) but append
416+
# the fmt block itself directly to preserve its formatting
417+
418+
# Only process prefix comments if there actually is a prefix with comments
419+
if leaf.prefix and any(
420+
line.strip().startswith("#")
421+
and not _contains_fmt_directive(line.strip())
422+
for line in leaf.prefix.split("\n")
423+
):
424+
for comment in generate_comments(leaf, mode=self.mode):
425+
yield from self.line()
426+
self.current_line.append(comment)
427+
yield from self.line()
428+
# Clear the prefix since we've processed it as comments above
429+
leaf.prefix = ""
430+
409431
self.current_line.append(leaf)
410432
yield from self.line()
411433
else:
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Test that Jupytext markdown comments are preserved before fmt:off/on blocks
2+
# %% [markdown]
3+
4+
# fmt: off
5+
# fmt: on
6+
7+
# Also test with other comments
8+
# Some comment
9+
# %% [markdown]
10+
# Another comment
11+
12+
# fmt: off
13+
x = 1
14+
# fmt: on
15+
16+
# Test multiple markdown comments
17+
# %% [markdown]
18+
# First markdown
19+
# %% [code]
20+
# Code cell
21+
22+
# fmt: off
23+
y = 2
24+
# fmt: on

0 commit comments

Comments
 (0)