Home | History | Annotate | Download | only in scripts
      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())
     90