Generating lines of code.
"""
import sys
-from dataclasses import dataclass
+from dataclasses import dataclass, replace
from enum import Enum, auto
from functools import partial, wraps
from typing import Collection, Iterator, List, Optional, Set, Union, cast
and not line.should_split_rhs
and not line.magic_trailing_comma
and (
- is_line_short_enough(line, line_length=mode.line_length, line_str=line_str)
+ is_line_short_enough(line, mode=mode, line_str=line_str)
or line.contains_unsplittable_type_ignore()
)
and not (line.inside_brackets and line.contains_standalone_comments())
bracket pair instead.
"""
for omit in generate_trailers_to_omit(line, mode.line_length):
- lines = list(
- right_hand_split(line, mode.line_length, features, omit=omit)
- )
+ lines = list(right_hand_split(line, mode, features, omit=omit))
# Note: this check is only able to figure out if the first line of the
# *current* transformation fits in the line length. This is true only
# for simple cases. All others require running more transforms via
# `transform_line()`. This check doesn't know if those would succeed.
- if is_line_short_enough(lines[0], line_length=mode.line_length):
+ if is_line_short_enough(lines[0], mode=mode):
yield from lines
return
# This mostly happens to multiline strings that are by definition
# reported as not fitting a single line, as well as lines that contain
# trailing commas (those have to be exploded).
- yield from right_hand_split(
- line, line_length=mode.line_length, features=features
- )
+ yield from right_hand_split(line, mode, features=features)
# HACK: nested functions (like _rhs) compiled by mypyc don't retain their
# __name__ attribute which is needed in `run_transformer` further down.
def right_hand_split(
line: Line,
- line_length: int,
+ mode: Mode,
features: Collection[Feature] = (),
omit: Collection[LeafID] = (),
) -> Iterator[Line]:
"""
rhs_result = _first_right_hand_split(line, omit=omit)
yield from _maybe_split_omitting_optional_parens(
- rhs_result, line, line_length, features=features, omit=omit
+ rhs_result, line, mode, features=features, omit=omit
)
def _maybe_split_omitting_optional_parens(
rhs: _RHSResult,
line: Line,
- line_length: int,
+ mode: Mode,
features: Collection[Feature] = (),
omit: Collection[LeafID] = (),
) -> Iterator[Line]:
# there are no standalone comments in the body
and not rhs.body.contains_standalone_comments(0)
# and we can actually remove the parens
- and can_omit_invisible_parens(rhs.body, line_length)
+ and can_omit_invisible_parens(rhs.body, mode.line_length)
):
omit = {id(rhs.closing_bracket), *omit}
try:
# the split is right after `=`
and len(rhs.head.leaves) >= 2
and rhs.head.leaves[-2].type == token.EQUAL
- # the left side of assignement contains brackets
+ # the left side of assignment contains brackets
and any(leaf.type in BRACKETS for leaf in rhs.head.leaves[:-1])
# the left side of assignment is short enough (the -1 is for the ending
# optional paren)
- and is_line_short_enough(rhs.head, line_length=line_length - 1)
+ and is_line_short_enough(
+ rhs.head, mode=replace(mode, line_length=mode.line_length - 1)
+ )
# the left side of assignment won't explode further because of magic
# trailing comma
and rhs.head.magic_trailing_comma is None
# the split by omitting optional parens isn't preferred by some other
# reason
- and not _prefer_split_rhs_oop(rhs_oop, line_length=line_length)
+ and not _prefer_split_rhs_oop(rhs_oop, mode)
):
yield from _maybe_split_omitting_optional_parens(
- rhs_oop, line, line_length, features=features, omit=omit
+ rhs_oop, line, mode, features=features, omit=omit
)
return
except CannotSplit as e:
if not (
- can_be_split(rhs.body)
- or is_line_short_enough(rhs.body, line_length=line_length)
+ can_be_split(rhs.body) or is_line_short_enough(rhs.body, mode=mode)
):
raise CannotSplit(
"Splitting failed, body is still too long and can't be split."
yield result
-def _prefer_split_rhs_oop(rhs_oop: _RHSResult, line_length: int) -> bool:
+def _prefer_split_rhs_oop(rhs_oop: _RHSResult, mode: Mode) -> bool:
"""
Returns whether we should prefer the result from a split omitting optional parens.
"""
# the first line still contains the `=`)
any(leaf.type == token.EQUAL for leaf in rhs_oop.head.leaves)
# the first line is short enough
- and is_line_short_enough(rhs_oop.head, line_length=line_length)
+ and is_line_short_enough(rhs_oop.head, mode=mode)
)
# contains unsplittable type ignore
or rhs_oop.head.contains_unsplittable_type_ignore()
or line.contains_multiline_strings()
or result[0].contains_uncollapsable_type_comments()
or result[0].contains_unsplittable_type_ignore()
- or is_line_short_enough(result[0], line_length=mode.line_length)
+ or is_line_short_enough(result[0], mode=mode)
# If any leaves have no parents (which _can_ occur since
# `transform(line)` potentially destroys the line's underlying node
# structure), then we can't proceed. Doing so would cause the below
second_opinion = run_transformer(
line_copy, transform, mode, features_fop, line_str=line_str
)
- if all(
- is_line_short_enough(ln, line_length=mode.line_length) for ln in second_opinion
- ):
+ if all(is_line_short_enough(ln, mode=mode) for ln in second_opinion):
result = second_opinion
return result