Skip to content

Commit 77f16a7

Browse files
authored
Fix bug where module docstrings would be treated as normal strings if preceded by comments (#4764)
1 parent 4a8e6b7 commit 77f16a7

File tree

7 files changed

+60
-9
lines changed

7 files changed

+60
-9
lines changed

CHANGES.md

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

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

17+
- Fix bug where module docstrings would be treated as normal strings if preceeded by
18+
comments (#4764)
19+
1720
### Configuration
1821

1922
<!-- Changes to how Black can be configured -->

docs/the_black_code_style/future_style.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ Currently, the following features are included in the preview style:
3535
types in `except` and `except*` without `as`. See PEP 758 for details.
3636
- `normalize_cr_newlines`: Add `\r` style newlines to the potential newlines to
3737
normalize file newlines both from and to.
38+
- `fix_module_docstring_detection`: Fix module docstrings being treated as normal
39+
strings if preceeded by comments.
3840

3941
(labels/unstable-features)=
4042

src/black/lines.py

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -559,15 +559,20 @@ def maybe_empty_lines(self, current_line: Line) -> LinesBlock:
559559
before, after = self._maybe_empty_lines(current_line)
560560
previous_after = self.previous_block.after if self.previous_block else 0
561561
before = max(0, before - previous_after)
562-
if (
562+
if Preview.fix_module_docstring_detection in self.mode:
563563
# Always have one empty line after a module docstring
564-
self.previous_block
565-
and self.previous_block.previous_block is None
566-
and len(self.previous_block.original_line.leaves) == 1
567-
and self.previous_block.original_line.is_docstring
568-
and not (current_line.is_class or current_line.is_def)
569-
):
570-
before = 1
564+
if self._line_is_module_docstring(current_line):
565+
before = 1
566+
else:
567+
if (
568+
# Always have one empty line after a module docstring
569+
self.previous_block
570+
and self.previous_block.previous_block is None
571+
and len(self.previous_block.original_line.leaves) == 1
572+
and self.previous_block.original_line.is_docstring
573+
and not (current_line.is_class or current_line.is_def)
574+
):
575+
before = 1
571576

572577
block = LinesBlock(
573578
mode=self.mode,
@@ -595,6 +600,22 @@ def maybe_empty_lines(self, current_line: Line) -> LinesBlock:
595600
self.previous_block = block
596601
return block
597602

603+
def _line_is_module_docstring(self, current_line: Line) -> bool:
604+
previous_block = self.previous_block
605+
if not previous_block:
606+
return False
607+
if (
608+
len(previous_block.original_line.leaves) != 1
609+
or not previous_block.original_line.is_docstring
610+
or current_line.is_class
611+
or current_line.is_def
612+
):
613+
return False
614+
while previous_block := previous_block.previous_block:
615+
if not previous_block.original_line.is_comment:
616+
return False
617+
return True
618+
598619
def _maybe_empty_lines(self, current_line: Line) -> tuple[int, int]: # noqa: C901
599620
max_allowed = 1
600621
if current_line.depth == 0:

src/black/mode.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ class Preview(Enum):
236236
# except* without as. See PEP 758 for details.
237237
remove_parens_around_except_types = auto()
238238
normalize_cr_newlines = auto()
239+
fix_module_docstring_detection = auto()
239240

240241

241242
UNSTABLE_FEATURES: set[Preview] = {

src/black/resources/black.schema.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@
8888
"fix_fmt_skip_in_one_liners",
8989
"wrap_comprehension_in",
9090
"remove_parens_around_except_types",
91-
"normalize_cr_newlines"
91+
"normalize_cr_newlines",
92+
"fix_module_docstring_detection"
9293
]
9394
},
9495
"description": "Enable specific features included in the `--unstable` style. Requires `--preview`. No compatibility guarantees are provided on the behavior or existence of any unstable features."

src/blib2to3/pgen2/parse.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
how this parsing engine works.
1010
1111
"""
12+
1213
from collections.abc import Callable, Iterator
1314
from contextlib import contextmanager
1415
from typing import TYPE_CHECKING, Any, Optional, Union, cast
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# flags: --preview
2+
#!/python
3+
4+
# regression test for #4762
5+
"""
6+
docstring
7+
"""
8+
from __future__ import annotations
9+
10+
import os
11+
12+
# output
13+
#!/python
14+
15+
# regression test for #4762
16+
"""
17+
docstring
18+
"""
19+
20+
from __future__ import annotations
21+
22+
import os

0 commit comments

Comments
 (0)