# Released to the public domain, by Tim Peters, 28 February 2000.
"""checkappend.py -- search for multi-argument .append() calls.
Usage: specify one or more file or directory paths:
checkappend [-v] file_or_dir [file_or_dir] ...
Each file_or_dir is checked for multi-argument .append() calls. When
a directory, all .py files in the directory, and recursively in its
subdirectories, are checked.
Use -v for status msgs. Use -vv for more status msgs.
In the absence of -v, the only output is pairs of the form
filename(linenumber):
line containing the suspicious append
Note that this finds multi-argument append calls regardless of whether
they're attached to list objects. If a module defines a class with an
append method that takes more than one argument, calls to that method
will be listed.
Note that this will not find multi-argument list.append calls made via a
bound method object. For example, this is not caught:
def main():
args = sys.argv[1:]
global verbose
try:
opts, args = getopt.getopt(sys.argv[1:], "v")
except getopt.error, msg:
errprint(str(msg) + "\n\n" + __doc__)
return
for opt, optarg in opts:
if opt == '-v':
verbose = verbose + 1
if not args:
errprint(__doc__)
return
for arg in args:
check(arg)
def check(file):
if os.path.isdir(file) and not os.path.islink(file):
if verbose:
print "%r: listing directory" % (file,)
names = os.listdir(file)
for name in names:
fullname = os.path.join(file, name)
if ((os.path.isdir(fullname) and
not os.path.islink(fullname))
or os.path.normcase(name[-3:]) == ".py"):
check(fullname)
return
elif state is FIND_DOT:
if type is OP and token == ".":
state = FIND_APPEND
elif state is FIND_APPEND:
if type is NAME and token == "append":
self.line = line
self.lineno = start[0]
state = FIND_LPAREN
else:
state = FIND_DOT
elif state is FIND_LPAREN:
if type is OP and token == "(":
self.level = 1
state = FIND_COMMA
else:
state = FIND_DOT
elif state is FIND_COMMA:
if type is OP:
if token in ("(", "{", "["):
self.level = self.level + 1
elif token in (")", "}", "]"):
self.level = self.level - 1
if self.level == 0:
state = FIND_DOT
elif token == "," and self.level == 1:
self.nerrors = self.nerrors + 1
print "%s(%d):\n%s" % (self.fname, self.lineno,
self.line)
# don't gripe about this stmt again
state = FIND_STMT
elif state is FIND_STMT:
if type is NEWLINE:
state = FIND_DOT
else:
raise SystemError("unknown internal state '%r'" % (state,))