Skip to content

Commit

Permalink
Merge branch 'master' into samuela/unicode-error
Browse files Browse the repository at this point in the history
  • Loading branch information
bwendling committed Aug 6, 2019
2 parents 28f14dd + f25e0e2 commit b8e1d10
Show file tree
Hide file tree
Showing 17 changed files with 732 additions and 198 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,6 @@
/dist
/.tox
/yapf.egg-info

/.idea

16 changes: 15 additions & 1 deletion CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,28 @@
# All notable changes to this project will be documented in this file.
# This project adheres to [Semantic Versioning](http://semver.org/).

## [0.28.0] UNRELEASED
## [0.28.1] UNRELEASED
### Changed
- Collect a parameter list into a single object. This allows us to track how a
parameter list is formatted, keeping state along the way. This helps when
supporting Python 3 type annotations.
### Fixed
- Format subscript lists so that splits are essentially free after a comma.
- Don't add a space between a string and its subscript.
- Extend discovery of '.style.yapf' & 'setup.cfg' files to search the root
directory as well.
- Make sure we have parameters before we start calculating penalties for
splitting them.

## [0.28.0] 2019-07-11
### Added
- New knob `SPLIT_ALL_TOP_LEVEL_COMMA_SEPARATED_VALUES` is a variation on
`SPLIT_ALL_COMMA_SEPARATED_VALUES` in which, if a subexpression with a comma
fits in its starting line, then the subexpression is not split (thus avoiding
unnecessary splits).
### Changed
- Set `INDENT_DICTIONARY_VALUE` for Google style.
- Set `JOIN_MULTIPLE_LINES = False` for Google style.
- Catch and report `UnicodeDecodeError` exceptions.
### Fixed
- `BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF=False` wasn't honored because the
Expand Down
2 changes: 1 addition & 1 deletion yapf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
from yapf.yapflib import style
from yapf.yapflib import yapf_api

__version__ = '0.27.0'
__version__ = '0.28.0'


def main(argv):
Expand Down
2 changes: 1 addition & 1 deletion yapf/yapflib/file_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,10 @@ def GetDefaultStyleForDir(dirname, default_style=style.DEFAULT_STYLE):
if config.has_section('yapf'):
return config_file

dirname = os.path.dirname(dirname)
if (not dirname or not os.path.basename(dirname) or
dirname == os.path.abspath(os.path.sep)):
break
dirname = os.path.dirname(dirname)

global_file = os.path.expanduser(style.GLOBAL_STYLE)
if os.path.exists(global_file):
Expand Down
124 changes: 121 additions & 3 deletions yapf/yapflib/format_decision_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class FormatDecisionState(object):
parenthesis levels.
comp_stack: A stack (of ComprehensionState) keeping track of properties
applying to comprehensions.
param_list_stack: A stack (of ParameterListState) keeping track of
properties applying to function parameter lists.
ignore_stack_for_comparison: Ignore the stack of _ParenState for state
comparison.
"""
Expand All @@ -70,6 +72,7 @@ def __init__(self, line, first_indent):
self.ignore_stack_for_comparison = False
self.stack = [_ParenState(first_indent, first_indent)]
self.comp_stack = []
self.param_list_stack = []
self.first_indent = first_indent
self.column_limit = style.Get('COLUMN_LIMIT')

Expand All @@ -86,6 +89,7 @@ def Clone(self):
new.first_indent = self.first_indent
new.stack = [state.Clone() for state in self.stack]
new.comp_stack = [state.Clone() for state in self.comp_stack]
new.param_list_stack = [state.Clone() for state in self.param_list_stack]
return new

def __eq__(self, other):
Expand All @@ -98,8 +102,9 @@ def __eq__(self, other):
self.line.depth == other.line.depth and
self.lowest_level_on_line == other.lowest_level_on_line and
(self.ignore_stack_for_comparison or
other.ignore_stack_for_comparison or
self.stack == other.stack and self.comp_stack == other.comp_stack))
other.ignore_stack_for_comparison or self.stack == other.stack and
self.comp_stack == other.comp_stack and
self.param_list_stack == other.param_list_stack))

def __ne__(self, other):
return not self == other
Expand Down Expand Up @@ -559,13 +564,16 @@ def AddTokenToState(self, newline, dry_run, must_split=False):
Returns:
The penalty of splitting after the current token.
"""
self._PushParameterListState(newline)

penalty = 0
if newline:
penalty = self._AddTokenOnNewline(dry_run, must_split)
else:
self._AddTokenOnCurrentLine(dry_run)

penalty += self._CalculateComprehensionState(newline)
penalty += self._CalculateParameterListState(newline)

return self.MoveStateToNextToken() + penalty

Expand Down Expand Up @@ -801,6 +809,105 @@ def _CalculateComprehensionState(self, newline):

return penalty

def _PushParameterListState(self, newline):
"""Push a new parameter list state for a function definition.
Args:
newline: Whether the current token is to be added on a newline.
"""
current = self.next_token
previous = current.previous_token

if _IsFunctionDefinition(previous):
first_param_column = previous.total_length + self.stack[-2].indent
self.param_list_stack.append(
object_state.ParameterListState(previous, newline,
first_param_column))

def _CalculateParameterListState(self, newline):
"""Makes required changes to parameter list state.
Args:
newline: Whether the current token is to be added on a newline.
Returns:
The penalty for the token-newline combination given the current
parameter state.
"""
current = self.next_token
previous = current.previous_token
penalty = 0

if _IsFunctionDefinition(previous):
first_param_column = previous.total_length + self.stack[-2].indent
if not newline:
param_list = self.param_list_stack[-1]
if param_list.parameters and param_list.has_typed_return:
last_param = param_list.parameters[-1].first_token
last_token = _LastTokenInLine(previous.matching_bracket)
total_length = last_token.total_length
total_length -= last_param.total_length - len(last_param.value)
if total_length + self.column > self.column_limit:
# If we need to split before the trailing code of a function
# definition with return types, then also split before the opening
# parameter so that the trailing bit isn't indented on a line by
# itself:
#
# def rrrrrrrrrrrrrrrrrrrrrr(ccccccccccccccccccccccc: Tuple[Text]
# ) -> List[Tuple[Text, Text]]:
# pass
penalty += split_penalty.VERY_STRONGLY_CONNECTED
return penalty

if first_param_column <= self.column:
# Make sure we don't split after the opening bracket if the
# continuation indent is greater than the opening bracket:
#
# a(
# b=1,
# c=2)
penalty += split_penalty.VERY_STRONGLY_CONNECTED
return penalty

if not self.param_list_stack:
return penalty

param_list = self.param_list_stack[-1]
if current == self.param_list_stack[-1].closing_bracket:
self.param_list_stack.pop() # We're done with this state.
if newline and param_list.has_typed_return:
if param_list.split_before_closing_bracket:
penalty -= split_penalty.STRONGLY_CONNECTED
elif param_list.LastParamFitsOnLine(self.column):
penalty += split_penalty.STRONGLY_CONNECTED

if (not newline and param_list.has_typed_return and
param_list.has_split_before_first_param):
# Prefer splitting before the closing bracket if there's a return type
# and we've already split before the first parameter.
penalty += split_penalty.STRONGLY_CONNECTED

return penalty

if not param_list.parameters:
return penalty

if newline:
if self._FitsOnLine(param_list.parameters[0].first_token,
_LastTokenInLine(param_list.closing_bracket)):
penalty += split_penalty.STRONGLY_CONNECTED

if (not newline and style.Get('SPLIT_BEFORE_NAMED_ASSIGNS') and
param_list.has_default_values and
current != param_list.parameters[0].first_token and
current != param_list.closing_bracket and
format_token.Subtype.PARAMETER_START in current.subtypes):
# If we want to split before parameters when there are named assigns,
# then add a penalty for not splitting.
penalty += split_penalty.STRONGLY_CONNECTED

return penalty

def _GetNewlineColumn(self):
"""Return the new column on the newline."""
current = self.next_token
Expand Down Expand Up @@ -841,7 +948,18 @@ def _GetNewlineColumn(self):
len(self.line.first.whitespace_prefix.split('\n')[-1]) +
style.Get('INDENT_WIDTH'))
if token_indent == top_of_stack.indent:
return top_of_stack.indent + style.Get('CONTINUATION_INDENT_WIDTH')
if self.param_list_stack and _IsFunctionDef(self.line.first):
last_param = self.param_list_stack[-1]
if (last_param.LastParamFitsOnLine(token_indent) and
not last_param.LastParamFitsOnLine(
token_indent + style.Get('CONTINUATION_INDENT_WIDTH'))):
self.param_list_stack[-1].split_before_closing_bracket = True
return token_indent

if not last_param.LastParamFitsOnLine(token_indent):
self.param_list_stack[-1].split_before_closing_bracket = True
return token_indent
return token_indent + style.Get('CONTINUATION_INDENT_WIDTH')

return top_of_stack.indent

Expand Down
47 changes: 26 additions & 21 deletions yapf/yapflib/format_token.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,28 +36,30 @@ class Subtype(object):
NONE = 0
UNARY_OPERATOR = 1
BINARY_OPERATOR = 2
A_EXPR_OPERATOR = 22
M_EXPR_OPERATOR = 23
SUBSCRIPT_COLON = 3
SUBSCRIPT_BRACKET = 4
DEFAULT_OR_NAMED_ASSIGN = 5
DEFAULT_OR_NAMED_ASSIGN_ARG_LIST = 6
VARARGS_LIST = 7
VARARGS_STAR = 8
KWARGS_STAR_STAR = 9
ASSIGN_OPERATOR = 10
DICTIONARY_KEY = 11
DICTIONARY_KEY_PART = 12
DICTIONARY_VALUE = 13
DICT_SET_GENERATOR = 14
COMP_EXPR = 21
COMP_FOR = 15
COMP_IF = 16
FUNC_DEF = 17
DECORATOR = 18
TYPED_NAME = 19
TYPED_NAME_ARG_LIST = 20
A_EXPR_OPERATOR = 3
M_EXPR_OPERATOR = 4
SUBSCRIPT_COLON = 5
SUBSCRIPT_BRACKET = 6
DEFAULT_OR_NAMED_ASSIGN = 7
DEFAULT_OR_NAMED_ASSIGN_ARG_LIST = 8
VARARGS_LIST = 9
VARARGS_STAR = 10
KWARGS_STAR_STAR = 11
ASSIGN_OPERATOR = 12
DICTIONARY_KEY = 13
DICTIONARY_KEY_PART = 14
DICTIONARY_VALUE = 15
DICT_SET_GENERATOR = 16
COMP_EXPR = 17
COMP_FOR = 18
COMP_IF = 19
FUNC_DEF = 20
DECORATOR = 21
TYPED_NAME = 22
TYPED_NAME_ARG_LIST = 23
SIMPLE_EXPRESSION = 24
PARAMETER_START = 25
PARAMETER_STOP = 26


def _TabbedContinuationAlignPadding(spaces, align_style, tab_width,
Expand Down Expand Up @@ -96,6 +98,8 @@ class FormatToken(object):
this is the first token in the unwrapped line.
matching_bracket: If a bracket token ('[', '{', or '(') the matching
bracket.
parameters: If this and its following tokens make up a parameter list, then
this is a list of those parameters.
container_opening: If the object is in a container, this points to its
opening bracket.
container_elements: If this is the start of a container, a list of the
Expand Down Expand Up @@ -125,6 +129,7 @@ def __init__(self, node):
self.next_token = None
self.previous_token = None
self.matching_bracket = None
self.parameters = []
self.container_opening = None
self.container_elements = []
self.whitespace_prefix = ''
Expand Down

0 comments on commit b8e1d10

Please sign in to comment.