summaryrefslogtreecommitdiffstats
path: root/Lib/lib2to3/fixes
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/lib2to3/fixes')
-rw-r--r--Lib/lib2to3/fixes/basefix.py6
-rw-r--r--Lib/lib2to3/fixes/fix_except.py14
-rw-r--r--Lib/lib2to3/fixes/fix_filter.py36
-rw-r--r--Lib/lib2to3/fixes/fix_future.py5
-rw-r--r--Lib/lib2to3/fixes/fix_has_key.py6
-rw-r--r--Lib/lib2to3/fixes/fix_idioms.py4
-rw-r--r--Lib/lib2to3/fixes/fix_imports.py4
-rw-r--r--Lib/lib2to3/fixes/fix_map.py38
-rw-r--r--Lib/lib2to3/fixes/fix_ne.py6
-rw-r--r--Lib/lib2to3/fixes/fix_next.py12
-rw-r--r--Lib/lib2to3/fixes/fix_print.py2
-rw-r--r--Lib/lib2to3/fixes/fix_raise.py14
-rw-r--r--Lib/lib2to3/fixes/fix_renames.py3
-rw-r--r--Lib/lib2to3/fixes/fix_repr.py8
-rw-r--r--Lib/lib2to3/fixes/fix_tuple_params.py4
-rw-r--r--Lib/lib2to3/fixes/fix_unicode.py34
-rw-r--r--Lib/lib2to3/fixes/fix_ws_comma.py50
-rw-r--r--Lib/lib2to3/fixes/fix_zip.py43
-rw-r--r--Lib/lib2to3/fixes/util.py49
19 files changed, 175 insertions, 163 deletions
diff --git a/Lib/lib2to3/fixes/basefix.py b/Lib/lib2to3/fixes/basefix.py
index 8eb4278..66c448e 100644
--- a/Lib/lib2to3/fixes/basefix.py
+++ b/Lib/lib2to3/fixes/basefix.py
@@ -87,7 +87,7 @@ class BaseFix(object):
Args:
node: the root of the parse tree that matched the fixer.
results: a dict mapping symbolic names to part of the match.
-
+
Returns:
None, or a node that is a modified copy of the
argument node. The node argument may also be modified in-place to
@@ -146,7 +146,7 @@ class BaseFix(object):
def start_tree(self, tree, filename):
"""Some fixers need to maintain tree-wide state.
This method is called once, at the start of tree fix-up.
-
+
tree - the root node of the tree to be processed.
filename - the name of the file the tree came from.
"""
@@ -158,7 +158,7 @@ class BaseFix(object):
def finish_tree(self, tree, filename):
"""Some fixers need to maintain tree-wide state.
This method is called once, at the conclusion of tree fix-up.
-
+
tree - the root node of the tree to be processed.
filename - the name of the file the tree came from.
"""
diff --git a/Lib/lib2to3/fixes/fix_except.py b/Lib/lib2to3/fixes/fix_except.py
index 340575a..34281a0 100644
--- a/Lib/lib2to3/fixes/fix_except.py
+++ b/Lib/lib2to3/fixes/fix_except.py
@@ -3,19 +3,19 @@
The following cases will be converted:
- "except E, T:" where T is a name:
-
+
except E as T:
-
+
- "except E, T:" where T is not a name, tuple or list:
-
+
except E as t:
T = t
-
+
This is done because the target of an "except" clause must be a
name.
-
+
- "except E, T:" where T is a tuple or list literal:
-
+
except E as t:
T = t.args
"""
@@ -39,7 +39,7 @@ class FixExcept(basefix.BaseFix):
try_stmt< 'try' ':' suite
cleanup=((except_clause ':' suite)+ ['else' ':' suite]
['finally' ':' suite]
- | 'finally' ':' suite) >
+ | 'finally' ':' suite) >
"""
def transform(self, node, results):
diff --git a/Lib/lib2to3/fixes/fix_filter.py b/Lib/lib2to3/fixes/fix_filter.py
index 096b9c8..70d8f5e 100644
--- a/Lib/lib2to3/fixes/fix_filter.py
+++ b/Lib/lib2to3/fixes/fix_filter.py
@@ -14,11 +14,9 @@ Python 2.6 figure it out.
"""
# Local imports
-from .. import pytree
-from .. import patcomp
from ..pgen2 import token
from . import basefix
-from .util import Name, Call, ListComp, attr_chain, does_tree_import
+from .util import Name, Call, ListComp, does_tree_import, in_special_context
class FixFilter(basefix.BaseFix):
@@ -85,35 +83,3 @@ class FixFilter(basefix.BaseFix):
new = Call(Name("list"), [new])
new.set_prefix(node.get_prefix())
return new
-
-P0 = """for_stmt< 'for' any 'in' node=any ':' any* >
- | comp_for< 'for' any 'in' node=any any* >
- """
-p0 = patcomp.compile_pattern(P0)
-
-P1 = """
-power<
- ( 'iter' | 'list' | 'tuple' | 'sorted' | 'set' | 'sum' |
- 'any' | 'all' | (any* trailer< '.' 'join' >) )
- trailer< '(' node=any ')' >
- any*
->
-"""
-p1 = patcomp.compile_pattern(P1)
-
-P2 = """
-power<
- 'sorted'
- trailer< '(' arglist<node=any any*> ')' >
- any*
->
-"""
-p2 = patcomp.compile_pattern(P2)
-
-def in_special_context(node):
- patterns = [p0, p1, p2]
- for pattern, parent in zip(patterns, attr_chain(node, "parent")):
- results = {}
- if pattern.match(parent, results) and results["node"] is node:
- return True
- return False
diff --git a/Lib/lib2to3/fixes/fix_future.py b/Lib/lib2to3/fixes/fix_future.py
index 5476df4..f3ba127 100644
--- a/Lib/lib2to3/fixes/fix_future.py
+++ b/Lib/lib2to3/fixes/fix_future.py
@@ -2,15 +2,14 @@
from __future__ import foo is replaced with an empty line.
"""
-# Author: Christian Heimes
+# Author: Christian Heimes
# Local imports
from . import basefix
-from .util import BlankLine
+from .util import BlankLine
class FixFuture(basefix.BaseFix):
PATTERN = """import_from< 'from' module_name="__future__" 'import' any >"""
def transform(self, node, results):
return BlankLine()
-
diff --git a/Lib/lib2to3/fixes/fix_has_key.py b/Lib/lib2to3/fixes/fix_has_key.py
index ea7bfc5..77684fb 100644
--- a/Lib/lib2to3/fixes/fix_has_key.py
+++ b/Lib/lib2to3/fixes/fix_has_key.py
@@ -18,14 +18,14 @@ CAVEATS:
m = d.has_key
if m(k):
...
-
+
Only *calls* to has_key() are converted. While it is possible to
convert the above to something like
-
+
m = d.__contains__
if m(k):
...
-
+
this is currently not done.
"""
diff --git a/Lib/lib2to3/fixes/fix_idioms.py b/Lib/lib2to3/fixes/fix_idioms.py
index e2f937b..2ca2a83 100644
--- a/Lib/lib2to3/fixes/fix_idioms.py
+++ b/Lib/lib2to3/fixes/fix_idioms.py
@@ -5,7 +5,7 @@
type(x) is T -> isinstance(x, T)
type(x) != T -> not isinstance(x, T)
type(x) is not T -> not isinstance(x, T)
-
+
* Change "while 1:" into "while True:".
* Change both
@@ -19,7 +19,7 @@ and the more general
v = EXPR
v.sort()
foo(v)
-
+
into
v = sorted(EXPR)
diff --git a/Lib/lib2to3/fixes/fix_imports.py b/Lib/lib2to3/fixes/fix_imports.py
index 1ad672b..fbdf7e4 100644
--- a/Lib/lib2to3/fixes/fix_imports.py
+++ b/Lib/lib2to3/fixes/fix_imports.py
@@ -16,7 +16,7 @@ builtin_names = [name for name in dir(__builtin__)
MAPPING = {"StringIO": ("io", ["StringIO"]),
"cStringIO": ("io", ["StringIO"]),
- "__builtin__" : ("builtins", builtin_names),
+ "__builtin__" : ("builtins", builtin_names),
}
@@ -86,4 +86,4 @@ class FixImports(basefix.BaseFix):
bare_name = bare_name[0]
new_name = self.replace.get(bare_name.value)
if new_name:
- bare_name.replace(Name(new_name, prefix=bare_name.get_prefix()))
+ bare_name.replace(Name(new_name, prefix=bare_name.get_prefix()))
diff --git a/Lib/lib2to3/fixes/fix_map.py b/Lib/lib2to3/fixes/fix_map.py
index b5dcaa2..d16cf9f 100644
--- a/Lib/lib2to3/fixes/fix_map.py
+++ b/Lib/lib2to3/fixes/fix_map.py
@@ -20,11 +20,9 @@ soon as the shortest argument is exhausted.
"""
# Local imports
-from .. import pytree
-from .. import patcomp
from ..pgen2 import token
from . import basefix
-from .util import Name, Call, ListComp, attr_chain, does_tree_import
+from .util import Name, Call, ListComp, does_tree_import, in_special_context
from ..pygram import python_symbols as syms
class FixMap(basefix.BaseFix):
@@ -71,7 +69,7 @@ class FixMap(basefix.BaseFix):
# If a future map has been imported for this file, we won't
# be making any modifications
return
-
+
if node.parent.type == syms.simple_stmt:
self.warning(node, "You should use a for loop here")
new = node.clone()
@@ -92,35 +90,3 @@ class FixMap(basefix.BaseFix):
new = Call(Name("list"), [new])
new.set_prefix(node.get_prefix())
return new
-
-P0 = """for_stmt< 'for' any 'in' node=any ':' any* >
- | comp_for< 'for' any 'in' node=any any* >
- """
-p0 = patcomp.compile_pattern(P0)
-
-P1 = """
-power<
- ( 'iter' | 'list' | 'tuple' | 'sorted' | 'set' | 'sum' |
- 'any' | 'all' | (any* trailer< '.' 'join' >) )
- trailer< '(' node=any ')' >
- any*
->
-"""
-p1 = patcomp.compile_pattern(P1)
-
-P2 = """
-power<
- 'sorted'
- trailer< '(' arglist<node=any any*> ')' >
- any*
->
-"""
-p2 = patcomp.compile_pattern(P2)
-
-def in_special_context(node):
- patterns = [p0, p1, p2]
- for pattern, parent in zip(patterns, attr_chain(node, "parent")):
- results = {}
- if pattern.match(parent, results) and results["node"] is node:
- return True
- return False
diff --git a/Lib/lib2to3/fixes/fix_ne.py b/Lib/lib2to3/fixes/fix_ne.py
index ecd18e0..f83ca43 100644
--- a/Lib/lib2to3/fixes/fix_ne.py
+++ b/Lib/lib2to3/fixes/fix_ne.py
@@ -17,6 +17,6 @@ class FixNe(basefix.BaseFix):
return node.type == token.NOTEQUAL and node.value == "<>"
def transform(self, node, results):
- new = pytree.Leaf(token.NOTEQUAL, "!=")
- new.set_prefix(node.get_prefix())
- return new
+ new = pytree.Leaf(token.NOTEQUAL, "!=")
+ new.set_prefix(node.get_prefix())
+ return new
diff --git a/Lib/lib2to3/fixes/fix_next.py b/Lib/lib2to3/fixes/fix_next.py
index adbc962..6b54376 100644
--- a/Lib/lib2to3/fixes/fix_next.py
+++ b/Lib/lib2to3/fixes/fix_next.py
@@ -47,12 +47,12 @@ class FixNext(basefix.BaseFix):
mod = results.get("mod")
if base:
- if self.shadowed_next:
- attr.replace(Name("__next__", prefix=attr.get_prefix()))
- else:
- base = [n.clone() for n in base]
- base[0].set_prefix("")
- node.replace(Call(Name("next", prefix=node.get_prefix()), base))
+ if self.shadowed_next:
+ attr.replace(Name("__next__", prefix=attr.get_prefix()))
+ else:
+ base = [n.clone() for n in base]
+ base[0].set_prefix("")
+ node.replace(Call(Name("next", prefix=node.get_prefix()), base))
elif name:
n = Name("__next__", prefix=name.get_prefix())
name.replace(n)
diff --git a/Lib/lib2to3/fixes/fix_print.py b/Lib/lib2to3/fixes/fix_print.py
index aa5c60a..ddd846a 100644
--- a/Lib/lib2to3/fixes/fix_print.py
+++ b/Lib/lib2to3/fixes/fix_print.py
@@ -5,7 +5,7 @@
Change:
'print' into 'print()'
- 'print ...' into 'print(...)'
+ 'print ...' into 'print(...)'
'print ... ,' into 'print(..., end=" ")'
'print >>x, ...' into 'print(..., file=x)'
"""
diff --git a/Lib/lib2to3/fixes/fix_raise.py b/Lib/lib2to3/fixes/fix_raise.py
index 2e9ffbc..dcf4278 100644
--- a/Lib/lib2to3/fixes/fix_raise.py
+++ b/Lib/lib2to3/fixes/fix_raise.py
@@ -12,9 +12,9 @@ raise "foo", V, T -> warns about string exceptions
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.
@@ -48,11 +48,11 @@ class FixRaise(basefix.BaseFix):
# 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.set_prefix(" ")
+ 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.set_prefix(" ")
if "val" not in results:
# One-argument raise
diff --git a/Lib/lib2to3/fixes/fix_renames.py b/Lib/lib2to3/fixes/fix_renames.py
index 336654a..58ad6ce 100644
--- a/Lib/lib2to3/fixes/fix_renames.py
+++ b/Lib/lib2to3/fixes/fix_renames.py
@@ -63,8 +63,7 @@ class FixRenames(basefix.BaseFix):
attr_name = results.get("attr_name")
#bare_name = results.get("bare_name")
#import_mod = results.get("module")
-
+
if mod_name and attr_name:
new_attr = LOOKUP[(mod_name.value, attr_name.value)]
attr_name.replace(Name(new_attr, prefix=attr_name.get_prefix()))
-
diff --git a/Lib/lib2to3/fixes/fix_repr.py b/Lib/lib2to3/fixes/fix_repr.py
index 9917ad5..62491df 100644
--- a/Lib/lib2to3/fixes/fix_repr.py
+++ b/Lib/lib2to3/fixes/fix_repr.py
@@ -15,8 +15,8 @@ class FixRepr(basefix.BaseFix):
"""
def transform(self, node, results):
- expr = results["expr"].clone()
+ expr = results["expr"].clone()
- if expr.type == self.syms.testlist1:
- expr = self.parenthesize(expr)
- return Call(Name("repr"), [expr], prefix=node.get_prefix())
+ if expr.type == self.syms.testlist1:
+ expr = self.parenthesize(expr)
+ return Call(Name("repr"), [expr], prefix=node.get_prefix())
diff --git a/Lib/lib2to3/fixes/fix_tuple_params.py b/Lib/lib2to3/fixes/fix_tuple_params.py
index 199f6e0..5542ff5 100644
--- a/Lib/lib2to3/fixes/fix_tuple_params.py
+++ b/Lib/lib2to3/fixes/fix_tuple_params.py
@@ -2,7 +2,7 @@
def func(((a, b), c), d):
...
-
+
->
def func(x, d):
@@ -10,7 +10,7 @@ def func(x, d):
...
It will also support lambdas:
-
+
lambda (x, y): x + y -> lambda t: t[0] + t[1]
# The parens are a syntax error in Python 3
diff --git a/Lib/lib2to3/fixes/fix_unicode.py b/Lib/lib2to3/fixes/fix_unicode.py
index 380f241..d7ad3b8 100644
--- a/Lib/lib2to3/fixes/fix_unicode.py
+++ b/Lib/lib2to3/fixes/fix_unicode.py
@@ -8,21 +8,21 @@ from .import basefix
class FixUnicode(basefix.BaseFix):
- PATTERN = "STRING | NAME<'unicode' | 'unichr'>"
+ PATTERN = "STRING | NAME<'unicode' | 'unichr'>"
- def transform(self, node, results):
- if node.type == token.NAME:
- if node.value == "unicode":
- new = node.clone()
- new.value = "str"
- return new
- if node.value == "unichr":
- new = node.clone()
- new.value = "chr"
- return new
- # XXX Warn when __unicode__ found?
- elif node.type == token.STRING:
- if re.match(r"[uU][rR]?[\'\"]", node.value):
- new = node.clone()
- new.value = new.value[1:]
- return new
+ def transform(self, node, results):
+ if node.type == token.NAME:
+ if node.value == "unicode":
+ new = node.clone()
+ new.value = "str"
+ return new
+ if node.value == "unichr":
+ new = node.clone()
+ new.value = "chr"
+ return new
+ # XXX Warn when __unicode__ found?
+ elif node.type == token.STRING:
+ if re.match(r"[uU][rR]?[\'\"]", node.value):
+ new = node.clone()
+ new.value = new.value[1:]
+ return new
diff --git a/Lib/lib2to3/fixes/fix_ws_comma.py b/Lib/lib2to3/fixes/fix_ws_comma.py
index 2ba1b49..53e0008 100644
--- a/Lib/lib2to3/fixes/fix_ws_comma.py
+++ b/Lib/lib2to3/fixes/fix_ws_comma.py
@@ -11,29 +11,29 @@ from .import basefix
class FixWsComma(basefix.BaseFix):
- explicit = True # The user must ask for this fixers
-
- PATTERN = """
- any<(not(',') any)+ ',' ((not(',') any)+ ',')* [not(',') any]>
- """
-
- COMMA = pytree.Leaf(token.COMMA, ",")
- COLON = pytree.Leaf(token.COLON, ":")
- SEPS = (COMMA, COLON)
-
- def transform(self, node, results):
- new = node.clone()
- comma = False
- for child in new.children:
- if child in self.SEPS:
- prefix = child.get_prefix()
- if prefix.isspace() and "\n" not in prefix:
- child.set_prefix("")
- comma = True
- else:
- if comma:
- prefix = child.get_prefix()
- if not prefix:
- child.set_prefix(" ")
+ explicit = True # The user must ask for this fixers
+
+ PATTERN = """
+ any<(not(',') any)+ ',' ((not(',') any)+ ',')* [not(',') any]>
+ """
+
+ COMMA = pytree.Leaf(token.COMMA, ",")
+ COLON = pytree.Leaf(token.COLON, ":")
+ SEPS = (COMMA, COLON)
+
+ def transform(self, node, results):
+ new = node.clone()
comma = False
- return new
+ for child in new.children:
+ if child in self.SEPS:
+ prefix = child.get_prefix()
+ if prefix.isspace() and "\n" not in prefix:
+ child.set_prefix("")
+ comma = True
+ else:
+ if comma:
+ prefix = child.get_prefix()
+ if not prefix:
+ child.set_prefix(" ")
+ comma = False
+ return new
diff --git a/Lib/lib2to3/fixes/fix_zip.py b/Lib/lib2to3/fixes/fix_zip.py
new file mode 100644
index 0000000..e072713
--- /dev/null
+++ b/Lib/lib2to3/fixes/fix_zip.py
@@ -0,0 +1,43 @@
+"""
+Fixer that changes zip(seq0, seq1, ...) into list(zip(seq0, seq1, ...)
+unless there exists a 'from future_builtins import zip' statement in the
+top-level namespace.
+
+We avoid the transformation if the zip() call is directly contained in
+iter(<>), list(<>), tuple(<>), sorted(<>), ...join(<>), or for V in <>:.
+"""
+
+# Local imports
+from . import basefix
+from .util import Name, Call, does_tree_import, in_special_context
+
+class FixZip(basefix.BaseFix):
+
+ PATTERN = """
+ power< 'zip' args=trailer< '(' [any] ')' >
+ >
+ """
+
+ def start_tree(self, *args):
+ super(FixZip, self).start_tree(*args)
+ self._future_zip_found = None
+
+ def has_future_zip(self, node):
+ if self._future_zip_found is not None:
+ return self._future_zip_found
+ self._future_zip_found = does_tree_import('future_builtins', 'zip', node)
+ return self._future_zip_found
+
+ def transform(self, node, results):
+ if self.has_future_zip(node):
+ # If a future zip has been imported for this file, we won't
+ # be making any modifications
+ return
+
+ if in_special_context(node):
+ return None
+ new = node.clone()
+ new.set_prefix("")
+ new = Call(Name("list"), [new])
+ new.set_prefix(node.get_prefix())
+ return new
diff --git a/Lib/lib2to3/fixes/util.py b/Lib/lib2to3/fixes/util.py
index 8b7ad9f..ef809af 100644
--- a/Lib/lib2to3/fixes/util.py
+++ b/Lib/lib2to3/fixes/util.py
@@ -5,6 +5,7 @@
from ..pgen2 import token
from ..pytree import Leaf, Node
from ..pygram import python_symbols as syms
+from .. import patcomp
###########################################################
@@ -163,15 +164,15 @@ except NameError:
def attr_chain(obj, attr):
"""Follow an attribute chain.
-
+
If you have a chain of objects where a.foo -> b, b.foo-> c, etc,
use this to iterate over all objects in the chain. Iteration is
terminated by getattr(x, attr) is None.
-
+
Args:
obj: the starting object
attr: the name of the chaining attribute
-
+
Yields:
Each successive object in the chain.
"""
@@ -180,6 +181,44 @@ def attr_chain(obj, attr):
yield next
next = getattr(next, attr)
+p0 = """for_stmt< 'for' any 'in' node=any ':' any* >
+ | comp_for< 'for' any 'in' node=any any* >
+ """
+p1 = """
+power<
+ ( 'iter' | 'list' | 'tuple' | 'sorted' | 'set' | 'sum' |
+ 'any' | 'all' | (any* trailer< '.' 'join' >) )
+ trailer< '(' node=any ')' >
+ any*
+>
+"""
+p2 = """
+power<
+ 'sorted'
+ trailer< '(' arglist<node=any any*> ')' >
+ any*
+>
+"""
+pats_built = False
+def in_special_context(node):
+ """ Returns true if node is in an environment where all that is required
+ of it is being itterable (ie, it doesn't matter if it returns a list
+ or an itterator).
+ See test_map_nochange in test_fixers.py for some examples and tests.
+ """
+ global p0, p1, p2, pats_built
+ if not pats_built:
+ p1 = patcomp.compile_pattern(p1)
+ p0 = patcomp.compile_pattern(p0)
+ p2 = patcomp.compile_pattern(p2)
+ pats_built = True
+ patterns = [p0, p1, p2]
+ for pattern, parent in zip(patterns, attr_chain(node, "parent")):
+ results = {}
+ if pattern.match(parent, results) and results["node"] is node:
+ return True
+ return False
+
###########################################################
### The following functions are to find bindings in a suite
###########################################################
@@ -240,8 +279,8 @@ def find_binding(name, node, package=None):
elif child.type == syms.simple_stmt:
ret = find_binding(name, child, package)
elif child.type == syms.expr_stmt:
- if _find(name, child.children[0]):
- ret = child
+ if _find(name, child.children[0]):
+ ret = child
if ret:
if not package: