@@ -117,11 +117,13 @@ def lru_cache(maxsize=128): # noqa as it's a fake implementation.
117
117
WS_OPTIONAL_OPERATORS = ARITHMETIC_OP .union (['^' , '&' , '|' , '<<' , '>>' , '%' ])
118
118
# Warn for -> function annotation operator in py3.5+ (issue 803)
119
119
FUNCTION_RETURN_ANNOTATION_OP = ['->' ] if sys .version_info >= (3 , 5 ) else []
120
+ ASSIGNMENT_EXPRESSION_OP = [':=' ] if sys .version_info >= (3 , 8 ) else []
120
121
WS_NEEDED_OPERATORS = frozenset ([
121
122
'**=' , '*=' , '/=' , '//=' , '+=' , '-=' , '!=' , '<>' , '<' , '>' ,
122
123
'%=' , '^=' , '&=' , '|=' , '==' , '<=' , '>=' , '<<=' , '>>=' , '=' ,
123
124
'and' , 'in' , 'is' , 'or' ] +
124
- FUNCTION_RETURN_ANNOTATION_OP )
125
+ FUNCTION_RETURN_ANNOTATION_OP +
126
+ ASSIGNMENT_EXPRESSION_OP )
125
127
WHITESPACE = frozenset (' \t ' )
126
128
NEWLINE = frozenset ([tokenize .NL , tokenize .NEWLINE ])
127
129
SKIP_TOKENS = NEWLINE .union ([tokenize .INDENT , tokenize .DEDENT ])
@@ -134,7 +136,7 @@ def lru_cache(maxsize=128): # noqa as it's a fake implementation.
134
136
RERAISE_COMMA_REGEX = re .compile (r'raise\s+\w+\s*,.*,\s*\w+\s*$' )
135
137
ERRORCODE_REGEX = re .compile (r'\b[A-Z]\d{3}\b' )
136
138
DOCSTRING_REGEX = re .compile (r'u?r?["\']' )
137
- EXTRANEOUS_WHITESPACE_REGEX = re .compile (r'[\[({] | [\]}),;:] ' )
139
+ EXTRANEOUS_WHITESPACE_REGEX = re .compile (r'[\[({] | [\]}),;]| :(?!=) ' )
138
140
WHITESPACE_AFTER_COMMA_REGEX = re .compile (r'[,;:]\s*(?: |\t)' )
139
141
COMPARE_SINGLETON_REGEX = re .compile (r'(\bNone|\bFalse|\bTrue)?\s*([=!]=)'
140
142
r'\s*(?(1)|(None|False|True))\b' )
@@ -495,13 +497,16 @@ def missing_whitespace(logical_line):
495
497
line = logical_line
496
498
for index in range (len (line ) - 1 ):
497
499
char = line [index ]
498
- if char in ',;:' and line [index + 1 ] not in WHITESPACE :
500
+ next_char = line [index + 1 ]
501
+ if char in ',;:' and next_char not in WHITESPACE :
499
502
before = line [:index ]
500
503
if char == ':' and before .count ('[' ) > before .count (']' ) and \
501
504
before .rfind ('{' ) < before .rfind ('[' ):
502
505
continue # Slice syntax, no space required
503
- if char == ',' and line [ index + 1 ] == ')' :
506
+ if char == ',' and next_char == ')' :
504
507
continue # Allow tuple with only one element: (3,)
508
+ if char == ':' and next_char == '=' and sys .version_info >= (3 , 8 ):
509
+ continue # Allow assignment expression
505
510
yield index , "E231 missing whitespace after '%s'" % char
506
511
507
512
@@ -1141,7 +1146,9 @@ def compound_statements(logical_line):
1141
1146
update_counts (line [prev_found :found ], counts )
1142
1147
if ((counts ['{' ] <= counts ['}' ] and # {'a': 1} (dict)
1143
1148
counts ['[' ] <= counts [']' ] and # [1:2] (slice)
1144
- counts ['(' ] <= counts [')' ])): # (annotation)
1149
+ counts ['(' ] <= counts [')' ]) and # (annotation)
1150
+ not (sys .version_info >= (3 , 8 ) and
1151
+ line [found + 1 ] == '=' )): # assignment expression
1145
1152
lambda_kw = LAMBDA_REGEX .search (line , 0 , found )
1146
1153
if lambda_kw :
1147
1154
before = line [:lambda_kw .start ()].rstrip ()
0 commit comments