+++ /dev/null
-#! /usr/bin/env python\r
-\r
-# Released to the public domain, by Tim Peters, 28 February 2000.\r
-\r
-"""checkappend.py -- search for multi-argument .append() calls.\r
-\r
-Usage: specify one or more file or directory paths:\r
- checkappend [-v] file_or_dir [file_or_dir] ...\r
-\r
-Each file_or_dir is checked for multi-argument .append() calls. When\r
-a directory, all .py files in the directory, and recursively in its\r
-subdirectories, are checked.\r
-\r
-Use -v for status msgs. Use -vv for more status msgs.\r
-\r
-In the absence of -v, the only output is pairs of the form\r
-\r
- filename(linenumber):\r
- line containing the suspicious append\r
-\r
-Note that this finds multi-argument append calls regardless of whether\r
-they're attached to list objects. If a module defines a class with an\r
-append method that takes more than one argument, calls to that method\r
-will be listed.\r
-\r
-Note that this will not find multi-argument list.append calls made via a\r
-bound method object. For example, this is not caught:\r
-\r
- somelist = []\r
- push = somelist.append\r
- push(1, 2, 3)\r
-"""\r
-\r
-__version__ = 1, 0, 0\r
-\r
-import os\r
-import sys\r
-import getopt\r
-import tokenize\r
-\r
-verbose = 0\r
-\r
-def errprint(*args):\r
- msg = ' '.join(args)\r
- sys.stderr.write(msg)\r
- sys.stderr.write("\n")\r
-\r
-def main():\r
- args = sys.argv[1:]\r
- global verbose\r
- try:\r
- opts, args = getopt.getopt(sys.argv[1:], "v")\r
- except getopt.error, msg:\r
- errprint(str(msg) + "\n\n" + __doc__)\r
- return\r
- for opt, optarg in opts:\r
- if opt == '-v':\r
- verbose = verbose + 1\r
- if not args:\r
- errprint(__doc__)\r
- return\r
- for arg in args:\r
- check(arg)\r
-\r
-def check(file):\r
- if os.path.isdir(file) and not os.path.islink(file):\r
- if verbose:\r
- print "%r: listing directory" % (file,)\r
- names = os.listdir(file)\r
- for name in names:\r
- fullname = os.path.join(file, name)\r
- if ((os.path.isdir(fullname) and\r
- not os.path.islink(fullname))\r
- or os.path.normcase(name[-3:]) == ".py"):\r
- check(fullname)\r
- return\r
-\r
- try:\r
- f = open(file)\r
- except IOError, msg:\r
- errprint("%r: I/O Error: %s" % (file, msg))\r
- return\r
-\r
- if verbose > 1:\r
- print "checking %r ..." % (file,)\r
-\r
- ok = AppendChecker(file, f).run()\r
- if verbose and ok:\r
- print "%r: Clean bill of health." % (file,)\r
-\r
-[FIND_DOT,\r
- FIND_APPEND,\r
- FIND_LPAREN,\r
- FIND_COMMA,\r
- FIND_STMT] = range(5)\r
-\r
-class AppendChecker:\r
- def __init__(self, fname, file):\r
- self.fname = fname\r
- self.file = file\r
- self.state = FIND_DOT\r
- self.nerrors = 0\r
-\r
- def run(self):\r
- try:\r
- tokenize.tokenize(self.file.readline, self.tokeneater)\r
- except tokenize.TokenError, msg:\r
- errprint("%r: Token Error: %s" % (self.fname, msg))\r
- self.nerrors = self.nerrors + 1\r
- return self.nerrors == 0\r
-\r
- def tokeneater(self, type, token, start, end, line,\r
- NEWLINE=tokenize.NEWLINE,\r
- JUNK=(tokenize.COMMENT, tokenize.NL),\r
- OP=tokenize.OP,\r
- NAME=tokenize.NAME):\r
-\r
- state = self.state\r
-\r
- if type in JUNK:\r
- pass\r
-\r
- elif state is FIND_DOT:\r
- if type is OP and token == ".":\r
- state = FIND_APPEND\r
-\r
- elif state is FIND_APPEND:\r
- if type is NAME and token == "append":\r
- self.line = line\r
- self.lineno = start[0]\r
- state = FIND_LPAREN\r
- else:\r
- state = FIND_DOT\r
-\r
- elif state is FIND_LPAREN:\r
- if type is OP and token == "(":\r
- self.level = 1\r
- state = FIND_COMMA\r
- else:\r
- state = FIND_DOT\r
-\r
- elif state is FIND_COMMA:\r
- if type is OP:\r
- if token in ("(", "{", "["):\r
- self.level = self.level + 1\r
- elif token in (")", "}", "]"):\r
- self.level = self.level - 1\r
- if self.level == 0:\r
- state = FIND_DOT\r
- elif token == "," and self.level == 1:\r
- self.nerrors = self.nerrors + 1\r
- print "%s(%d):\n%s" % (self.fname, self.lineno,\r
- self.line)\r
- # don't gripe about this stmt again\r
- state = FIND_STMT\r
-\r
- elif state is FIND_STMT:\r
- if type is NEWLINE:\r
- state = FIND_DOT\r
-\r
- else:\r
- raise SystemError("unknown internal state '%r'" % (state,))\r
-\r
- self.state = state\r
-\r
-if __name__ == '__main__':\r
- main()\r