]> git.madduck.net Git - etc/vim.git/commitdiff

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Actually disable docstring prefix normalization with -S + fix instability (#3168)
authorRichard Si <63936253+ichard26@users.noreply.github.com>
Thu, 14 Jul 2022 23:47:33 +0000 (19:47 -0400)
committerGitHub <noreply@github.com>
Thu, 14 Jul 2022 23:47:33 +0000 (19:47 -0400)
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>
CHANGES.md
src/black/linegen.py
src/black/mode.py
tests/data/miscellaneous/docstring_preview_no_string_normalization.py [new file with mode: 0644]
tests/data/simple_cases/docstring.py
tests/test_format.py

index 7d2e0bc09d1e7e8b0f4ea3fd863849df0f431413..8543a8dbfe09da072b82f86d5092746e4f5ac5a4 100644 (file)
@@ -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_
 
index 20f3ac6fffb1524b014f1dd43435630c073c6b85..1f132b7888fe9a07fda7ad738a198d70e0e4e0a4 100644 (file)
@@ -293,7 +293,24 @@ class LineGenerator(Visitor[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]
index 896c516df79e16967744fd083436644a473f56d9..b7359fab213d29bfe8fe0b1ecdebc67cade79f6a 100644 (file)
@@ -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):
diff --git a/tests/data/miscellaneous/docstring_preview_no_string_normalization.py b/tests/data/miscellaneous/docstring_preview_no_string_normalization.py
new file mode 100644 (file)
index 0000000..0957231
--- /dev/null
@@ -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.'''
index 7153be468c112963806ea2a7623717b1c3a88b7b..f08bba575fea03bc734e1fbe6457d9c58c2bbc0c 100644 (file)
@@ -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>
+    """
index 0e1059c61e4aa16aa41532d8c32a9224bac87a8b..86339f24b864e153b70b7d0f32e75dea6b4f7ac4 100644 (file)
@@ -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")