]> 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:

Always explode data structure literals
authorŁukasz Langa <lukasz@langa.pl>
Thu, 17 May 2018 04:33:29 +0000 (21:33 -0700)
committerŁukasz Langa <lukasz@langa.pl>
Fri, 18 May 2018 00:32:43 +0000 (17:32 -0700)
Fixes #152

README.md
black.py
docs/reference/reference_functions.rst
tests/cantfit.py
tests/comments2.py
tests/expression.diff
tests/expression.py

index 475954f1461d2473e7a31c1b4dbf8247984b14b3..f58774428d03e8c287f483500ddefdaef4c15e64 100644 (file)
--- a/README.md
+++ b/README.md
@@ -131,13 +131,13 @@ brackets and put that in a separate indented line.
 ```py3
 # in:
 
-l = [[n for n in list_bosses()], [n for n in list_employees()]]
+TracebackException.from_exception(exc, limit, lookup_lines, capture_locals)
 
 # out:
 
-l = [
-    [n for n in list_bosses()], [n for n in list_employees()]
-]
+TracebackException.from_exception(
+    exc, limit, lookup_lines, capture_locals
+)
 ```
 
 If that still doesn't fit the bill, it will decompose the internal
@@ -176,13 +176,13 @@ between two distinct sections of the code that otherwise share the same
 indentation level (like the arguments list and the docstring in the
 example above).
 
-If a line of "from" imports cannot fit in the allotted length, it's always split
-into one per line.  Imports tend to change often and this minimizes diffs, as well
-as enables readers of code to easily find which commit introduced a particular
-import.  This exception also makes *Black* compatible with
-[isort](https://pypi.org/p/isort/).  Use `multi_line_output=3`,
-`include_trailing_comma=True`, `force_grid_wrap=0`, and `line_length=88` in your
-isort config.
+If a data structure literal (tuple, list, set, dict) or a line of "from"
+imports cannot fit in the allotted length, it's always split into one
+per line.  This minimizes diffs as well as enables readers of code to
+find which commit introduced a particular entry.  This also makes
+*Black* compatible with [isort](https://pypi.org/p/isort/).  Use
+`multi_line_output=3`, `include_trailing_comma=True`,
+`force_grid_wrap=0`, and `line_length=88` in your isort config.
 
 
 ### Line length
@@ -630,7 +630,13 @@ More details can be found in [CONTRIBUTING](CONTRIBUTING.md).
 
 ### 18.5a0 (unreleased)
 
-* call chains are now formatted according to the [fluent interfaces](https://en.wikipedia.org/wiki/Fluent_interface) style (#67)
+* call chains are now formatted according to the
+  [fluent interfaces](https://en.wikipedia.org/wiki/Fluent_interface)
+  style (#67)
+
+* data structure literals (tuples, lists, dictionaries, and sets) are
+  now also always exploded like imports when they don't fit in a single
+  line (#152)
 
 * slices are now formatted according to PEP 8 (#178)
 
index 298597bcb30f8aad947056fc8583327a75814d5e..c48b8d102f58cf2dfd1c9f9db97cf75f6f405af6 100644 (file)
--- a/black.py
+++ b/black.py
@@ -776,6 +776,7 @@ class Line:
     comments: List[Tuple[Index, Leaf]] = Factory(list)
     bracket_tracker: BracketTracker = Factory(BracketTracker)
     inside_brackets: bool = False
+    should_explode: bool = False
 
     def append(self, leaf: Leaf, preformatted: bool = False) -> None:
         """Add a new `leaf` to the end of the line.
@@ -1473,7 +1474,9 @@ def whitespace(leaf: Leaf, *, complex_subscript: bool) -> str:  # noqa C901
 
     assert p is not None, f"INTERNAL ERROR: hand-made leaf without parent: {leaf!r}"
     if t == token.COLON and p.type not in {
-        syms.subscript, syms.subscriptlist, syms.sliceop
+        syms.subscript,
+        syms.subscriptlist,
+        syms.sliceop,
     }:
         return NO
 
@@ -1495,7 +1498,10 @@ def whitespace(leaf: Leaf, *, complex_subscript: bool) -> str:  # noqa C901
         if prevp.type == token.EQUAL:
             if prevp.parent:
                 if prevp.parent.type in {
-                    syms.arglist, syms.argument, syms.parameters, syms.varargslist
+                    syms.arglist,
+                    syms.argument,
+                    syms.parameters,
+                    syms.varargslist,
                 }:
                     return NO
 
@@ -1649,7 +1655,8 @@ def whitespace(leaf: Leaf, *, complex_subscript: bool) -> str:  # noqa C901
             prevp_parent = prevp.parent
             assert prevp_parent is not None
             if prevp.type == token.COLON and prevp_parent.type in {
-                syms.subscript, syms.sliceop
+                syms.subscript,
+                syms.sliceop,
             }:
                 return NO
 
@@ -1902,15 +1909,15 @@ def split_line(
         return
 
     line_str = str(line).strip("\n")
-    if is_line_short_enough(line, line_length=line_length, line_str=line_str):
+    if not line.should_explode and is_line_short_enough(
+        line, line_length=line_length, line_str=line_str
+    ):
         yield line
         return
 
     split_funcs: List[SplitFunc]
     if line.is_def:
         split_funcs = [left_hand_split]
-    elif line.is_import:
-        split_funcs = [explode_split]
     else:
 
         def rhs(line: Line, py36: bool = False) -> Iterator[Line]:
@@ -2073,6 +2080,7 @@ def right_hand_split(
 
     ensure_visible(opening_bracket)
     ensure_visible(closing_bracket)
+    body.should_explode = should_explode(body, opening_bracket)
     for result in (head, body, tail):
         if result:
             yield result
@@ -2212,26 +2220,6 @@ def standalone_comment_split(line: Line, py36: bool = False) -> Iterator[Line]:
         yield current_line
 
 
-def explode_split(
-    line: Line, py36: bool = False, omit: Collection[LeafID] = ()
-) -> Iterator[Line]:
-    """Split by rightmost bracket and immediately split contents by a delimiter."""
-    new_lines = list(right_hand_split(line, py36, omit))
-    if len(new_lines) != 3:
-        yield from new_lines
-        return
-
-    yield new_lines[0]
-
-    try:
-        yield from delimiter_split(new_lines[1], py36)
-
-    except CannotSplit:
-        yield new_lines[1]
-
-    yield new_lines[2]
-
-
 def is_import(leaf: Leaf) -> bool:
     """Return True if the given leaf starts an import statement."""
     p = leaf.parent
@@ -2547,6 +2535,17 @@ def ensure_visible(leaf: Leaf) -> None:
         leaf.value = ")"
 
 
+def should_explode(line: Line, opening_bracket: Leaf) -> bool:
+    """Should `line` immediately be split with `delimiter_split()` after RHS?"""
+    return bool(
+        opening_bracket.parent
+        and opening_bracket.parent.type in {syms.atom, syms.import_from}
+        and opening_bracket.value in "[{("
+        and line.bracket_tracker.delimiters
+        and line.bracket_tracker.max_delimiter_priority() == COMMA_PRIORITY
+    )
+
+
 def is_python36(node: Node) -> bool:
     """Return True if the current file is using Python 3.6+ features.
 
@@ -2675,7 +2674,15 @@ def get_future_imports(node: Node) -> Set[str]:
 
 PYTHON_EXTENSIONS = {".py", ".pyi"}
 BLACKLISTED_DIRECTORIES = {
-    "build", "buck-out", "dist", "_build", ".git", ".hg", ".mypy_cache", ".tox", ".venv"
+    "build",
+    "buck-out",
+    "dist",
+    "_build",
+    ".git",
+    ".hg",
+    ".mypy_cache",
+    ".tox",
+    ".venv",
 }
 
 
index 4e7a4f65933010c6981bbf922b376fa173d7c756..133f249d2b3eeb46397c768acfc9313096027ff1 100644 (file)
@@ -66,8 +66,6 @@ Split functions
 
 .. autofunction:: black.delimiter_split
 
-.. autofunction:: black.explode_split
-
 .. autofunction:: black.left_hand_split
 
 .. autofunction:: black.right_hand_split
index 54f692c8b57158768e4561a4098cae020b3eafbe..bc38ed22ecc1cb12b7d5418c41b7b3b5f77123f3 100644 (file)
@@ -38,7 +38,9 @@ this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_li
     1
 )  # with a comment
 this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = [
-    1, 2, 3
+    1,
+    2,
+    3,
 ]
 this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = (
     function()
index 44a4711a6aa0a9a7f0fe40992b5c1175a1d42b46..2045c93ffb88bdfc14603d3457fa250b8da0a4d4 100644 (file)
@@ -35,9 +35,9 @@ else:
 def inline_comments_in_brackets_ruin_everything():
     if typedargslist:
         parameters.children = [
-            parameters.children[0],  # (1
+            children[0],  # (1
             body,
-            parameters.children[-1],  # )1
+            children[-1],  # )1
         ]
     else:
         parameters.children = [
@@ -163,9 +163,7 @@ else:
 # Comment before function.
 def inline_comments_in_brackets_ruin_everything():
     if typedargslist:
-        parameters.children = [
-            parameters.children[0], body, parameters.children[-1]  # (1  # )1
-        ]
+        parameters.children = [children[0], body, children[-1]]  # (1  # )1
     else:
         parameters.children = [
             parameters.children[0],  # (2 what if this was actually long
index dfca37c7d4a38e12633b7c8d3af08ca66d13be87..d7a03130a90a4fd87d1ba43ae1d3e00a8c179c77 100644 (file)
@@ -11,7 +11,7 @@
  True
  False
  1
-@@ -29,62 +29,82 @@
+@@ -29,62 +29,83 @@
  ~great
  +value
  -1
@@ -29,7 +29,8 @@
  manylambdas = lambda x=lambda y=lambda z=1: z: y(): x()
 -foo = (lambda port_id, ignore_missing: {"port1": port1_resource, "port2": port2_resource}[port_id])
 +foo = lambda port_id, ignore_missing: {
-+    "port1": port1_resource, "port2": port2_resource
++    "port1": port1_resource,
++    "port2": port2_resource,
 +}[port_id]
  1 if True else 2
  str or None if True else str or bytes or None
  call(**self.screen_kwargs)
  call(b, **self.screen_kwargs)
  lukasz.langa.pl
-@@ -93,11 +113,11 @@
+@@ -93,11 +114,11 @@
  1.0 .real
  ....__class__
  list[str]
  ]
  slice[0]
  slice[0:1]
-@@ -124,107 +144,159 @@
+@@ -124,107 +145,159 @@
  numpy[-(c + 1) :, d]
  numpy[:, l[-2]]
  numpy[:, ::-1]
index cc6f399b4c95447a292c4e76ee552e580b9f2372..9221c8eb098ffa827060776f651f41eae5377461 100644 (file)
@@ -273,7 +273,8 @@ lambda a, b, c=True, *, d=(1 << v2), e="str": a
 lambda a, b, c=True, *vararg, d=(v1 << 2), e="str", **kwargs: a + b
 manylambdas = lambda x=lambda y=lambda z=1: z: y(): x()
 foo = lambda port_id, ignore_missing: {
-    "port1": port1_resource, "port2": port2_resource
+    "port1": port1_resource,
+    "port2": port2_resource,
 }[port_id]
 1 if True else 2
 str or None if True else str or bytes or None