@@ -117,11 +117,13 @@ def lru_cache(maxsize=128): # noqa as it's a fake implementation.
117117WS_OPTIONAL_OPERATORS = ARITHMETIC_OP .union (['^' , '&' , '|' , '<<' , '>>' , '%' ])
118118# Warn for -> function annotation operator in py3.5+ (issue 803)
119119FUNCTION_RETURN_ANNOTATION_OP = ['->' ] if sys .version_info >= (3 , 5 ) else []
120+ ASSIGNMENT_EXPRESSION_OP = [':=' ] if sys .version_info >= (3 , 8 ) else []
120121WS_NEEDED_OPERATORS = frozenset ([
121122 '**=' , '*=' , '/=' , '//=' , '+=' , '-=' , '!=' , '<>' , '<' , '>' ,
122123 '%=' , '^=' , '&=' , '|=' , '==' , '<=' , '>=' , '<<=' , '>>=' , '=' ,
123124 'and' , 'in' , 'is' , 'or' ] +
124- FUNCTION_RETURN_ANNOTATION_OP )
125+ FUNCTION_RETURN_ANNOTATION_OP +
126+ ASSIGNMENT_EXPRESSION_OP )
125127WHITESPACE = frozenset (' \t ' )
126128NEWLINE = frozenset ([tokenize .NL , tokenize .NEWLINE ])
127129SKIP_TOKENS = NEWLINE .union ([tokenize .INDENT , tokenize .DEDENT ])
@@ -134,7 +136,7 @@ def lru_cache(maxsize=128): # noqa as it's a fake implementation.
134136RERAISE_COMMA_REGEX = re .compile (r'raise\s+\w+\s*,.*,\s*\w+\s*$' )
135137ERRORCODE_REGEX = re .compile (r'\b[A-Z]\d{3}\b' )
136138DOCSTRING_REGEX = re .compile (r'u?r?["\']' )
137- EXTRANEOUS_WHITESPACE_REGEX = re .compile (r'[\[({] | [\]}),;:] ' )
139+ EXTRANEOUS_WHITESPACE_REGEX = re .compile (r'[\[({] | [\]}),;]| :(?!=) ' )
138140WHITESPACE_AFTER_COMMA_REGEX = re .compile (r'[,;:]\s*(?: |\t)' )
139141COMPARE_SINGLETON_REGEX = re .compile (r'(\bNone|\bFalse|\bTrue)?\s*([=!]=)'
140142 r'\s*(?(1)|(None|False|True))\b' )
@@ -495,13 +497,16 @@ def missing_whitespace(logical_line):
495497 line = logical_line
496498 for index in range (len (line ) - 1 ):
497499 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 :
499502 before = line [:index ]
500503 if char == ':' and before .count ('[' ) > before .count (']' ) and \
501504 before .rfind ('{' ) < before .rfind ('[' ):
502505 continue # Slice syntax, no space required
503- if char == ',' and line [ index + 1 ] == ')' :
506+ if char == ',' and next_char == ')' :
504507 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
505510 yield index , "E231 missing whitespace after '%s'" % char
506511
507512
@@ -1142,7 +1147,9 @@ def compound_statements(logical_line):
11421147 update_counts (line [prev_found :found ], counts )
11431148 if ((counts ['{' ] <= counts ['}' ] and # {'a': 1} (dict)
11441149 counts ['[' ] <= counts [']' ] and # [1:2] (slice)
1145- counts ['(' ] <= counts [')' ])): # (annotation)
1150+ counts ['(' ] <= counts [')' ]) and # (annotation)
1151+ not (sys .version_info >= (3 , 8 ) and
1152+ line [found + 1 ] == '=' )): # assignment expression
11461153 lambda_kw = LAMBDA_REGEX .search (line , 0 , found )
11471154 if lambda_kw :
11481155 before = line [:lambda_kw .start ()].rstrip ()
0 commit comments