Actually disable docstring prefix normalization with -S + fix instability (#3168)
The former was a regression I introduced a long time ago. To avoid changing the stable style too much, the regression is only fixed if --preview is enabled Annoyingly enough, as we currently always enforce a second format pass if changes were made, there's no good way to prove the existence of the docstring quote normalization instability issue. For posterity, here's one failing example: --- source +++ first pass @@ -1,7 +1,7 @@ def some_function(self): - ''''<text here> + """ '<text here> <text here, since without another non-empty line black is stable> - ''' + """ pass --- first pass +++ second pass @@ -1,7 +1,7 @@ def some_function(self): - """ '<text here> + """'<text here> <text here, since without another non-empty line black is stable> """ pass Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
This commit is contained in:
parent
9aa33f467b
commit
ad5c315dda
@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
- Single-character closing docstring quotes are no longer moved to their own line as
|
- Single-character closing docstring quotes are no longer moved to their own line as
|
||||||
this is invalid. This was a bug introduced in version 22.6.0. (#3166)
|
this is invalid. This was a bug introduced in version 22.6.0. (#3166)
|
||||||
|
- `--skip-string-normalization` / `-S` now prevents docstring prefixes from being
|
||||||
|
normalized as expected (#3168)
|
||||||
|
|
||||||
### _Blackd_
|
### _Blackd_
|
||||||
|
|
||||||
|
@ -293,7 +293,24 @@ def visit_STRING(self, leaf: Leaf) -> Iterator[Line]:
|
|||||||
if is_docstring(leaf) and "\\\n" not in leaf.value:
|
if is_docstring(leaf) and "\\\n" not in 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.
|
||||||
docstring = normalize_string_prefix(leaf.value)
|
if Preview.normalize_docstring_quotes_and_prefixes_properly in self.mode:
|
||||||
|
# There was a bug where --skip-string-normalization wouldn't stop us
|
||||||
|
# from normalizing docstring prefixes. To maintain stability, we can
|
||||||
|
# only address this buggy behaviour while the preview style is enabled.
|
||||||
|
if self.mode.string_normalization:
|
||||||
|
docstring = normalize_string_prefix(leaf.value)
|
||||||
|
# visit_default() does handle string normalization for us, but
|
||||||
|
# since this method acts differently depending on quote style (ex.
|
||||||
|
# see padding logic below), there's a possibility for unstable
|
||||||
|
# formatting as visit_default() is called *after*. To avoid a
|
||||||
|
# situation where this function formats a docstring differently on
|
||||||
|
# the second pass, normalize it early.
|
||||||
|
docstring = normalize_string_quotes(docstring)
|
||||||
|
else:
|
||||||
|
docstring = leaf.value
|
||||||
|
else:
|
||||||
|
# ... otherwise, we'll keep the buggy behaviour >.<
|
||||||
|
docstring = normalize_string_prefix(leaf.value)
|
||||||
prefix = get_string_prefix(docstring)
|
prefix = get_string_prefix(docstring)
|
||||||
docstring = docstring[len(prefix) :] # Remove the prefix
|
docstring = docstring[len(prefix) :] # Remove the prefix
|
||||||
quote_char = docstring[0]
|
quote_char = docstring[0]
|
||||||
|
@ -145,12 +145,13 @@ def supports_feature(target_versions: Set[TargetVersion], feature: Feature) -> b
|
|||||||
class Preview(Enum):
|
class Preview(Enum):
|
||||||
"""Individual preview style features."""
|
"""Individual preview style features."""
|
||||||
|
|
||||||
string_processing = auto()
|
|
||||||
remove_redundant_parens = auto()
|
|
||||||
one_element_subscript = auto()
|
|
||||||
annotation_parens = auto()
|
annotation_parens = auto()
|
||||||
long_docstring_quotes_on_newline = auto()
|
long_docstring_quotes_on_newline = auto()
|
||||||
|
normalize_docstring_quotes_and_prefixes_properly = auto()
|
||||||
|
one_element_subscript = auto()
|
||||||
remove_block_trailing_newline = auto()
|
remove_block_trailing_newline = auto()
|
||||||
|
remove_redundant_parens = auto()
|
||||||
|
string_processing = auto()
|
||||||
|
|
||||||
|
|
||||||
class Deprecated(UserWarning):
|
class Deprecated(UserWarning):
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
def do_not_touch_this_prefix():
|
||||||
|
R"""There was a bug where docstring prefixes would be normalized even with -S."""
|
||||||
|
|
||||||
|
|
||||||
|
def do_not_touch_this_prefix2():
|
||||||
|
F'There was a bug where docstring prefixes would be normalized even with -S.'
|
||||||
|
|
||||||
|
|
||||||
|
def do_not_touch_this_prefix3():
|
||||||
|
uR'''There was a bug where docstring prefixes would be normalized even with -S.'''
|
@ -209,6 +209,13 @@ def multiline_docstring_at_line_limit():
|
|||||||
second line----------------------------------------------------------------------"""
|
second line----------------------------------------------------------------------"""
|
||||||
|
|
||||||
|
|
||||||
|
def stable_quote_normalization_with_immediate_inner_single_quote(self):
|
||||||
|
''''<text here>
|
||||||
|
|
||||||
|
<text here, since without another non-empty line black is stable>
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
# output
|
# output
|
||||||
|
|
||||||
class MyClass:
|
class MyClass:
|
||||||
@ -417,3 +424,10 @@ def multiline_docstring_at_line_limit():
|
|||||||
"""first line-----------------------------------------------------------------------
|
"""first line-----------------------------------------------------------------------
|
||||||
|
|
||||||
second line----------------------------------------------------------------------"""
|
second line----------------------------------------------------------------------"""
|
||||||
|
|
||||||
|
|
||||||
|
def stable_quote_normalization_with_immediate_inner_single_quote(self):
|
||||||
|
"""'<text here>
|
||||||
|
|
||||||
|
<text here, since without another non-empty line black is stable>
|
||||||
|
"""
|
||||||
|
@ -139,6 +139,18 @@ def test_docstring_no_string_normalization() -> None:
|
|||||||
assert_format(source, expected, mode)
|
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
|
||||||
|
enabled.
|
||||||
|
"""
|
||||||
|
source, expected = read_data(
|
||||||
|
"miscellaneous", "docstring_preview_no_string_normalization"
|
||||||
|
)
|
||||||
|
mode = replace(DEFAULT_MODE, string_normalization=False, preview=True)
|
||||||
|
assert_format(source, expected, mode)
|
||||||
|
|
||||||
|
|
||||||
def test_long_strings_flag_disabled() -> None:
|
def test_long_strings_flag_disabled() -> None:
|
||||||
"""Tests for turning off the string processing logic."""
|
"""Tests for turning off the string processing logic."""
|
||||||
source, expected = read_data("miscellaneous", "long_strings_flag_disabled")
|
source, expected = read_data("miscellaneous", "long_strings_flag_disabled")
|
||||||
|
Loading…
Reference in New Issue
Block a user