@@ -138,8 +138,8 @@ def tabs_or_spaces(physical_line, indent_char):
138138 warnings about code that illegally mixes tabs and spaces. When using -tt
139139 these warnings become errors. These options are highly recommended!
140140
141- Okay: if a == 0:\n a = 1\n b = 1
142- E101: if a == 0:\n a = 1\n\tb = 1
141+ Okay: if a == 0:\n a = 1
142+ E101: if a == 0:\n \ta = 1
143143 """
144144 indent = INDENT_REGEX .match (physical_line ).group (1 )
145145 for offset , char in enumerate (indent ):
@@ -351,8 +351,8 @@ def missing_whitespace(logical_line):
351351 yield index , "E231 missing whitespace after '%s'" % char
352352
353353
354- def indentation (logical_line , previous_logical , indent_char ,
355- indent_level , previous_indent_level ):
354+ def indentation (logical_line , previous_logical , indent_char , initial_indent ,
355+ indent_level , previous_indent_level , physical_line ):
356356 r"""Use 4 spaces per indentation level.
357357
358358 For really old code that you don't want to mess up, you can continue to
@@ -370,14 +370,53 @@ def indentation(logical_line, previous_logical, indent_char,
370370 Okay: a = 1\nb = 2
371371 E113: a = 1\n b = 2
372372 E116: a = 1\n # b = 2
373+
374+ Okay: if a == 0:\n a = 1\nif a == 1:\n a = 1
375+ W191: if a == 0:\n\ta = 1\nif a == 1:\n\ta = 1
376+
377+ E117: if a == 0:\n\ta = 1\nif a == 1:\n a = 1
378+
379+ E118: # if a == 0:\n a = 1\nif a == 1:\n\ta = 1
380+
373381 """
382+
374383 c = 0 if logical_line else 3
384+ indent = INDENT_REGEX .match (physical_line ).group (1 )
385+ tab = "\t "
375386 tmpl = "E11%d %s" if logical_line else "E11%d %s (comment)"
376- if indent_level % 4 :
377- yield 0 , tmpl % (1 + c , "indentation is not a multiple of four" )
378387 indent_expect = previous_logical .endswith (':' )
388+
389+ expectedTabs = previous_indent_level // 4 + 1
390+ expectedSpaces = previous_indent_level + 4
391+ numTabs = indent .count ("\t " )
392+ numSpaces = sum (a .isspace () for a in indent ) - numTabs
393+
394+ if indent_level % 4 :
395+ yield 0 , tmpl % (1 + c , "indentation is not a multiple of 4" )
396+
379397 if indent_expect and indent_level <= previous_indent_level :
380398 yield 0 , tmpl % (2 + c , "expected an indented block" )
399+ elif indent_expect and indent_level > previous_indent_level :
400+ if initial_indent == tab :
401+ if ' ' in indent :
402+ yield 0 , tmpl % (7 , "TAB ERROR: %d tabs indentation "
403+ "expected; indentation was %d tabs and "
404+ "%d spaces" %
405+ (expectedTabs , numTabs , numSpaces ))
406+ elif indent_level != previous_indent_level + 4 :
407+ yield 0 , tmpl % (7 , "TAB ERROR: %d tabs indentation "
408+ "expected; indentation was %d tabs" %
409+ (expectedTabs , numTabs ))
410+ else :
411+ if tab in indent :
412+ yield 0 , tmpl % (8 , "SPACE ERROR: %d spaces indentation "
413+ "expected; indentation was %d tabs and "
414+ "%d spaces" %
415+ (expectedSpaces , numTabs , numSpaces ))
416+ elif indent_level != previous_indent_level + 4 :
417+ yield 0 , tmpl % (8 , "SPACE ERROR: %d SPACES indentation "
418+ "expected; indentation was %d spaces" %
419+ (expectedSpaces , indent_level ))
381420 elif not indent_expect and indent_level > previous_indent_level :
382421 yield 0 , tmpl % (3 + c , "unexpected indentation" )
383422
@@ -1207,18 +1246,18 @@ def expand_indent(line):
12071246 >>> expand_indent(' ')
12081247 4
12091248 >>> expand_indent('\t')
1210- 8
1249+ 4
12111250 >>> expand_indent(' \t')
12121251 8
12131252 >>> expand_indent(' \t')
1214- 16
1253+ 12
12151254 """
12161255 if '\t ' not in line :
12171256 return len (line ) - len (line .lstrip ())
12181257 result = 0
12191258 for char in line :
12201259 if char == '\t ' :
1221- result = result // 8 * 8 + 8
1260+ result = result // 4 * 4 + 4
12221261 elif char == ' ' :
12231262 result += 1
12241263 else :
@@ -1419,6 +1458,7 @@ def readline(self):
14191458 self .line_number += 1
14201459 if self .indent_char is None and line [:1 ] in WHITESPACE :
14211460 self .indent_char = line [0 ]
1461+ self .initial_indent = line [0 ]
14221462 return line
14231463
14241464 def run_check (self , check , argument_names ):
@@ -1574,6 +1614,7 @@ def check_all(self, expected=None, line_offset=0):
15741614 self .check_ast ()
15751615 self .line_number = 0
15761616 self .indent_char = None
1617+ self .initial_indent = None
15771618 self .indent_level = self .previous_indent_level = 0
15781619 self .previous_logical = ''
15791620 self .tokens = []
0 commit comments