python-2.5.2/win32/Tools/Scripts/checkappend.py
changeset 0 ae805ac0140d
equal deleted inserted replaced
-1:000000000000 0:ae805ac0140d
       
     1 #! /usr/bin/env python
       
     2 
       
     3 # Released to the public domain, by Tim Peters, 28 February 2000.
       
     4 
       
     5 """checkappend.py -- search for multi-argument .append() calls.
       
     6 
       
     7 Usage:  specify one or more file or directory paths:
       
     8     checkappend [-v] file_or_dir [file_or_dir] ...
       
     9 
       
    10 Each file_or_dir is checked for multi-argument .append() calls.  When
       
    11 a directory, all .py files in the directory, and recursively in its
       
    12 subdirectories, are checked.
       
    13 
       
    14 Use -v for status msgs.  Use -vv for more status msgs.
       
    15 
       
    16 In the absence of -v, the only output is pairs of the form
       
    17 
       
    18     filename(linenumber):
       
    19     line containing the suspicious append
       
    20 
       
    21 Note that this finds multi-argument append calls regardless of whether
       
    22 they're attached to list objects.  If a module defines a class with an
       
    23 append method that takes more than one argument, calls to that method
       
    24 will be listed.
       
    25 
       
    26 Note that this will not find multi-argument list.append calls made via a
       
    27 bound method object.  For example, this is not caught:
       
    28 
       
    29     somelist = []
       
    30     push = somelist.append
       
    31     push(1, 2, 3)
       
    32 """
       
    33 
       
    34 __version__ = 1, 0, 0
       
    35 
       
    36 import os
       
    37 import sys
       
    38 import getopt
       
    39 import tokenize
       
    40 
       
    41 verbose = 0
       
    42 
       
    43 def errprint(*args):
       
    44     msg = ' '.join(args)
       
    45     sys.stderr.write(msg)
       
    46     sys.stderr.write("\n")
       
    47 
       
    48 def main():
       
    49     args = sys.argv[1:]
       
    50     global verbose
       
    51     try:
       
    52         opts, args = getopt.getopt(sys.argv[1:], "v")
       
    53     except getopt.error, msg:
       
    54         errprint(str(msg) + "\n\n" + __doc__)
       
    55         return
       
    56     for opt, optarg in opts:
       
    57         if opt == '-v':
       
    58             verbose = verbose + 1
       
    59     if not args:
       
    60         errprint(__doc__)
       
    61         return
       
    62     for arg in args:
       
    63         check(arg)
       
    64 
       
    65 def check(file):
       
    66     if os.path.isdir(file) and not os.path.islink(file):
       
    67         if verbose:
       
    68             print "%r: listing directory" % (file,)
       
    69         names = os.listdir(file)
       
    70         for name in names:
       
    71             fullname = os.path.join(file, name)
       
    72             if ((os.path.isdir(fullname) and
       
    73                  not os.path.islink(fullname))
       
    74                 or os.path.normcase(name[-3:]) == ".py"):
       
    75                 check(fullname)
       
    76         return
       
    77 
       
    78     try:
       
    79         f = open(file)
       
    80     except IOError, msg:
       
    81         errprint("%r: I/O Error: %s" % (file, msg))
       
    82         return
       
    83 
       
    84     if verbose > 1:
       
    85         print "checking %r ..." % (file,)
       
    86 
       
    87     ok = AppendChecker(file, f).run()
       
    88     if verbose and ok:
       
    89         print "%r: Clean bill of health." % (file,)
       
    90 
       
    91 [FIND_DOT,
       
    92  FIND_APPEND,
       
    93  FIND_LPAREN,
       
    94  FIND_COMMA,
       
    95  FIND_STMT]   = range(5)
       
    96 
       
    97 class AppendChecker:
       
    98     def __init__(self, fname, file):
       
    99         self.fname = fname
       
   100         self.file = file
       
   101         self.state = FIND_DOT
       
   102         self.nerrors = 0
       
   103 
       
   104     def run(self):
       
   105         try:
       
   106             tokenize.tokenize(self.file.readline, self.tokeneater)
       
   107         except tokenize.TokenError, msg:
       
   108             errprint("%r: Token Error: %s" % (self.fname, msg))
       
   109             self.nerrors = self.nerrors + 1
       
   110         return self.nerrors == 0
       
   111 
       
   112     def tokeneater(self, type, token, start, end, line,
       
   113                 NEWLINE=tokenize.NEWLINE,
       
   114                 JUNK=(tokenize.COMMENT, tokenize.NL),
       
   115                 OP=tokenize.OP,
       
   116                 NAME=tokenize.NAME):
       
   117 
       
   118         state = self.state
       
   119 
       
   120         if type in JUNK:
       
   121             pass
       
   122 
       
   123         elif state is FIND_DOT:
       
   124             if type is OP and token == ".":
       
   125                 state = FIND_APPEND
       
   126 
       
   127         elif state is FIND_APPEND:
       
   128             if type is NAME and token == "append":
       
   129                 self.line = line
       
   130                 self.lineno = start[0]
       
   131                 state = FIND_LPAREN
       
   132             else:
       
   133                 state = FIND_DOT
       
   134 
       
   135         elif state is FIND_LPAREN:
       
   136             if type is OP and token == "(":
       
   137                 self.level = 1
       
   138                 state = FIND_COMMA
       
   139             else:
       
   140                 state = FIND_DOT
       
   141 
       
   142         elif state is FIND_COMMA:
       
   143             if type is OP:
       
   144                 if token in ("(", "{", "["):
       
   145                     self.level = self.level + 1
       
   146                 elif token in (")", "}", "]"):
       
   147                     self.level = self.level - 1
       
   148                     if self.level == 0:
       
   149                         state = FIND_DOT
       
   150                 elif token == "," and self.level == 1:
       
   151                     self.nerrors = self.nerrors + 1
       
   152                     print "%s(%d):\n%s" % (self.fname, self.lineno,
       
   153                                            self.line)
       
   154                     # don't gripe about this stmt again
       
   155                     state = FIND_STMT
       
   156 
       
   157         elif state is FIND_STMT:
       
   158             if type is NEWLINE:
       
   159                 state = FIND_DOT
       
   160 
       
   161         else:
       
   162             raise SystemError("unknown internal state '%r'" % (state,))
       
   163 
       
   164         self.state = state
       
   165 
       
   166 if __name__ == '__main__':
       
   167     main()