|
| 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 file in args: |
| 41 | + x = process(file, 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(file, listnames): |
| 51 | + if os.path.isdir(file): |
| 52 | + return processdir(file, listnames) |
| 53 | + try: |
| 54 | + fp = open(file) |
| 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 file |
| 64 | + break |
| 65 | + if row != lastrow: |
| 66 | + lastrow = row |
| 67 | + print "%s:%d:%s" % (file, 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()) |
0 commit comments