within brackets a given leaf is. 0 means there are no enclosing brackets
that started on this line.
- If a leaf is itself a closing bracket, it receives an `opening_bracket`
- field that it forms a pair with. This is a one-directional link to
- avoid reference cycles.
+ If a leaf is itself a closing bracket and there is a matching opening
+ bracket earlier, it receives an `opening_bracket` field with which it forms a
+ pair. This is a one-directional link to avoid reference cycles. Closing
+ bracket without opening happens on lines continued from previous
+ breaks, e.g. `) -> "ReturnType":` as part of a funcdef where we place
+ the return type annotation on its own line of the previous closing RPAR.
If a leaf is a delimiter (a token on which Black can split the line if
needed) and it's on depth 0, its `id()` is stored in the tracker's
if leaf.type == token.COMMENT:
return
+ if (
+ self.depth == 0
+ and leaf.type in CLOSING_BRACKETS
+ and (self.depth, leaf.type) not in self.bracket_match
+ ):
+ return
+
self.maybe_decrement_after_for_loop_variable(leaf)
self.maybe_decrement_after_lambda_arguments(leaf)
if leaf.type in CLOSING_BRACKETS:
from mypy_extensions import trait
-from black.brackets import BracketMatchError
from black.comments import contains_pragma_comment
from black.lines import Line, append_leaves
from black.mode import Feature
is_empty_lpar,
is_empty_par,
is_empty_rpar,
+ is_part_of_annotation,
parent_type,
replace_child,
syms,
Requirements:
(A) The line contains adjacent strings such that ALL of the validation checks
- listed in StringMerger.__validate_msg(...)'s docstring pass.
+ listed in StringMerger._validate_msg(...)'s docstring pass.
OR
(B) The line contains a string which uses line continuation backslashes.
and is_valid_index(i + 1)
and LL[i + 1].type == token.STRING
):
+ if is_part_of_annotation(leaf):
+ return TErr("String is part of type annotation.")
return Ok(i)
if leaf.type == token.STRING and "\\\n" in leaf.value:
Returns:
Ok(new_line), if ALL of the validation checks found in
- __validate_msg(...) pass.
+ _validate_msg(...) pass.
OR
Err(CannotTransform), otherwise.
"""
def _validate_msg(line: Line, string_idx: int) -> TResult[None]:
"""Validate (M)erge (S)tring (G)roup
- Transform-time string validation logic for __merge_string_group(...).
+ Transform-time string validation logic for _merge_string_group(...).
Returns:
* Ok(None), if ALL validation checks (listed below) pass.
- The set of all string prefixes in the string group is of
length greater than one and is not equal to {"", "f"}.
- The string group consists of raw strings.
+ - The string group is stringified type annotations. We don't want to
+ process stringified type annotations since pyright doesn't support
+ them spanning multiple string values. (NOTE: mypy, pytype, pyre do
+ support them, so we can change if pyright also gains support in the
+ future. See https://github.com/microsoft/pyright/issues/4359.)
"""
# We first check for "inner" stand-alone comments (i.e. stand-alone
# comments that have a string leaf before them AND after them).
new_line = line.clone()
new_line.comments = line.comments.copy()
- try:
- append_leaves(new_line, line, LL[: string_idx - 1])
- except BracketMatchError:
- # HACK: I believe there is currently a bug somewhere in
- # right_hand_split() that is causing brackets to not be tracked
- # properly by a shared BracketTracker.
- append_leaves(new_line, line, LL[: string_idx - 1], preformatted=True)
+ append_leaves(new_line, line, LL[: string_idx - 1])
string_leaf = Leaf(token.STRING, LL[string_idx].value)
LL[string_idx - 1].remove()
--- /dev/null
+def func(
+ arg1,
+ arg2,
+) -> Set["this_is_a_very_long_module_name.AndAVeryLongClasName"
+ ".WithAVeryVeryVeryVeryVeryLongSubClassName"]:
+ pass
+
+
+def func(
+ argument: (
+ "VeryLongClassNameWithAwkwardGenericSubtype[int] |"
+ "VeryLongClassNameWithAwkwardGenericSubtype[str]"
+ ),
+) -> (
+ "VeryLongClassNameWithAwkwardGenericSubtype[int] |"
+ "VeryLongClassNameWithAwkwardGenericSubtype[str]"
+):
+ pass
+
+
+def func(
+ argument: (
+ "int |"
+ "str"
+ ),
+) -> Set["int |"
+ " str"]:
+ pass
+
+
+# output
+
+
+def func(
+ arg1,
+ arg2,
+) -> Set[
+ "this_is_a_very_long_module_name.AndAVeryLongClasName"
+ ".WithAVeryVeryVeryVeryVeryLongSubClassName"
+]:
+ pass
+
+
+def func(
+ argument: (
+ "VeryLongClassNameWithAwkwardGenericSubtype[int] |"
+ "VeryLongClassNameWithAwkwardGenericSubtype[str]"
+ ),
+) -> (
+ "VeryLongClassNameWithAwkwardGenericSubtype[int] |"
+ "VeryLongClassNameWithAwkwardGenericSubtype[str]"
+):
+ pass
+
+
+def func(
+ argument: ("int |" "str"),
+) -> Set["int |" " str"]:
+ pass