| #! /usr/bin/env python | 
 |  | 
 | """finddiv - a grep-like tool that looks for division operators. | 
 |  | 
 | Usage: finddiv [-l] file_or_directory ... | 
 |  | 
 | For directory arguments, all files in the directory whose name ends in | 
 | .py are processed, and subdirectories are processed recursively. | 
 |  | 
 | This actually tokenizes the files to avoid false hits in comments or | 
 | strings literals. | 
 |  | 
 | By default, this prints all lines containing a / or /= operator, in | 
 | grep -n style.  With the -l option specified, it prints the filename | 
 | of files that contain at least one / or /= operator. | 
 | """ | 
 |  | 
 | import os | 
 | import sys | 
 | import getopt | 
 | import tokenize | 
 |  | 
 | def main(): | 
 |     try: | 
 |         opts, args = getopt.getopt(sys.argv[1:], "lh") | 
 |     except getopt.error, msg: | 
 |         usage(msg) | 
 |         return 2 | 
 |     if not args: | 
 |         usage("at least one file argument is required") | 
 |         return 2 | 
 |     listnames = 0 | 
 |     for o, a in opts: | 
 |         if o == "-h": | 
 |             print __doc__ | 
 |             return | 
 |         if o == "-l": | 
 |             listnames = 1 | 
 |     exit = None | 
 |     for file in args: | 
 |         x = process(file, listnames) | 
 |         exit = exit or x | 
 |     return exit | 
 |  | 
 | def usage(msg): | 
 |     sys.stderr.write("%s: %s\n" % (sys.argv[0], msg)) | 
 |     sys.stderr.write("Usage: %s [-l] file ...\n" % sys.argv[0]) | 
 |     sys.stderr.write("Try `%s -h' for more information.\n" % sys.argv[0]) | 
 |  | 
 | def process(file, listnames): | 
 |     if os.path.isdir(file): | 
 |         return processdir(file, listnames) | 
 |     try: | 
 |         fp = open(file) | 
 |     except IOError, msg: | 
 |         sys.stderr.write("Can't open: %s\n" % msg) | 
 |         return 1 | 
 |     g = tokenize.generate_tokens(fp.readline) | 
 |     lastrow = None | 
 |     for type, token, (row, col), end, line in g: | 
 |         if token in ("/", "/="): | 
 |             if listnames: | 
 |                 print file | 
 |                 break | 
 |             if row != lastrow: | 
 |                 lastrow = row | 
 |                 print "%s:%d:%s" % (file, row, line), | 
 |     fp.close() | 
 |  | 
 | def processdir(dir, listnames): | 
 |     try: | 
 |         names = os.listdir(dir) | 
 |     except os.error, msg: | 
 |         sys.stderr.write("Can't list directory: %s\n" % dir) | 
 |         return 1 | 
 |     files = [] | 
 |     for name in names: | 
 |         fn = os.path.join(dir, name) | 
 |         if os.path.normcase(fn).endswith(".py") or os.path.isdir(fn): | 
 |             files.append(fn) | 
 |     files.sort(lambda a, b: cmp(os.path.normcase(a), os.path.normcase(b))) | 
 |     exit = None | 
 |     for fn in files: | 
 |         x = process(fn, listnames) | 
 |         exit = exit or x | 
 |     return exit | 
 |  | 
 | if __name__ == "__main__": | 
 |     sys.exit(main()) |