blob: ae97581fd86956392f6f8ee62543031fd960a9f3 [file] [log] [blame]
Guido van Rossum6f73c1a1998-03-20 19:23:04 +00001#! /usr/bin/env python
2
3"""The Tab Police watches for possibly inconsistent indentation."""
4
5import os
6import sys
7import getopt
Guido van Rossum6f73c1a1998-03-20 19:23:04 +00008import tokenize
9
10verbose = 0
Guido van Rossum97df7f81998-03-26 19:23:43 +000011quiet = 0
Guido van Rossum6f73c1a1998-03-20 19:23:04 +000012
13def main():
Guido van Rossum97df7f81998-03-26 19:23:43 +000014 global verbose, quiet
Guido van Rossum6f73c1a1998-03-20 19:23:04 +000015 try:
Guido van Rossum97df7f81998-03-26 19:23:43 +000016 opts, args = getopt.getopt(sys.argv[1:], "qv")
Guido van Rossum6f73c1a1998-03-20 19:23:04 +000017 except getopt.error, msg:
18 print msg
Guido van Rossum8053d891998-04-06 14:45:26 +000019 return
Guido van Rossum6f73c1a1998-03-20 19:23:04 +000020 for o, a in opts:
21 if o == '-v':
22 verbose = verbose + 1
Guido van Rossum97df7f81998-03-26 19:23:43 +000023 quiet = 0
24 if o == '-q':
25 quiet = 1
26 verbose = 0
Guido van Rossum8053d891998-04-06 14:45:26 +000027 if not args:
28 print "Usage:", sys.argv[0], "file_or_directory ..."
29 return
Guido van Rossum6f73c1a1998-03-20 19:23:04 +000030 for arg in args:
31 check(arg)
32
33def check(file):
34 if os.path.isdir(file) and not os.path.islink(file):
35 if verbose:
36 print "%s: listing directory" % `file`
37 names = os.listdir(file)
38 for name in names:
39 fullname = os.path.join(file, name)
40 if (os.path.isdir(fullname) and
41 not os.path.islink(fullname) or
42 os.path.normcase(name[-3:]) == ".py"):
43 check(fullname)
44 return
45
46 try:
47 f = open(file)
48 except IOError, msg:
49 print "%s: I/O Error: %s" % (`file`, str(msg))
50 return
51
52 if verbose > 1:
53 print "checking", `file`, "with tabsize 8..."
54 tokens = []
55 tokenize.tabsize = 8
56 try:
57 tokenize.tokenize(f.readline, tokens.append)
58 except tokenize.TokenError, msg:
59 print "%s: Token Error: %s" % (`file`, str(msg))
60
61 if verbose > 1:
Guido van Rossum3db0e371998-03-24 04:58:04 +000062 print "checking", `file`, "with tabsize 1..."
Guido van Rossum6f73c1a1998-03-20 19:23:04 +000063 f.seek(0)
64 alttokens = []
Guido van Rossum3db0e371998-03-24 04:58:04 +000065 tokenize.tabsize = 1
Guido van Rossum6f73c1a1998-03-20 19:23:04 +000066 try:
67 tokenize.tokenize(f.readline, alttokens.append)
68 except tokenize.TokenError, msg:
69 print "%s: Token Error: %s" % (`file`, str(msg))
70 f.close()
71
Guido van Rossum97df7f81998-03-26 19:23:43 +000072 if tokens == alttokens:
73 if verbose:
74 print "%s: Clean bill of health." % `file`
75 elif quiet:
76 print file
77 else:
Guido van Rossum3db0e371998-03-24 04:58:04 +000078 badline = 0
79 n, altn = len(tokens), len(alttokens)
80 for i in range(max(n, altn)):
81 if i >= n:
82 x = None
83 else:
84 x = tokens[i]
85 if i >= altn:
86 y = None
87 else:
88 y = alttokens[i]
89 if x != y:
90 if x:
91 kind, token, start, end, line = x
92 else:
93 kind, token, start, end, line = y
94 badline = start[0]
95 break
Guido van Rossum6f73c1a1998-03-20 19:23:04 +000096 if verbose:
Guido van Rossum3db0e371998-03-24 04:58:04 +000097 print "%s: *** Line %d: trouble in tab city! ***" % (
98 `file`, badline)
99 print "offending line:", `line`
Guido van Rossum6f73c1a1998-03-20 19:23:04 +0000100 else:
Guido van Rossum3db0e371998-03-24 04:58:04 +0000101 print file, badline, `line`
Guido van Rossum6f73c1a1998-03-20 19:23:04 +0000102
103if __name__ == '__main__':
104 main()