[Python-checkins] r53677 - in sandbox/trunk/2to3: example.py fixer_tests.py fixes/basefix.py fixes/fix_apply.py fixes/fix_except.py fixes/fix_exec.py fixes/fix_has_key.py fixes/fix_intern.py fixes/fix_long.py fixes/fix_print.py fixes/fix_raise.py fixes/fix_repr.py fixes/fix_sysexcinfo.py fixes/fix_throw.py fixes/macros.py pytree.py refactor.py
guido.van.rossum
python-checkins at python.org
Thu Feb 8 23:42:36 CET 2007
Author: guido.van.rossum
Date: Thu Feb 8 23:42:35 2007
New Revision: 53677
Added:
sandbox/trunk/2to3/fixes/fix_sysexcinfo.py (contents, props changed)
sandbox/trunk/2to3/fixes/fix_throw.py (contents, props changed)
sandbox/trunk/2to3/fixes/macros.py (contents, props changed)
Modified:
sandbox/trunk/2to3/example.py
sandbox/trunk/2to3/fixer_tests.py
sandbox/trunk/2to3/fixes/basefix.py
sandbox/trunk/2to3/fixes/fix_apply.py
sandbox/trunk/2to3/fixes/fix_except.py
sandbox/trunk/2to3/fixes/fix_exec.py
sandbox/trunk/2to3/fixes/fix_has_key.py
sandbox/trunk/2to3/fixes/fix_intern.py
sandbox/trunk/2to3/fixes/fix_long.py
sandbox/trunk/2to3/fixes/fix_print.py
sandbox/trunk/2to3/fixes/fix_raise.py
sandbox/trunk/2to3/fixes/fix_repr.py
sandbox/trunk/2to3/pytree.py
sandbox/trunk/2to3/refactor.py
Log:
Lots of new stuff by Collin Winter:
- macros.patch is a new version of the earlier macros.patch.
- better_raise.patch allows 2to3 to convert three-argument raise
statements. This depends on macros.patch.
- fix_throw.patch converts two- and three-argument generator.throw()
calls much like fix_raise does.
- fix_sysexcinfo.patch adds a fixer that warns on usage of
sys.exc_{info,type,value,traceback}.
Right now I see some test failures; I'll ask Collin to address these.
Modified: sandbox/trunk/2to3/example.py
==============================================================================
--- sandbox/trunk/2to3/example.py (original)
+++ sandbox/trunk/2to3/example.py Thu Feb 8 23:42:35 2007
@@ -165,7 +165,7 @@
except Exception, (f, e):
pass
except ImportError, e:
- pass
+ print e.args
#
try:
pass
@@ -208,7 +208,7 @@
pass
except (Exception, SystemExit):
pass
-
+
def raise_examples():
raise Exception, 5
#
@@ -223,10 +223,14 @@
raise Exception(5, 6)
#
# These should produce a warning
+ # TODO: convert "raise E, V, T" to
+ # "e = E(V); e.__traceback__ = T; raise e;"
#
raise Exception, 5, 6
#
raise Exception,5,6
+ #
+ raise Exception, (5, 6, 7), 6
def long_examples():
x = long(x)
@@ -238,6 +242,6 @@
a = 12
b = 0x12
c = 3.14
-
-
+
+
# This is the last line.
Modified: sandbox/trunk/2to3/fixer_tests.py
==============================================================================
--- sandbox/trunk/2to3/fixer_tests.py (original)
+++ sandbox/trunk/2to3/fixer_tests.py Thu Feb 8 23:42:35 2007
@@ -11,14 +11,18 @@
import refactor
+# We wrap the RefactoringTool's fixer objects so we can intercept
+# the call to set_filename() and so modify the fixers' logging objects.
+# This allows us to make sure that certain code chunks produce certain
+# warnings.
class Fixer(object):
def __init__(self, fixer, handler):
self.fixer = fixer
self.handler = handler
-
+
def __getattr__(self, attr):
return getattr(self.fixer, attr)
-
+
def set_filename(self, filename):
self.fixer.set_filename(filename)
self.fixer.logger.addHandler(self.handler)
@@ -27,30 +31,29 @@
def __init__(self, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
-
+
self.verbose = False
class FixerTestCase(unittest.TestCase):
def setUp(self):
options = Options(fix=[self.fixer])
self.refactor = refactor.RefactoringTool(options)
-
+
self.logging_stream = StringIO()
sh = logging.StreamHandler(self.logging_stream)
sh.setFormatter(logging.Formatter("%(message)s"))
self.refactor.fixers = [Fixer(f, sh) for f in self.refactor.fixers]
-
+
def check(self, before, after):
before += "\n"
after += "\n"
refactored = self.refactor_stream("<string>", StringIO(before))
self.failUnlessEqual(after, refactored)
-
+
def warns(self, before, after, message):
self.check(before, after)
-
- self.logging_stream.seek(0)
- self.failUnless(message in '\n'.join(self.logging_stream))
+
+ self.failUnless(message in self.logging_stream.getvalue())
def refactor_stream(self, stream_name, stream):
try:
@@ -70,158 +73,158 @@
def test_1(self):
b = """if x <> y:
pass"""
-
+
a = """if x != y:
pass"""
self.check(b, a)
-
+
def test_2(self):
b = """if x<>y:
pass"""
-
+
a = """if x!=y:
pass"""
self.check(b, a)
-
+
def test_3(self):
b = """if x<>y<>z:
pass"""
-
+
a = """if x!=y!=z:
pass"""
self.check(b, a)
-
+
class Test_has_key(FixerTestCase):
fixer = "has_key"
-
+
def test_1(self):
b = """x = d.has_key("x") or d.has_key("y")"""
a = """x = "x" in d or "y" in d"""
self.check(b, a)
-
+
def test_2(self):
b = """x = a.b.c.d.has_key("x") ** 3"""
a = """x = ("x" in a.b.c.d) ** 3"""
self.check(b, a)
-
+
def test_3(self):
b = """x = a.b.has_key(1 + 2).__repr__()"""
a = """x = (1 + 2 in a.b).__repr__()"""
self.check(b, a)
-
+
def test_4(self):
b = """x = a.b.has_key(1 + 2).__repr__() ** -3 ** 4"""
a = """x = (1 + 2 in a.b).__repr__() ** -3 ** 4"""
self.check(b, a)
-
+
def test_5(self):
b = """x = a.has_key(f or g)"""
a = """x = (f or g) in a"""
self.check(b, a)
-
+
def test_6(self):
b = """x = a + b.has_key(c)"""
a = """x = a + (c in b)"""
self.check(b, a)
-
+
def test_7(self):
b = """x = a.has_key(lambda: 12)"""
a = """x = (lambda: 12) in a"""
self.check(b, a)
-
+
def test_8(self):
b = """x = a.has_key(a for a in b)"""
a = """x = (a for a in b) in a"""
self.check(b, a)
-
+
def test_9(self):
b = """if not a.has_key(b): pass"""
a = """if b not in a: pass"""
self.check(b, a)
-
+
def test_10(self):
b = """if not a.has_key(b).__repr__(): pass"""
a = """if not (b in a).__repr__(): pass"""
self.check(b, a)
-
+
def test_11(self):
b = """if not a.has_key(b) ** 2: pass"""
a = """if not (b in a) ** 2: pass"""
self.check(b, a)
-
+
class Test_apply(FixerTestCase):
fixer = "apply"
-
+
def test_1(self):
b = """x = apply(f, g + h)"""
a = """x = f(*g + h)"""
self.check(b, a)
-
+
def test_2(self):
b = """y = apply(f, g, h)"""
a = """y = f(*g, **h)"""
self.check(b, a)
-
+
def test_3(self):
b = """z = apply(fs[0], g or h, h or g)"""
a = """z = fs[0](*g or h, **h or g)"""
self.check(b, a)
-
+
def test_4(self):
b = """apply(f, (x, y) + t)"""
a = """f(*(x, y) + t)"""
self.check(b, a)
-
+
def test_5(self):
b = """apply(f, args,)"""
a = """f(*args)"""
self.check(b, a)
-
+
def test_6(self):
b = """apply(f, args, kwds,)"""
a = """f(*args, **kwds)"""
self.check(b, a)
-
+
# Test that complex functions are parenthesized
-
+
def test_7(self):
b = """x = apply(f+g, args)"""
a = """x = (f+g)(*args)"""
self.check(b, a)
-
+
def test_8(self):
b = """x = apply(f*g, args)"""
a = """x = (f*g)(*args)"""
self.check(b, a)
-
+
def test_9(self):
b = """x = apply(f**g, args)"""
a = """x = (f**g)(*args)"""
self.check(b, a)
-
+
# But dotted names etc. not
-
+
def test_10(self):
b = """x = apply(f.g, args)"""
a = """x = f.g(*args)"""
self.check(b, a)
-
+
def test_11(self):
b = """x = apply(f[x], args)"""
a = """x = f[x](*args)"""
self.check(b, a)
-
+
def test_12(self):
b = """x = apply(f(), args)"""
a = """x = f()(*args)"""
self.check(b, a)
-
+
# Extreme case
def test_13(self):
b = """x = apply(a.b.c.d.e.f, args, kwds)"""
a = """x = a.b.c.d.e.f(*args, **kwds)"""
self.check(b, a)
-
+
# XXX Comments in weird places still get lost
def test_14(self):
b = """apply( # foo
@@ -229,49 +232,49 @@
args)"""
a = """f(*args)"""
self.check(b, a)
-
+
# These should *not* be touched
-
+
def test_15(self):
b = """apply()"""
a = """apply()"""
self.check(b, a)
-
+
def test_16(self):
b = """apply(f)"""
a = """apply(f)"""
self.check(b, a)
-
+
def test_17(self):
b = """apply(f,)"""
a = """apply(f,)"""
self.check(b, a)
-
+
def test_18(self):
b = """apply(f, args, kwds, extras)"""
a = """apply(f, args, kwds, extras)"""
self.check(b, a)
-
+
def test_19(self):
b = """apply(f, *args, **kwds)"""
a = """apply(f, *args, **kwds)"""
self.check(b, a)
-
+
def test_20(self):
b = """apply(f, *args)"""
a = """apply(f, *args)"""
self.check(b, a)
-
+
def test_21(self):
b = """apply(func=f, args=args, kwds=kwds)"""
a = """apply(func=f, args=args, kwds=kwds)"""
self.check(b, a)
-
+
def test_22(self):
b = """apply(f, args=args, kwds=kwds)"""
a = """apply(f, args=args, kwds=kwds)"""
self.check(b, a)
-
+
def test_23(self):
b = """apply(f, args, kwds=kwds)"""
a = """apply(f, args, kwds=kwds)"""
@@ -280,106 +283,106 @@
class Test_intern(FixerTestCase):
fixer = "intern"
-
+
def test_1(self):
b = """x = intern(a)"""
a = """x = sys.intern(a)"""
self.check(b, a)
-
+
def test_2(self):
b = """y = intern("b" # test
)"""
a = """y = sys.intern("b" # test
)"""
self.check(b, a)
-
+
def test_3(self):
b = """z = intern(a+b+c.d,)"""
a = """z = sys.intern(a+b+c.d,)"""
self.check(b, a)
-
+
def test_4(self):
b = """intern("y%s" % 5).replace("y", "")"""
a = """sys.intern("y%s" % 5).replace("y", "")"""
self.check(b, a)
-
+
# These should not be refactored
-
+
def test_5(self):
b = """intern(a=1)"""
a = """intern(a=1)"""
self.check(b, a)
-
+
def test_6(self):
b = """intern(f, g)"""
a = """intern(f, g)"""
self.check(b, a)
-
+
def test_7(self):
b = """intern(*h)"""
a = """intern(*h)"""
self.check(b, a)
-
+
def test_8(self):
b = """intern(**i)"""
a = """intern(**i)"""
self.check(b, a)
-
+
class Test_print(FixerTestCase):
fixer = "print"
-
+
def test_1(self):
b = """print 1, 1+1, 1+1+1"""
a = """Print(1, 1+1, 1+1+1)"""
self.check(b, a)
-
+
def test_2(self):
b = """print 1, 2"""
a = """Print(1, 2)"""
self.check(b, a)
-
+
def test_3(self):
b = """print"""
a = """Print()"""
self.check(b, a)
-
+
# trailing commas
-
+
def test_4(self):
b = """print 1, 2, 3,"""
a = """Print(1, 2, 3, end=' ')"""
self.check(b, a)
-
+
def test_5(self):
b = """print 1, 2,"""
a = """Print(1, 2, end=' ')"""
self.check(b, a)
-
+
def test_6(self):
b = """print 1,"""
a = """Print(1, end=' ')"""
self.check(b, a)
-
+
# >> stuff
-
+
# no trailing comma
def test_7(self):
b = """print >>sys.stderr, 1, 2, 3"""
a = """Print(1, 2, 3, file=sys.stderr)"""
self.check(b, a)
-
+
# trailing comma
def test_8(self):
b = """print >>sys.stderr, 1, 2,"""
a = """Print(1, 2, end=' ', file=sys.stderr)"""
self.check(b, a)
-
+
# no trailing comma
def test_9(self):
b = """print >>sys.stderr, 1+1"""
a = """Print(1+1, file=sys.stderr)"""
self.check(b, a)
-
+
# spaces before sys.stderr
def test_10(self):
b = """print >> sys.stderr"""
@@ -389,49 +392,49 @@
class Test_exec(FixerTestCase):
fixer = "exec"
-
+
def test_1(self):
b = """exec code"""
a = """exec(code)"""
self.check(b, a)
-
+
def test_2(self):
b = """exec code in ns"""
a = """exec(code, ns)"""
self.check(b, a)
-
+
def test_3(self):
b = """exec code in ns1, ns2"""
a = """exec(code, ns1, ns2)"""
self.check(b, a)
-
+
def test_4(self):
b = """exec (a.b()) in ns"""
a = """exec((a.b()), ns)"""
self.check(b, a)
-
+
def test_5(self):
b = """exec a.b() + c in ns"""
a = """exec(a.b() + c, ns)"""
self.check(b, a)
-
+
# These should not be touched
-
+
def test_6(self):
b = """exec(code)"""
a = """exec(code)"""
self.check(b, a)
-
+
def test_7(self):
b = """exec (code)"""
a = """exec (code)"""
self.check(b, a)
-
+
def test_8(self):
b = """exec(code, ns)"""
a = """exec(code, ns)"""
self.check(b, a)
-
+
def test_9(self):
b = """exec(code, ns1, ns2)"""
a = """exec(code, ns1, ns2)"""
@@ -440,40 +443,40 @@
class Test_repr(FixerTestCase):
fixer = "repr"
-
+
def test_1(self):
b = """x = `1 + 2`"""
a = """x = repr(1 + 2)"""
self.check(b, a)
-
+
def test_2(self):
b = """y = `x`"""
a = """y = repr(x)"""
self.check(b, a)
-
+
def test_3(self):
b = """z = `y`.__repr__()"""
a = """z = repr(y).__repr__()"""
self.check(b, a)
-
+
def test_4(self):
b = """x = `1, 2, 3`"""
a = """x = repr((1, 2, 3))"""
self.check(b, a)
-
+
def test_5(self):
b = """x = `1 + `2``"""
a = """x = repr(1 + repr(2))"""
self.check(b, a)
-
+
def test_6(self):
b = """x = `1, 2 + `3, 4``"""
a = """x = repr((1, 2 + repr((3, 4))))"""
self.check(b, a)
-
+
class Test_except():
fixer = "except"
-
+
def test_1(self):
b = """
try:
@@ -482,7 +485,7 @@
pass
except ImportError, e:
pass"""
-
+
a = """
try:
pass
@@ -491,42 +494,42 @@
except ImportError as e:
pass"""
self.check(b, a)
-
+
def test_2(self):
b = """
try:
pass
except (RuntimeError, ImportError), e:
pass"""
-
+
a = """
try:
pass
except (RuntimeError, ImportError) as e:
pass"""
self.check(b, a)
-
+
def test_3(self):
b = """
try:
pass
except Exception, (a, b):
pass"""
-
+
a = """
try:
pass
except Exception as (a, b):
pass"""
self.check(b, a)
-
+
def test_4(self):
b = """
try:
pass
except Exception, d[5]:
pass"""
-
+
a = """
try:
pass
@@ -534,14 +537,14 @@
d[5] = xxx_todo_changeme
pass"""
self.check(b, a)
-
+
def test_5(self):
b = """
try:
pass
except Exception, a.foo:
pass"""
-
+
a = """
try:
pass
@@ -549,14 +552,14 @@
a.foo = xxx_todo_changeme1
pass"""
self.check(b, a)
-
+
def test_6(self):
b = """
try:
pass
except Exception, a().foo:
pass"""
-
+
a = """
try:
pass
@@ -564,9 +567,9 @@
a().foo = xxx_todo_changeme2
pass"""
self.check(b, a)
-
+
# These should not be touched:
-
+
def test_7(self):
b = """
try:
@@ -580,7 +583,7 @@
except:
pass"""
self.check(b, a)
-
+
def test_8(self):
b = """
try:
@@ -594,7 +597,7 @@
except Exception:
pass"""
self.check(b, a)
-
+
def test_9(self):
b = """
try:
@@ -609,94 +612,303 @@
pass"""
self.check(b, a)
-
+
class Test_raise(FixerTestCase):
fixer = "raise"
-
+
def test_1(self):
b = """raise Exception, 5"""
a = """raise Exception(5)"""
self.check(b, a)
-
+
def test_2(self):
b = """raise Exception,5"""
a = """raise Exception(5)"""
self.check(b, a)
-
+
def test_3(self):
b = """raise Exception, (5, 6, 7)"""
a = """raise Exception((5, 6, 7))"""
self.check(b, a)
-
+
# These should not be touched
-
+
def test_4(self):
b = """raise Exception"""
a = """raise Exception"""
self.check(b, a)
-
+
def test_5(self):
b = """raise Exception(5, 6)"""
a = """raise Exception(5, 6)"""
self.check(b, a)
-
- # These should produce a warning
-
+
+ # These should result in traceback-assignment
+
+ def test_tb_1(self):
+ b = """def foo():
+ raise Exception, 5, 6"""
+ a = """def foo():
+ xxx_todo_changeme = Exception(5)
+ xxx_todo_changeme.__traceback__ = 6
+ raise xxx_todo_changeme"""
+ self.check(b, a)
+
+ def test_tb_2(self):
+ b = """def foo():
+ a = 5
+ raise Exception, 5, 6
+ b = 6"""
+ a = """def foo():
+ a = 5
+ xxx_todo_changeme1 = Exception(5)
+ xxx_todo_changeme1.__traceback__ = 6
+ raise xxx_todo_changeme1
+ b = 6"""
+ self.check(b, a)
+
+ def test_tb_3(self):
+ b = """def foo():
+ raise Exception,5,6"""
+ a = """def foo():
+ xxx_todo_changeme2 = Exception(5)
+ xxx_todo_changeme2.__traceback__ = 6
+ raise xxx_todo_changeme2"""
+ self.check(b, a)
+
+ def test_tb_4(self):
+ b = """def foo():
+ a = 5
+ raise Exception,5,6
+ b = 6"""
+ a = """def foo():
+ a = 5
+ xxx_todo_changeme3 = Exception(5)
+ xxx_todo_changeme3.__traceback__ = 6
+ raise xxx_todo_changeme3
+ b = 6"""
+ self.check(b, a)
+
+ def test_tb_5(self):
+ b = """def foo():
+ raise Exception, (5, 6, 7), 6"""
+ a = """def foo():
+ xxx_todo_changeme4 = Exception((5, 6, 7))
+ xxx_todo_changeme4.__traceback__ = 6
+ raise xxx_todo_changeme4"""
+ self.check(b, a)
+
+ def test_tb_6(self):
+ b = """def foo():
+ a = 5
+ raise Exception, (5, 6, 7), 6
+ b = 6"""
+ a = """def foo():
+ a = 5
+ xxx_todo_changeme5 = Exception((5, 6, 7))
+ xxx_todo_changeme5.__traceback__ = 6
+ raise xxx_todo_changeme5
+ b = 6"""
+ self.check(b, a)
+
+
+class Test_throw(FixerTestCase):
+ fixer = "throw"
+
+ def test_1(self):
+ b = """g.throw(Exception, 5)"""
+ a = """g.throw(Exception(5))"""
+ self.check(b, a)
+
+ def test_2(self):
+ b = """g.throw(Exception,5)"""
+ a = """g.throw(Exception(5))"""
+ self.check(b, a)
+
+ def test_3(self):
+ b = """g.throw(Exception, (5, 6, 7))"""
+ a = """g.throw(Exception((5, 6, 7)))"""
+ self.check(b, a)
+
+ def test_4(self):
+ b = """5 + g.throw(Exception, 5)"""
+ a = """5 + g.throw(Exception(5))"""
+ self.check(b, a)
+
+ # These should not be touched
+
+ def test_5(self):
+ b = """g.throw(Exception)"""
+ a = """g.throw(Exception)"""
+ self.check(b, a)
+
def test_6(self):
- b = """raise Exception, 5, 6"""
- a = """raise Exception, 5, 6"""
- self.warns(b, a, "raise will not support providing a traceback")
-
+ b = """g.throw(Exception(5, 6))"""
+ a = """g.throw(Exception(5, 6))"""
+ self.check(b, a)
+
def test_7(self):
- b = """raise Exception,5,6"""
- a = """raise Exception,5,6"""
- self.warns(b, a, "raise will not support providing a traceback")
-
+ b = """5 + g.throw(Exception(5, 6))"""
+ a = """5 + g.throw(Exception(5, 6))"""
+ self.check(b, a)
+
+ # These should result in traceback-assignment
+
+ def test_tb_1(self):
+ b = """def foo():
+ g.throw(Exception, 5, 6)"""
+ a = """def foo():
+ xxx_todo_changeme6 = Exception(5)
+ xxx_todo_changeme6.__traceback__ = 6
+ g.throw(xxx_todo_changeme6)"""
+ self.check(b, a)
+
+ def test_tb_2(self):
+ b = """def foo():
+ a = 5
+ g.throw(Exception, 5, 6)
+ b = 6"""
+ a = """def foo():
+ a = 5
+ xxx_todo_changeme7 = Exception(5)
+ xxx_todo_changeme7.__traceback__ = 6
+ g.throw(xxx_todo_changeme7)
+ b = 6"""
+ self.check(b, a)
+
+ def test_tb_3(self):
+ b = """def foo():
+ g.throw(Exception,5,6)"""
+ a = """def foo():
+ xxx_todo_changeme8 = Exception(5)
+ xxx_todo_changeme8.__traceback__ = 6
+ g.throw(xxx_todo_changeme8)"""
+ self.check(b, a)
+
+ def test_tb_4(self):
+ b = """def foo():
+ a = 5
+ g.throw(Exception,5,6)
+ b = 6"""
+ a = """def foo():
+ a = 5
+ xxx_todo_changeme9 = Exception(5)
+ xxx_todo_changeme9.__traceback__ = 6
+ g.throw(xxx_todo_changeme9)
+ b = 6"""
+ self.check(b, a)
+
+ def test_tb_5(self):
+ b = """def foo():
+ g.throw(Exception, (5, 6, 7), 6)"""
+ a = """def foo():
+ xxx_todo_changeme10 = Exception((5, 6, 7))
+ xxx_todo_changeme10.__traceback__ = 6
+ g.throw(xxx_todo_changeme10)"""
+ self.check(b, a)
+
+ def test_tb_6(self):
+ b = """def foo():
+ a = 5
+ g.throw(Exception, (5, 6, 7), 6)
+ b = 6"""
+ a = """def foo():
+ a = 5
+ xxx_todo_changeme11 = Exception((5, 6, 7))
+ xxx_todo_changeme11.__traceback__ = 6
+ g.throw(xxx_todo_changeme11)
+ b = 6"""
+ self.check(b, a)
+
+ def test_tb_7(self):
+ b = """def foo():
+ a + g.throw(Exception, 5, 6)"""
+ a = """def foo():
+ xxx_todo_changeme12 = Exception(5)
+ xxx_todo_changeme12.__traceback__ = 6
+ a + g.throw(xxx_todo_changeme12)"""
+ self.check(b, a)
+
+ def test_tb_8(self):
+ b = """def foo():
+ a = 5
+ a + g.throw(Exception, 5, 6)
+ b = 6"""
+ a = """def foo():
+ a = 5
+ xxx_todo_changeme13 = Exception(5)
+ xxx_todo_changeme13.__traceback__ = 6
+ a + g.throw(xxx_todo_changeme13)
+ b = 6"""
+ self.check(b, a)
+
+
class Test_long(FixerTestCase):
fixer = "long"
-
+
def test_1(self):
b = """x = long(x)"""
a = """x = int(x)"""
self.check(b, a)
-
+
def test_2(self):
b = """y = isinstance(x, long)"""
a = """y = isinstance(x, int)"""
self.check(b, a)
-
+
def test_3(self):
b = """z = type(x) in (int, long)"""
a = """z = type(x) in (int, int)"""
self.check(b, a)
-
+
def test_4(self):
b = """a = 12L"""
a = """a = 12"""
self.check(b, a)
-
+
def test_5(self):
b = """b = 0x12l"""
a = """b = 0x12"""
self.check(b, a)
-
+
# These should not be touched
-
+
def test_6(self):
b = """a = 12"""
a = """a = 12"""
self.check(b, a)
-
+
def test_7(self):
b = """b = 0x12"""
a = """b = 0x12"""
self.check(b, a)
-
+
def test_8(self):
b = """c = 3.14"""
a = """c = 3.14"""
self.check(b, a)
-
+
+
+class Test_sysexcinfo(FixerTestCase):
+ fixer = "sysexcinfo"
+
+ def test_1(self):
+ s = """sys.exc_info()"""
+ self.warns(s, s, "This function is going away")
+
+ def test_2(self):
+ s = """if sys.exc_info()[1] == 1:
+ pass"""
+
+ self.warns(s, s, "This function is going away")
+
+ def test_3(self):
+ s = """f = sys.exc_info"""
+ self.warns(s, s, "This function is going away")
+
+ def test_4(self):
+ s = """f = sys.exc_type + ":" + sys.exc_value"""
+ self.warns(s, s, "This attribute is going away")
if __name__ == "__main__":
import sys
Modified: sandbox/trunk/2to3/fixes/basefix.py
==============================================================================
--- sandbox/trunk/2to3/fixes/basefix.py (original)
+++ sandbox/trunk/2to3/fixes/basefix.py Thu Feb 8 23:42:35 2007
@@ -86,6 +86,10 @@
return pygram.parenthesize(node)
def new_name(self, template="xxx_todo_changeme"):
+ """Return a string suitable for use as an identifier
+
+ The new name is guaranteed not to conflict with other identifiers.
+ """
name = template
while name in self.used_names:
name = template + str(numbers.next())
@@ -93,6 +97,12 @@
return name
def cannot_convert(self, node, reason=None):
+ """Warn the user that a given chunk of code is not valid Python 3,
+ but that it cannot be converted automatically.
+
+ First argument is the top-level node for the code in question.
+ Optional second argument is why it can't be converted.
+ """
lineno = node.get_lineno()
for_output = node.clone()
for_output.set_prefix("")
Modified: sandbox/trunk/2to3/fixes/fix_apply.py
==============================================================================
--- sandbox/trunk/2to3/fixes/fix_apply.py (original)
+++ sandbox/trunk/2to3/fixes/fix_apply.py Thu Feb 8 23:42:35 2007
@@ -9,7 +9,7 @@
# Local imports
import pytree
from fixes import basefix
-
+from fixes.macros import Call, Comma
class FixApply(basefix.BaseFix):
@@ -49,17 +49,13 @@
kwds.set_prefix("")
l_newargs = [pytree.Leaf(token.STAR, "*"), args]
if kwds is not None:
- l_newargs.extend([pytree.Leaf(token.COMMA, ","),
+ l_newargs.extend([Comma(),
pytree.Leaf(token.DOUBLESTAR, "**"),
kwds])
l_newargs[-2].set_prefix(" ") # that's the ** token
# XXX Sometimes we could be cleverer, e.g. apply(f, (x, y) + t)
# can be translated into f(x, y, *t) instead of f(*(x, y) + t)
- new = pytree.Node(syms.power,
- (func,
- pytree.Node(syms.trailer,
- (pytree.Leaf(token.LPAR, "("),
- pytree.Node(syms.arglist, l_newargs),
- pytree.Leaf(token.RPAR, ")")))))
+ #new = pytree.Node(syms.power, (func, ArgList(l_newargs)))
+ new = Call(func, l_newargs)
new.set_prefix(prefix)
return new
Modified: sandbox/trunk/2to3/fixes/fix_except.py
==============================================================================
--- sandbox/trunk/2to3/fixes/fix_except.py (original)
+++ sandbox/trunk/2to3/fixes/fix_except.py Thu Feb 8 23:42:35 2007
@@ -7,6 +7,7 @@
# Local imports
import pytree
from fixes import basefix
+from fixes.macros import Assign, Attr, Name
def find_excepts(nodes):
for i in range(len(nodes)):
@@ -19,9 +20,6 @@
as_leaf = pytree.Leaf(token.NAME, "as")
as_leaf.set_prefix(" ")
-ass_leaf = pytree.Leaf(token.EQUAL, "=")
-ass_leaf.set_prefix(" ")
-
tuple_reason = "exception unpacking is going away"
class FixExcept(basefix.BaseFix):
@@ -32,42 +30,44 @@
['finally' ':' suite]
| 'finally' ':' suite) >
"""
-
+
def transform(self, node):
syms = self.syms
results = self.match(node)
assert results
-
+
try_cleanup = [ch.clone() for ch in results['cleanup']]
for except_clause, e_suite in find_excepts(try_cleanup):
if len(except_clause.children) == 4:
(E, comma, N) = except_clause.children[1:4]
comma.replace(as_leaf.clone())
- if str(N).strip()[0] == '(':
- # We're dealing with a tuple
- self.cannot_convert(N, tuple_reason)
- elif N.type != token.NAME:
+ if N.type != token.NAME:
# Generate a new N for the except clause
- new_N = pytree.Leaf(token.NAME, self.new_name())
+ new_N = Name(self.new_name())
new_N.set_prefix(" ")
target = N.clone()
target.set_prefix("")
N.replace(new_N)
-
+ new_N = new_N.clone()
+
# Insert "old_N = new_N" as the first statement in
- # the except body
+ # the except body. This loop skips leading whitespace
+ # and indents
suite_stmts = list(e_suite.children)
for i, stmt in enumerate(suite_stmts):
if isinstance(stmt, pytree.Node):
break
- assign = pytree.Node(syms.atom,
- [target,
- ass_leaf.clone(),
- new_N.clone()])
-
- assign.parent = e_suite
+
+ # The assignment is different if old_N is a tuple
+ # In that case, the assignment is old_N = new_N.message
+ if str(N).strip()[0] == '(':
+ assign = Assign(target, Attr(new_N, Name('message')))
+ else:
+ assign = Assign(target, new_N)
+
+ assign.parent = e_suite
suite_stmts = suite_stmts[:i] + [assign] + suite_stmts
e_suite.children = tuple(suite_stmts)
-
+
children = [c.clone() for c in node.children[:3]] + try_cleanup
return pytree.Node(node.type, children)
Modified: sandbox/trunk/2to3/fixes/fix_exec.py
==============================================================================
--- sandbox/trunk/2to3/fixes/fix_exec.py (original)
+++ sandbox/trunk/2to3/fixes/fix_exec.py Thu Feb 8 23:42:35 2007
@@ -9,6 +9,7 @@
# Local imports
import pytree
from fixes import basefix
+from fixes.macros import Comma, Name, Call
class FixExec(basefix.BaseFix):
@@ -29,14 +30,10 @@
args = [a.clone()]
args[0].set_prefix("")
if b is not None:
- args.extend([pytree.Leaf(token.COMMA, ","), b.clone()])
+ args.extend([Comma(), b.clone()])
if c is not None:
- args.extend([pytree.Leaf(token.COMMA, ","), c.clone()])
- new = pytree.Node(syms.factor,
- [pytree.Leaf(token.NAME, "exec"),
- pytree.Node(syms.trailer,
- [pytree.Leaf(token.LPAR, "("),
- pytree.Node(syms.arglist, args),
- pytree.Leaf(token.RPAR, ")")])])
+ args.extend([Comma(), c.clone()])
+
+ new = Call(Name("exec"), args)
new.set_prefix(node.get_prefix())
return new
Modified: sandbox/trunk/2to3/fixes/fix_has_key.py
==============================================================================
--- sandbox/trunk/2to3/fixes/fix_has_key.py (original)
+++ sandbox/trunk/2to3/fixes/fix_has_key.py Thu Feb 8 23:42:35 2007
@@ -9,6 +9,7 @@
# Local imports
import pytree
from fixes import basefix
+from fixes.macros import Name
class FixHasKey(basefix.BaseFix):
@@ -68,10 +69,10 @@
else:
before = pytree.Node(syms.power, before)
before.set_prefix(" ")
- n_op = pytree.Leaf(token.NAME, "in")
+ n_op = Name("in")
n_op.set_prefix(" ")
if negation:
- n_not = pytree.Leaf(token.NAME, "not")
+ n_not = Name("not")
n_not.set_prefix(" ")
n_op = pytree.Node(syms.comp_op, (n_not, n_op))
new = pytree.Node(syms.comparison, (arg, n_op, before))
Modified: sandbox/trunk/2to3/fixes/fix_intern.py
==============================================================================
--- sandbox/trunk/2to3/fixes/fix_intern.py (original)
+++ sandbox/trunk/2to3/fixes/fix_intern.py Thu Feb 8 23:42:35 2007
@@ -9,6 +9,7 @@
# Local imports
import pytree
from fixes import basefix
+from fixes.macros import Name, Attr
class FixIntern(basefix.BaseFix):
@@ -36,14 +37,11 @@
if after:
after = tuple(n.clone() for n in after)
new = pytree.Node(syms.power,
- (pytree.Leaf(token.NAME, "sys"),
- pytree.Node(syms.trailer,
- [pytree.Leaf(token.DOT, "."),
- pytree.Leaf(token.NAME, "intern")]),
- pytree.Node(syms.trailer,
+ Attr(Name("sys"), Name("intern")) +
+ (pytree.Node(syms.trailer,
[results["lpar"].clone(),
newarglist,
- results["rpar"].clone()]))
+ results["rpar"].clone()]),)
+ after)
new.set_prefix(node.get_prefix())
return new
Modified: sandbox/trunk/2to3/fixes/fix_long.py
==============================================================================
--- sandbox/trunk/2to3/fixes/fix_long.py (original)
+++ sandbox/trunk/2to3/fixes/fix_long.py Thu Feb 8 23:42:35 2007
@@ -12,6 +12,7 @@
# Local imports
import pytree
from fixes import basefix
+from fixes.macros import Name
class FixLong(basefix.BaseFix):
@@ -20,8 +21,8 @@
(long_type = 'long' | number = NUMBER)
"""
- static_long = pytree.Leaf(token.NAME, "long")
- static_int = pytree.Leaf(token.NAME, "int")
+ static_long = Name("long")
+ static_int = Name("int")
def transform(self, node):
results = self.match(node)
Modified: sandbox/trunk/2to3/fixes/fix_print.py
==============================================================================
--- sandbox/trunk/2to3/fixes/fix_print.py (original)
+++ sandbox/trunk/2to3/fixes/fix_print.py Thu Feb 8 23:42:35 2007
@@ -16,6 +16,7 @@
# Local imports
import pytree
from fixes import basefix
+from fixes.macros import Name, Call, Comma
class FixPrint(basefix.BaseFix):
@@ -36,19 +37,15 @@
results = self.match(node)
assert results
- if node == pytree.Leaf(token.NAME, "print"):
+ if node == Name("print"):
# Special-case print all by itself
- new = pytree.Node(syms.power,
- (pytree.Leaf(token.NAME, "Print"),
- pytree.Node(syms.trailer,
- (pytree.Leaf(token.LPAR, "("),
- pytree.Leaf(token.RPAR, ")")))))
+ new = Call(Name("Print"), [])
new.set_prefix(node.get_prefix())
return new
- assert node.children[0] == pytree.Leaf(token.NAME, "print")
+ assert node.children[0] == Name("print")
args = node.children[1:]
sep = end = file = None
- if args and args[-1] == pytree.Leaf(token.COMMA, ","):
+ if args and args[-1] == Comma():
args = args[:-1]
end = " "
if args and args[0] == pytree.Leaf(token.RIGHTSHIFT, ">>"):
@@ -56,7 +53,6 @@
file = args[1].clone()
args = args[3:] # Strip a possible comma after the file expression
# Now synthesize a Print(args, sep=..., end=..., file=...) node.
- n_print = pytree.Leaf(token.NAME, "Print") # XXX -> "print"
l_args = [arg.clone() for arg in args]
if l_args:
l_args[0].set_prefix("")
@@ -69,15 +65,7 @@
pytree.Leaf(token.STRING, repr(end)))
if file is not None:
self.add_kwarg(l_args, "file", file)
- if l_args:
- n_arglist = pytree.Node(syms.arglist, l_args)
- else:
- n_arglist = None
- l_args = [pytree.Leaf(token.LPAR, "("), pytree.Leaf(token.RPAR, ")")]
- if n_arglist:
- l_args.insert(1, n_arglist)
- n_trailer = pytree.Node(syms.trailer, l_args)
- n_stmt = pytree.Node(syms.power, (n_print, n_trailer))
+ n_stmt = Call(Name("Print"), l_args)
n_stmt.set_prefix(node.get_prefix())
return n_stmt
@@ -85,10 +73,10 @@
# XXX All this prefix-setting may lose comments (though rarely)
n_expr.set_prefix("")
n_argument = pytree.Node(self.syms.argument,
- (pytree.Leaf(token.NAME, s_kwd),
+ (Name(s_kwd),
pytree.Leaf(token.EQUAL, "="),
n_expr))
if l_nodes:
- l_nodes.append(pytree.Leaf(token.COMMA, ","))
+ l_nodes.append(Comma())
n_argument.set_prefix(" ")
l_nodes.append(n_argument)
Modified: sandbox/trunk/2to3/fixes/fix_raise.py
==============================================================================
--- sandbox/trunk/2to3/fixes/fix_raise.py (original)
+++ sandbox/trunk/2to3/fixes/fix_raise.py Thu Feb 8 23:42:35 2007
@@ -1,4 +1,4 @@
-"""Fixer for 'raise E, a1, a2, ...'"""
+"""Fixer for 'raise E, V, T'"""
# Author: Collin Winter
# Python imports
@@ -7,35 +7,57 @@
# Local imports
import pytree
from fixes import basefix
-
-reason = "Python 3's raise will not support providing a traceback"
+from fixes.macros import Name, Call, Assign, Newline, Attr
class FixRaise(basefix.BaseFix):
PATTERN = """
- raise_stmt< 'raise' exc=any ',' a1=any [',' a2=any] >
+ raise_stmt< 'raise' exc=any ',' val=any [',' tb=any] >
"""
def transform(self, node):
syms = self.syms
results = self.match(node)
assert results
-
+
exc = results["exc"].clone()
- args = [results["a1"].clone()]
+ args = [results["val"].clone()]
args[0].set_prefix("")
-
- arg2 = results.get("a2")
- if arg2 is not None:
- self.cannot_convert(node, reason)
- return node
-
- new = pytree.Node(syms.raise_stmt,
- [pytree.Leaf(token.NAME, "raise"),
- exc,
- pytree.Node(syms.trailer,
- [pytree.Leaf(token.LPAR, "("),
- pytree.Node(syms.arglist, args),
- pytree.Leaf(token.RPAR, ")")])])
- new.set_prefix(node.get_prefix())
- return new
+
+ if "tb" in results:
+ tb = results["tb"].clone()
+ name = Name(self.new_name())
+ children = list(node.parent.parent.children)
+ i = children.index(node.parent)
+ indent = children[1].value
+
+ # Instance the exception
+ build_e = pytree.Node(syms.simple_stmt,
+ [Assign(name.clone(), Call(exc, args)),
+ Newline()])
+ build_e.parent = node.parent.parent
+ if node.get_prefix():
+ # Over-indents otherwise
+ build_e.set_prefix(indent)
+
+ # Assign the traceback
+ set_tb = pytree.Node(syms.simple_stmt,
+ [Assign(Attr(name.clone(),
+ Name("__traceback__")), tb),
+ Newline()])
+ set_tb.set_prefix(indent)
+ set_tb.parent = node.parent.parent
+
+ # Insert into the suite
+ children[i:i] = [build_e, set_tb]
+ node.parent.parent.children = tuple(children)
+
+ name.set_prefix(" ")
+ new = pytree.Node(syms.simple_stmt, [Name("raise"), name])
+ new.set_prefix(indent)
+ return new
+ else:
+ new = pytree.Node(syms.raise_stmt,
+ [Name("raise"), Call(exc, args)])
+ new.set_prefix(node.get_prefix())
+ return new
Modified: sandbox/trunk/2to3/fixes/fix_repr.py
==============================================================================
--- sandbox/trunk/2to3/fixes/fix_repr.py (original)
+++ sandbox/trunk/2to3/fixes/fix_repr.py Thu Feb 8 23:42:35 2007
@@ -9,6 +9,7 @@
# Local imports
import pytree
from fixes import basefix
+from fixes.macros import Call, Name
class FixRepr(basefix.BaseFix):
@@ -23,11 +24,6 @@
expr = results["expr"].clone()
if expr.type == self.syms.testlist1:
expr = self.parenthesize(expr)
- new = pytree.Node(self.syms.power,
- (pytree.Leaf(token.NAME, "repr"),
- pytree.Node(self.syms.trailer,
- (pytree.Leaf(token.LPAR, "("),
- expr,
- pytree.Leaf(token.RPAR, ")")))))
+ new = Call(Name("repr"), [expr])
new.set_prefix(node.get_prefix())
return new
Added: sandbox/trunk/2to3/fixes/fix_sysexcinfo.py
==============================================================================
--- (empty file)
+++ sandbox/trunk/2to3/fixes/fix_sysexcinfo.py Thu Feb 8 23:42:35 2007
@@ -0,0 +1,32 @@
+"""Fixer/warner for sys.exc_{info,value,type,traceback}"""
+# Author: Collin Winter
+
+# Python imports
+import token
+
+# Local imports
+from pytree import Leaf
+from fixes import basefix
+
+
+class FixSysexcinfo(basefix.BaseFix):
+
+ PATTERN = """
+ power< 'sys' trailer< '.' attr='exc_info'> any* >
+ |
+ power< 'sys'
+ trailer< '.' attr=('exc_value' | 'exc_traceback' | 'exc_type')>
+ any* >
+ """
+
+ def transform(self, node):
+ results = self.match(node)
+ assert results
+ attr = results['attr']
+
+ if isinstance(attr, Leaf) and attr.value == 'exc_info':
+ self.cannot_convert(node,
+ "This function is going away in Python 3")
+ else:
+ self.cannot_convert(node,
+ "This attribute is going away in Python 3")
Added: sandbox/trunk/2to3/fixes/fix_throw.py
==============================================================================
--- (empty file)
+++ sandbox/trunk/2to3/fixes/fix_throw.py Thu Feb 8 23:42:35 2007
@@ -0,0 +1,80 @@
+"""Fixer for generator.throw(E, V, T)"""
+# Author: Collin Winter
+
+# Python imports
+import token
+
+# Local imports
+import pytree
+from fixes import basefix
+from fixes.macros import Name, Call, Assign, Newline, Attr
+
+class FixThrow(basefix.BaseFix):
+
+ PATTERN = """
+ power< any trailer< '.' 'throw' >
+ trailer< '(' args=arglist< exc=any ',' val=any [',' tb=any] > ')' >
+ >
+ """
+
+ def transform(self, node):
+ syms = self.syms
+ results = self.match(node)
+ assert results
+
+ throw_args = results["args"]
+ exc = results["exc"].clone()
+ args = [results["val"].clone()]
+ args[0].set_prefix("")
+
+ if "tb" in results:
+ tb = results["tb"].clone()
+ name = Name(self.new_name())
+ suite = find_parent_suite(node)
+ stmts = list(suite.children)
+ node_stmt = find_stmt(stmts, node)
+ i = stmts.index(node_stmt)
+ indent = stmts[1].value
+
+ # Instance the exception
+ build_e = pytree.Node(syms.simple_stmt,
+ [Assign(name.clone(), Call(exc, args)),
+ Newline()])
+ build_e.parent = node.parent.parent
+ if node_stmt.get_prefix():
+ # Over-indents otherwise
+ build_e.set_prefix(indent)
+
+ # Assign the traceback
+ tb.set_prefix(" ")
+ set_tb = pytree.Node(syms.simple_stmt,
+ [Assign(Attr(name.clone(),
+ Name("__traceback__")), tb),
+ Newline()])
+ set_tb.set_prefix(indent)
+ set_tb.parent = node.parent.parent
+
+ # Insert into the suite
+ stmts[i:i] = [build_e, set_tb]
+ suite.children = tuple(stmts)
+
+ throw_args.replace(name)
+ if not node_stmt.get_prefix():
+ node_stmt.set_prefix(indent)
+ # No return
+ else:
+ throw_args.replace(Call(exc, args))
+ # No return
+
+
+def find_parent_suite(node):
+ parent = node.parent
+ while parent:
+ if len(parent.children) > 2 and parent.children[0].value == "\n":
+ return parent
+ parent = parent.parent
+
+def find_stmt(stmts, node):
+ while node not in stmts:
+ node = node.parent
+ return node
Added: sandbox/trunk/2to3/fixes/macros.py
==============================================================================
--- (empty file)
+++ sandbox/trunk/2to3/fixes/macros.py Thu Feb 8 23:42:35 2007
@@ -0,0 +1,57 @@
+"""Abstract away often-used node construction routines."""
+# Author: Collin Winter
+
+# Python imports
+import token
+
+# Local imports
+from pytree import Leaf, Node
+from pygram import python_symbols as syms
+
+
+### Constant nodes
+ass_leaf = Leaf(token.EQUAL, "=")
+ass_leaf.set_prefix(" ")
+
+comma_leaf = Leaf(token.COMMA, ",")
+lparen_leaf = Leaf(token.LPAR, "(")
+rparen_leaf = Leaf(token.RPAR, ")")
+
+def Assign(target, source):
+ """Build an assignment statement"""
+ if not isinstance(target, tuple):
+ target = (target,)
+ if not isinstance(source, tuple):
+ source.set_prefix(" ")
+ source = (source,)
+
+ return Node(syms.atom, target + (ass_leaf.clone(),) + source)
+
+def Name(name):
+ """Return a NAME leaf"""
+ return Leaf(token.NAME, name)
+
+def Attr(obj, attr):
+ """A node tuple for obj.attr"""
+ return (obj,
+ Node(syms.trailer, [Leaf(token.DOT, '.'),
+ attr]))
+
+def Comma():
+ """A comma leaf"""
+ return comma_leaf.clone()
+
+def ArgList(args, lparen=lparen_leaf, rparen=rparen_leaf):
+ """A parenthesised argument list, used by Call()"""
+ return Node(syms.trailer,
+ [lparen.clone(),
+ Node(syms.arglist, args),
+ rparen.clone()])
+
+def Call(func_name, args):
+ """A function call"""
+ return Node(syms.power, [func_name, ArgList(args)])
+
+def Newline():
+ """A newline literal"""
+ return Leaf(token.NEWLINE, "\n")
Modified: sandbox/trunk/2to3/pytree.py
==============================================================================
--- sandbox/trunk/2to3/pytree.py (original)
+++ sandbox/trunk/2to3/pytree.py Thu Feb 8 23:42:35 2007
@@ -115,8 +115,9 @@
if new is not None:
new.parent = self.parent
self.parent = None
-
+
def get_lineno(self):
+ """Returns the line number which generated the invocant node."""
node = self
while not isinstance(node, Leaf):
if not node.children:
Modified: sandbox/trunk/2to3/refactor.py
==============================================================================
--- sandbox/trunk/2to3/refactor.py (original)
+++ sandbox/trunk/2to3/refactor.py Thu Feb 8 23:42:35 2007
@@ -24,6 +24,7 @@
import patcomp
from pgen2 import driver
import fixes
+import fixes.macros
import pygram
logging.basicConfig(format='%(name)s: %(message)s', level=logging.INFO)
More information about the Python-checkins
mailing list