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 two docstring crashes #3451

Merged
merged 4 commits into from Jan 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Expand Up @@ -32,6 +32,7 @@
- Long values in dict literals are now wrapped in parentheses; correspondingly
unnecessary parentheses around short values in dict literals are now removed; long
string lambda values are now wrapped in parentheses (#3440)
- Fix two crashes in preview style involving edge cases with docstrings (#3451)
- Exclude string type annotations from improved string processing; fix crash when the
return type annotation is stringified and spans across multiple lines (#3462)

Expand Down
4 changes: 4 additions & 0 deletions src/black/linegen.py
Expand Up @@ -401,6 +401,7 @@ def visit_STRING(self, leaf: Leaf) -> Iterator[Line]:
else:
docstring = docstring.strip()

has_trailing_backslash = False
if docstring:
# Add some padding if the docstring starts / ends with a quote mark.
if docstring[0] == quote_char:
Expand All @@ -413,6 +414,7 @@ def visit_STRING(self, leaf: Leaf) -> Iterator[Line]:
# Odd number of tailing backslashes, add some padding to
# avoid escaping the closing string quote.
docstring += " "
has_trailing_backslash = True
elif not docstring_started_empty:
docstring = " "

Expand All @@ -435,6 +437,8 @@ def visit_STRING(self, leaf: Leaf) -> Iterator[Line]:
if (
len(lines) > 1
and last_line_length + quote_len > self.mode.line_length
and len(indent) + quote_len <= self.mode.line_length
and not has_trailing_backslash
):
leaf.value = prefix + quote + docstring + "\n" + indent + quote
else:
Expand Down
5 changes: 5 additions & 0 deletions tests/data/miscellaneous/linelength6.py
@@ -0,0 +1,5 @@
# Regression test for #3427, which reproes only with line length <= 6
def f():
"""
x
"""
11 changes: 11 additions & 0 deletions tests/data/simple_cases/docstring.py
Expand Up @@ -173,6 +173,11 @@ def multiline_backslash_2():
'''
hey there \ '''

# Regression test for #3425
def multiline_backslash_really_long_dont_crash():
"""
hey there hello guten tag hi hoow are you ola zdravstvuyte ciao como estas ca va \ """


def multiline_backslash_3():
'''
Expand Down Expand Up @@ -391,6 +396,12 @@ def multiline_backslash_2():
hey there \ """


# Regression test for #3425
def multiline_backslash_really_long_dont_crash():
"""
hey there hello guten tag hi hoow are you ola zdravstvuyte ciao como estas ca va \ """


def multiline_backslash_3():
"""
already escaped \\"""
Expand Down
7 changes: 7 additions & 0 deletions tests/test_format.py
Expand Up @@ -146,6 +146,13 @@ def test_docstring_no_string_normalization() -> None:
assert_format(source, expected, mode)


def test_docstring_line_length_6() -> None:
"""Like test_docstring but with line length set to 6."""
source, expected = read_data("miscellaneous", "linelength6")
mode = black.Mode(line_length=6)
assert_format(source, expected, mode)


def test_preview_docstring_no_string_normalization() -> None:
"""
Like test_docstring but with string normalization off *and* the preview style
Expand Down