Skip to content

Commit f04e2a1

Browse files
committed
combine whitespace around operator checks
this slightly simplifies some checking
1 parent 1d83954 commit f04e2a1

File tree

3 files changed

+54
-52
lines changed

3 files changed

+54
-52
lines changed

pycodestyle.py

Lines changed: 50 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -499,48 +499,6 @@ def missing_whitespace_after_keyword(logical_line, tokens):
499499
yield tok0.end, "E275 missing whitespace after keyword"
500500

501501

502-
@register_check
503-
def missing_whitespace(logical_line, tokens):
504-
r"""Each comma, semicolon or colon should be followed by whitespace.
505-
506-
Okay: [a, b]
507-
Okay: (3,)
508-
Okay: a[3,] = 1
509-
Okay: a[1:4]
510-
Okay: a[:4]
511-
Okay: a[1:]
512-
Okay: a[1:4:2]
513-
E231: ['a','b']
514-
E231: foo(bar,baz)
515-
E231: [{'a':'b'}]
516-
"""
517-
brace_stack = []
518-
for tok in tokens:
519-
if tok.type == tokenize.OP and tok.string in {'[', '(', '{'}:
520-
brace_stack.append(tok.string)
521-
elif tok.type == FSTRING_START:
522-
brace_stack.append('f')
523-
elif brace_stack:
524-
if tok.type == tokenize.OP and tok.string in {']', ')', '}'}:
525-
brace_stack.pop()
526-
elif tok.type == FSTRING_END:
527-
brace_stack.pop()
528-
529-
if tok.type == tokenize.OP and tok.string in {',', ';', ':'}:
530-
next_char = tok.line[tok.end[1]:tok.end[1] + 1]
531-
if next_char not in WHITESPACE and next_char not in '\r\n':
532-
# slice
533-
if tok.string == ':' and brace_stack[-1:] == ['[']:
534-
continue
535-
# 3.12+ fstring format specifier
536-
elif tok.string == ':' and brace_stack[-2:] == ['f', '{']:
537-
continue
538-
# tuple (and list for some reason?)
539-
elif tok.string == ',' and next_char in ')]':
540-
continue
541-
yield tok.end, f'E231 missing whitespace after {tok.string!r}'
542-
543-
544502
@register_check
545503
def indentation(logical_line, previous_logical, indent_char,
546504
indent_level, previous_indent_level,
@@ -856,14 +814,16 @@ def whitespace_around_operator(logical_line):
856814

857815

858816
@register_check
859-
def missing_whitespace_around_operator(logical_line, tokens):
860-
r"""Surround operators with a single space on either side.
817+
def missing_whitespace(logical_line, tokens):
818+
r"""Surround operators with the correct amount of whitespace.
861819
862820
- Always surround these binary operators with a single space on
863821
either side: assignment (=), augmented assignment (+=, -= etc.),
864822
comparisons (==, <, >, !=, <=, >=, in, not in, is, is not),
865823
Booleans (and, or, not).
866824
825+
- Each comma, semicolon or colon should be followed by whitespace.
826+
867827
- If operators with different priorities are used, consider adding
868828
whitespace around the operators with the lowest priorities.
869829
@@ -874,6 +834,13 @@ def missing_whitespace_around_operator(logical_line, tokens):
874834
Okay: c = (a + b) * (a - b)
875835
Okay: foo(bar, key='word', *args, **kwargs)
876836
Okay: alpha[:-i]
837+
Okay: [a, b]
838+
Okay: (3,)
839+
Okay: a[3,] = 1
840+
Okay: a[1:4]
841+
Okay: a[:4]
842+
Okay: a[1:]
843+
Okay: a[1:4:2]
877844
878845
E225: i=i+1
879846
E225: submitted +=1
@@ -884,19 +851,52 @@ def missing_whitespace_around_operator(logical_line, tokens):
884851
E226: hypot2 = x*x + y*y
885852
E227: c = a|b
886853
E228: msg = fmt%(errno, errmsg)
854+
E231: ['a','b']
855+
E231: foo(bar,baz)
856+
E231: [{'a':'b'}]
887857
"""
888-
parens = 0
889858
need_space = False
890859
prev_type = tokenize.OP
891860
prev_text = prev_end = None
892861
operator_types = (tokenize.OP, tokenize.NAME)
862+
brace_stack = []
893863
for token_type, text, start, end, line in tokens:
864+
if token_type == tokenize.OP and text in {'[', '(', '{'}:
865+
brace_stack.append(text)
866+
elif token_type == FSTRING_START:
867+
brace_stack.append('f')
868+
elif token_type == tokenize.NAME and text == 'lambda':
869+
brace_stack.append('l')
870+
elif brace_stack:
871+
if token_type == tokenize.OP and text in {']', ')', '}'}:
872+
brace_stack.pop()
873+
elif token_type == FSTRING_END:
874+
brace_stack.pop()
875+
elif (
876+
brace_stack[-1] == 'l' and
877+
token_type == tokenize.OP and
878+
text == ':'
879+
):
880+
brace_stack.pop()
881+
894882
if token_type in SKIP_COMMENTS:
895883
continue
896-
if text in ('(', 'lambda'):
897-
parens += 1
898-
elif text == ')':
899-
parens -= 1
884+
885+
if token_type == tokenize.OP and text in {',', ';', ':'}:
886+
next_char = line[end[1]:end[1] + 1]
887+
if next_char not in WHITESPACE and next_char not in '\r\n':
888+
# slice
889+
if text == ':' and brace_stack[-1:] == ['[']:
890+
pass
891+
# 3.12+ fstring format specifier
892+
elif text == ':' and brace_stack[-2:] == ['f', '{']:
893+
pass
894+
# tuple (and list for some reason?)
895+
elif text == ',' and next_char in ')]':
896+
pass
897+
else:
898+
yield end, f'E231 missing whitespace after {text!r}'
899+
900900
if need_space:
901901
if start != prev_end:
902902
# Found a (probably) needed space
@@ -933,7 +933,7 @@ def missing_whitespace_around_operator(logical_line, tokens):
933933
"around %s operator" % (code, optype))
934934
need_space = False
935935
elif token_type in operator_types and prev_end is not None:
936-
if text == '=' and parens:
936+
if text == '=' and brace_stack and brace_stack[-1] in {'l', '('}:
937937
# Allow keyword args or defaults: foo(bar=None).
938938
pass
939939
elif text in WS_NEEDED_OPERATORS:

testsuite/E22.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@
9898
c = (a +b)*(a - b)
9999
#: E225 E226
100100
c = (a+ b)*(a - b)
101+
#: E225
102+
x[lambda: None]=1
101103
#:
102104

103105
#: E226

testsuite/test_E901.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def lasting(self, duration=300):
2323
'''
2424
errors = errors_from_src(src)
2525
if sys.version_info < (3, 12):
26-
expected = ['E122:4:1', 'E225:4:27', 'E251:5:13', 'E251:5:15']
26+
expected = ['E122:4:1', 'E251:5:13', 'E251:5:15']
2727
else:
28-
expected = ['E122:4:1', 'E225:4:27', 'E251:5:13', 'E251:5:15', 'E901:5:1'] # noqa: E501
28+
expected = ['E122:4:1', 'E251:5:13', 'E251:5:15', 'E901:5:1'] # noqa: E501
2929
self.assertEqual(errors, expected)

0 commit comments

Comments
 (0)