mirror of
https://github.com/python/cpython.git
synced 2024-12-01 11:15:56 +01:00
aaab30e00c
(with one small bugfix in bgen/bgen/scantools.py) This replaces string module functions with string methods for the stuff in the Tools directory. Several uses of string.letters etc. are still remaining.
168 lines
4.6 KiB
Python
Executable File
168 lines
4.6 KiB
Python
Executable File
#! /usr/bin/env python
|
|
|
|
# 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:
|
|
|
|
somelist = []
|
|
push = somelist.append
|
|
push(1, 2, 3)
|
|
"""
|
|
|
|
__version__ = 1, 0, 0
|
|
|
|
import os
|
|
import sys
|
|
import getopt
|
|
import tokenize
|
|
|
|
verbose = 0
|
|
|
|
def errprint(*args):
|
|
msg = ' '.join(args)
|
|
sys.stderr.write(msg)
|
|
sys.stderr.write("\n")
|
|
|
|
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 "%s: 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
|
|
|
|
try:
|
|
f = open(file)
|
|
except IOError, msg:
|
|
errprint("%s: I/O Error: %s" % (`file`, str(msg)))
|
|
return
|
|
|
|
if verbose > 1:
|
|
print "checking", `file`, "..."
|
|
|
|
ok = AppendChecker(file, f).run()
|
|
if verbose and ok:
|
|
print "%s: Clean bill of health." % `file`
|
|
|
|
[FIND_DOT,
|
|
FIND_APPEND,
|
|
FIND_LPAREN,
|
|
FIND_COMMA,
|
|
FIND_STMT] = range(5)
|
|
|
|
class AppendChecker:
|
|
def __init__(self, fname, file):
|
|
self.fname = fname
|
|
self.file = file
|
|
self.state = FIND_DOT
|
|
self.nerrors = 0
|
|
|
|
def run(self):
|
|
try:
|
|
tokenize.tokenize(self.file.readline, self.tokeneater)
|
|
except tokenize.TokenError, msg:
|
|
errprint("%s: Token Error: %s" % (`self.fname`, str(msg)))
|
|
self.nerrors = self.nerrors + 1
|
|
return self.nerrors == 0
|
|
|
|
def tokeneater(self, type, token, start, end, line,
|
|
NEWLINE=tokenize.NEWLINE,
|
|
JUNK=(tokenize.COMMENT, tokenize.NL),
|
|
OP=tokenize.OP,
|
|
NAME=tokenize.NAME):
|
|
|
|
state = self.state
|
|
|
|
if type in JUNK:
|
|
pass
|
|
|
|
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 '%s'" % `state`)
|
|
|
|
self.state = state
|
|
|
|
if __name__ == '__main__':
|
|
main()
|