Hello community, here is the log from the commit of package python-yapf for openSUSE:Factory checked in at 2019-04-14 12:22:04 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-yapf (Old) and /work/SRC/openSUSE:Factory/.python-yapf.new.27019 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-yapf" Sun Apr 14 12:22:04 2019 rev:6 rq:692780 version:0.27.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-yapf/python-yapf.changes 2019-02-27 17:28:02.843344481 +0100 +++ /work/SRC/openSUSE:Factory/.python-yapf.new.27019/python-yapf.changes 2019-04-14 12:22:09.899742619 +0200 @@ -1,0 +2,6 @@ +Tue Apr 9 11:51:52 UTC 2019 - Marketa Calabkova <mcalabk...@suse.com> + +- update to version 0.27.0 + * mostly bugfix release, see CHANGELOG for details + +------------------------------------------------------------------- Old: ---- yapf-0.26.0.tar.gz New: ---- yapf-0.27.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-yapf.spec ++++++ --- /var/tmp/diff_new_pack.ofZ7zM/_old 2019-04-14 12:22:13.523746966 +0200 +++ /var/tmp/diff_new_pack.ofZ7zM/_new 2019-04-14 12:22:13.547746995 +0200 @@ -18,7 +18,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-yapf -Version: 0.26.0 +Version: 0.27.0 Release: 0 Summary: A formatter for Python code License: Apache-2.0 ++++++ yapf-0.26.0.tar.gz -> yapf-0.27.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yapf-0.26.0/CHANGELOG new/yapf-0.27.0/CHANGELOG --- old/yapf-0.26.0/CHANGELOG 2019-02-09 08:11:25.000000000 +0100 +++ new/yapf-0.27.0/CHANGELOG 2019-04-07 12:43:54.000000000 +0200 @@ -2,6 +2,33 @@ # All notable changes to this project will be documented in this file. # This project adheres to [Semantic Versioning](http://semver.org/). +## [0.27.0] 2019-04-07 +### Added +- `SPLIT_BEFORE_ARITHMETIC_OPERATOR` splits before an arithmetic operator when + set. `SPLIT_PENALTY_ARITHMETIC_OPERATOR` allows you to set the split penalty + around arithmetic operators. +### Changed +- Catch lib2to3's "TokenError" exception and output a nicer message. +### Fixed +- Parse integer lists correctly, removing quotes if the list is within a + string. +- Adjust the penalties of bitwise operands for '&' and '^', similar to '|'. +- Avoid splitting after opening parens if SPLIT_BEFORE_FIRST_ARGUMENT is set + to False. +- Adjust default SPLIT_PENALTY_AFTER_OPENING_BRACKET. +- Re-enable removal of extra lines on the boundaries of formatted regions. +- Adjust list splitting to avoid splitting before a dictionary element, because + those are likely to be split anyway. If we do split, it leads to horrible + looking code. +- Dictionary arguments were broken in a recent version. It resulted in + unreadable formatting, where the remaining arguments were indented far more + than the dictionary. Fixed so that if the dictionary is the first argument in + a function call and doesn't fit on a single line, then it forces a split. +- Improve the connectiveness between items in a list. This prevents random + splitting when it's not 100% necessary. +- Don't remove a comment attached to a previous object just because it's part + of the "prefix" of a function/class node. + ## [0.26.0] 2019-02-08 ### Added - `ALLOW_SPLIT_BEFORE_DEFAULT_OR_NAMED_ASSIGNS` allows us to split before @@ -10,7 +37,7 @@ if they have higher precedence than other operators in the same expression. ### Changed - `SPACES_BEFORE_COMMENT` can now be assigned to a specific value (standard - behavior) or a list of column values. When assigned to a list, trailing + behavior) or a list of column values. When assigned to a list, trailing comments will be horizontally aligned to the first column value within the list that is greater than the maximum line length in the block. - Don't modify the vertical spacing of a line that has a comment "pylint: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yapf-0.26.0/PKG-INFO new/yapf-0.27.0/PKG-INFO --- old/yapf-0.26.0/PKG-INFO 2019-02-09 08:13:47.000000000 +0100 +++ new/yapf-0.27.0/PKG-INFO 2019-04-07 12:45:51.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: yapf -Version: 0.26.0 +Version: 0.27.0 Summary: A formatter for Python code. Home-page: UNKNOWN Author: Bill Wendling @@ -573,8 +573,11 @@ line that is too long, split such that all elements are on a single line. ``SPLIT_BEFORE_BITWISE_OPERATOR`` - Set to ``True`` to prefer splitting before ``&``, ``|`` or ``^`` rather - than after. + Set to True to prefer splitting before '&', '|' or '^' rather than after. + + ``SPLIT_BEFORE_ARITHMETIC_OPERATOR`` + Set to True to prefer splitting before '+', '-', '*', '/', '//', or '@' + rather than after. ``SPLIT_BEFORE_CLOSING_BRACKET`` Split before the closing bracket if a list or dict literal doesn't fit on @@ -647,6 +650,10 @@ ``SPLIT_PENALTY_AFTER_UNARY_OPERATOR`` The penalty for splitting the line after a unary operator. + ``SPLIT_PENALTY_ARITHMETIC_OPERATOR`` + The penalty of splitting the line around the ``+``, ``-``, ``*``, ``/``, + ``//``, ``%``, and ``@`` operators. + ``SPLIT_PENALTY_BEFORE_IF_EXPR`` The penalty for splitting right before an ``if`` expression. @@ -747,6 +754,31 @@ Please do! YAPF was designed to be used as a library as well as a command line tool. This means that a tool or IDE plugin is free to use YAPF. + ----------------------------------------- + I still get non Pep8 compliant code! Why? + ----------------------------------------- + + YAPF tries very hard to be fully PEP 8 compliant. However, it is paramount + to not risk altering the semantics of your code. Thus, YAPF tries to be as + safe as possible and does not change the token stream + (e.g., by adding parenthesis). + All these cases however, can be easily fixed manually. For instance, + + .. code-block:: python + + from my_package import my_function_1, my_function_2, my_function_3, my_function_4, my_function_5 + + FOO = my_variable_1 + my_variable_2 + my_variable_3 + my_variable_4 + my_variable_5 + my_variable_6 + my_variable_7 + my_variable_8 + + won't be split, but you can easily get it right by just adding parenthesis: + + .. code-block:: python + + from my_package import (my_function_1, my_function_2, my_function_3, + my_function_4, my_function_5) + + FOO = (my_variable_1 + my_variable_2 + my_variable_3 + my_variable_4 + + my_variable_5 + my_variable_6 + my_variable_7 + my_variable_8) Gory Details ============ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yapf-0.26.0/README.rst new/yapf-0.27.0/README.rst --- old/yapf-0.26.0/README.rst 2019-02-08 23:29:19.000000000 +0100 +++ new/yapf-0.27.0/README.rst 2019-03-24 08:56:40.000000000 +0100 @@ -565,8 +565,11 @@ line that is too long, split such that all elements are on a single line. ``SPLIT_BEFORE_BITWISE_OPERATOR`` - Set to ``True`` to prefer splitting before ``&``, ``|`` or ``^`` rather - than after. + Set to True to prefer splitting before '&', '|' or '^' rather than after. + +``SPLIT_BEFORE_ARITHMETIC_OPERATOR`` + Set to True to prefer splitting before '+', '-', '*', '/', '//', or '@' + rather than after. ``SPLIT_BEFORE_CLOSING_BRACKET`` Split before the closing bracket if a list or dict literal doesn't fit on @@ -639,6 +642,10 @@ ``SPLIT_PENALTY_AFTER_UNARY_OPERATOR`` The penalty for splitting the line after a unary operator. +``SPLIT_PENALTY_ARITHMETIC_OPERATOR`` + The penalty of splitting the line around the ``+``, ``-``, ``*``, ``/``, + ``//``, ``%``, and ``@`` operators. + ``SPLIT_PENALTY_BEFORE_IF_EXPR`` The penalty for splitting right before an ``if`` expression. @@ -739,6 +746,31 @@ Please do! YAPF was designed to be used as a library as well as a command line tool. This means that a tool or IDE plugin is free to use YAPF. +----------------------------------------- +I still get non Pep8 compliant code! Why? +----------------------------------------- + +YAPF tries very hard to be fully PEP 8 compliant. However, it is paramount +to not risk altering the semantics of your code. Thus, YAPF tries to be as +safe as possible and does not change the token stream +(e.g., by adding parenthesis). +All these cases however, can be easily fixed manually. For instance, + +.. code-block:: python + + from my_package import my_function_1, my_function_2, my_function_3, my_function_4, my_function_5 + + FOO = my_variable_1 + my_variable_2 + my_variable_3 + my_variable_4 + my_variable_5 + my_variable_6 + my_variable_7 + my_variable_8 + +won't be split, but you can easily get it right by just adding parenthesis: + +.. code-block:: python + + from my_package import (my_function_1, my_function_2, my_function_3, + my_function_4, my_function_5) + + FOO = (my_variable_1 + my_variable_2 + my_variable_3 + my_variable_4 + + my_variable_5 + my_variable_6 + my_variable_7 + my_variable_8) Gory Details ============ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yapf-0.26.0/yapf/__init__.py new/yapf-0.27.0/yapf/__init__.py --- old/yapf-0.26.0/yapf/__init__.py 2019-02-09 08:11:25.000000000 +0100 +++ new/yapf-0.27.0/yapf/__init__.py 2019-04-07 12:43:41.000000000 +0200 @@ -32,13 +32,15 @@ import os import sys +from lib2to3.pgen2 import tokenize + from yapf.yapflib import errors from yapf.yapflib import file_resources from yapf.yapflib import py3compat from yapf.yapflib import style from yapf.yapflib import yapf_api -__version__ = '0.26.0' +__version__ = '0.27.0' def main(argv): @@ -182,12 +184,17 @@ source = [line.rstrip() for line in original_source] source[0] = py3compat.removeBOM(source[0]) - reformatted_source, _ = yapf_api.FormatCode( - py3compat.unicode('\n'.join(source) + '\n'), - filename='<stdin>', - style_config=style_config, - lines=lines, - verify=args.verify) + + try: + reformatted_source, _ = yapf_api.FormatCode( + py3compat.unicode('\n'.join(source) + '\n'), + filename='<stdin>', + style_config=style_config, + lines=lines, + verify=args.verify) + except tokenize.TokenError as e: + raise errors.YapfError('%s:%s' % (e.args[1][0], e.args[0])) + file_resources.WriteReformattedCode('<stdout>', reformatted_source) return 0 @@ -195,9 +202,9 @@ exclude_patterns_from_ignore_file = file_resources.GetExcludePatternsForDir( os.getcwd()) - files = file_resources.GetCommandLineFiles( - args.files, args.recursive, - (args.exclude or []) + exclude_patterns_from_ignore_file) + files = file_resources.GetCommandLineFiles(args.files, args.recursive, + (args.exclude or []) + + exclude_patterns_from_ignore_file) if not files: raise errors.YapfError('Input filenames did not match any python files') @@ -291,6 +298,8 @@ file_resources.WriteReformattedCode(filename, reformatted_code, encoding, in_place) return has_change + except tokenize.TokenError as e: + raise errors.YapfError('%s:%s:%s' % (filename, e.args[1][0], e.args[0])) except SyntaxError as e: e.filename = filename raise diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yapf-0.26.0/yapf/yapflib/comment_splicer.py new/yapf-0.27.0/yapf/yapflib/comment_splicer.py --- old/yapf-0.26.0/yapf/yapflib/comment_splicer.py 2018-08-27 06:43:49.000000000 +0200 +++ new/yapf-0.27.0/yapf/yapflib/comment_splicer.py 2019-04-07 12:40:17.000000000 +0200 @@ -152,6 +152,16 @@ # parent to insert into. See comments above # _STANDALONE_LINE_NODES for more details. node_with_line_parent = _FindNodeWithStandaloneLineParent(child) + + if pytree_utils.NodeName( + node_with_line_parent.parent) in {'funcdef', 'classdef'}: + # Keep a comment that's not attached to a function or class + # next to the object it is attached to. + comment_end = ( + comment_lineno + comment_prefix.rstrip('\n').count('\n')) + if comment_end < node_with_line_parent.lineno - 1: + node_with_line_parent = node_with_line_parent.parent + pytree_utils.InsertNodesBefore( _CreateCommentsFromPrefix( comment_prefix, comment_lineno, 0, standalone=True), @@ -177,8 +187,8 @@ rindex = (0 if '\n' not in comment_prefix.rstrip() else comment_prefix.rstrip().rindex('\n') + 1) comment_column = ( - len(comment_prefix[rindex:]) - len( - comment_prefix[rindex:].lstrip())) + len(comment_prefix[rindex:]) - + len(comment_prefix[rindex:].lstrip())) comments = _CreateCommentsFromPrefix( comment_prefix, comment_lineno, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yapf-0.26.0/yapf/yapflib/format_decision_state.py new/yapf-0.27.0/yapf/yapflib/format_decision_state.py --- old/yapf-0.26.0/yapf/yapflib/format_decision_state.py 2018-12-05 04:29:56.000000000 +0100 +++ new/yapf-0.27.0/yapf/yapflib/format_decision_state.py 2019-04-07 11:18:51.000000000 +0200 @@ -281,7 +281,8 @@ if not self._FitsOnLine(current, tok.matching_bracket): return True - if current.OpensScope() and previous.value == ',': + if (current.OpensScope() and previous.value == ',' and + format_token.Subtype.DICTIONARY_KEY not in current.next_token.subtypes): # If we have a list of tuples, then we can get a similar look as above. If # the full list cannot fit on the line, then we want a split. open_bracket = unwrapped_line.IsSurroundedByBrackets(current) @@ -359,6 +360,11 @@ # assigns. return False + # Don't split if not required + if (not style.Get('SPLIT_BEFORE_EXPRESSION_AFTER_OPENING_PAREN') and + not style.Get('SPLIT_BEFORE_FIRST_ARGUMENT')): + return False + column = self.column - self.stack[-1].last_space return column > style.Get('CONTINUATION_INDENT_WIDTH') @@ -410,14 +416,34 @@ return True pprevious = previous.previous_token + + # A function call with a dictionary as its first argument may result in + # unreadable formatting if the dictionary spans multiple lines. The + # dictionary itself is formatted just fine, but the remaning arguments are + # indented too far: + # + # function_call({ + # KEY_1: 'value one', + # KEY_2: 'value two', + # }, + # default=False) + if (current.value == '{' and previous.value == '(' and pprevious and + pprevious.is_name): + dict_end = current.matching_bracket + next_token = dict_end.next_token + if next_token.value == ',' and not self._FitsOnLine(current, dict_end): + return True + if (current.is_name and pprevious and pprevious.is_name and previous.value == '('): + if (not self._FitsOnLine(previous, previous.matching_bracket) and _IsFunctionCallWithArguments(current)): # There is a function call, with more than 1 argument, where the first - # argument is itself a function call with arguments. In this specific - # case, if we split after the first argument's opening '(', then the - # formatting will look bad for the rest of the arguments. E.g.: + # argument is itself a function call with arguments that does not fit + # into the line. In this specific case, if we split after the first + # argument's opening '(', then the formatting will look bad for the + # rest of the arguments. E.g.: # # outer_function_call(inner_function_call( # inner_arg1, inner_arg2), @@ -425,7 +451,31 @@ # # Instead, enforce a split before that argument to keep things looking # good. - return True + if (style.Get('SPLIT_BEFORE_EXPRESSION_AFTER_OPENING_PAREN') or + style.Get('SPLIT_BEFORE_FIRST_ARGUMENT')): + return True + + opening = _GetOpeningBracket(current) + if (opening and opening.value == '(' and opening.previous_token and + (opening.previous_token.is_name or + opening.previous_token.value in {'*', '**'})): + is_func_call = False + opening = current + while opening: + if opening.value == '(': + is_func_call = True + break + if (not (opening.is_name or opening.value in {'*', '**'}) and + opening.value != '.'): + break + opening = opening.next_token + + if is_func_call: + if (not self._FitsOnLine(current, opening.matching_bracket) or + (opening.matching_bracket.next_token and + opening.matching_bracket.next_token.value != ',' and + not opening.matching_bracket.next_token.ClosesScope())): + return True if (previous.OpensScope() and not current.OpensScope() and not current.is_comment and diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yapf-0.26.0/yapf/yapflib/format_token.py new/yapf-0.27.0/yapf/yapflib/format_token.py --- old/yapf-0.26.0/yapf/yapflib/format_token.py 2019-02-08 23:29:19.000000000 +0100 +++ new/yapf-0.27.0/yapf/yapflib/format_token.py 2019-03-27 05:32:40.000000000 +0100 @@ -89,6 +89,7 @@ the code. Attributes: + node: The PyTree node this token represents. next_token: The token in the unwrapped line after this token or None if this is the last token in the unwrapped line. previous_token: The token in the unwrapped line before this token or None if @@ -169,8 +170,8 @@ else: indent_before = '\t' * indent_level + ' ' * spaces else: - indent_before = ( - ' ' * indent_level * style.Get('INDENT_WIDTH') + ' ' * spaces) + indent_before = (' ' * indent_level * style.Get('INDENT_WIDTH') + + ' ' * spaces) if self.is_comment: comment_lines = [s.lstrip() for s in self.value.splitlines()] @@ -180,15 +181,15 @@ self.value = self.node.value if not self.whitespace_prefix: - self.whitespace_prefix = ( - '\n' * (self.newlines or newlines_before) + indent_before) + self.whitespace_prefix = ('\n' * (self.newlines or newlines_before) + + indent_before) else: self.whitespace_prefix += indent_before def AdjustNewlinesBefore(self, newlines_before): """Change the number of newlines before this token.""" - self.whitespace_prefix = ( - '\n' * newlines_before + self.whitespace_prefix.lstrip('\n')) + self.whitespace_prefix = ('\n' * newlines_before + + self.whitespace_prefix.lstrip('\n')) def RetainHorizontalSpacing(self, first_column, depth): """Retains a token's horizontal spacing.""" @@ -342,18 +343,14 @@ @property @py3compat.lru_cache() def is_multiline_string(self): - """A multiline string.""" - if py3compat.PY3: - prefix = '(' - prefix += 'r|u|R|U|f|F|fr|Fr|fR|FR|rf|rF|Rf|RF' # strings - prefix += '|b|B|br|Br|bR|BR|rb|rB|Rb|RB' # bytes - prefix += ')?' - else: - prefix = '[uUbB]?[rR]?' + """Test if this string is a multiline string. - regex = r'^{prefix}(?P<delim>"""|\'\'\').*(?P=delim)$'.format(prefix=prefix) - return (self.is_string and - re.match(regex, self.value, re.DOTALL) is not None) + Returns: + A multiline string always ends with triple quotes, so if it is a string + token, inspect the last 3 characters and return True if it is a triple + double or triple single quote mark. + """ + return self.is_string and self.value.endswith(('"""', "'''")) @property @py3compat.lru_cache() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yapf-0.26.0/yapf/yapflib/reformatter.py new/yapf-0.27.0/yapf/yapflib/reformatter.py --- old/yapf-0.26.0/yapf/yapflib/reformatter.py 2018-12-05 07:46:02.000000000 +0100 +++ new/yapf-0.27.0/yapf/yapflib/reformatter.py 2019-04-07 11:58:21.000000000 +0200 @@ -114,12 +114,22 @@ def _RetainRequiredVerticalSpacing(cur_uwline, prev_uwline, lines): + """Retain all vertical spacing between lines.""" + if cur_uwline.disable and (not prev_uwline or prev_uwline.disable): + # If both lines are disabled we aren't allowed to reformat anything. + lines = set() + prev_tok = None if prev_uwline is not None: prev_tok = prev_uwline.last for cur_tok in cur_uwline.tokens: _RetainRequiredVerticalSpacingBetweenTokens(cur_tok, prev_tok, lines) + prev_tok = cur_tok + if cur_uwline.disable: + # After the first token we are acting on a single line. So if it is + # disabled we must not reformat. + lines = set() def _RetainRequiredVerticalSpacingBetweenTokens(cur_tok, prev_tok, lines): @@ -151,8 +161,6 @@ pass elif lines and (cur_lineno in lines or prev_lineno in lines): desired_newlines = cur_tok.whitespace_prefix.count('\n') - if desired_newlines < required_newlines: - desired_newlines = required_newlines whitespace_lines = range(prev_lineno + 1, cur_lineno) deletable_lines = len(lines.intersection(whitespace_lines)) required_newlines = max(required_newlines - deletable_lines, @@ -660,8 +668,9 @@ prev_last_token.AdjustNewlinesBefore( 1 + style.Get('BLANK_LINES_AROUND_TOP_LEVEL_DEFINITION')) if first_token.newlines is not None: - pytree_utils.SetNodeAnnotation( - first_token.node, pytree_utils.Annotation.NEWLINES, None) + pytree_utils.SetNodeAnnotation(first_token.node, + pytree_utils.Annotation.NEWLINES, + None) return NO_BLANK_LINES elif _IsClassOrDef(prev_uwline): if not style.Get('BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF'): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yapf-0.26.0/yapf/yapflib/split_penalty.py new/yapf-0.27.0/yapf/yapflib/split_penalty.py --- old/yapf-0.26.0/yapf/yapflib/split_penalty.py 2019-01-14 05:20:23.000000000 +0100 +++ new/yapf-0.27.0/yapf/yapflib/split_penalty.py 2019-04-07 11:46:46.000000000 +0200 @@ -31,6 +31,7 @@ VERY_STRONGLY_CONNECTED = 3500 STRONGLY_CONNECTED = 3000 CONNECTED = 500 +TOGETHER = 100 OR_TEST = 1000 AND_TEST = 1100 @@ -414,27 +415,19 @@ # expr ::= xor_expr ('|' xor_expr)* self.DefaultNodeVisit(node) _IncreasePenalty(node, EXPR) - index = 1 - while index < len(node.children) - 1: - child = node.children[index] - if isinstance(child, pytree.Leaf) and child.value == '|': - if style.Get('SPLIT_BEFORE_BITWISE_OPERATOR'): - _SetSplitPenalty(child, style.Get('SPLIT_PENALTY_BITWISE_OPERATOR')) - else: - _SetSplitPenalty( - pytree_utils.FirstLeafNode(node.children[index + 1]), - style.Get('SPLIT_PENALTY_BITWISE_OPERATOR')) - index += 1 + _SetBitwiseOperandPenalty(node, '|') def Visit_xor_expr(self, node): # pylint: disable=invalid-name # xor_expr ::= and_expr ('^' and_expr)* self.DefaultNodeVisit(node) _IncreasePenalty(node, XOR_EXPR) + _SetBitwiseOperandPenalty(node, '^') def Visit_and_expr(self, node): # pylint: disable=invalid-name # and_expr ::= shift_expr ('&' shift_expr)* self.DefaultNodeVisit(node) _IncreasePenalty(node, AND_EXPR) + _SetBitwiseOperandPenalty(node, '&') def Visit_shift_expr(self, node): # pylint: disable=invalid-name # shift_expr ::= arith_expr (('<<'|'>>') arith_expr)* @@ -447,14 +440,7 @@ # arith_expr ::= term (('+'|'-') term)* self.DefaultNodeVisit(node) _IncreasePenalty(node, ARITH_EXPR) - - index = 1 - while index < len(node.children) - 1: - child = node.children[index] - if pytree_utils.NodeName(child) in self._ARITH_OPS: - next_node = pytree_utils.FirstLeafNode(node.children[index + 1]) - _SetSplitPenalty(next_node, ARITH_EXPR) - index += 1 + _SetExpressionOperandPenalty(node, self._ARITH_OPS) _TERM_OPS = frozenset({'STAR', 'AT', 'SLASH', 'PERCENT', 'DOUBLESLASH'}) @@ -462,14 +448,7 @@ # term ::= factor (('*'|'@'|'/'|'%'|'//') factor)* self.DefaultNodeVisit(node) _IncreasePenalty(node, TERM) - - index = 1 - while index < len(node.children) - 1: - child = node.children[index] - if pytree_utils.NodeName(child) in self._TERM_OPS: - next_node = pytree_utils.FirstLeafNode(node.children[index + 1]) - _SetSplitPenalty(next_node, TERM) - index += 1 + _SetExpressionOperandPenalty(node, self._TERM_OPS) def Visit_factor(self, node): # pyline: disable=invalid-name # factor ::= ('+'|'-'|'~') factor | power @@ -503,7 +482,7 @@ prev_was_comma = True else: if prev_was_comma: - _SetSplitPenalty(pytree_utils.FirstLeafNode(child), 0) + _SetSplitPenalty(pytree_utils.FirstLeafNode(child), TOGETHER) prev_was_comma = False ############################################################################ @@ -558,6 +537,30 @@ RecExpression(node, pytree_utils.FirstLeafNode(node)) +def _SetBitwiseOperandPenalty(node, op): + for index in py3compat.range(1, len(node.children) - 1): + child = node.children[index] + if isinstance(child, pytree.Leaf) and child.value == op: + if style.Get('SPLIT_BEFORE_BITWISE_OPERATOR'): + _SetSplitPenalty(child, style.Get('SPLIT_PENALTY_BITWISE_OPERATOR')) + else: + _SetSplitPenalty( + pytree_utils.FirstLeafNode(node.children[index + 1]), + style.Get('SPLIT_PENALTY_BITWISE_OPERATOR')) + + +def _SetExpressionOperandPenalty(node, ops): + for index in py3compat.range(1, len(node.children) - 1): + child = node.children[index] + if pytree_utils.NodeName(child) in ops: + if style.Get('SPLIT_BEFORE_ARITHMETIC_OPERATOR'): + _SetSplitPenalty(child, style.Get('SPLIT_PENALTY_ARITHMETIC_OPERATOR')) + else: + _SetSplitPenalty( + pytree_utils.FirstLeafNode(node.children[index + 1]), + style.Get('SPLIT_PENALTY_ARITHMETIC_OPERATOR')) + + def _IncreasePenalty(node, amt): """Increase a penalty annotation on children nodes.""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yapf-0.26.0/yapf/yapflib/style.py new/yapf-0.27.0/yapf/yapflib/style.py --- old/yapf-0.26.0/yapf/yapflib/style.py 2019-02-09 08:11:18.000000000 +0100 +++ new/yapf-0.27.0/yapf/yapflib/style.py 2019-03-24 08:56:40.000000000 +0100 @@ -125,8 +125,6 @@ - FIXED: Use fixed number (CONTINUATION_INDENT_WIDTH) of columns (ie: CONTINUATION_INDENT_WIDTH/INDENT_WIDTH tabs) for continuation alignment. - - LESS: Slightly left if cannot vertically align continuation lines with - indent characters. - VALIGN-RIGHT: Vertically align continuation lines with indent characters. Slightly right (one more indent character) if cannot vertically align continuation lines with indent characters. @@ -189,7 +187,6 @@ will be formatted as follows when configured with "*,/": 1 + 2*3 - 4/5 - """), SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET=textwrap.dedent("""\ Insert a space between the ending comma and closing bracket of a list, @@ -205,7 +202,7 @@ alignment column values; trailing comments within a block will be aligned to the first column value that is greater than the maximum line length within the block). For example: - + With spaces_before_comment=5: 1 + 1 # Adding values @@ -242,6 +239,9 @@ comma."""), SPLIT_ALL_COMMA_SEPARATED_VALUES=textwrap.dedent("""\ Split before arguments"""), + SPLIT_BEFORE_ARITHMETIC_OPERATOR=textwrap.dedent("""\ + Set to True to prefer splitting before '+', '-', '*', '/', '//', or '@' + rather than after."""), SPLIT_BEFORE_BITWISE_OPERATOR=textwrap.dedent("""\ Set to True to prefer splitting before '&', '|' or '^' rather than after."""), @@ -298,6 +298,9 @@ The penalty for splitting right after the opening bracket."""), SPLIT_PENALTY_AFTER_UNARY_OPERATOR=textwrap.dedent("""\ The penalty for splitting the line after a unary operator."""), + SPLIT_PENALTY_ARITHMETIC_OPERATOR=textwrap.dedent("""\ + The penalty of splitting the line around the '+', '-', '*', '/', '//', + ``%``, and '@' operators."""), SPLIT_PENALTY_BEFORE_IF_EXPR=textwrap.dedent("""\ The penalty for splitting right before an if expression."""), SPLIT_PENALTY_BITWISE_OPERATOR=textwrap.dedent("""\ @@ -364,6 +367,7 @@ SPACES_BEFORE_COMMENT=2, SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED=False, SPLIT_ALL_COMMA_SEPARATED_VALUES=False, + SPLIT_BEFORE_ARITHMETIC_OPERATOR=False, SPLIT_BEFORE_BITWISE_OPERATOR=True, SPLIT_BEFORE_CLOSING_BRACKET=True, SPLIT_BEFORE_DICT_SET_GENERATOR=True, @@ -373,8 +377,9 @@ SPLIT_BEFORE_LOGICAL_OPERATOR=True, SPLIT_BEFORE_NAMED_ASSIGNS=True, SPLIT_COMPLEX_COMPREHENSION=False, - SPLIT_PENALTY_AFTER_OPENING_BRACKET=30, + SPLIT_PENALTY_AFTER_OPENING_BRACKET=300, SPLIT_PENALTY_AFTER_UNARY_OPERATOR=10000, + SPLIT_PENALTY_ARITHMETIC_OPERATOR=300, SPLIT_PENALTY_BEFORE_IF_EXPR=0, SPLIT_PENALTY_BITWISE_OPERATOR=300, SPLIT_PENALTY_COMPREHENSION=80, @@ -494,6 +499,8 @@ def _IntOrIntListConverter(s): """Option value converter for an integer or list of integers.""" + if len(s) > 2 and s[0] in '"\'': + s = s[1:-1] return _IntListConverter(s) if ',' in s else int(s) @@ -535,6 +542,7 @@ SPACES_BEFORE_COMMENT=_IntOrIntListConverter, SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED=_BoolConverter, SPLIT_ALL_COMMA_SEPARATED_VALUES=_BoolConverter, + SPLIT_BEFORE_ARITHMETIC_OPERATOR=_BoolConverter, SPLIT_BEFORE_BITWISE_OPERATOR=_BoolConverter, SPLIT_BEFORE_CLOSING_BRACKET=_BoolConverter, SPLIT_BEFORE_DICT_SET_GENERATOR=_BoolConverter, @@ -546,6 +554,7 @@ SPLIT_COMPLEX_COMPREHENSION=_BoolConverter, SPLIT_PENALTY_AFTER_OPENING_BRACKET=int, SPLIT_PENALTY_AFTER_UNARY_OPERATOR=int, + SPLIT_PENALTY_ARITHMETIC_OPERATOR=int, SPLIT_PENALTY_BEFORE_IF_EXPR=int, SPLIT_PENALTY_BITWISE_OPERATOR=int, SPLIT_PENALTY_COMPREHENSION=int, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yapf-0.26.0/yapf/yapflib/subtype_assigner.py new/yapf-0.27.0/yapf/yapflib/subtype_assigner.py --- old/yapf-0.26.0/yapf/yapflib/subtype_assigner.py 2019-02-08 23:29:19.000000000 +0100 +++ new/yapf-0.27.0/yapf/yapflib/subtype_assigner.py 2019-02-10 12:14:20.000000000 +0100 @@ -470,4 +470,4 @@ def _IsSimpleExpression(node): """A node with only leafs as children.""" - return all(map(lambda c: isinstance(c, pytree.Leaf), node.children)) + return all(isinstance(child, pytree.Leaf) for child in node.children) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yapf-0.26.0/yapf/yapflib/unwrapped_line.py new/yapf-0.27.0/yapf/yapflib/unwrapped_line.py --- old/yapf-0.26.0/yapf/yapflib/unwrapped_line.py 2019-02-09 08:08:24.000000000 +0100 +++ new/yapf-0.27.0/yapf/yapflib/unwrapped_line.py 2019-02-10 12:06:49.000000000 +0100 @@ -228,7 +228,7 @@ def _HasPrecedence(tok): - """Whether a binary operation has presedence within its context.""" + """Whether a binary operation has precedence within its context.""" node = tok.node # We let ancestor be the statement surrounding the operation that tok is the @@ -241,12 +241,12 @@ predecessor_type = pytree_utils.NodeName(ancestor) if predecessor_type in ['arith_expr', 'term']: # An ancestor "arith_expr" or "term" means we have found an operator - # with lower presedence than our tok. + # with lower precedence than our tok. return True if predecessor_type != 'atom': # We understand the context to look for precedence within as an # arbitrary nesting of "arith_expr", "term", and "atom" nodes. If we - # leave this context we have not found a lower presedence operator. + # leave this context we have not found a lower precedence operator. return False # Under normal usage we expect a complete parse tree to be available and # we will return before we get an AttributeError from the root. @@ -254,7 +254,7 @@ def _PriorityIndicatingNoSpace(tok): - """Whether to remove spaces around an operator due to presedence.""" + """Whether to remove spaces around an operator due to precedence.""" if not tok.is_arithmetic_op or not tok.is_simple_expr: # Limit space removal to highest priority arithmetic operators return False @@ -519,7 +519,7 @@ _LOGICAL_OPERATORS = frozenset({'and', 'or'}) _BITWISE_OPERATORS = frozenset({'&', '|', '^'}) -_TERM_OPERATORS = frozenset({'*', '/', '%', '//', '@'}) +_ARITHMETIC_OPERATORS = frozenset({'+', '-', '*', '/', '%', '//', '@'}) def _SplitPenalty(prev_token, cur_token): @@ -568,9 +568,6 @@ if pval == ',': # Breaking after a comma is fine, if need be. return 0 - if prev_token.is_binary_op: - # We would rather not split after an equality operator. - return split_penalty.CONNECTED if pval == '**' or cval == '**': return split_penalty.STRONGLY_CONNECTED if (format_token.Subtype.VARARGS_STAR in prev_token.subtypes or @@ -596,6 +593,4 @@ if cur_token.ClosesScope(): # Give a slight penalty for splitting before the closing scope. return 100 - if pval in _TERM_OPERATORS or cval in _TERM_OPERATORS: - return 50 return 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yapf-0.26.0/yapf.egg-info/PKG-INFO new/yapf-0.27.0/yapf.egg-info/PKG-INFO --- old/yapf-0.26.0/yapf.egg-info/PKG-INFO 2019-02-09 08:13:47.000000000 +0100 +++ new/yapf-0.27.0/yapf.egg-info/PKG-INFO 2019-04-07 12:45:51.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: yapf -Version: 0.26.0 +Version: 0.27.0 Summary: A formatter for Python code. Home-page: UNKNOWN Author: Bill Wendling @@ -573,8 +573,11 @@ line that is too long, split such that all elements are on a single line. ``SPLIT_BEFORE_BITWISE_OPERATOR`` - Set to ``True`` to prefer splitting before ``&``, ``|`` or ``^`` rather - than after. + Set to True to prefer splitting before '&', '|' or '^' rather than after. + + ``SPLIT_BEFORE_ARITHMETIC_OPERATOR`` + Set to True to prefer splitting before '+', '-', '*', '/', '//', or '@' + rather than after. ``SPLIT_BEFORE_CLOSING_BRACKET`` Split before the closing bracket if a list or dict literal doesn't fit on @@ -647,6 +650,10 @@ ``SPLIT_PENALTY_AFTER_UNARY_OPERATOR`` The penalty for splitting the line after a unary operator. + ``SPLIT_PENALTY_ARITHMETIC_OPERATOR`` + The penalty of splitting the line around the ``+``, ``-``, ``*``, ``/``, + ``//``, ``%``, and ``@`` operators. + ``SPLIT_PENALTY_BEFORE_IF_EXPR`` The penalty for splitting right before an ``if`` expression. @@ -747,6 +754,31 @@ Please do! YAPF was designed to be used as a library as well as a command line tool. This means that a tool or IDE plugin is free to use YAPF. + ----------------------------------------- + I still get non Pep8 compliant code! Why? + ----------------------------------------- + + YAPF tries very hard to be fully PEP 8 compliant. However, it is paramount + to not risk altering the semantics of your code. Thus, YAPF tries to be as + safe as possible and does not change the token stream + (e.g., by adding parenthesis). + All these cases however, can be easily fixed manually. For instance, + + .. code-block:: python + + from my_package import my_function_1, my_function_2, my_function_3, my_function_4, my_function_5 + + FOO = my_variable_1 + my_variable_2 + my_variable_3 + my_variable_4 + my_variable_5 + my_variable_6 + my_variable_7 + my_variable_8 + + won't be split, but you can easily get it right by just adding parenthesis: + + .. code-block:: python + + from my_package import (my_function_1, my_function_2, my_function_3, + my_function_4, my_function_5) + + FOO = (my_variable_1 + my_variable_2 + my_variable_3 + my_variable_4 + + my_variable_5 + my_variable_6 + my_variable_7 + my_variable_8) Gory Details ============ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yapf-0.26.0/yapftests/blank_line_calculator_test.py new/yapf-0.27.0/yapftests/blank_line_calculator_test.py --- old/yapf-0.26.0/yapftests/blank_line_calculator_test.py 2018-01-15 01:48:30.000000000 +0100 +++ new/yapf-0.27.0/yapftests/blank_line_calculator_test.py 2019-03-27 05:32:40.000000000 +0100 @@ -350,6 +350,73 @@ self.assertCodeEqual(expected_formatted_code, code) self.assertFalse(changed) + def testLinesRangeRemove(self): + unformatted_code = textwrap.dedent(u"""\ + def A(): + pass + + + + def B(): # 6 + pass # 7 + + + + + def C(): + pass + """) + expected_formatted_code = textwrap.dedent(u"""\ + def A(): + pass + + + def B(): # 6 + pass # 7 + + + def C(): + pass + """) + code, changed = yapf_api.FormatCode(unformatted_code, lines=[(5, 9)]) + self.assertCodeEqual(expected_formatted_code, code) + self.assertTrue(changed) + + def testLinesRangeRemoveSome(self): + unformatted_code = textwrap.dedent(u"""\ + def A(): + pass + + + + + def B(): # 7 + pass # 8 + + + + + def C(): + pass + """) + expected_formatted_code = textwrap.dedent(u"""\ + def A(): + pass + + + + def B(): # 7 + pass # 8 + + + + def C(): + pass + """) + code, changed = yapf_api.FormatCode(unformatted_code, lines=[(6, 9)]) + self.assertCodeEqual(expected_formatted_code, code) + self.assertTrue(changed) + if __name__ == '__main__': unittest.main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yapf-0.26.0/yapftests/reformatter_basic_test.py new/yapf-0.27.0/yapftests/reformatter_basic_test.py --- old/yapf-0.26.0/yapftests/reformatter_basic_test.py 2019-02-09 08:08:24.000000000 +0100 +++ new/yapf-0.27.0/yapftests/reformatter_basic_test.py 2019-04-07 11:45:24.000000000 +0200 @@ -1346,7 +1346,7 @@ return True """) uwlines = yapf_test_helper.ParseAndUnwrap(unformatted_code) - self.assertEqual(expected_code, reformatter.Reformat(uwlines)) + self.assertCodeEqual(expected_code, reformatter.Reformat(uwlines)) def testDictSetGenerator(self): code = textwrap.dedent("""\ @@ -1896,8 +1896,8 @@ if True: if True: if True: - boxes[id_] = np.concatenate((points.min(axis=0), - qoints.max(axis=0))) + boxes[id_] = np.concatenate( + (points.min(axis=0), qoints.max(axis=0))) """) uwlines = yapf_test_helper.ParseAndUnwrap(unformatted_code) self.assertCodeEqual(expected_formatted_code, reformatter.Reformat(uwlines)) @@ -2202,7 +2202,7 @@ not True) """) uwlines = yapf_test_helper.ParseAndUnwrap(unformatted_code) - self.assertEqual(expected_code, reformatter.Reformat(uwlines)) + self.assertCodeEqual(expected_code, reformatter.Reformat(uwlines)) def testNamedAssignNotAtEndOfLine(self): unformatted_code = textwrap.dedent("""\ @@ -2220,7 +2220,7 @@ pass """) uwlines = yapf_test_helper.ParseAndUnwrap(unformatted_code) - self.assertEqual(expected_code, reformatter.Reformat(uwlines)) + self.assertCodeEqual(expected_code, reformatter.Reformat(uwlines)) def testBlankLineBeforeClassDocstring(self): unformatted_code = textwrap.dedent('''\ @@ -2245,7 +2245,7 @@ pass ''') uwlines = yapf_test_helper.ParseAndUnwrap(unformatted_code) - self.assertEqual(expected_code, reformatter.Reformat(uwlines)) + self.assertCodeEqual(expected_code, reformatter.Reformat(uwlines)) try: style.SetGlobalStyle( @@ -2301,7 +2301,7 @@ pass ''') uwlines = yapf_test_helper.ParseAndUnwrap(unformatted_code) - self.assertEqual(expected_code, reformatter.Reformat(uwlines)) + self.assertCodeEqual(expected_code, reformatter.Reformat(uwlines)) try: style.SetGlobalStyle( @@ -2346,7 +2346,7 @@ ('a string that may be too long %s' % 'M15')) """) uwlines = yapf_test_helper.ParseAndUnwrap(unformatted_code) - self.assertEqual(expected_code, reformatter.Reformat(uwlines)) + self.assertCodeEqual(expected_code, reformatter.Reformat(uwlines)) def testSubscriptExpression(self): code = textwrap.dedent("""\ @@ -2380,7 +2380,7 @@ ] """) uwlines = yapf_test_helper.ParseAndUnwrap(unformatted_code) - self.assertEqual(expected_code, reformatter.Reformat(uwlines)) + self.assertCodeEqual(expected_code, reformatter.Reformat(uwlines)) def testEllipses(self): unformatted_code = textwrap.dedent("""\ @@ -2392,7 +2392,7 @@ Y = X if ... else X """) uwlines = yapf_test_helper.ParseAndUnwrap(unformatted_code) - self.assertEqual(expected_code, reformatter.Reformat(uwlines)) + self.assertCodeEqual(expected_code, reformatter.Reformat(uwlines)) def testPseudoParens(self): unformatted_code = """\ @@ -2410,7 +2410,7 @@ } """ uwlines = yapf_test_helper.ParseAndUnwrap(unformatted_code) - self.assertEqual(expected_code, reformatter.Reformat(uwlines)) + self.assertCodeEqual(expected_code, reformatter.Reformat(uwlines)) def testSplittingBeforeFirstArgumentOnFunctionCall(self): """Tests split_before_first_argument on a function call.""" @@ -2598,6 +2598,59 @@ finally: style.SetGlobalStyle(style.CreateChromiumStyle()) + def testMultipleDictionariesInList(self): + unformatted_code = """\ +class A: + def b(): + d = { + "123456": [ + { + "12": "aa" + }, + { + "12": "bb" + }, + { + "12": "cc", + "1234567890": { + "1234567": [{ + "12": "dd", + "12345": "text 1" + }, { + "12": "ee", + "12345": "text 2" + }] + } + } + ] + } +""" + expected_formatted_code = """\ +class A: + + def b(): + d = { + "123456": [{ + "12": "aa" + }, { + "12": "bb" + }, { + "12": "cc", + "1234567890": { + "1234567": [{ + "12": "dd", + "12345": "text 1" + }, { + "12": "ee", + "12345": "text 2" + }] + } + }] + } +""" + uwlines = yapf_test_helper.ParseAndUnwrap(unformatted_code) + self.assertCodeEqual(expected_formatted_code, reformatter.Reformat(uwlines)) + if __name__ == '__main__': unittest.main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yapf-0.26.0/yapftests/reformatter_buganizer_test.py new/yapf-0.27.0/yapftests/reformatter_buganizer_test.py --- old/yapf-0.26.0/yapftests/reformatter_buganizer_test.py 2018-12-05 12:44:21.000000000 +0100 +++ new/yapf-0.27.0/yapftests/reformatter_buganizer_test.py 2019-04-07 12:30:31.000000000 +0200 @@ -28,6 +28,42 @@ def setUpClass(cls): style.SetGlobalStyle(style.CreateChromiumStyle()) + def testB122541552(self): + code = """\ +# pylint: disable=g-explicit-bool-comparison,singleton-comparison +_QUERY = account.Account.query(account.Account.enabled == True) +# pylint: enable=g-explicit-bool-comparison,singleton-comparison + + +def _(): + pass +""" + uwlines = yapf_test_helper.ParseAndUnwrap(code) + self.assertCodeEqual(code, reformatter.Reformat(uwlines)) + + def testB124415889(self): + code = """\ +class _(): + + def run_queue_scanners(): + return xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx( + { + components.NAME.FNOR: True, + components.NAME.DEVO: True, + }, + default=False) + + def modules_to_install(): + modules = DeepCopy(GetDef({})) + modules.update({ + 'xxxxxxxxxxxxxxxxxxxx': + GetDef('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz', None), + }) + return modules +""" + uwlines = yapf_test_helper.ParseAndUnwrap(code) + self.assertCodeEqual(code, reformatter.Reformat(uwlines)) + def testB73166511(self): code = """\ def _(): @@ -840,8 +876,8 @@ expected_formatted_code = textwrap.dedent("""\ class _(): def _(): - hints.append(('hg tag -f -l -r %s %s # %s' % (short( - ctx.node()), candidatetag, firstline))[:78]) + hints.append(('hg tag -f -l -r %s %s # %s' % + (short(ctx.node()), candidatetag, firstline))[:78]) """) uwlines = yapf_test_helper.ParseAndUnwrap(unformatted_code) self.assertCodeEqual(expected_formatted_code, reformatter.Reformat(uwlines)) @@ -1149,8 +1185,8 @@ class _(): def __repr__(self): - return '<session %s on %s>' % (self._id, - self._stub._stub.rpc_channel().target()) # pylint:disable=protected-access + return '<session %s on %s>' % ( + self._id, self._stub._stub.rpc_channel().target()) # pylint:disable=protected-access """) uwlines = yapf_test_helper.ParseAndUnwrap(code) self.assertCodeEqual(code, reformatter.Reformat(uwlines)) @@ -1457,8 +1493,8 @@ expected_formatted_code = textwrap.dedent("""\ def foo(): if True: - return ( - struct.pack('aaaa', bbbbbbbbbb, ccccccccccccccc, dddddddd) + eeeeeee) + return (struct.pack('aaaa', bbbbbbbbbb, ccccccccccccccc, dddddddd) + + eeeeeee) """) uwlines = yapf_test_helper.ParseAndUnwrap(unformatted_code) self.assertCodeEqual(expected_formatted_code, reformatter.Reformat(uwlines)) @@ -1546,7 +1582,7 @@ try: style.SetGlobalStyle( style.CreateStyleFromConfig( - '{based_on_style: pep8, split_penalty_import_names: 35}')) + '{based_on_style: pep8, split_penalty_import_names: 350}')) unformatted_code = textwrap.dedent("""\ from a_very_long_or_indented_module_name_yada_yada import (long_argument_1, long_argument_2) @@ -2193,8 +2229,8 @@ }) """) expected_formatted_code = textwrap.dedent("""\ - shelf_renderer.expand_text = text.translate_to_unicode( - expand_text % {'creator': creator}) + shelf_renderer.expand_text = text.translate_to_unicode(expand_text % + {'creator': creator}) """) uwlines = yapf_test_helper.ParseAndUnwrap(unformatted_code) self.assertCodeEqual(expected_formatted_code, reformatter.Reformat(uwlines)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yapf-0.26.0/yapftests/reformatter_pep8_test.py new/yapf-0.27.0/yapftests/reformatter_pep8_test.py --- old/yapf-0.26.0/yapftests/reformatter_pep8_test.py 2019-01-14 05:20:23.000000000 +0100 +++ new/yapf-0.27.0/yapftests/reformatter_pep8_test.py 2019-04-07 11:44:33.000000000 +0200 @@ -165,8 +165,8 @@ """) expected_formatted_code = textwrap.dedent("""\ if True: - runtime_mins = ( - program_end_time - program_start_time).total_seconds() / 60.0 + runtime_mins = (program_end_time - + program_start_time).total_seconds() / 60.0 """) uwlines = yapf_test_helper.ParseAndUnwrap(unformatted_code) self.assertCodeEqual(expected_formatted_code, reformatter.Reformat(uwlines)) @@ -190,8 +190,10 @@ if (aaaaaaaaaaaaaa + bbbbbbbbbbbbbbbb == ccccccccccccccccc and xxxxxxxxxxxxx or yyyyyyyyyyyyyyyyy): pass - elif (xxxxxxxxxxxxxxx( - aaaaaaaaaaa, bbbbbbbbbbbbbb, cccccccccccc, dddddddddd=None)): + elif (xxxxxxxxxxxxxxx(aaaaaaaaaaa, + bbbbbbbbbbbbbb, + cccccccccccc, + dddddddddd=None)): pass @@ -431,6 +433,64 @@ finally: style.SetGlobalStyle(style.CreatePEP8Style()) + def testBitwiseOperandSplitting(self): + unformatted_code = """\ +def _(): + include_values = np.where( + (cdffile['Quality_Flag'][:] >= 5) & ( + cdffile['Day_Night_Flag'][:] == 1) & ( + cdffile['Longitude'][:] >= select_lon - radius) & ( + cdffile['Longitude'][:] <= select_lon + radius) & ( + cdffile['Latitude'][:] >= select_lat - radius) & ( + cdffile['Latitude'][:] <= select_lat + radius)) +""" + expected_code = """\ +def _(): + include_values = np.where( + (cdffile['Quality_Flag'][:] >= 5) & (cdffile['Day_Night_Flag'][:] == 1) + & (cdffile['Longitude'][:] >= select_lon - radius) + & (cdffile['Longitude'][:] <= select_lon + radius) + & (cdffile['Latitude'][:] >= select_lat - radius) + & (cdffile['Latitude'][:] <= select_lat + radius)) +""" + uwlines = yapf_test_helper.ParseAndUnwrap(unformatted_code) + self.assertEqual(expected_code, reformatter.Reformat(uwlines)) + + def testSplitBeforeArithmeticOperators(self): + try: + style.SetGlobalStyle( + style.CreateStyleFromConfig( + '{based_on_style: pep8, split_before_arithmetic_operator: true}')) + + unformatted_code = """\ +def _(): + raise ValueError('This is a long message that ends with an argument: ' + str(42)) +""" + expected_formatted_code = """\ +def _(): + raise ValueError('This is a long message that ends with an argument: ' + + str(42)) +""" + uwlines = yapf_test_helper.ParseAndUnwrap(unformatted_code) + self.assertCodeEqual(expected_formatted_code, + reformatter.Reformat(uwlines)) + finally: + style.SetGlobalStyle(style.CreatePEP8Style()) + + def testListSplitting(self): + unformatted_code = """\ +foo([(1,1), (1,1), (1,1), (1,1), (1,1), (1,1), (1,1), + (1,1), (1,1), (1,1), (1,1), (1,1), (1,1), (1,1), + (1,10), (1,11), (1, 10), (1,11), (10,11)]) +""" + expected_code = """\ +foo([(1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), + (1, 1), (1, 1), (1, 1), (1, 1), (1, 1), (1, 10), (1, 11), (1, 10), + (1, 11), (10, 11)]) +""" + uwlines = yapf_test_helper.ParseAndUnwrap(unformatted_code) + self.assertCodeEqual(expected_code, reformatter.Reformat(uwlines)) + if __name__ == '__main__': unittest.main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yapf-0.26.0/yapftests/reformatter_style_config_test.py new/yapf-0.27.0/yapftests/reformatter_style_config_test.py --- old/yapf-0.26.0/yapftests/reformatter_style_config_test.py 2019-02-09 08:08:24.000000000 +0100 +++ new/yapf-0.27.0/yapftests/reformatter_style_config_test.py 2019-03-24 08:56:40.000000000 +0100 @@ -121,6 +121,78 @@ style.SetGlobalStyle(style.CreatePEP8Style()) style.DEFAULT_STYLE = self.current_style + def testNoSplitBeforeFirstArgumentStyle1(self): + try: + pep8_no_split_before_first = style.CreatePEP8Style() + pep8_no_split_before_first['SPLIT_BEFORE_FIRST_ARGUMENT'] = False + pep8_no_split_before_first['SPLIT_BEFORE_NAMED_ASSIGNS'] = False + style.SetGlobalStyle(pep8_no_split_before_first) + formatted_code = textwrap.dedent("""\ + # Example from in-code MustSplit comments + foo = outer_function_call(fitting_inner_function_call(inner_arg1, inner_arg2), + outer_arg1, outer_arg2) + + foo = outer_function_call( + not_fitting_inner_function_call(inner_arg1, inner_arg2), outer_arg1, + outer_arg2) + + # Examples Issue#424 + a_super_long_version_of_print(argument1, argument2, argument3, argument4, + argument5, argument6, argument7) + + CREDS_FILE = os.path.join(os.path.expanduser('~'), + 'apis/super-secret-admin-creds.json') + + # Examples Issue#556 + i_take_a_lot_of_params(arg1, param1=very_long_expression1(), + param2=very_long_expression2(), + param3=very_long_expression3(), + param4=very_long_expression4()) + + # Examples Issue#590 + plt.plot(numpy.linspace(0, 1, 10), numpy.linspace(0, 1, 10), marker="x", + color="r") + + plt.plot(veryverylongvariablename, veryverylongvariablename, marker="x", + color="r") + """) + uwlines = yapf_test_helper.ParseAndUnwrap(formatted_code) + self.assertCodeEqual(formatted_code, reformatter.Reformat(uwlines)) + finally: + style.SetGlobalStyle(style.CreatePEP8Style()) + style.DEFAULT_STYLE = self.current_style + + def testNoSplitBeforeFirstArgumentStyle2(self): + try: + pep8_no_split_before_first = style.CreatePEP8Style() + pep8_no_split_before_first['SPLIT_BEFORE_FIRST_ARGUMENT'] = False + pep8_no_split_before_first['SPLIT_BEFORE_NAMED_ASSIGNS'] = True + style.SetGlobalStyle(pep8_no_split_before_first) + formatted_code = textwrap.dedent("""\ + # Examples Issue#556 + i_take_a_lot_of_params(arg1, + param1=very_long_expression1(), + param2=very_long_expression2(), + param3=very_long_expression3(), + param4=very_long_expression4()) + + # Examples Issue#590 + plt.plot(numpy.linspace(0, 1, 10), + numpy.linspace(0, 1, 10), + marker="x", + color="r") + + plt.plot(veryverylongvariablename, + veryverylongvariablename, + marker="x", + color="r") + """) + uwlines = yapf_test_helper.ParseAndUnwrap(formatted_code) + self.assertCodeEqual(formatted_code, reformatter.Reformat(uwlines)) + finally: + style.SetGlobalStyle(style.CreatePEP8Style()) + style.DEFAULT_STYLE = self.current_style + if __name__ == '__main__': unittest.main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yapf-0.26.0/yapftests/yapf_test.py new/yapf-0.27.0/yapftests/yapf_test.py --- old/yapf-0.26.0/yapftests/yapf_test.py 2018-12-05 07:45:00.000000000 +0100 +++ new/yapf-0.27.0/yapftests/yapf_test.py 2019-04-07 12:38:27.000000000 +0200 @@ -24,11 +24,14 @@ import textwrap import unittest +from lib2to3.pgen2 import tokenize + from yapf.yapflib import py3compat from yapf.yapflib import style from yapf.yapflib import yapf_api from yapftests import utils +from yapftests import yapf_test_helper ROOT_DIR = os.path.dirname(os.path.abspath(os.path.dirname(__file__))) @@ -36,12 +39,12 @@ YAPF_BINARY = [sys.executable, '-m', 'yapf', '--verify', '--no-local-style'] -class FormatCodeTest(unittest.TestCase): +class FormatCodeTest(yapf_test_helper.YAPFTest): def _Check(self, unformatted_code, expected_formatted_code): formatted_code, _ = yapf_api.FormatCode( unformatted_code, style_config='chromium') - self.assertEqual(expected_formatted_code, formatted_code) + self.assertCodeEqual(expected_formatted_code, formatted_code) def testSimple(self): unformatted_code = textwrap.dedent("""\ @@ -512,7 +515,26 @@ style_file = textwrap.dedent(u'''\ [style] based_on_style = chromium - SPACES_BEFORE_COMMENT = 4 + spaces_before_comment = 4 + ''') + with utils.TempFileContents(self.test_tmpdir, style_file) as stylepath: + self.assertYapfReformats( + unformatted_code, + expected_formatted_code, + extra_options=['--style={0}'.format(stylepath)]) + + def testSetCustomStyleSpacesBeforeComment(self): + unformatted_code = textwrap.dedent("""\ + a_very_long_statement_that_extends_way_beyond # Comment + short # This is a shorter statement + """) + expected_formatted_code = textwrap.dedent("""\ + a_very_long_statement_that_extends_way_beyond # Comment + short # This is a shorter statement + """) + style_file = textwrap.dedent(u'''\ + [style] + spaces_before_comment = 15, 20 ''') with utils.TempFileContents(self.test_tmpdir, style_file) as stylepath: self.assertYapfReformats( @@ -1409,6 +1431,10 @@ code = ' a = 1\n' self.assertRaises(SyntaxError, yapf_api.FormatCode, code) + def testBadCode(self): + code = 'x = """hello\n' + self.assertRaises(tokenize.TokenError, yapf_api.FormatCode, code) + class DiffIndentTest(unittest.TestCase): @@ -1436,12 +1462,12 @@ self._Check(unformatted_code, expected_formatted_code) -class HorizontallyAlignedTrailingCommentsTest(unittest.TestCase): +class HorizontallyAlignedTrailingCommentsTest(yapf_test_helper.YAPFTest): @staticmethod def _OwnStyle(): my_style = style.CreatePEP8Style() - my_style["SPACES_BEFORE_COMMENT"] = [ + my_style['SPACES_BEFORE_COMMENT'] = [ 15, 25, 35, @@ -1451,7 +1477,7 @@ def _Check(self, unformatted_code, expected_formatted_code): formatted_code, _ = yapf_api.FormatCode( unformatted_code, style_config=style.SetGlobalStyle(self._OwnStyle())) - self.assertEqual(expected_formatted_code, formatted_code) + self.assertCodeEqual(expected_formatted_code, formatted_code) def testSimple(self): unformatted_code = textwrap.dedent("""\ @@ -1518,7 +1544,7 @@ func(2) # Line 2 # Line 3 func(3) # Line 4 - # Line 5 - SpliceComments makes this a new block + # Line 5 # Line 6 def Func(): @@ -1529,9 +1555,8 @@ func(2) # Line 2 # Line 3 func(3) # Line 4 - - # Line 5 - SpliceComments makes this a new block - # Line 6 + # Line 5 + # Line 6 def Func():