Unify docstring detection (#4095)

Co-authored-by: hauntsaninja <hauntsaninja@gmail.com>
This commit is contained in:
Jelle Zijlstra 2023-12-27 22:59:30 -08:00 committed by GitHub
parent bf6cabc804
commit db9c592967
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 37 additions and 7 deletions

View File

@ -14,6 +14,7 @@
<!-- Changes that affect Black's preview style --> <!-- Changes that affect Black's preview style -->
- Format module docstrings the same as class and function docstrings (#4095)
- Fix bug where spaces were not added around parenthesized walruses in subscripts, - Fix bug where spaces were not added around parenthesized walruses in subscripts,
unlike other binary operators (#4109) unlike other binary operators (#4109)

View File

@ -424,7 +424,7 @@ def visit_STRING(self, leaf: Leaf) -> Iterator[Line]:
if Preview.hex_codes_in_unicode_sequences in self.mode: if Preview.hex_codes_in_unicode_sequences in self.mode:
normalize_unicode_escape_sequences(leaf) normalize_unicode_escape_sequences(leaf)
if is_docstring(leaf) and not re.search(r"\\\s*\n", leaf.value): if is_docstring(leaf, self.mode) and not re.search(r"\\\s*\n", leaf.value):
# We're ignoring docstrings with backslash newline escapes because changing # We're ignoring docstrings with backslash newline escapes because changing
# indentation of those changes the AST representation of the code. # indentation of those changes the AST representation of the code.
if self.mode.string_normalization: if self.mode.string_normalization:
@ -477,7 +477,7 @@ def visit_STRING(self, leaf: Leaf) -> Iterator[Line]:
quote = quote_char * quote_len quote = quote_char * quote_len
# It's invalid to put closing single-character quotes on a new line. # It's invalid to put closing single-character quotes on a new line.
if self.mode and quote_len == 3: if quote_len == 3:
# We need to find the length of the last line of the docstring # We need to find the length of the last line of the docstring
# to find if we can add the closing quotes to the line without # to find if we can add the closing quotes to the line without
# exceeding the maximum line length. # exceeding the maximum line length.

View File

@ -196,7 +196,7 @@ def is_class_paren_empty(self) -> bool:
) )
@property @property
def is_triple_quoted_string(self) -> bool: def _is_triple_quoted_string(self) -> bool:
"""Is the line a triple quoted string?""" """Is the line a triple quoted string?"""
if not self or self.leaves[0].type != token.STRING: if not self or self.leaves[0].type != token.STRING:
return False return False
@ -209,6 +209,13 @@ def is_triple_quoted_string(self) -> bool:
return True return True
return False return False
@property
def is_docstring(self) -> bool:
"""Is the line a docstring?"""
if Preview.unify_docstring_detection not in self.mode:
return self._is_triple_quoted_string
return bool(self) and is_docstring(self.leaves[0], self.mode)
@property @property
def is_chained_assignment(self) -> bool: def is_chained_assignment(self) -> bool:
"""Is the line a chained assignment""" """Is the line a chained assignment"""
@ -583,7 +590,7 @@ def maybe_empty_lines(self, current_line: Line) -> LinesBlock:
and self.previous_block and self.previous_block
and self.previous_block.previous_block is None and self.previous_block.previous_block is None
and len(self.previous_block.original_line.leaves) == 1 and len(self.previous_block.original_line.leaves) == 1
and self.previous_block.original_line.is_triple_quoted_string and self.previous_block.original_line.is_docstring
and not (current_line.is_class or current_line.is_def) and not (current_line.is_class or current_line.is_def)
): ):
before = 1 before = 1
@ -690,7 +697,7 @@ def _maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
if ( if (
self.previous_line self.previous_line
and self.previous_line.is_class and self.previous_line.is_class
and current_line.is_triple_quoted_string and current_line.is_docstring
): ):
if Preview.no_blank_line_before_class_docstring in current_line.mode: if Preview.no_blank_line_before_class_docstring in current_line.mode:
return 0, 1 return 0, 1
@ -701,7 +708,7 @@ def _maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
is_empty_first_line_ok = ( is_empty_first_line_ok = (
Preview.allow_empty_first_line_in_block in current_line.mode Preview.allow_empty_first_line_in_block in current_line.mode
and ( and (
not is_docstring(current_line.leaves[0]) not is_docstring(current_line.leaves[0], current_line.mode)
or ( or (
self.previous_line self.previous_line
and self.previous_line.leaves[0] and self.previous_line.leaves[0]

View File

@ -195,6 +195,7 @@ class Preview(Enum):
single_line_format_skip_with_multiple_comments = auto() single_line_format_skip_with_multiple_comments = auto()
long_case_block_line_splitting = auto() long_case_block_line_splitting = auto()
allow_form_feeds = auto() allow_form_feeds = auto()
unify_docstring_detection = auto()
respect_east_asian_width = auto() respect_east_asian_width = auto()

View File

@ -531,7 +531,7 @@ def is_arith_like(node: LN) -> bool:
} }
def is_docstring(leaf: Leaf) -> bool: def is_docstring(leaf: Leaf, mode: Mode) -> bool:
if leaf.type != token.STRING: if leaf.type != token.STRING:
return False return False
@ -539,6 +539,16 @@ def is_docstring(leaf: Leaf) -> bool:
if set(prefix).intersection("bBfF"): if set(prefix).intersection("bBfF"):
return False return False
if (
Preview.unify_docstring_detection in mode
and leaf.parent
and leaf.parent.type == syms.simple_stmt
and not leaf.parent.prev_sibling
and leaf.parent.parent
and leaf.parent.parent.type == syms.file_input
):
return True
if prev_siblings_are( if prev_siblings_are(
leaf.parent, [None, token.NEWLINE, token.INDENT, syms.simple_stmt] leaf.parent, [None, token.NEWLINE, token.INDENT, syms.simple_stmt]
): ):

View File

@ -63,6 +63,8 @@ def lines_with_leading_tabs_expanded(s: str) -> List[str]:
) )
else: else:
lines.append(line) lines.append(line)
if s.endswith("\n"):
lines.append("")
return lines return lines

View File

@ -1,6 +1,7 @@
# flags: --preview # flags: --preview
"""I am a very helpful module docstring. """I am a very helpful module docstring.
With trailing spaces:
Lorem ipsum dolor sit amet, consectetur adipiscing elit, Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, Ut enim ad minim veniam,
@ -38,6 +39,7 @@
# output # output
"""I am a very helpful module docstring. """I am a very helpful module docstring.
With trailing spaces:
Lorem ipsum dolor sit amet, consectetur adipiscing elit, Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, Ut enim ad minim veniam,

View File

@ -29,6 +29,9 @@ class MultilineDocstringsAsWell:
and on so many lines... and on so many lines...
""" """
class SingleQuotedDocstring:
"I'm a docstring but I don't even get triple quotes."
# output # output
@ -57,3 +60,7 @@ class MultilineDocstringsAsWell:
and on so many lines... and on so many lines...
""" """
class SingleQuotedDocstring:
"I'm a docstring but I don't even get triple quotes."