Skip to content

Commit bcbd486

Browse files
committed
Merge pull request #305 from yole/break-around-binary-operator
Thanks for the patch!
2 parents 1f4227b + 7f2a185 commit bcbd486

File tree

2 files changed

+47
-7
lines changed

2 files changed

+47
-7
lines changed

pep8.py

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -515,8 +515,9 @@ def continued_indentation(logical_line, tokens, indent_level, hang_closing,
515515
yield start, "%s continuation line %s" % error
516516

517517
# look for visual indenting
518-
if (parens[row] and token_type not in (tokenize.NL, tokenize.COMMENT)
519-
and not indent[depth]):
518+
if (parens[row] and
519+
token_type not in (tokenize.NL, tokenize.COMMENT) and
520+
not indent[depth]):
520521
indent[depth] = start[1]
521522
indent_chances[start[1]] = True
522523
if verbose >= 4:
@@ -1000,6 +1001,45 @@ def explicit_line_join(logical_line, tokens):
10001001
parens -= 1
10011002

10021003

1004+
def break_around_binary_operator(logical_line, tokens):
1005+
r"""
1006+
Avoid breaks before binary operators.
1007+
1008+
The preferred place to break around a binary operator is after the
1009+
operator, not before it.
1010+
1011+
W503: (width == 0\n + height == 0)
1012+
W503: (width == 0\n and height == 0)
1013+
1014+
Okay: (width == 0 +\n height == 0)
1015+
Okay: foo(\n -x)
1016+
Okay: foo(x\n [])
1017+
Okay: x = '''\n''' + ''
1018+
Okay: foo(x,\n -y)
1019+
Okay: foo(x, # comment\n -y)
1020+
"""
1021+
def is_binary_operator(token_type, text):
1022+
# The % character is strictly speaking a binary operator, but the
1023+
# common usage seems to be to put it next to the format parameters,
1024+
# after a line break.
1025+
return ((token_type == tokenize.OP or text in ['and', 'or']) and
1026+
text not in "()[]{},:.;@=%")
1027+
1028+
line_break = False
1029+
unary_context = True
1030+
for token_type, text, start, end, line in tokens:
1031+
if token_type == tokenize.COMMENT:
1032+
continue
1033+
if ('\n' in text or '\r' in text) and token_type != tokenize.STRING:
1034+
line_break = True
1035+
else:
1036+
if (is_binary_operator(token_type, text) and line_break and
1037+
not unary_context):
1038+
yield start, "W503 line break before binary operator"
1039+
unary_context = text in '([{,;'
1040+
line_break = False
1041+
1042+
10031043
def comparison_to_singleton(logical_line, noqa):
10041044
r"""Comparison to singletons should use "is" or "is not".
10051045
@@ -1415,8 +1455,8 @@ def build_tokens_line(self):
14151455
(start_row, start_col) = start
14161456
if prev_row != start_row: # different row
14171457
prev_text = self.lines[prev_row - 1][prev_col - 1]
1418-
if prev_text == ',' or (prev_text not in '{[('
1419-
and text not in '}])'):
1458+
if prev_text == ',' or (prev_text not in '{[(' and
1459+
text not in '}])'):
14201460
text = ' ' + text
14211461
elif prev_col != start_col: # different column
14221462
text = line[prev_col:start_col] + text

testsuite/E12.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -323,14 +323,14 @@ def qualify_by_address(self, cr, uid, ids, context=None,
323323
rv.update(d=('a', 'b', 'c'),
324324
e=42)
325325
#
326-
#: E127
326+
#: E127 W503
327327
rv.update(d=('a' + 'b', 'c'),
328328
e=42, f=42
329329
+ 42)
330-
#: E127
330+
#: E127 W503
331331
input1 = {'a': {'calc': 1 + 2}, 'b': 1
332332
+ 42}
333-
#: E128
333+
#: E128 W503
334334
rv.update(d=('a' + 'b', 'c'),
335335
e=42, f=(42
336336
+ 42))

0 commit comments

Comments
 (0)