Skip to content

Commit

Permalink
Fix multiline docstring quote normalization
Browse files Browse the repository at this point in the history
The quotes of multiline docstrings are now only normalized when string
normalization is off, instead of the string normalization setting being
ignored and the quotes being *always* normalized.

I had to make a new test case and data file since the current pair for
docstrings only worked when there is no formatting difference between the
formatting results with string normalization on and off. I needed to add
tests for when there *are* differences between the two. So I split
test_docstring's test code when string normalization is disabled into a
new test case along with a new data file.
  • Loading branch information
ichard26 authored and ambv committed Aug 26, 2020
1 parent 5f78401 commit 7fe19fa
Show file tree
Hide file tree
Showing 5 changed files with 232 additions and 5 deletions.
7 changes: 7 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
## Change Log

### Unreleased

#### _Black_

- `Black` now respects `--skip-string-normalization` when normalizing multiline
docstring quotes (#1637)

### 20.8b1

#### _Packaging_
Expand Down
7 changes: 7 additions & 0 deletions docs/change_log.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

## Change Log

### Unreleased

#### _Black_

- `Black` now respects `--skip-string-normalization` when normalizing multiline
docstring quotes (#1637)

### 20.8b1

#### _Packaging_
Expand Down
1 change: 0 additions & 1 deletion src/black/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2049,7 +2049,6 @@ def visit_STRING(self, leaf: Leaf) -> Iterator[Line]:
if leaf.value[tail_len + 1] == docstring[-1]:
docstring = docstring + " "
leaf.value = leaf.value[0:lead_len] + docstring + leaf.value[tail_len:]
normalize_string_quotes(leaf)

yield from self.visit_default(leaf)

Expand Down
209 changes: 209 additions & 0 deletions tests/data/docstring_no_string_normalization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
class ALonelyClass:
'''
A multiline class docstring.
'''
def AnEquallyLonelyMethod(self):
'''
A multiline method docstring'''
pass


def one_function():
'''This is a docstring with a single line of text.'''
pass


def shockingly_the_quotes_are_normalized():
'''This is a multiline docstring.
This is a multiline docstring.
This is a multiline docstring.
'''
pass


def foo():
"""This is a docstring with
some lines of text here
"""
return


def baz():
'''"This" is a string with some
embedded "quotes"'''
return


def poit():
"""
Lorem ipsum dolor sit amet.
Consectetur adipiscing elit:
- sed do eiusmod tempor incididunt ut labore
- dolore magna aliqua
- enim ad minim veniam
- quis nostrud exercitation ullamco laboris nisi
- aliquip ex ea commodo consequat
"""
pass


def under_indent():
"""
These lines are indented in a way that does not
make sense.
"""
pass


def over_indent():
"""
This has a shallow indent
- But some lines are deeper
- And the closing quote is too deep
"""
pass


def single_line():
"""But with a newline after it!
"""
pass


def this():
r"""
'hey ho'
"""


def that():
""" "hey yah" """


def and_that():
"""
"hey yah" """


def and_this():
'''
"hey yah"'''


def believe_it_or_not_this_is_in_the_py_stdlib(): '''
"hey yah"'''


def shockingly_the_quotes_are_normalized_v2():
'''
Docstring Docstring Docstring
'''
pass

# output

class ALonelyClass:
'''
A multiline class docstring.
'''

def AnEquallyLonelyMethod(self):
'''
A multiline method docstring'''
pass


def one_function():
'''This is a docstring with a single line of text.'''
pass


def shockingly_the_quotes_are_normalized():
'''This is a multiline docstring.
This is a multiline docstring.
This is a multiline docstring.
'''
pass


def foo():
"""This is a docstring with
some lines of text here
"""
return


def baz():
'''"This" is a string with some
embedded "quotes"'''
return


def poit():
"""
Lorem ipsum dolor sit amet.
Consectetur adipiscing elit:
- sed do eiusmod tempor incididunt ut labore
- dolore magna aliqua
- enim ad minim veniam
- quis nostrud exercitation ullamco laboris nisi
- aliquip ex ea commodo consequat
"""
pass


def under_indent():
"""
These lines are indented in a way that does not
make sense.
"""
pass


def over_indent():
"""
This has a shallow indent
- But some lines are deeper
- And the closing quote is too deep
"""
pass


def single_line():
"""But with a newline after it!"""
pass


def this():
r"""
'hey ho'
"""


def that():
""" "hey yah" """


def and_that():
"""
"hey yah" """


def and_this():
'''
"hey yah"'''


def believe_it_or_not_this_is_in_the_py_stdlib():
'''
"hey yah"'''


def shockingly_the_quotes_are_normalized_v2():
'''
Docstring Docstring Docstring
'''
pass
13 changes: 9 additions & 4 deletions tests/test_black.py
Original file line number Diff line number Diff line change
Expand Up @@ -517,11 +517,16 @@ def test_docstring(self) -> None:
self.assertFormatEqual(expected, actual)
black.assert_equivalent(source, actual)
black.assert_stable(source, actual, DEFAULT_MODE)

@patch("black.dump_to_file", dump_to_stderr)
def test_docstring_no_string_normalization(self) -> None:
"""Like test_docstring but with string normalization off."""
source, expected = read_data("docstring_no_string_normalization")
mode = replace(DEFAULT_MODE, string_normalization=False)
not_normalized = fs(source, mode=mode)
self.assertFormatEqual(expected, not_normalized)
black.assert_equivalent(source, not_normalized)
black.assert_stable(source, not_normalized, mode=mode)
actual = fs(source, mode=mode)
self.assertFormatEqual(expected, actual)
black.assert_equivalent(source, actual)
black.assert_stable(source, actual, mode)

def test_long_strings(self) -> None:
"""Tests for splitting long strings."""
Expand Down

0 comments on commit 7fe19fa

Please sign in to comment.