blob: 22005e119e62917c1c06353fea6139f6f0fd8a74 [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
19 for o, a in opts:
20 if o == '-v':
21 verbose = verbose + 1
Guido van Rossum97df7f81998-03-26 19:23:43 +000022 quiet = 0
23 if o == '-q':
24 quiet = 1
25 verbose = 0
Guido van Rossum6f73c1a1998-03-20 19:23:04 +000026 for arg in args:
27 check(arg)
28
29def check(file):
30 if os.path.isdir(file) and not os.path.islink(file):
31 if verbose:
32 print "%s: listing directory" % `file`
33 names = os.listdir(file)
34 for name in names:
35 fullname = os.path.join(file, name)
36 if (os.path.isdir(fullname) and
37 not os.path.islink(fullname) or
38 os.path.normcase(name[-3:]) == ".py"):
39 check(fullname)
40 return
41
42 try:
43 f = open(file)
44 except IOError, msg:
45 print "%s: I/O Error: %s" % (`file`, str(msg))
46 return
47
48 if verbose > 1:
49 print "checking", `file`, "with tabsize 8..."
50 tokens = []
51 tokenize.tabsize = 8
52 try:
53 tokenize.tokenize(f.readline, tokens.append)
54 except tokenize.TokenError, msg:
55 print "%s: Token Error: %s" % (`file`, str(msg))
56
57 if verbose > 1:
Guido van Rossum3db0e371998-03-24 04:58:04 +000058 print "checking", `file`, "with tabsize 1..."
Guido van Rossum6f73c1a1998-03-20 19:23:04 +000059 f.seek(0)
60 alttokens = []
Guido van Rossum3db0e371998-03-24 04:58:04 +000061 tokenize.tabsize = 1
Guido van Rossum6f73c1a1998-03-20 19:23:04 +000062 try:
63 tokenize.tokenize(f.readline, alttokens.append)
64 except tokenize.TokenError, msg:
65 print "%s: Token Error: %s" % (`file`, str(msg))
66 f.close()
67
Guido van Rossum97df7f81998-03-26 19:23:43 +000068 if tokens == alttokens:
69 if verbose:
70 print "%s: Clean bill of health." % `file`
71 elif quiet:
72 print file
73 else:
Guido van Rossum3db0e371998-03-24 04:58:04 +000074 badline = 0
75 n, altn = len(tokens), len(alttokens)
76 for i in range(max(n, altn)):
77 if i >= n:
78 x = None
79 else:
80 x = tokens[i]
81 if i >= altn:
82 y = None
83 else:
84 y = alttokens[i]
85 if x != y:
86 if x:
87 kind, token, start, end, line = x
88 else:
89 kind, token, start, end, line = y
90 badline = start[0]
91 break
Guido van Rossum6f73c1a1998-03-20 19:23:04 +000092 if verbose:
Guido van Rossum3db0e371998-03-24 04:58:04 +000093 print "%s: *** Line %d: trouble in tab city! ***" % (
94 `file`, badline)
95 print "offending line:", `line`
Guido van Rossum6f73c1a1998-03-20 19:23:04 +000096 else:
Guido van Rossum3db0e371998-03-24 04:58:04 +000097 print file, badline, `line`
Guido van Rossum6f73c1a1998-03-20 19:23:04 +000098
99if __name__ == '__main__':
100 main()