Fix invalid code on stars in long from-imports being wrapped in parentheses
Fixes #234
This commit is contained in:
parent
808754af18
commit
9a6c88c7f4
@ -661,6 +661,8 @@ More details can be found in [CONTRIBUTING](CONTRIBUTING.md).
|
||||
|
||||
* fixed optional parentheses being removed within `# fmt: off` sections (#224)
|
||||
|
||||
* fixed invalid code produced when stars in very long imports were incorrectly
|
||||
wrapped in optional parentheses (#234)
|
||||
|
||||
### 18.5b0
|
||||
|
||||
|
44
black.py
44
black.py
@ -1375,32 +1375,6 @@ def visit_decorators(self, node: Node) -> Iterator[Line]:
|
||||
yield from self.line()
|
||||
yield from self.visit(child)
|
||||
|
||||
def visit_import_from(self, node: Node) -> Iterator[Line]:
|
||||
"""Visit import_from and maybe put invisible parentheses.
|
||||
|
||||
This is separate from `visit_stmt` because import statements don't
|
||||
support arbitrary atoms and thus handling of parentheses is custom.
|
||||
"""
|
||||
check_lpar = False
|
||||
for index, child in enumerate(node.children):
|
||||
if check_lpar:
|
||||
if child.type == token.LPAR:
|
||||
# make parentheses invisible
|
||||
child.value = "" # type: ignore
|
||||
node.children[-1].value = "" # type: ignore
|
||||
else:
|
||||
# insert invisible parentheses
|
||||
node.insert_child(index, Leaf(token.LPAR, ""))
|
||||
node.append_child(Leaf(token.RPAR, ""))
|
||||
break
|
||||
|
||||
check_lpar = (
|
||||
child.type == token.NAME and child.value == "import" # type: ignore
|
||||
)
|
||||
|
||||
for child in node.children:
|
||||
yield from self.visit(child)
|
||||
|
||||
def visit_SEMI(self, leaf: Leaf) -> Iterator[Line]:
|
||||
"""Remove a semicolon and put the other statement on a separate line."""
|
||||
yield from self.line()
|
||||
@ -1447,6 +1421,7 @@ def __attrs_post_init__(self) -> None:
|
||||
self.visit_classdef = partial(v, keywords={"class"}, parens=Ø)
|
||||
self.visit_expr_stmt = partial(v, keywords=Ø, parens=ASSIGNMENTS)
|
||||
self.visit_return_stmt = partial(v, keywords={"return"}, parens={"return"})
|
||||
self.visit_import_from = partial(v, keywords=Ø, parens={"import"})
|
||||
self.visit_async_funcdef = self.visit_async_stmt
|
||||
self.visit_decorated = self.visit_decorators
|
||||
|
||||
@ -2343,7 +2318,7 @@ def normalize_invisible_parens(node: Node, parens_after: Set[str]) -> None:
|
||||
return # This `node` has a prefix with `# fmt: off`, don't mess with parens.
|
||||
|
||||
check_lpar = False
|
||||
for child in list(node.children):
|
||||
for index, child in enumerate(list(node.children)):
|
||||
if check_lpar:
|
||||
if child.type == syms.atom:
|
||||
maybe_make_parens_invisible_in_atom(child)
|
||||
@ -2351,8 +2326,21 @@ def normalize_invisible_parens(node: Node, parens_after: Set[str]) -> None:
|
||||
# wrap child in visible parentheses
|
||||
lpar = Leaf(token.LPAR, "(")
|
||||
rpar = Leaf(token.RPAR, ")")
|
||||
index = child.remove() or 0
|
||||
child.remove()
|
||||
node.insert_child(index, Node(syms.atom, [lpar, child, rpar]))
|
||||
elif node.type == syms.import_from:
|
||||
# "import from" nodes store parentheses directly as part of
|
||||
# the statement
|
||||
if child.type == token.LPAR:
|
||||
# make parentheses invisible
|
||||
child.value = "" # type: ignore
|
||||
node.children[-1].value = "" # type: ignore
|
||||
elif child.type != token.STAR:
|
||||
# insert invisible parentheses
|
||||
node.insert_child(index, Leaf(token.LPAR, ""))
|
||||
node.append_child(Leaf(token.RPAR, ""))
|
||||
break
|
||||
|
||||
elif not (isinstance(child, Leaf) and is_multiline_string(child)):
|
||||
# wrap child in invisible parentheses
|
||||
lpar = Leaf(token.LPAR, "")
|
||||
|
@ -6,6 +6,10 @@
|
||||
|
||||
from library import some_connection, \
|
||||
some_decorator
|
||||
# fmt: off
|
||||
from third_party import (X,
|
||||
Y, Z)
|
||||
# fmt: on
|
||||
f'trigger 3.6 mode'
|
||||
# fmt: off
|
||||
def func_no_args():
|
||||
@ -102,6 +106,10 @@ def single_literal_yapf_disable():
|
||||
|
||||
from library import some_connection, some_decorator
|
||||
|
||||
# fmt: off
|
||||
from third_party import (X,
|
||||
Y, Z)
|
||||
# fmt: on
|
||||
f"trigger 3.6 mode"
|
||||
# fmt: off
|
||||
def func_no_args():
|
||||
|
@ -24,6 +24,7 @@
|
||||
Just, Enough, Libraries, To, Fit, In, This, Nice, Split, Which, We, No, Longer, Use
|
||||
)
|
||||
from name_of_a_company.extremely_long_project_name.component.ttypes import CuteLittleServiceHandlerFactoryyy
|
||||
from name_of_a_company.extremely_long_project_name.extremely_long_component_name.ttypes import *
|
||||
|
||||
from .a.b.c.subprocess import *
|
||||
from . import (tasks)
|
||||
@ -87,6 +88,7 @@
|
||||
from name_of_a_company.extremely_long_project_name.component.ttypes import (
|
||||
CuteLittleServiceHandlerFactoryyy
|
||||
)
|
||||
from name_of_a_company.extremely_long_project_name.extremely_long_component_name.ttypes import *
|
||||
|
||||
from .a.b.c.subprocess import *
|
||||
from . import tasks
|
||||
|
Loading…
Reference in New Issue
Block a user