1# Copyright 2015 Google Inc. All Rights Reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14"""LogicalLine primitive for formatting. 15 16A logical line is the containing data structure produced by the parser. It 17collects all nodes (stored in FormatToken objects) that could appear on a single 18line if there were no line length restrictions. It's then used by the parser to 19perform the wrapping required to comply with the style guide. 20""" 21 22from yapf.yapflib import format_token 23from yapf.yapflib import py3compat 24from yapf.yapflib import pytree_utils 25from yapf.yapflib import split_penalty 26from yapf.yapflib import style 27from yapf.yapflib import subtypes 28 29from lib2to3.fixer_util import syms as python_symbols 30 31 32class LogicalLine(object): 33 """Represents a single logical line in the output. 34 35 Attributes: 36 depth: indentation depth of this line. This is just a numeric value used to 37 distinguish lines that are more deeply nested than others. It is not the 38 actual amount of spaces, which is style-dependent. 39 """ 40 41 def __init__(self, depth, tokens=None): 42 """Constructor. 43 44 Creates a new logical line with the given depth an initial list of tokens. 45 Constructs the doubly-linked lists for format tokens using their built-in 46 next_token and previous_token attributes. 47 48 Arguments: 49 depth: indentation depth of this line 50 tokens: initial list of tokens 51 """ 52 self.depth = depth 53 self._tokens = tokens or [] 54 self.disable = False 55 56 if self._tokens: 57 # Set up a doubly linked list. 58 for index, tok in enumerate(self._tokens[1:]): 59 # Note, 'index' is the index to the previous token. 60 tok.previous_token = self._tokens[index] 61 self._tokens[index].next_token = tok 62 63 def CalculateFormattingInformation(self): 64 """Calculate the split penalty and total length for the tokens.""" 65 # Say that the first token in the line should have a space before it. This 66 # means only that if this logical line is joined with a predecessor line, 67 # then there will be a space between them. 68 self.first.spaces_required_before = 1 69 self.first.total_length = len(self.first.value) 70 71 prev_token = self.first 72 prev_length = self.first.total_length 73 for token in self._tokens[1:]: 74 if (token.spaces_required_before == 0 and 75 _SpaceRequiredBetween(prev_token, token, self.disable)): 76 token.spaces_required_before = 1 77 78 tok_len = len(token.value) if not token.is_pseudo else 0 79 80 spaces_required_before = token.spaces_required_before 81 if isinstance(spaces_required_before, list): 82 assert token.is_comment, token 83 84 # If here, we are looking at a comment token that appears on a line 85 # with other tokens (but because it is a comment, it is always the last 86 # token). Rather than specifying the actual number of spaces here, 87 # hard code a value of 0 and then set it later. This logic only works 88 # because this comment token is guaranteed to be the last token in the 89 # list. 90 spaces_required_before = 0 91 92 token.total_length = prev_length + tok_len + spaces_required_before 93 94 # The split penalty has to be computed before {must|can}_break_before, 95 # because these may use it for their decision. 96 token.split_penalty += _SplitPenalty(prev_token, token) 97 token.must_break_before = _MustBreakBefore(prev_token, token) 98 token.can_break_before = ( 99 token.must_break_before or _CanBreakBefore(prev_token, token)) 100 101 prev_length = token.total_length 102 prev_token = token 103 104 def Split(self): 105 """Split the line at semicolons.""" 106 if not self.has_semicolon or self.disable: 107 return [self] 108 109 llines = [] 110 lline = LogicalLine(self.depth) 111 for tok in self._tokens: 112 if tok.value == ';': 113 llines.append(lline) 114 lline = LogicalLine(self.depth) 115 else: 116 lline.AppendToken(tok) 117 118 if lline.tokens: 119 llines.append(lline) 120 121 for lline in llines: 122 lline.first.previous_token = None 123 lline.last.next_token = None 124 125 return llines 126 127 ############################################################################ 128 # Token Access and Manipulation Methods # 129 ############################################################################ 130 131 def AppendToken(self, token): 132 """Append a new FormatToken to the tokens contained in this line.""" 133 if self._tokens: 134 token.previous_token = self.last 135 self.last.next_token = token 136 self._tokens.append(token) 137 138 def AppendNode(self, node): 139 """Convenience method to append a pytree node directly. 140 141 Wraps the node with a FormatToken. 142 143 Arguments: 144 node: the node to append 145 """ 146 self.AppendToken(format_token.FormatToken(node)) 147 148 @property 149 def first(self): 150 """Returns the first non-whitespace token.""" 151 return self._tokens[0] 152 153 @property 154 def last(self): 155 """Returns the last non-whitespace token.""" 156 return self._tokens[-1] 157 158 ############################################################################ 159 # Token -> String Methods # 160 ############################################################################ 161 162 def AsCode(self, indent_per_depth=2): 163 """Return a "code" representation of this line. 164 165 The code representation shows how the line would be printed out as code. 166 167 TODO(eliben): for now this is rudimentary for debugging - once we add 168 formatting capabilities, this method will have other uses (not all tokens 169 have spaces around them, for example). 170 171 Arguments: 172 indent_per_depth: how much spaces to indend per depth level. 173 174 Returns: 175 A string representing the line as code. 176 """ 177 indent = ' ' * indent_per_depth * self.depth 178 tokens_str = ' '.join(tok.value for tok in self._tokens) 179 return indent + tokens_str 180 181 def __str__(self): # pragma: no cover 182 return self.AsCode() 183 184 def __repr__(self): # pragma: no cover 185 tokens_repr = ','.join( 186 '{0}({1!r})'.format(tok.name, tok.value) for tok in self._tokens) 187 return 'LogicalLine(depth={0}, tokens=[{1}])'.format( 188 self.depth, tokens_repr) 189 190 ############################################################################ 191 # Properties # 192 ############################################################################ 193 194 @property 195 def tokens(self): 196 """Access the tokens contained within this line. 197 198 The caller must not modify the tokens list returned by this method. 199 200 Returns: 201 List of tokens in this line. 202 """ 203 return self._tokens 204 205 @property 206 def lineno(self): 207 """Return the line number of this logical line. 208 209 Returns: 210 The line number of the first token in this logical line. 211 """ 212 return self.first.lineno 213 214 @property 215 def start(self): 216 """The start of the logical line. 217 218 Returns: 219 A tuple of the starting line number and column. 220 """ 221 return (self.first.lineno, self.first.column) 222 223 @property 224 def end(self): 225 """The end of the logical line. 226 227 Returns: 228 A tuple of the ending line number and column. 229 """ 230 return (self.last.lineno, self.last.column + len(self.last.value)) 231 232 @property 233 def is_comment(self): 234 return self.first.is_comment 235 236 @property 237 def has_semicolon(self): 238 return any(tok.value == ';' for tok in self._tokens) 239 240 241def _IsIdNumberStringToken(tok): 242 return tok.is_keyword or tok.is_name or tok.is_number or tok.is_string 243 244 245def _IsUnaryOperator(tok): 246 return subtypes.UNARY_OPERATOR in tok.subtypes 247 248 249def _HasPrecedence(tok): 250 """Whether a binary operation has precedence within its context.""" 251 node = tok.node 252 253 # We let ancestor be the statement surrounding the operation that tok is the 254 # operator in. 255 ancestor = node.parent.parent 256 257 while ancestor is not None: 258 # Search through the ancestor nodes in the parse tree for operators with 259 # lower precedence. 260 predecessor_type = pytree_utils.NodeName(ancestor) 261 if predecessor_type in ['arith_expr', 'term']: 262 # An ancestor "arith_expr" or "term" means we have found an operator 263 # with lower precedence than our tok. 264 return True 265 if predecessor_type != 'atom': 266 # We understand the context to look for precedence within as an 267 # arbitrary nesting of "arith_expr", "term", and "atom" nodes. If we 268 # leave this context we have not found a lower precedence operator. 269 return False 270 # Under normal usage we expect a complete parse tree to be available and 271 # we will return before we get an AttributeError from the root. 272 ancestor = ancestor.parent 273 274 275def _PriorityIndicatingNoSpace(tok): 276 """Whether to remove spaces around an operator due to precedence.""" 277 if not tok.is_arithmetic_op or not tok.is_simple_expr: 278 # Limit space removal to highest priority arithmetic operators 279 return False 280 return _HasPrecedence(tok) 281 282 283def _IsSubscriptColonAndValuePair(token1, token2): 284 return (token1.is_number or token1.is_name) and token2.is_subscript_colon 285 286 287def _SpaceRequiredBetween(left, right, is_line_disabled): 288 """Return True if a space is required between the left and right token.""" 289 lval = left.value 290 rval = right.value 291 if (left.is_pseudo and _IsIdNumberStringToken(right) and 292 left.previous_token and _IsIdNumberStringToken(left.previous_token)): 293 # Space between keyword... tokens and pseudo parens. 294 return True 295 if left.is_pseudo or right.is_pseudo: 296 # There should be a space after the ':' in a dictionary. 297 if left.OpensScope(): 298 return True 299 # The closing pseudo-paren shouldn't affect spacing. 300 return False 301 if left.is_continuation or right.is_continuation: 302 # The continuation node's value has all of the spaces it needs. 303 return False 304 if right.name in pytree_utils.NONSEMANTIC_TOKENS: 305 # No space before a non-semantic token. 306 return False 307 if _IsIdNumberStringToken(left) and _IsIdNumberStringToken(right): 308 # Spaces between keyword, string, number, and identifier tokens. 309 return True 310 if lval == ',' and rval == ':': 311 # We do want a space between a comma and colon. 312 return True 313 if style.Get('SPACE_INSIDE_BRACKETS'): 314 # Supersede the "no space before a colon or comma" check. 315 if lval in pytree_utils.OPENING_BRACKETS and rval == ':': 316 return True 317 if rval in pytree_utils.CLOSING_BRACKETS and lval == ':': 318 return True 319 if (style.Get('SPACES_AROUND_SUBSCRIPT_COLON') and 320 (_IsSubscriptColonAndValuePair(left, right) or 321 _IsSubscriptColonAndValuePair(right, left))): 322 # Supersede the "never want a space before a colon or comma" check. 323 return True 324 if rval in ':,': 325 # Otherwise, we never want a space before a colon or comma. 326 return False 327 if lval == ',' and rval in ']})': 328 # Add a space between ending ',' and closing bracket if requested. 329 return style.Get('SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET') 330 if lval == ',': 331 # We want a space after a comma. 332 return True 333 if lval == 'from' and rval == '.': 334 # Space before the '.' in an import statement. 335 return True 336 if lval == '.' and rval == 'import': 337 # Space after the '.' in an import statement. 338 return True 339 if (lval == '=' and rval in {'.', ',,,'} and 340 subtypes.DEFAULT_OR_NAMED_ASSIGN not in left.subtypes): 341 # Space between equal and '.' as in "X = ...". 342 return True 343 if lval == ':' and rval in {'.', '...'}: 344 # Space between : and ... 345 return True 346 if ((right.is_keyword or right.is_name) and 347 (left.is_keyword or left.is_name)): 348 # Don't merge two keywords/identifiers. 349 return True 350 if (subtypes.SUBSCRIPT_COLON in left.subtypes or 351 subtypes.SUBSCRIPT_COLON in right.subtypes): 352 # A subscript shouldn't have spaces separating its colons. 353 return False 354 if (subtypes.TYPED_NAME in left.subtypes or 355 subtypes.TYPED_NAME in right.subtypes): 356 # A typed argument should have a space after the colon. 357 return True 358 if left.is_string: 359 if (rval == '=' and 360 subtypes.DEFAULT_OR_NAMED_ASSIGN_ARG_LIST in right.subtypes): 361 # If there is a type hint, then we don't want to add a space between the 362 # equal sign and the hint. 363 return False 364 if rval not in '[)]}.' and not right.is_binary_op: 365 # A string followed by something other than a subscript, closing bracket, 366 # dot, or a binary op should have a space after it. 367 return True 368 if rval in pytree_utils.CLOSING_BRACKETS: 369 # A string followed by closing brackets should have a space after it 370 # depending on SPACE_INSIDE_BRACKETS. A string followed by opening 371 # brackets, however, should not. 372 return style.Get('SPACE_INSIDE_BRACKETS') 373 if subtypes.SUBSCRIPT_BRACKET in right.subtypes: 374 # It's legal to do this in Python: 'hello'[a] 375 return False 376 if left.is_binary_op and lval != '**' and _IsUnaryOperator(right): 377 # Space between the binary operator and the unary operator. 378 return True 379 if left.is_keyword and _IsUnaryOperator(right): 380 # Handle things like "not -3 < x". 381 return True 382 if _IsUnaryOperator(left) and _IsUnaryOperator(right): 383 # No space between two unary operators. 384 return False 385 if left.is_binary_op or right.is_binary_op: 386 if lval == '**' or rval == '**': 387 # Space around the "power" operator. 388 return style.Get('SPACES_AROUND_POWER_OPERATOR') 389 # Enforce spaces around binary operators except the blocked ones. 390 block_list = style.Get('NO_SPACES_AROUND_SELECTED_BINARY_OPERATORS') 391 if lval in block_list or rval in block_list: 392 return False 393 if style.Get('ARITHMETIC_PRECEDENCE_INDICATION'): 394 if _PriorityIndicatingNoSpace(left) or _PriorityIndicatingNoSpace(right): 395 return False 396 else: 397 return True 398 else: 399 return True 400 if (_IsUnaryOperator(left) and lval != 'not' and 401 (right.is_name or right.is_number or rval == '(')): 402 # The previous token was a unary op. No space is desired between it and 403 # the current token. 404 return False 405 if (subtypes.DEFAULT_OR_NAMED_ASSIGN in left.subtypes and 406 subtypes.TYPED_NAME not in right.subtypes): 407 # A named argument or default parameter shouldn't have spaces around it. 408 return style.Get('SPACES_AROUND_DEFAULT_OR_NAMED_ASSIGN') 409 if (subtypes.DEFAULT_OR_NAMED_ASSIGN in right.subtypes and 410 subtypes.TYPED_NAME not in left.subtypes): 411 # A named argument or default parameter shouldn't have spaces around it. 412 return style.Get('SPACES_AROUND_DEFAULT_OR_NAMED_ASSIGN') 413 if (subtypes.VARARGS_LIST in left.subtypes or 414 subtypes.VARARGS_LIST in right.subtypes): 415 return False 416 if (subtypes.VARARGS_STAR in left.subtypes or 417 subtypes.KWARGS_STAR_STAR in left.subtypes): 418 # Don't add a space after a vararg's star or a keyword's star-star. 419 return False 420 if lval == '@' and subtypes.DECORATOR in left.subtypes: 421 # Decorators shouldn't be separated from the 'at' sign. 422 return False 423 if left.is_keyword and rval == '.': 424 # Add space between keywords and dots. 425 return lval not in {'None', 'print'} 426 if lval == '.' and right.is_keyword: 427 # Add space between keywords and dots. 428 return rval not in {'None', 'print'} 429 if lval == '.' or rval == '.': 430 # Don't place spaces between dots. 431 return False 432 if ((lval == '(' and rval == ')') or (lval == '[' and rval == ']') or 433 (lval == '{' and rval == '}')): 434 # Empty objects shouldn't be separated by spaces. 435 return False 436 if not is_line_disabled and (left.OpensScope() or right.ClosesScope()): 437 if (style.GetOrDefault('SPACES_AROUND_DICT_DELIMITERS', False) and ( 438 (lval == '{' and _IsDictListTupleDelimiterTok(left, is_opening=True)) or 439 (rval == '}' and 440 _IsDictListTupleDelimiterTok(right, is_opening=False)))): 441 return True 442 if (style.GetOrDefault('SPACES_AROUND_LIST_DELIMITERS', False) and ( 443 (lval == '[' and _IsDictListTupleDelimiterTok(left, is_opening=True)) or 444 (rval == ']' and 445 _IsDictListTupleDelimiterTok(right, is_opening=False)))): 446 return True 447 if (style.GetOrDefault('SPACES_AROUND_TUPLE_DELIMITERS', False) and ( 448 (lval == '(' and _IsDictListTupleDelimiterTok(left, is_opening=True)) or 449 (rval == ')' and 450 _IsDictListTupleDelimiterTok(right, is_opening=False)))): 451 return True 452 if (lval in pytree_utils.OPENING_BRACKETS and 453 rval in pytree_utils.OPENING_BRACKETS): 454 # Nested objects' opening brackets shouldn't be separated, unless enabled 455 # by SPACE_INSIDE_BRACKETS. 456 return style.Get('SPACE_INSIDE_BRACKETS') 457 if (lval in pytree_utils.CLOSING_BRACKETS and 458 rval in pytree_utils.CLOSING_BRACKETS): 459 # Nested objects' closing brackets shouldn't be separated, unless enabled 460 # by SPACE_INSIDE_BRACKETS. 461 return style.Get('SPACE_INSIDE_BRACKETS') 462 if lval in pytree_utils.CLOSING_BRACKETS and rval in '([': 463 # A call, set, dictionary, or subscript that has a call or subscript after 464 # it shouldn't have a space between them. 465 return False 466 if lval in pytree_utils.OPENING_BRACKETS and _IsIdNumberStringToken(right): 467 # Don't separate the opening bracket from the first item, unless enabled 468 # by SPACE_INSIDE_BRACKETS. 469 return style.Get('SPACE_INSIDE_BRACKETS') 470 if left.is_name and rval in '([': 471 # Don't separate a call or array access from the name. 472 return False 473 if rval in pytree_utils.CLOSING_BRACKETS: 474 # Don't separate the closing bracket from the last item, unless enabled 475 # by SPACE_INSIDE_BRACKETS. 476 # FIXME(morbo): This might be too permissive. 477 return style.Get('SPACE_INSIDE_BRACKETS') 478 if lval == 'print' and rval == '(': 479 # Special support for the 'print' function. 480 return False 481 if lval in pytree_utils.OPENING_BRACKETS and _IsUnaryOperator(right): 482 # Don't separate a unary operator from the opening bracket, unless enabled 483 # by SPACE_INSIDE_BRACKETS. 484 return style.Get('SPACE_INSIDE_BRACKETS') 485 if (lval in pytree_utils.OPENING_BRACKETS and 486 (subtypes.VARARGS_STAR in right.subtypes or 487 subtypes.KWARGS_STAR_STAR in right.subtypes)): 488 # Don't separate a '*' or '**' from the opening bracket, unless enabled 489 # by SPACE_INSIDE_BRACKETS. 490 return style.Get('SPACE_INSIDE_BRACKETS') 491 if rval == ';': 492 # Avoid spaces before a semicolon. (Why is there a semicolon?!) 493 return False 494 if lval == '(' and rval == 'await': 495 # Special support for the 'await' keyword. Don't separate the 'await' 496 # keyword from an opening paren, unless enabled by SPACE_INSIDE_BRACKETS. 497 return style.Get('SPACE_INSIDE_BRACKETS') 498 return True 499 500 501def _MustBreakBefore(prev_token, cur_token): 502 """Return True if a line break is required before the current token.""" 503 if prev_token.is_comment or (prev_token.previous_token and 504 prev_token.is_pseudo and 505 prev_token.previous_token.is_comment): 506 # Must break if the previous token was a comment. 507 return True 508 if (cur_token.is_string and prev_token.is_string and 509 IsSurroundedByBrackets(cur_token)): 510 # We want consecutive strings to be on separate lines. This is a 511 # reasonable assumption, because otherwise they should have written them 512 # all on the same line, or with a '+'. 513 return True 514 return cur_token.must_break_before 515 516 517def _CanBreakBefore(prev_token, cur_token): 518 """Return True if a line break may occur before the current token.""" 519 pval = prev_token.value 520 cval = cur_token.value 521 if py3compat.PY3: 522 if pval == 'yield' and cval == 'from': 523 # Don't break before a yield argument. 524 return False 525 if pval in {'async', 'await'} and cval in {'def', 'with', 'for'}: 526 # Don't break after sync keywords. 527 return False 528 if cur_token.split_penalty >= split_penalty.UNBREAKABLE: 529 return False 530 if pval == '@': 531 # Don't break right after the beginning of a decorator. 532 return False 533 if cval == ':': 534 # Don't break before the start of a block of code. 535 return False 536 if cval == ',': 537 # Don't break before a comma. 538 return False 539 if prev_token.is_name and cval == '(': 540 # Don't break in the middle of a function definition or call. 541 return False 542 if prev_token.is_name and cval == '[': 543 # Don't break in the middle of an array dereference. 544 return False 545 if cur_token.is_comment and prev_token.lineno == cur_token.lineno: 546 # Don't break a comment at the end of the line. 547 return False 548 if subtypes.UNARY_OPERATOR in prev_token.subtypes: 549 # Don't break after a unary token. 550 return False 551 if not style.Get('ALLOW_SPLIT_BEFORE_DEFAULT_OR_NAMED_ASSIGNS'): 552 if (subtypes.DEFAULT_OR_NAMED_ASSIGN in cur_token.subtypes or 553 subtypes.DEFAULT_OR_NAMED_ASSIGN in prev_token.subtypes): 554 return False 555 return True 556 557 558def IsSurroundedByBrackets(tok): 559 """Return True if the token is surrounded by brackets.""" 560 paren_count = 0 561 brace_count = 0 562 sq_bracket_count = 0 563 previous_token = tok.previous_token 564 while previous_token: 565 if previous_token.value == ')': 566 paren_count -= 1 567 elif previous_token.value == '}': 568 brace_count -= 1 569 elif previous_token.value == ']': 570 sq_bracket_count -= 1 571 572 if previous_token.value == '(': 573 if paren_count == 0: 574 return previous_token 575 paren_count += 1 576 elif previous_token.value == '{': 577 if brace_count == 0: 578 return previous_token 579 brace_count += 1 580 elif previous_token.value == '[': 581 if sq_bracket_count == 0: 582 return previous_token 583 sq_bracket_count += 1 584 585 previous_token = previous_token.previous_token 586 return None 587 588 589def _IsDictListTupleDelimiterTok(tok, is_opening): 590 assert tok 591 592 if tok.matching_bracket is None: 593 return False 594 595 if is_opening: 596 open_tok = tok 597 close_tok = tok.matching_bracket 598 else: 599 open_tok = tok.matching_bracket 600 close_tok = tok 601 602 # There must be something in between the tokens 603 if open_tok.next_token == close_tok: 604 return False 605 606 assert open_tok.next_token.node 607 assert open_tok.next_token.node.parent 608 609 return open_tok.next_token.node.parent.type in [ 610 python_symbols.dictsetmaker, 611 python_symbols.listmaker, 612 python_symbols.testlist_gexp, 613 ] 614 615 616_LOGICAL_OPERATORS = frozenset({'and', 'or'}) 617_BITWISE_OPERATORS = frozenset({'&', '|', '^'}) 618_ARITHMETIC_OPERATORS = frozenset({'+', '-', '*', '/', '%', '//', '@'}) 619 620 621def _SplitPenalty(prev_token, cur_token): 622 """Return the penalty for breaking the line before the current token.""" 623 pval = prev_token.value 624 cval = cur_token.value 625 if pval == 'not': 626 return split_penalty.UNBREAKABLE 627 628 if cur_token.node_split_penalty > 0: 629 return cur_token.node_split_penalty 630 631 if style.Get('SPLIT_BEFORE_LOGICAL_OPERATOR'): 632 # Prefer to split before 'and' and 'or'. 633 if pval in _LOGICAL_OPERATORS: 634 return style.Get('SPLIT_PENALTY_LOGICAL_OPERATOR') 635 if cval in _LOGICAL_OPERATORS: 636 return 0 637 else: 638 # Prefer to split after 'and' and 'or'. 639 if pval in _LOGICAL_OPERATORS: 640 return 0 641 if cval in _LOGICAL_OPERATORS: 642 return style.Get('SPLIT_PENALTY_LOGICAL_OPERATOR') 643 644 if style.Get('SPLIT_BEFORE_BITWISE_OPERATOR'): 645 # Prefer to split before '&', '|', and '^'. 646 if pval in _BITWISE_OPERATORS: 647 return style.Get('SPLIT_PENALTY_BITWISE_OPERATOR') 648 if cval in _BITWISE_OPERATORS: 649 return 0 650 else: 651 # Prefer to split after '&', '|', and '^'. 652 if pval in _BITWISE_OPERATORS: 653 return 0 654 if cval in _BITWISE_OPERATORS: 655 return style.Get('SPLIT_PENALTY_BITWISE_OPERATOR') 656 657 if (subtypes.COMP_FOR in cur_token.subtypes or 658 subtypes.COMP_IF in cur_token.subtypes): 659 # We don't mind breaking before the 'for' or 'if' of a list comprehension. 660 return 0 661 if subtypes.UNARY_OPERATOR in prev_token.subtypes: 662 # Try not to break after a unary operator. 663 return style.Get('SPLIT_PENALTY_AFTER_UNARY_OPERATOR') 664 if pval == ',': 665 # Breaking after a comma is fine, if need be. 666 return 0 667 if pval == '**' or cval == '**': 668 return split_penalty.STRONGLY_CONNECTED 669 if (subtypes.VARARGS_STAR in prev_token.subtypes or 670 subtypes.KWARGS_STAR_STAR in prev_token.subtypes): 671 # Don't split after a varargs * or kwargs **. 672 return split_penalty.UNBREAKABLE 673 if prev_token.OpensScope() and cval != '(': 674 # Slightly prefer 675 return style.Get('SPLIT_PENALTY_AFTER_OPENING_BRACKET') 676 if cval == ':': 677 # Don't split before a colon. 678 return split_penalty.UNBREAKABLE 679 if cval == '=': 680 # Don't split before an assignment. 681 return split_penalty.UNBREAKABLE 682 if (subtypes.DEFAULT_OR_NAMED_ASSIGN in prev_token.subtypes or 683 subtypes.DEFAULT_OR_NAMED_ASSIGN in cur_token.subtypes): 684 # Don't break before or after an default or named assignment. 685 return split_penalty.UNBREAKABLE 686 if cval == '==': 687 # We would rather not split before an equality operator. 688 return split_penalty.STRONGLY_CONNECTED 689 if cur_token.ClosesScope(): 690 # Give a slight penalty for splitting before the closing scope. 691 return 100 692 return 0 693