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
|
||||
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_
|
||||
|
||||
|
@ -293,7 +293,24 @@ def visit_STRING(self, leaf: Leaf) -> Iterator[Line]:
|
||||
if is_docstring(leaf) and "\\\n" not in leaf.value:
|
||||
# We're ignoring docstrings with backslash newline escapes because changing
|
||||
# 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)
|
||||
docstring = docstring[len(prefix) :] # Remove the prefix
|
||||
quote_char = docstring[0]
|
||||
|
@ -145,12 +145,13 @@ def supports_feature(target_versions: Set[TargetVersion], feature: Feature) -> b
|
||||
class Preview(Enum):
|
||||
"""Individual preview style features."""
|
||||
|
||||
string_processing = auto()
|
||||
remove_redundant_parens = auto()
|
||||
one_element_subscript = auto()
|
||||
annotation_parens = auto()
|
||||
long_docstring_quotes_on_newline = auto()
|
||||
normalize_docstring_quotes_and_prefixes_properly = auto()
|
||||
one_element_subscript = auto()
|
||||
remove_block_trailing_newline = auto()
|
||||
remove_redundant_parens = auto()
|
||||
string_processing = auto()
|
||||
|
||||
|
||||
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----------------------------------------------------------------------"""
|
||||
|
||||
|
||||
def stable_quote_normalization_with_immediate_inner_single_quote(self):
|
||||
''''<text here>
|
||||
|
||||
<text here, since without another non-empty line black is stable>
|
||||
'''
|
||||
|
||||
|
||||
# output
|
||||
|
||||
class MyClass:
|
||||
@ -417,3 +424,10 @@ def multiline_docstring_at_line_limit():
|
||||
"""first 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)
|
||||
|
||||
|
||||
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:
|
||||
"""Tests for turning off the string processing logic."""
|
||||
source, expected = read_data("miscellaneous", "long_strings_flag_disabled")
|
||||
|
Loading…
Reference in New Issue
Block a user