parent
013cb2b374
commit
8a8c58252c
@ -824,6 +824,8 @@ More details can be found in [CONTRIBUTING](CONTRIBUTING.md).
|
||||
|
||||
* typing stub files (`.pyi`) now have blank lines added after constants (#340)
|
||||
|
||||
* `# fmt: off` and `# fmt: on` now work also within bracket pairs (#329)
|
||||
|
||||
* fixed improper formatting of f-strings with quotes inside interpolated
|
||||
expressions (#322)
|
||||
|
||||
|
103
black.py
103
black.py
@ -628,6 +628,7 @@ def format_str(
|
||||
is_pyi = bool(mode & FileMode.PYI)
|
||||
py36 = bool(mode & FileMode.PYTHON36) or is_python36(src_node)
|
||||
normalize_strings = not bool(mode & FileMode.NO_STRING_NORMALIZATION)
|
||||
normalize_fmt_off(src_node)
|
||||
lines = LineGenerator(
|
||||
remove_u_prefix=py36 or "unicode_literals" in future_imports,
|
||||
is_pyi=is_pyi,
|
||||
@ -781,6 +782,7 @@ def show(cls, code: str) -> None:
|
||||
syms.classdef,
|
||||
}
|
||||
STANDALONE_COMMENT = 153
|
||||
token.tok_name[STANDALONE_COMMENT] = "STANDALONE_COMMENT"
|
||||
LOGIC_OPERATORS = {"and", "or"}
|
||||
COMPARATORS = {
|
||||
token.LESS,
|
||||
@ -821,6 +823,18 @@ def show(cls, code: str) -> None:
|
||||
syms.testlist_gexp,
|
||||
syms.testlist_star_expr,
|
||||
}
|
||||
SURROUNDED_BY_BRACKETS = {
|
||||
syms.typedargslist,
|
||||
syms.arglist,
|
||||
syms.subscriptlist,
|
||||
syms.vfplist,
|
||||
syms.import_as_names,
|
||||
syms.yield_expr,
|
||||
syms.testlist_gexp,
|
||||
syms.testlist_star_expr,
|
||||
syms.listmaker,
|
||||
syms.dictsetmaker,
|
||||
}
|
||||
TEST_DESCENDANTS = {
|
||||
syms.test,
|
||||
syms.lambdef,
|
||||
@ -1940,6 +1954,28 @@ def child_towards(ancestor: Node, descendant: LN) -> Optional[LN]:
|
||||
return node
|
||||
|
||||
|
||||
def container_of(leaf: Leaf) -> LN:
|
||||
"""Return `leaf` or one of its ancestors that is the topmost container of it.
|
||||
|
||||
By "container" we mean a node where `leaf` is the very first child.
|
||||
"""
|
||||
same_prefix = leaf.prefix
|
||||
container: LN = leaf
|
||||
while container:
|
||||
parent = container.parent
|
||||
if parent is None:
|
||||
break
|
||||
|
||||
if parent.children[0].prefix != same_prefix:
|
||||
break
|
||||
|
||||
if parent.type in SURROUNDED_BY_BRACKETS:
|
||||
break
|
||||
|
||||
container = parent
|
||||
return container
|
||||
|
||||
|
||||
def is_split_after_delimiter(leaf: Leaf, previous: Leaf = None) -> int:
|
||||
"""Return the priority of the `leaf` delimiter, given a line break after it.
|
||||
|
||||
@ -2091,7 +2127,7 @@ class ProtoComment:
|
||||
|
||||
|
||||
@lru_cache(maxsize=4096)
|
||||
def list_comments(prefix: str, is_endmarker: bool) -> List[ProtoComment]:
|
||||
def list_comments(prefix: str, *, is_endmarker: bool) -> List[ProtoComment]:
|
||||
result: List[ProtoComment] = []
|
||||
if not prefix or "#" not in prefix:
|
||||
return result
|
||||
@ -2643,6 +2679,71 @@ def normalize_invisible_parens(node: Node, parens_after: Set[str]) -> None:
|
||||
check_lpar = isinstance(child, Leaf) and child.value in parens_after
|
||||
|
||||
|
||||
def normalize_fmt_off(node: Node) -> None:
|
||||
"""Allow `# fmt: off`/`# fmt: on` within bracket pairs.
|
||||
|
||||
Ignores `# fmt: off` and `# fmt: on` outside of brackets.
|
||||
|
||||
Raises :exc:`SyntaxError` if no matching `# fmt: on` is found for a `# fmt: off`
|
||||
given inside brackets.
|
||||
"""
|
||||
try_again = True
|
||||
while try_again:
|
||||
try_again = hide_fmt_off(node)
|
||||
|
||||
|
||||
def hide_fmt_off(node: Node) -> bool:
|
||||
bt = BracketTracker()
|
||||
for leaf in node.leaves():
|
||||
bt.mark(leaf)
|
||||
if bt.depth == 0:
|
||||
continue
|
||||
|
||||
previous_consumed = 0
|
||||
for comment in list_comments(leaf.prefix, is_endmarker=False):
|
||||
if comment.value in FMT_OFF:
|
||||
ignored_nodes = list(generate_ignored_nodes(leaf))
|
||||
first = ignored_nodes[0] # Can be a container node with the `leaf`.
|
||||
parent = first.parent
|
||||
prefix = first.prefix
|
||||
first.prefix = prefix[comment.consumed :]
|
||||
hidden_value = (
|
||||
comment.value + "\n" + "".join(str(n) for n in ignored_nodes)
|
||||
)
|
||||
first_idx = None
|
||||
for ignored in ignored_nodes:
|
||||
index = ignored.remove()
|
||||
if first_idx is None:
|
||||
first_idx = index
|
||||
assert parent is not None, "INTERNAL ERROR: fmt: on/off handling (1)"
|
||||
assert first_idx is not None, "INTERNAL ERROR: fmt: on/off handling (2)"
|
||||
parent.insert_child(
|
||||
first_idx,
|
||||
Leaf(
|
||||
STANDALONE_COMMENT,
|
||||
hidden_value,
|
||||
prefix=prefix[:previous_consumed] + "\n" * comment.newlines,
|
||||
),
|
||||
)
|
||||
return True
|
||||
|
||||
previous_consumed += comment.consumed
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def generate_ignored_nodes(leaf: Leaf) -> Iterator[LN]:
|
||||
container: Optional[LN] = container_of(leaf)
|
||||
while container is not None:
|
||||
for comment in list_comments(container.prefix, is_endmarker=False):
|
||||
if comment.value in FMT_ON:
|
||||
return
|
||||
|
||||
yield container
|
||||
|
||||
container = container.next_sibling
|
||||
|
||||
|
||||
def maybe_make_parens_invisible_in_atom(node: LN) -> bool:
|
||||
"""If it's safe, make the parens in the atom `node` invisible, recursively."""
|
||||
if (
|
||||
|
@ -40,6 +40,10 @@ def spaces(a=1, b=(), c=[], d={}, e=True, f=-1, g=1 if False else 2, h="", i=r''
|
||||
def spaces_types(a: int = 1, b: tuple = (), c: list = [], d: dict = {}, e: bool = True, f: int = -1, g: int = 1 if False else 2, h: str = "", i: str = r''): ...
|
||||
def spaces2(result= _core.Value(None)):
|
||||
...
|
||||
something = {
|
||||
# fmt: off
|
||||
key: 'value',
|
||||
}
|
||||
def example(session):
|
||||
# fmt: off
|
||||
result = session\
|
||||
@ -78,10 +82,11 @@ def long_lines():
|
||||
\n?
|
||||
)
|
||||
$
|
||||
""", # fmt: off
|
||||
re.MULTILINE | re.VERBOSE
|
||||
""",
|
||||
# fmt: off
|
||||
re.MULTILINE|re.VERBOSE
|
||||
# fmt: on
|
||||
)
|
||||
# fmt: on
|
||||
def single_literal_yapf_disable():
|
||||
"""Black does not support this."""
|
||||
BAZ = {
|
||||
@ -89,6 +94,28 @@ def single_literal_yapf_disable():
|
||||
(5, 6, 7, 8),
|
||||
(9, 10, 11, 12),
|
||||
} # yapf: disable
|
||||
cfg.rule(
|
||||
"Default", "address",
|
||||
xxxx_xxxx=["xxx-xxxxxx-xxxxxxxxxx"],
|
||||
xxxxxx="xx_xxxxx", xxxxxxx="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
||||
xxxxxxxxx_xxxx=True, xxxxxxxx_xxxxxxxxxx=False,
|
||||
xxxxxx_xxxxxx=2, xxxxxx_xxxxx_xxxxxxxx=70, xxxxxx_xxxxxx_xxxxx=True,
|
||||
# fmt: off
|
||||
xxxxxxx_xxxxxxxxxxxx={
|
||||
"xxxxxxxx": {
|
||||
"xxxxxx": False,
|
||||
"xxxxxxx": False,
|
||||
"xxxx_xxxxxx": "xxxxx",
|
||||
},
|
||||
"xxxxxxxx-xxxxx": {
|
||||
"xxxxxx": False,
|
||||
"xxxxxxx": True,
|
||||
"xxxx_xxxxxx": "xxxxxx",
|
||||
},
|
||||
},
|
||||
# fmt: on
|
||||
xxxxxxxxxx_xxxxxxxxxxx_xxxxxxx_xxxxxxxxx=5
|
||||
)
|
||||
# fmt: off
|
||||
# No formatting to the end of the file
|
||||
l=[1,2,3]
|
||||
@ -157,6 +184,12 @@ def spaces2(result=_core.Value(None)):
|
||||
...
|
||||
|
||||
|
||||
something = {
|
||||
# fmt: off
|
||||
key: 'value',
|
||||
}
|
||||
|
||||
|
||||
def example(session):
|
||||
# fmt: off
|
||||
result = session\
|
||||
@ -202,10 +235,11 @@ def long_lines():
|
||||
\n?
|
||||
)
|
||||
$
|
||||
""", # fmt: off
|
||||
re.MULTILINE | re.VERBOSE,
|
||||
""",
|
||||
# fmt: off
|
||||
re.MULTILINE|re.VERBOSE
|
||||
# fmt: on
|
||||
)
|
||||
# fmt: on
|
||||
|
||||
|
||||
def single_literal_yapf_disable():
|
||||
@ -213,6 +247,33 @@ def single_literal_yapf_disable():
|
||||
BAZ = {(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)} # yapf: disable
|
||||
|
||||
|
||||
cfg.rule(
|
||||
"Default",
|
||||
"address",
|
||||
xxxx_xxxx=["xxx-xxxxxx-xxxxxxxxxx"],
|
||||
xxxxxx="xx_xxxxx",
|
||||
xxxxxxx="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
||||
xxxxxxxxx_xxxx=True,
|
||||
xxxxxxxx_xxxxxxxxxx=False,
|
||||
xxxxxx_xxxxxx=2,
|
||||
xxxxxx_xxxxx_xxxxxxxx=70,
|
||||
xxxxxx_xxxxxx_xxxxx=True,
|
||||
# fmt: off
|
||||
xxxxxxx_xxxxxxxxxxxx={
|
||||
"xxxxxxxx": {
|
||||
"xxxxxx": False,
|
||||
"xxxxxxx": False,
|
||||
"xxxx_xxxxxx": "xxxxx",
|
||||
},
|
||||
"xxxxxxxx-xxxxx": {
|
||||
"xxxxxx": False,
|
||||
"xxxxxxx": True,
|
||||
"xxxx_xxxxxx": "xxxxxx",
|
||||
},
|
||||
},
|
||||
# fmt: on
|
||||
xxxxxxxxxx_xxxxxxxxxxx_xxxxxxx_xxxxxxxxx=5,
|
||||
)
|
||||
# fmt: off
|
||||
# No formatting to the end of the file
|
||||
l=[1,2,3]
|
||||
|
Loading…
Reference in New Issue
Block a user