parent
dafa12f10b
commit
dd4477b701
30
README.md
30
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)
|
||||
|
||||
|
61
black.py
61
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 append_to_line(leaf: Leaf) -> 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",
|
||||
}
|
||||
|
||||
|
||||
|
@ -66,8 +66,6 @@ Split functions
|
||||
|
||||
.. autofunction:: black.delimiter_split
|
||||
|
||||
.. autofunction:: black.explode_split
|
||||
|
||||
.. autofunction:: black.left_hand_split
|
||||
|
||||
.. autofunction:: black.right_hand_split
|
||||
|
@ -38,7 +38,9 @@
|
||||
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()
|
||||
|
@ -35,9 +35,9 @@
|
||||
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 @@ def inline_comments_in_brackets_ruin_everything():
|
||||
# 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
|
||||
|
@ -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
|
||||
@ -115,7 +116,7 @@
|
||||
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]
|
||||
@ -128,7 +129,7 @@
|
||||
]
|
||||
slice[0]
|
||||
slice[0:1]
|
||||
@@ -124,107 +144,159 @@
|
||||
@@ -124,107 +145,159 @@
|
||||
numpy[-(c + 1) :, d]
|
||||
numpy[:, l[-2]]
|
||||
numpy[:, ::-1]
|
||||
|
@ -273,7 +273,8 @@ async def f():
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user