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 2 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 @@ -24,6 +24,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)

### Configuration

Expand Down
4 changes: 4 additions & 0 deletions src/black/linegen.py
Expand Up @@ -385,6 +385,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 @@ -397,6 +398,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 @@ -419,6 +421,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 string normalization off."""
JelleZijlstra marked this conversation as resolved.
Show resolved Hide resolved
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