Permalink
Browse files

Initial commit

  • Loading branch information...
0 parents commit bdc2d5801ddfcf3ee0a6d7f98e71e4306238bec0 @mitsuhiko mitsuhiko committed Feb 4, 2012
14 README
@@ -0,0 +1,14 @@
+
+ Python _ _
+ _ __ ___ __| |___ _ _ _ _ (_)______
+ | ' \/ _ \/ _` / -_) '_| ' \| |_ / -_)
+ |_|_|_\___/\__,_\___|_| |_||_|_/__\___|
+
+ This library is a very thin wrapper around lib2to3 to utilize it
+ to make Python 2 code more modern with the intention of eventually
+ porting it over to Python 3.
+
+ It does not guarantee, but it attempts to spit out a Python 2/3
+ compatible codebase. The code that it generates has a runtime
+ dependency on `six`.
+
No changes.
@@ -0,0 +1,32 @@
+import sys
+from lib2to3 import refactor
+
+
+lib2to3_fix_names = set([
+ 'lib2to3.fixes.fix_apply',
+ 'lib2to3.fixes.fix_except',
+ 'lib2to3.fixes.fix_exec',
+ 'lib2to3.fixes.fix_execfile',
+ 'lib2to3.fixes.fix_exitfunc',
+ 'lib2to3.fixes.fix_funcattrs',
+ 'lib2to3.fixes.fix_has_key',
+ 'lib2to3.fixes.fix_idioms',
+ 'lib2to3.fixes.fix_import',
+ 'lib2to3.fixes.fix_methodattrs',
+ 'lib2to3.fixes.fix_ne',
+ 'lib2to3.fixes.fix_numliterals',
+ 'lib2to3.fixes.fix_operator',
+ 'lib2to3.fixes.fix_paren',
+ 'lib2to3.fixes.fix_reduce',
+ 'lib2to3.fixes.fix_repr',
+ 'lib2to3.fixes.fix_set_literal',
+ 'lib2to3.fixes.fix_standarderror',
+ 'lib2to3.fixes.fix_sys_exc',
+ 'lib2to3.fixes.fix_throw',
+ 'lib2to3.fixes.fix_tuple_params',
+ 'lib2to3.fixes.fix_types',
+ 'lib2to3.fixes.fix_ws_comma',
+ 'lib2to3.fixes.fix_xrange',
+ 'lib2to3.fixes.fix_xreadlines',
+ 'lib2to3.fixes.fix_zip'
+])
@@ -0,0 +1,28 @@
+# Copyright 2008 Armin Ronacher.
+# Licensed to PSF under a Contributor Agreement.
+
+from lib2to3 import fixer_base
+from lib2to3.fixer_util import touch_import
+
+
+class FixFilter(fixer_base.BaseFix):
+
+ BM_compatible = True
+ order = "pre"
+
+ PATTERN = """
+ power< 'filter'
+ trailer< '('
+ arglist< (
+ (not(argument<any '=' any>) any ','
+ not(argument<any '=' any>) any) |
+ (not(argument<any '=' any>) any ','
+ not(argument<any '=' any>) any ','
+ not(argument<any '=' any>) any)
+ ) >
+ ')' >
+ >
+ """
+
+ def transform(self, node, results):
+ touch_import(u'six.moves', u'filter', node)
@@ -0,0 +1,28 @@
+# Copyright 2008 Armin Ronacher.
+# Licensed to PSF under a Contributor Agreement.
+
+from lib2to3 import fixer_base
+from lib2to3.fixer_util import touch_import
+
+
+class FixMap(fixer_base.BaseFix):
+
+ BM_compatible = True
+ order = "pre"
+
+ PATTERN = """
+ power< 'map'
+ trailer< '('
+ arglist< (
+ (not(argument<any '=' any>) any ','
+ not(argument<any '=' any>) any) |
+ (not(argument<any '=' any>) any ','
+ not(argument<any '=' any>) any ','
+ not(argument<any '=' any>) any)
+ ) >
+ ')' >
+ >
+ """
+
+ def transform(self, node, results):
+ touch_import(u'six.moves', u'map', node)
@@ -0,0 +1,28 @@
+"""Fixer for it.next() -> advance_iterator(it)"""
+
+# Local imports
+from lib2to3 import fixer_base
+from lib2to3.fixer_util import touch_import, Name, Call
+
+bind_warning = "Calls to builtin next() possibly shadowed by global binding"
+
+
+class FixNext(fixer_base.BaseFix):
+ BM_compatible = True
+ PATTERN = """
+ power< base=any+ trailer< '.' attr='next' > trailer< '(' ')' > >
+ |
+ power< head=any+ trailer< '.' attr='next' > not trailer< '(' ')' > >
+ """
+
+ order = "pre" # Pre-order tree traversal
+
+ def transform(self, node, results):
+ assert results
+ base = results.get('base')
+ if not base:
+ return
+ touch_import(None, u'six', node)
+ base = [n.clone() for n in base]
+ base[0].prefix = u""
+ node.replace(Call(Name(u"six.advance_iterator", prefix=node.prefix), base))
@@ -0,0 +1,86 @@
+# Copyright 2006 Google, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+"""Fixer for print.
+
+Change:
+ 'print' into 'print()'
+ 'print ...' into 'print(...)'
+ 'print ... ,' into 'print(..., end=" ")'
+ 'print >>x, ...' into 'print(..., file=x)'
+
+No changes are applied if print_function is imported from __future__
+
+"""
+
+# Local imports
+from lib2to3 import patcomp, pytree, fixer_base
+from lib2to3.pgen2 import token
+from lib2to3.fixer_util import Name, Call, Comma, String, touch_import
+
+
+parend_expr = patcomp.compile_pattern(
+ """atom< '(' [atom|STRING|NAME] ')' >"""
+ )
+
+
+class FixPrint(fixer_base.BaseFix):
+
+ BM_compatible = True
+
+ PATTERN = """
+ simple_stmt< any* bare='print' any* > | print_stmt
+ """
+
+ def transform(self, node, results):
+ assert results
+
+ bare_print = results.get("bare")
+
+ if bare_print:
+ # Special-case print all by itself
+ bare_print.replace(Call(Name(u"print"), [],
+ prefix=bare_print.prefix))
+ return
+ assert node.children[0] == Name(u"print")
+ args = node.children[1:]
+ if len(args) == 1 and parend_expr.match(args[0]):
+ # We don't want to keep sticking parens around an
+ # already-parenthesised expression.
+ return
+
+ sep = end = file = None
+ if args and args[-1] == Comma():
+ args = args[:-1]
+ end = " "
+ if args and args[0] == pytree.Leaf(token.RIGHTSHIFT, u">>"):
+ assert len(args) >= 2
+ file = args[1].clone()
+ args = args[3:] # Strip a possible comma after the file expression
+ # Now synthesize a print(args, sep=..., end=..., file=...) node.
+ l_args = [arg.clone() for arg in args]
+ if l_args:
+ l_args[0].prefix = u""
+ if sep is not None or end is not None or file is not None:
+ if sep is not None:
+ self.add_kwarg(l_args, u"sep", String(repr(sep)))
+ if end is not None:
+ self.add_kwarg(l_args, u"end", String(repr(end)))
+ if file is not None:
+ self.add_kwarg(l_args, u"file", file)
+ n_stmt = Call(Name(u"print"), l_args)
+ n_stmt.prefix = node.prefix
+ touch_import(u'__future__', u'print_function', node)
+ return n_stmt
+
+ def add_kwarg(self, l_nodes, s_kwd, n_expr):
+ # XXX All this prefix-setting may lose comments (though rarely)
+ n_expr.prefix = u""
+ n_argument = pytree.Node(self.syms.argument,
+ (Name(s_kwd),
+ pytree.Leaf(token.EQUAL, u"="),
+ n_expr))
+ if l_nodes:
+ l_nodes.append(Comma())
+ n_argument.prefix = u" "
+ l_nodes.append(n_argument)
@@ -0,0 +1,71 @@
+"""Fixer for 'raise E, V, T'
+
+raise -> raise
+raise E -> raise E
+raise E, V -> raise E(V)
+
+raise (((E, E'), E''), E'''), V -> raise E(V)
+
+
+CAVEATS:
+1) "raise E, V" will be incorrectly translated if V is an exception
+ instance. The correct Python 3 idiom is
+
+ raise E from V
+
+ but since we can't detect instance-hood by syntax alone and since
+ any client code would have to be changed as well, we don't automate
+ this.
+"""
+# Author: Collin Winter, Armin Ronacher
+
+# Local imports
+from lib2to3 import pytree, fixer_base
+from lib2to3.pgen2 import token
+from lib2to3.fixer_util import Name, Call, is_tuple
+
+class FixRaise(fixer_base.BaseFix):
+
+ BM_compatible = True
+ PATTERN = """
+ raise_stmt< 'raise' exc=any [',' val=any] >
+ """
+
+ def transform(self, node, results):
+ syms = self.syms
+
+ exc = results["exc"].clone()
+ if exc.type == token.STRING:
+ msg = "Python 3 does not support string exceptions"
+ self.cannot_convert(node, msg)
+ return
+
+ # Python 2 supports
+ # raise ((((E1, E2), E3), E4), E5), V
+ # as a synonym for
+ # raise E1, V
+ # Since Python 3 will not support this, we recurse down any tuple
+ # literals, always taking the first element.
+ if is_tuple(exc):
+ while is_tuple(exc):
+ # exc.children[1:-1] is the unparenthesized tuple
+ # exc.children[1].children[0] is the first element of the tuple
+ exc = exc.children[1].children[0].clone()
+ exc.prefix = u" "
+
+ if "val" not in results:
+ # One-argument raise
+ new = pytree.Node(syms.raise_stmt, [Name(u"raise"), exc])
+ new.prefix = node.prefix
+ return new
+
+ val = results["val"].clone()
+ if is_tuple(val):
+ args = [c.clone() for c in val.children[1:-1]]
+ else:
+ val.prefix = u""
+ args = [val]
+
+ return pytree.Node(syms.raise_stmt,
+ [Name(u"raise"), Call(exc, args)],
+ prefix=node.prefix)
@@ -0,0 +1,23 @@
+import re
+from lib2to3.pgen2 import token
+from lib2to3 import fixer_base
+from lib2to3.fixer_util import touch_import, Name, Call
+
+_mapping = {u"unichr" : u"chr", u"unicode" : u"str"}
+_literal_re = re.compile(ur"[uU][rR]?[\'\"]")
+
+class FixUnicode(fixer_base.BaseFix):
+ BM_compatible = True
+ PATTERN = "STRING | 'unicode'"
+
+ def transform(self, node, results):
+ if node.type == token.NAME:
+ touch_import(None, u'six', node)
+ new = node.clone()
+ new.value = u'six.text_type'
+ return new
+ elif node.type == token.STRING and _literal_re.match(node.value):
+ touch_import(None, u'six', node)
+ new = node.clone()
+ new.value = new.value[1:]
+ node.replace(Call(Name(u'six.u', prefix=node.prefix), [new]))
Oops, something went wrong.

0 comments on commit bdc2d58

Please sign in to comment.