[pypy-svn] r5168 - pypy/branch/src-new-utest/pypy/tool
lac at codespeak.net
lac at codespeak.net
Sat Jun 19 15:59:39 CEST 2004
Author: lac
Date: Sat Jun 19 15:59:38 2004
New Revision: 5168
Modified:
pypy/branch/src-new-utest/pypy/tool/tiny.py
Log:
Most of the special cases handled now. Still working on it.
Modified: pypy/branch/src-new-utest/pypy/tool/tiny.py
==============================================================================
--- pypy/branch/src-new-utest/pypy/tool/tiny.py (original)
+++ pypy/branch/src-new-utest/pypy/tool/tiny.py Sat Jun 19 15:59:38 2004
@@ -1,5 +1,6 @@
import re
import unittest
+import parser
# d is the dictionary of unittest changes, keyed to the old name
@@ -7,6 +8,7 @@
# d['change type'] is one of the following functions
# namechange_only e.g. assertRaises becomes raises
# strip_parens e.g. assert_(expr) becomes assert expr
+# fail_special e.g. fail() becomes raise AssertionError
# comma to op e.g. assertEquals(l, r) becomes assert l == r
# rounding e.g. assertAlmostEqual(l, r) becomes
# assert round(l - r, 7) == 0
@@ -15,11 +17,95 @@
# First define the functions you want to dispatch
def namechange_only(old, new, block):
+ # dictionary dispatch function.
# this is the simplest of changes.
return re.sub('self.'+old, new, block)
def strip_parens(old, new, block):
+ # dictionary dispatch function.
+
+ pat = re.search(r'^(\s*)', block)
+ indent = pat.group()
+ pat = re.search('self.' + old + r'\(', block)
+ rest = block[pat.end():]
+
+ expr, trailer = get_expr(rest, ')')
+
+ try:
+ parser.expr(expr) # the parens came off easily
+ return indent + new + ' ' + expr + trailer
+
+ except SyntaxError:
+
+ # now we have to go to work. It would be nice if we could
+ # just keep the parens, since the original author probably
+ # used them to group things nicely in a complicated multi-line
+ # expression.
+ #
+ # There is one hitch.
+ #
+ # self.assertx_(0, string) prints the string, as does
+ # assert 0, string . But not only does assert(0, string) not
+ # print the string, it also doesn't print the AssertionError
+ # either. So nothing for it, we have to paste continuation
+ # backslashes on our multiline constructs.
+
+ try:
+ realexpr, s = get_expr(expr, ',')
+
+ # aha. we found an expr followed by a ', something_else'
+ # we should probably test to make sure that something_else
+ # is a string, and not, say, another expr. But the whole
+ # question of what to do when your input is bogus requires
+ # more thought than I want to do at this hour ...
+ # Given that assert 0, range(10) is legal, and prints
+ # AssertionError: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], is it
+ # even true that s has to be a string?
+
+ expr_w_slash = re.sub(r'\n', r'\\\n', realexpr)
+
+ if s[0] == '\n': # that needs a slash too ...
+ return indent + new + ' ' + expr_w_slash + ',\\' + s + trailer
+ else:
+ return indent + new + ' ' + expr_w_slash + ',' + s + trailer
+
+ except SyntaxError:
+ # we couldn't find a 'expr, string' so it is
+ # probably just a regular old multiline expression
+ # t.ex. self.assertx(0
+ # +f(x)
+ # +g(x))
+
+ expr_w_slash = re.sub(r'\n', r'\\\n', expr)
+ return indent + new + ' ' + expr_w_slash + trailer
+
+def fail_special(old, new, block):
+ # dictionary dispatch function.
+ # while assert_() is an error, fail() and
+ # fail('message') are just fine.
return re.sub('self.'+old, new, block)
+
+
+def get_expr(s, char):
+ # read from the beginning of the string until you get an expression.
+ # return it, and the stuff left over, minus the char you separated on
+ pos = pos_finder(s, char)
+
+ for p in pos:
+ try:
+ parser.expr('(' + s[:p] + ')')
+ return s[:p], s[p+1:]
+ except SyntaxError: # It's not an expression yet
+ pass
+ raise SyntaxError # We never found anything that worked.
+
+def pos_finder(s, char=','):
+ # returns the list of string positions where the char 'char' was found
+ pos=[]
+ for i in range(len(s)):
+ if s[i] == char:
+ pos.append(i)
+ return pos
d={}
@@ -35,11 +121,19 @@
'change type': strip_parens,
'op': None}
+d['failUnless'] = d['assert_']
+
+
+d['failIf'] = {'new': 'assert not',
+ 'change type': fail_special,
+ 'op': None}
+
+d['fail'] = {'old': 'fail',
+ 'new': 'raise AssertionError ',
+ 'change type': strip_parens,
+ 'op': None}
+
"""
-d['failUnless'] = {'old':'failUnless',
- 'new': 'assert',
- 'change type': 'strip_parens',
- 'op': None}
d['failUnlessEqual'] = {'old': 'failUnlessEqual',
'new': 'assert not',
@@ -82,16 +176,6 @@
'comma to op',
'op': '!='}
-d['failIf'] = {'old': 'failIf',
- 'new': 'assert not',
- 'change type': 'strip_parens',
- 'op': None}
-
-d['fail'] = {'old': 'fail',
- 'new': 'raise AssertionError ',
- 'change type': 'strip_parens',
- 'op': None}
-
d['assertEqual'] = {'old': 'assertEqual',
'new': 'assert',
'change type': 'comma to op',
@@ -136,18 +220,34 @@
return blocklist
def process_block(s):
- #print 'found the block ', block
f = old_names.match(s)
if f:
key = f.group(0).lstrip()[5:-1] # '\tself.blah(' -> 'blah'
+ # now do the dictionary dispatch.
return d[key]['change type'](key, d[key]['new'], s)
else:
return s
+def which_comma(tuplelist):
+ import parser
+
+ # make the python parser do the hard work of deciding which comma
+ # splits the string into two expressions
+
+ for l, r in tuplelist:
+ try:
+
+ parser.expr(l + ')')
+ parser.expr('(' + r)
+ return l , r # Great! Both sides are expressions!
+ except SyntaxError: # It wasn't that comma
+ pass
+ raise SyntaxError # We never found anything that worked.
+
class Testit(unittest.TestCase):
def test(self):
self.assertEquals(process_block("badger badger badger"),
- "badger badger badger")
+ "badger badger badger")
self.assertEquals(process_block(
"self.assertRaises(excClass, callableObj, *args, **kwargs)"
@@ -157,11 +257,11 @@
self.assertEquals(process_block(
"""
- self.assertRaises(TypeError, func, 42, {'arg1': 23})
+ self.failUnlessRaises(TypeError, func, 42, **{'arg1': 23})
"""
),
"""
- raises(TypeError, func, 42, {'arg1': 23})
+ raises(TypeError, func, 42, **{'arg1': 23})
"""
)
self.assertEquals(process_block(
@@ -179,8 +279,56 @@
)
self.assertEquals(process_block("self.assert_(x)"),
"assert x")
-
+ self.assertEquals(process_block("self.failUnless(func(x)) # XXX"),
+ "assert func(x) # XXX")
+ self.assertEquals(process_block(
+ """
+ self.assert_(1 + f(y)
+ + z) # multiline, add continuation backslash
+ """
+ ),
+ r"""
+ assert 1 + f(y)\
+ + z # multiline, add continuation backslash
+ """
+ )
+
+ self.assertEquals(process_block("self.assert_(0, 'badger badger')"),
+ "assert 0, 'badger badger'")
+
+ self.assertEquals(process_block(
+ r"""
+ self.assert_(0,
+ 'Meet the badger.\n')
+ """
+ ),
+ r"""
+ assert 0,\
+ 'Meet the badger.\n'
+ """
+ )
+
+
+ self.assertEquals(process_block(
+ r"""
+ self.assert_(0 + 0
+ + len('badger\n')
+ + 0, '''badger badger badger badger
+ mushroom mushroom
+ Snake! It's a snake!
+ ''') # multiline, must remove the parens
+ """
+ ),
+ r"""
+ assert 0 + 0\
+ + len('badger\n')\
+ + 0, '''badger badger badger badger
+ mushroom mushroom
+ Snake! It's a snake!
+ ''' # multiline, must remove the parens
+ """
+ )
if __name__ == '__main__':
unittest.main()
More information about the Pypy-commit
mailing list