From 60a2e8e2c26d6312cd86b40f680c5037571acafc Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Mon, 16 Jan 2023 12:26:03 -0800 Subject: [PATCH] Fix two docstring crashes (#3451) --- CHANGES.md | 1 + src/black/linegen.py | 4 ++++ tests/data/miscellaneous/linelength6.py | 5 +++++ tests/data/simple_cases/docstring.py | 11 +++++++++++ tests/test_format.py | 7 +++++++ 5 files changed, 28 insertions(+) create mode 100644 tests/data/miscellaneous/linelength6.py diff --git a/CHANGES.md b/CHANGES.md index 2da0fb4720c..17dc0d686df 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -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) diff --git a/src/black/linegen.py b/src/black/linegen.py index 4da75b28235..da41886f80d 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -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: @@ -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 = " " @@ -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: diff --git a/tests/data/miscellaneous/linelength6.py b/tests/data/miscellaneous/linelength6.py new file mode 100644 index 00000000000..4fb342726f5 --- /dev/null +++ b/tests/data/miscellaneous/linelength6.py @@ -0,0 +1,5 @@ +# Regression test for #3427, which reproes only with line length <= 6 +def f(): + """ + x + """ diff --git a/tests/data/simple_cases/docstring.py b/tests/data/simple_cases/docstring.py index f08bba575fe..c31d6a68783 100644 --- a/tests/data/simple_cases/docstring.py +++ b/tests/data/simple_cases/docstring.py @@ -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(): ''' @@ -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 \\""" diff --git a/tests/test_format.py b/tests/test_format.py index 01cd61eef63..0816bbd3692 100644 --- a/tests/test_format.py +++ b/tests/test_format.py @@ -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