@@ -80,7 +80,7 @@ def lru_cache(maxsize=128): # noqa as it's a fake implementation.
8080__version__ = '2.3.1'
8181
8282DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__,.tox'
83- DEFAULT_IGNORE = 'E121,E123,E126,E226,E24,E704,W503'
83+ DEFAULT_IGNORE = 'E121,E123,E126,E226,E24,E704,W503,W504 '
8484try :
8585 if sys .platform == 'win32' :
8686 USER_CONFIG = os .path .expanduser (r'~\.pycodestyle' )
@@ -1135,8 +1135,47 @@ def explicit_line_join(logical_line, tokens):
11351135 parens -= 1
11361136
11371137
1138+ def _is_binary_operator (token_type , text ):
1139+ is_op_token = token_type == tokenize .OP
1140+ is_conjunction = text in ['and' , 'or' ]
1141+ # NOTE(sigmavirus24): Previously the not_a_symbol check was executed
1142+ # conditionally. Since it is now *always* executed, text may be None.
1143+ # In that case we get a TypeError for `text not in str`.
1144+ not_a_symbol = text and text not in "()[]{},:.;@=%~"
1145+ # The % character is strictly speaking a binary operator, but the
1146+ # common usage seems to be to put it next to the format parameters,
1147+ # after a line break.
1148+ return ((is_op_token or is_conjunction ) and not_a_symbol )
1149+
1150+
1151+ def _break_around_binary_operators (tokens ):
1152+ """Private function to reduce duplication.
1153+
1154+ This factors out the shared details between
1155+ :func:`break_before_binary_operator` and
1156+ :func:`break_after_binary_operator`.
1157+ """
1158+ line_break = False
1159+ unary_context = True
1160+ # Previous non-newline token types and text
1161+ previous_token_type = None
1162+ previous_text = None
1163+ for token_type , text , start , end , line in tokens :
1164+ if token_type == tokenize .COMMENT :
1165+ continue
1166+ if ('\n ' in text or '\r ' in text ) and token_type != tokenize .STRING :
1167+ line_break = True
1168+ else :
1169+ yield (token_type , text , previous_token_type , previous_text ,
1170+ line_break , unary_context , start )
1171+ unary_context = text in '([{,;'
1172+ line_break = False
1173+ previous_token_type = token_type
1174+ previous_text = text
1175+
1176+
11381177@register_check
1139- def break_around_binary_operator (logical_line , tokens ):
1178+ def break_before_binary_operator (logical_line , tokens ):
11401179 r"""
11411180 Avoid breaks before binary operators.
11421181
@@ -1156,33 +1195,47 @@ def break_around_binary_operator(logical_line, tokens):
11561195 Okay: var = (1 /\n -2)
11571196 Okay: var = (1 +\n -1 +\n -2)
11581197 """
1159- def is_binary_operator (token_type , text ):
1160- # The % character is strictly speaking a binary operator, but the
1161- # common usage seems to be to put it next to the format parameters,
1162- # after a line break.
1163- return ((token_type == tokenize .OP or text in ['and' , 'or' ]) and
1164- text not in "()[]{},:.;@=%~" )
1198+ for context in _break_around_binary_operators (tokens ):
1199+ (token_type , text , previous_token_type , previous_text ,
1200+ line_break , unary_context , start ) = context
1201+ if (_is_binary_operator (token_type , text ) and line_break and
1202+ not unary_context and
1203+ not _is_binary_operator (previous_token_type ,
1204+ previous_text )):
1205+ yield start , "W503 line break before binary operator"
11651206
1166- line_break = False
1167- unary_context = True
1168- # Previous non-newline token types and text
1169- previous_token_type = None
1170- previous_text = None
1171- for token_type , text , start , end , line in tokens :
1172- if token_type == tokenize .COMMENT :
1173- continue
1174- if ('\n ' in text or '\r ' in text ) and token_type != tokenize .STRING :
1175- line_break = True
1176- else :
1177- if (is_binary_operator (token_type , text ) and line_break and
1178- not unary_context and
1179- not is_binary_operator (previous_token_type ,
1180- previous_text )):
1181- yield start , "W503 line break before binary operator"
1182- unary_context = text in '([{,;'
1183- line_break = False
1184- previous_token_type = token_type
1185- previous_text = text
1207+
1208+ @register_check
1209+ def break_after_binary_operator (logical_line , tokens ):
1210+ r"""
1211+ Avoid breaks after binary operators.
1212+
1213+ The preferred place to break around a binary operator is after the
1214+ operator, not before it.
1215+
1216+ W504: (width == 0 +\n height == 0)
1217+ W504: (width == 0 and\n height == 0)
1218+
1219+ Okay: (width == 0\n + height == 0)
1220+ Okay: foo(\n -x)
1221+ Okay: foo(x\n [])
1222+ Okay: x = '''\n''' + ''
1223+ Okay: x = '' + '''\n'''
1224+ Okay: foo(x,\n -y)
1225+ Okay: foo(x, # comment\n -y)
1226+ Okay: var = (1\n & ~2)
1227+ Okay: var = (1\n / -2)
1228+ Okay: var = (1\n + -1\n + -2)
1229+ """
1230+ for context in _break_around_binary_operators (tokens ):
1231+ (token_type , text , previous_token_type , previous_text ,
1232+ line_break , unary_context , start ) = context
1233+ if (_is_binary_operator (previous_token_type , previous_text )
1234+ and line_break
1235+ and not unary_context
1236+ and not _is_binary_operator (token_type , text )):
1237+ error_pos = (start [0 ] - 1 , start [1 ])
1238+ yield error_pos , "W504 line break after binary operator"
11861239
11871240
11881241@register_check
0 commit comments