68
68
__version__ = '2.1.0.dev0'
69
69
70
70
DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__,.tox'
71
- DEFAULT_IGNORE = 'E121,E123,E126,E226,E24,E704,W503'
71
+ DEFAULT_IGNORE = 'E121,E123,E126,E226,E24,E704,W503,W504 '
72
72
try :
73
73
if sys .platform == 'win32' :
74
74
USER_CONFIG = os .path .expanduser (r'~\.pycodestyle' )
@@ -1033,7 +1033,46 @@ def explicit_line_join(logical_line, tokens):
1033
1033
parens -= 1
1034
1034
1035
1035
1036
- def break_around_binary_operator (logical_line , tokens ):
1036
+ def _is_binary_operator (token_type , text ):
1037
+ is_op_token = token_type == tokenize .OP
1038
+ is_conjunction = text in ['and' , 'or' ]
1039
+ # NOTE(sigmavirus24): Previously the not_a_symbol check was executed
1040
+ # conditionally. Since it is now *always* executed, text may be None.
1041
+ # In that case we get a TypeError for `text not in str`.
1042
+ not_a_symbol = text and text not in "()[]{},:.;@=%~"
1043
+ # The % character is strictly speaking a binary operator, but the
1044
+ # common usage seems to be to put it next to the format parameters,
1045
+ # after a line break.
1046
+ return ((is_op_token or is_conjunction ) and not_a_symbol )
1047
+
1048
+
1049
+ def _break_around_binary_operators (tokens ):
1050
+ """Private function to reduce duplication.
1051
+
1052
+ This factors out the shared details between
1053
+ :func:`break_before_binary_operator` and
1054
+ :func:`break_after_binary_operator`.
1055
+ """
1056
+ line_break = False
1057
+ unary_context = True
1058
+ # Previous non-newline token types and text
1059
+ previous_token_type = None
1060
+ previous_text = None
1061
+ for token_type , text , start , end , line in tokens :
1062
+ if token_type == tokenize .COMMENT :
1063
+ continue
1064
+ if ('\n ' in text or '\r ' in text ) and token_type != tokenize .STRING :
1065
+ line_break = True
1066
+ else :
1067
+ yield (token_type , text , previous_token_type , previous_text ,
1068
+ line_break , unary_context , start )
1069
+ unary_context = text in '([{,;'
1070
+ line_break = False
1071
+ previous_token_type = token_type
1072
+ previous_text = text
1073
+
1074
+
1075
+ def break_before_binary_operator (logical_line , tokens ):
1037
1076
r"""
1038
1077
Avoid breaks before binary operators.
1039
1078
@@ -1053,33 +1092,46 @@ def break_around_binary_operator(logical_line, tokens):
1053
1092
Okay: var = (1 /\n -2)
1054
1093
Okay: var = (1 +\n -1 +\n -2)
1055
1094
"""
1056
- def is_binary_operator (token_type , text ):
1057
- # The % character is strictly speaking a binary operator, but the
1058
- # common usage seems to be to put it next to the format parameters,
1059
- # after a line break.
1060
- return ((token_type == tokenize .OP or text in ['and' , 'or' ]) and
1061
- text not in "()[]{},:.;@=%~" )
1095
+ for context in _break_around_binary_operators (tokens ):
1096
+ (token_type , text , previous_token_type , previous_text ,
1097
+ line_break , unary_context , start ) = context
1098
+ if (_is_binary_operator (token_type , text ) and line_break and
1099
+ not unary_context and
1100
+ not _is_binary_operator (previous_token_type ,
1101
+ previous_text )):
1102
+ yield start , "W503 line break before binary operator"
1062
1103
1063
- line_break = False
1064
- unary_context = True
1065
- # Previous non-newline token types and text
1066
- previous_token_type = None
1067
- previous_text = None
1068
- for token_type , text , start , end , line in tokens :
1069
- if token_type == tokenize .COMMENT :
1070
- continue
1071
- if ('\n ' in text or '\r ' in text ) and token_type != tokenize .STRING :
1072
- line_break = True
1073
- else :
1074
- if (is_binary_operator (token_type , text ) and line_break and
1075
- not unary_context and
1076
- not is_binary_operator (previous_token_type ,
1077
- previous_text )):
1078
- yield start , "W503 line break before binary operator"
1079
- unary_context = text in '([{,;'
1080
- line_break = False
1081
- previous_token_type = token_type
1082
- previous_text = text
1104
+
1105
+ def break_after_binary_operator (logical_line , tokens ):
1106
+ r"""
1107
+ Avoid breaks after binary operators.
1108
+
1109
+ The preferred place to break around a binary operator is after the
1110
+ operator, not before it.
1111
+
1112
+ W504: (width == 0 +\n height == 0)
1113
+ W504: (width == 0 and\n height == 0)
1114
+
1115
+ Okay: (width == 0\n + height == 0)
1116
+ Okay: foo(\n -x)
1117
+ Okay: foo(x\n [])
1118
+ Okay: x = '''\n''' + ''
1119
+ Okay: x = '' + '''\n'''
1120
+ Okay: foo(x,\n -y)
1121
+ Okay: foo(x, # comment\n -y)
1122
+ Okay: var = (1\n & ~2)
1123
+ Okay: var = (1\n / -2)
1124
+ Okay: var = (1\n + -1\n + -2)
1125
+ """
1126
+ for context in _break_around_binary_operators (tokens ):
1127
+ (token_type , text , previous_token_type , previous_text ,
1128
+ line_break , unary_context , start ) = context
1129
+ if (_is_binary_operator (previous_token_type , previous_text )
1130
+ and line_break
1131
+ and not unary_context
1132
+ and not _is_binary_operator (token_type , text )):
1133
+ error_pos = (start [0 ] - 1 , start [1 ])
1134
+ yield error_pos , "W504 line break after binary operator"
1083
1135
1084
1136
1085
1137
def comparison_to_singleton (logical_line , noqa ):
0 commit comments