import re |
import sys |
import parser |
|
d={} |
|
|
|
|
|
|
|
|
d['assertRaises'] = ('raises', '', ['Any']) |
d['fail'] = ('raise AssertionError', '', [0,1]) |
d['assert_'] = ('assert', '', [1,2]) |
d['failIf'] = ('assert not', '', [1,2]) |
d['assertEqual'] = ('assert', ' ==', [2,3]) |
d['failIfEqual'] = ('assert not', ' ==', [2,3]) |
d['assertIn'] = ('assert', ' in', [2,3]) |
d['assertNotIn'] = ('assert', ' not in', [2,3]) |
d['assertNotEqual'] = ('assert', ' !=', [2,3]) |
d['failUnlessEqual'] = ('assert', ' ==', [2,3]) |
d['assertAlmostEqual'] = ('assert round', ' ==', [2,3,4]) |
d['failIfAlmostEqual'] = ('assert not round', ' ==', [2,3,4]) |
d['assertNotAlmostEqual'] = ('assert round', ' !=', [2,3,4]) |
d['failUnlessAlmostEquals'] = ('assert round', ' ==', [2,3,4]) |
|
|
d['failUnlessRaises'] = d['assertRaises'] |
d['failUnless'] = d['assert_'] |
d['assertEquals'] = d['assertEqual'] |
d['assertNotEquals'] = d['assertNotEqual'] |
d['assertAlmostEquals'] = d['assertAlmostEqual'] |
d['assertNotAlmostEquals'] = d['assertNotAlmostEqual'] |
|
|
leading_spaces = re.compile(r'^(\s*)') |
|
pat = '' |
for k in d.keys(): |
pat += '|' + r'^(\s*)' + 'self.' + k + r'\(' |
|
old_names = re.compile(pat[1:]) |
linesep='\n' |
|
|
|
def blocksplitter(fp): |
'''split a file into blocks that are headed by functions to rename''' |
|
blocklist = [] |
blockstring = '' |
|
for line in fp: |
interesting = old_names.match(line) |
if interesting : |
if blockstring: |
blocklist.append(blockstring) |
blockstring = line |
else: |
blockstring += line |
|
blocklist.append(blockstring) |
return blocklist |
|
def rewrite_utest(block): |
'''rewrite every block to use the new utest functions''' |
|
'''returns the rewritten unittest, unless it ran into problems, |
in which case it just returns the block unchanged. |
''' |
utest = old_names.match(block) |
|
if not utest: |
return block |
|
old = utest.group(0).lstrip()[5:-1] |
new = d[old][0] |
op = d[old][1] |
possible_args = d[old][2] |
|
|
if possible_args == ['Any']: |
return re.sub('self.'+old, new, block) |
|
message_pos = possible_args[-1] |
|
|
|
try: |
indent, argl, trailer = decompose_unittest(old, block) |
|
except SyntaxError: |
return block |
|
argnum = len(argl) |
if argnum not in possible_args: |
|
return block |
|
elif argnum == message_pos: |
message = argl[-1] |
argl = argl[:-1] |
else: |
message = None |
|
if argnum is 0 or (argnum is 1 and argnum is message_pos): |
string = '' |
if message: |
message = ' ' + message |
|
elif message_pos is 4: |
try: |
pos = argl[2].lstrip() |
except IndexError: |
pos = '7' |
string = '(%s -%s, %s)%s 0' % (argl[0], argl[1], pos, op ) |
|
else: |
string = ' ' + op.join(argl) |
|
if message: |
string = string + ',' + message |
|
return indent + new + string + trailer |
|
def decompose_unittest(old, block): |
'''decompose the block into its component parts''' |
|
''' returns indent, arglist, trailer |
indent -- the indentation |
arglist -- the arguments to the unittest function |
trailer -- any extra junk after the closing paren, such as #commment |
''' |
|
indent = re.match(r'(\s*)', block).group() |
pat = re.search('self.' + old + r'\(', block) |
|
args, trailer = get_expr(block[pat.end():], ')') |
arglist = break_args(args, []) |
|
if arglist == ['']: |
return indent, [], trailer |
|
for i in range(len(arglist)): |
try: |
parser.expr(arglist[i].lstrip('\t ')) |
except SyntaxError: |
if i == 0: |
arglist[i] = '(' + arglist[i] + ')' |
else: |
arglist[i] = ' (' + arglist[i] + ')' |
|
return indent, arglist, trailer |
|
def break_args(args, arglist): |
'''recursively break a string into a list of arguments''' |
try: |
first, rest = get_expr(args, ',') |
if not rest: |
return arglist + [first] |
else: |
return [first] + break_args(rest, arglist) |
except SyntaxError: |
return arglist + [args] |
|
def get_expr(s, char): |
'''split a string into an expression, and the rest of the string''' |
|
pos=[] |
for i in range(len(s)): |
if s[i] == char: |
pos.append(i) |
if pos == []: |
raise SyntaxError |
|
for p in pos: |
|
|
try: |
parser.expr('(' + s[:p] + ')') |
return s[:p], s[p+1:] |
except SyntaxError: |
pass |
raise SyntaxError |
|
if __name__ == '__main__': |
|
import sys |
import py |
|
usage = "usage: %prog [-s [filename ...] | [-i | -c filename ...]]" |
optparser = py.compat.optparse.OptionParser(usage) |
|
def select_output (option, opt, value, optparser, **kw): |
if hasattr(optparser, 'output'): |
optparser.error( |
'Cannot combine -s -i and -c options. Use one only.') |
else: |
optparser.output = kw['output'] |
|
optparser.add_option("-s", "--stdout", action="callback", |
callback=select_output, |
callback_kwargs={'output':'stdout'}, |
help="send your output to stdout") |
|
optparser.add_option("-i", "--inplace", action="callback", |
callback=select_output, |
callback_kwargs={'output':'inplace'}, |
help="overwrite files in place") |
|
optparser.add_option("-c", "--copy", action="callback", |
callback=select_output, |
callback_kwargs={'output':'copy'}, |
help="copy files ... fn.py --> fn_cp.py") |
|
options, args = optparser.parse_args() |
|
output = getattr(optparser, 'output', 'stdout') |
|
if output in ['inplace', 'copy'] and not args: |
optparser.error( |
'-i and -c option require at least one filename') |
|
if not args: |
s = '' |
for block in blocksplitter(sys.stdin.read()): |
s += rewrite_utest(block) |
sys.stdout.write(s) |
|
else: |
for infilename in args: |
infile = file(infilename) |
s = '' |
for block in blocksplitter(infile): |
s += rewrite_utest(block) |
if output == 'inplace': |
outfile = file(infilename, 'w+') |
elif output == 'copy': |
outfile = file (infilename[:-3]+ '_cp.py', 'w+') |
else: |
outfile = sys.stdout |
|
outfile.write(s) |
|
|
|