]> git.madduck.net Git - etc/vim.git/blobdiff - black.py

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:

Fix multiline strings unnecessarily wrapped in optional parentheses
[etc/vim.git] / black.py
index f335ebd828402c6167719bf23d673aa99cb15ddf..298597bcb30f8aad947056fc8583327a75814d5e 100644 (file)
--- a/black.py
+++ b/black.py
@@ -626,21 +626,22 @@ LOGIC_PRIORITY = 14
 STRING_PRIORITY = 12
 COMPARATOR_PRIORITY = 10
 MATH_PRIORITIES = {
-    token.VBAR: 8,
-    token.CIRCUMFLEX: 7,
-    token.AMPER: 6,
-    token.LEFTSHIFT: 5,
-    token.RIGHTSHIFT: 5,
-    token.PLUS: 4,
-    token.MINUS: 4,
-    token.STAR: 3,
-    token.SLASH: 3,
-    token.DOUBLESLASH: 3,
-    token.PERCENT: 3,
-    token.AT: 3,
-    token.TILDE: 2,
-    token.DOUBLESTAR: 1,
+    token.VBAR: 9,
+    token.CIRCUMFLEX: 8,
+    token.AMPER: 7,
+    token.LEFTSHIFT: 6,
+    token.RIGHTSHIFT: 6,
+    token.PLUS: 5,
+    token.MINUS: 5,
+    token.STAR: 4,
+    token.SLASH: 4,
+    token.DOUBLESLASH: 4,
+    token.PERCENT: 4,
+    token.AT: 4,
+    token.TILDE: 3,
+    token.DOUBLESTAR: 2,
 }
+DOT_PRIORITY = 1
 
 
 @dataclass
@@ -1314,7 +1315,7 @@ class LineGenerator(Visitor[Line]):
         The relevant Python language `keywords` for a given statement will be
         NAME leaves within it. This methods puts those on a separate line.
 
-        `parens` holds a set of string leaf values immeditely after which
+        `parens` holds a set of string leaf values immediately after which
         invisible parens should be put.
         """
         normalize_invisible_parens(node, parens_after=parens)
@@ -1729,6 +1730,14 @@ def is_split_before_delimiter(leaf: Leaf, previous: Leaf = None) -> int:
         # Don't treat them as a delimiter.
         return 0
 
+    if (
+        leaf.type == token.DOT
+        and leaf.parent
+        and leaf.parent.type not in {syms.import_from, syms.dotted_name}
+        and (previous is None or previous.type != token.NAME)
+    ):
+        return DOT_PRIORITY
+
     if (
         leaf.type in MATH_OPERATORS
         and leaf.parent
@@ -1746,31 +1755,54 @@ def is_split_before_delimiter(leaf: Leaf, previous: Leaf = None) -> int:
     ):
         return STRING_PRIORITY
 
+    if leaf.type != token.NAME:
+        return 0
+
     if (
-        leaf.type == token.NAME
-        and leaf.value == "for"
+        leaf.value == "for"
         and leaf.parent
         and leaf.parent.type in {syms.comp_for, syms.old_comp_for}
     ):
         return COMPREHENSION_PRIORITY
 
     if (
-        leaf.type == token.NAME
-        and leaf.value == "if"
+        leaf.value == "if"
         and leaf.parent
         and leaf.parent.type in {syms.comp_if, syms.old_comp_if}
     ):
         return COMPREHENSION_PRIORITY
 
+    if leaf.value in {"if", "else"} and leaf.parent and leaf.parent.type == syms.test:
+        return TERNARY_PRIORITY
+
+    if leaf.value == "is":
+        return COMPARATOR_PRIORITY
+
     if (
-        leaf.type == token.NAME
-        and leaf.value in {"if", "else"}
+        leaf.value == "in"
         and leaf.parent
-        and leaf.parent.type == syms.test
+        and leaf.parent.type in {syms.comp_op, syms.comparison}
+        and not (
+            previous is not None
+            and previous.type == token.NAME
+            and previous.value == "not"
+        )
     ):
-        return TERNARY_PRIORITY
+        return COMPARATOR_PRIORITY
+
+    if (
+        leaf.value == "not"
+        and leaf.parent
+        and leaf.parent.type == syms.comp_op
+        and not (
+            previous is not None
+            and previous.type == token.NAME
+            and previous.value == "is"
+        )
+    ):
+        return COMPARATOR_PRIORITY
 
-    if leaf.type == token.NAME and leaf.value in LOGIC_OPERATORS and leaf.parent:
+    if leaf.value in LOGIC_OPERATORS and leaf.parent:
         return LOGIC_PRIORITY
 
     return 0
@@ -2105,6 +2137,10 @@ def delimiter_split(line: Line, py36: bool = False) -> Iterator[Line]:
     except ValueError:
         raise CannotSplit("No delimiters found")
 
+    if delimiter_priority == DOT_PRIORITY:
+        if bt.delimiter_count_with_priority(delimiter_priority) == 1:
+            raise CannotSplit("Splitting a single attribute from its owner looks wrong")
+
     current_line = Line(depth=line.depth, inside_brackets=line.inside_brackets)
     lowest_depth = sys.maxsize
     trailing_comma_safe = True
@@ -2325,7 +2361,7 @@ def normalize_invisible_parens(node: Node, parens_after: Set[str]) -> None:
                 rpar = Leaf(token.RPAR, ")")
                 index = child.remove() or 0
                 node.insert_child(index, Node(syms.atom, [lpar, child, rpar]))
-            else:
+            elif not (isinstance(child, Leaf) and is_multiline_string(child)):
                 # wrap child in invisible parentheses
                 lpar = Leaf(token.LPAR, "")
                 rpar = Leaf(token.RPAR, "")
@@ -2436,6 +2472,12 @@ def is_vararg(leaf: Leaf, within: Set[NodeType]) -> bool:
     return p.type in within
 
 
+def is_multiline_string(leaf: Leaf) -> bool:
+    """Return True if `leaf` is a multiline string that actually spans many lines."""
+    value = leaf.value.lstrip("furbFURB")
+    return value[:3] in {'"""', "'''"} and "\n" in value
+
+
 def is_stub_suite(node: Node) -> bool:
     """Return True if `node` is a suite with a stub body."""
     if (