|
1 #! /usr/bin/env python |
|
2 |
|
3 """finddiv - a grep-like tool that looks for division operators. |
|
4 |
|
5 Usage: finddiv [-l] file_or_directory ... |
|
6 |
|
7 For directory arguments, all files in the directory whose name ends in |
|
8 .py are processed, and subdirectories are processed recursively. |
|
9 |
|
10 This actually tokenizes the files to avoid false hits in comments or |
|
11 strings literals. |
|
12 |
|
13 By default, this prints all lines containing a / or /= operator, in |
|
14 grep -n style. With the -l option specified, it prints the filename |
|
15 of files that contain at least one / or /= operator. |
|
16 """ |
|
17 |
|
18 import os |
|
19 import sys |
|
20 import getopt |
|
21 import tokenize |
|
22 |
|
23 def main(): |
|
24 try: |
|
25 opts, args = getopt.getopt(sys.argv[1:], "lh") |
|
26 except getopt.error, msg: |
|
27 usage(msg) |
|
28 return 2 |
|
29 if not args: |
|
30 usage("at least one file argument is required") |
|
31 return 2 |
|
32 listnames = 0 |
|
33 for o, a in opts: |
|
34 if o == "-h": |
|
35 print __doc__ |
|
36 return |
|
37 if o == "-l": |
|
38 listnames = 1 |
|
39 exit = None |
|
40 for filename in args: |
|
41 x = process(filename, listnames) |
|
42 exit = exit or x |
|
43 return exit |
|
44 |
|
45 def usage(msg): |
|
46 sys.stderr.write("%s: %s\n" % (sys.argv[0], msg)) |
|
47 sys.stderr.write("Usage: %s [-l] file ...\n" % sys.argv[0]) |
|
48 sys.stderr.write("Try `%s -h' for more information.\n" % sys.argv[0]) |
|
49 |
|
50 def process(filename, listnames): |
|
51 if os.path.isdir(filename): |
|
52 return processdir(filename, listnames) |
|
53 try: |
|
54 fp = open(filename) |
|
55 except IOError, msg: |
|
56 sys.stderr.write("Can't open: %s\n" % msg) |
|
57 return 1 |
|
58 g = tokenize.generate_tokens(fp.readline) |
|
59 lastrow = None |
|
60 for type, token, (row, col), end, line in g: |
|
61 if token in ("/", "/="): |
|
62 if listnames: |
|
63 print filename |
|
64 break |
|
65 if row != lastrow: |
|
66 lastrow = row |
|
67 print "%s:%d:%s" % (filename, row, line), |
|
68 fp.close() |
|
69 |
|
70 def processdir(dir, listnames): |
|
71 try: |
|
72 names = os.listdir(dir) |
|
73 except os.error, msg: |
|
74 sys.stderr.write("Can't list directory: %s\n" % dir) |
|
75 return 1 |
|
76 files = [] |
|
77 for name in names: |
|
78 fn = os.path.join(dir, name) |
|
79 if os.path.normcase(fn).endswith(".py") or os.path.isdir(fn): |
|
80 files.append(fn) |
|
81 files.sort(lambda a, b: cmp(os.path.normcase(a), os.path.normcase(b))) |
|
82 exit = None |
|
83 for fn in files: |
|
84 x = process(fn, listnames) |
|
85 exit = exit or x |
|
86 return exit |
|
87 |
|
88 if __name__ == "__main__": |
|
89 sys.exit(main()) |