mirror of
https://github.com/python/cpython.git
synced 2025-08-17 07:11:51 +00:00

svn+ssh://pythondev@svn.python.org/python/trunk ................ r67428 | benjamin.peterson | 2008-11-28 16:12:14 -0600 (Fri, 28 Nov 2008) | 57 lines Merged revisions 67384,67386-67387,67389-67390,67392,67399-67400,67403-67405,67426 via svnmerge from svn+ssh://pythondev@svn.python.org/sandbox/trunk/2to3/lib2to3 ........ r67384 | benjamin.peterson | 2008-11-25 16:13:31 -0600 (Tue, 25 Nov 2008) | 4 lines don't duplicate calls to start_tree() RefactoringTool.pre_order values now holds a list of the fixers while pre_order_mapping holds the dict. ........ r67386 | benjamin.peterson | 2008-11-25 16:44:52 -0600 (Tue, 25 Nov 2008) | 1 line #4423 fix_imports was still replacing usage of a module if attributes were being used ........ r67387 | benjamin.peterson | 2008-11-25 16:47:54 -0600 (Tue, 25 Nov 2008) | 1 line fix broken test ........ r67389 | benjamin.peterson | 2008-11-25 17:13:17 -0600 (Tue, 25 Nov 2008) | 1 line remove compatibility code; we only cater to 2.5+ ........ r67390 | benjamin.peterson | 2008-11-25 22:03:36 -0600 (Tue, 25 Nov 2008) | 1 line fix #3994; the usage of changed imports was fixed in nested cases ........ r67392 | benjamin.peterson | 2008-11-26 11:11:40 -0600 (Wed, 26 Nov 2008) | 1 line simpilfy and comment fix_imports ........ r67399 | benjamin.peterson | 2008-11-26 11:47:03 -0600 (Wed, 26 Nov 2008) | 1 line remove more compatibility code ........ r67400 | benjamin.peterson | 2008-11-26 12:07:41 -0600 (Wed, 26 Nov 2008) | 1 line set svn:ignore ........ r67403 | benjamin.peterson | 2008-11-26 13:11:11 -0600 (Wed, 26 Nov 2008) | 1 line wrap import ........ r67404 | benjamin.peterson | 2008-11-26 13:29:49 -0600 (Wed, 26 Nov 2008) | 1 line build the fix_imports pattern in compile_pattern, so MAPPING can be changed and reflected in the pattern ........ r67405 | benjamin.peterson | 2008-11-26 14:01:24 -0600 (Wed, 26 Nov 2008) | 1 line stop ugly messages about runtime errors being from printed ........ r67426 | benjamin.peterson | 2008-11-28 16:01:40 -0600 (Fri, 28 Nov 2008) | 5 lines don't replace a module name if it is in the middle of a attribute lookup This fix also stops module names from being replaced if they are not in an attribute lookup. ........ ................
99 lines
3.5 KiB
Python
99 lines
3.5 KiB
Python
# Copyright 2007 Google, Inc. All Rights Reserved.
|
|
# Licensed to PSF under a Contributor Agreement.
|
|
|
|
"""Fixer for dict methods.
|
|
|
|
d.keys() -> list(d.keys())
|
|
d.items() -> list(d.items())
|
|
d.values() -> list(d.values())
|
|
|
|
d.iterkeys() -> iter(d.keys())
|
|
d.iteritems() -> iter(d.items())
|
|
d.itervalues() -> iter(d.values())
|
|
|
|
Except in certain very specific contexts: the iter() can be dropped
|
|
when the context is list(), sorted(), iter() or for...in; the list()
|
|
can be dropped when the context is list() or sorted() (but not iter()
|
|
or for...in!). Special contexts that apply to both: list(), sorted(), tuple()
|
|
set(), any(), all(), sum().
|
|
|
|
Note: iter(d.keys()) could be written as iter(d) but since the
|
|
original d.iterkeys() was also redundant we don't fix this. And there
|
|
are (rare) contexts where it makes a difference (e.g. when passing it
|
|
as an argument to a function that introspects the argument).
|
|
"""
|
|
|
|
# Local imports
|
|
from .. import pytree
|
|
from .. import patcomp
|
|
from ..pgen2 import token
|
|
from .. import fixer_base
|
|
from ..fixer_util import Name, Call, LParen, RParen, ArgList, Dot
|
|
from .. import fixer_util
|
|
|
|
|
|
iter_exempt = fixer_util.consuming_calls | set(["iter"])
|
|
|
|
|
|
class FixDict(fixer_base.BaseFix):
|
|
PATTERN = """
|
|
power< head=any+
|
|
trailer< '.' method=('keys'|'items'|'values'|
|
|
'iterkeys'|'iteritems'|'itervalues') >
|
|
parens=trailer< '(' ')' >
|
|
tail=any*
|
|
>
|
|
"""
|
|
|
|
def transform(self, node, results):
|
|
head = results["head"]
|
|
method = results["method"][0] # Extract node for method name
|
|
tail = results["tail"]
|
|
syms = self.syms
|
|
method_name = method.value
|
|
isiter = method_name.startswith("iter")
|
|
if isiter:
|
|
method_name = method_name[4:]
|
|
assert method_name in ("keys", "items", "values"), repr(method)
|
|
head = [n.clone() for n in head]
|
|
tail = [n.clone() for n in tail]
|
|
special = not tail and self.in_special_context(node, isiter)
|
|
args = head + [pytree.Node(syms.trailer,
|
|
[Dot(),
|
|
Name(method_name,
|
|
prefix=method.get_prefix())]),
|
|
results["parens"].clone()]
|
|
new = pytree.Node(syms.power, args)
|
|
if not special:
|
|
new.set_prefix("")
|
|
new = Call(Name(isiter and "iter" or "list"), [new])
|
|
if tail:
|
|
new = pytree.Node(syms.power, [new] + tail)
|
|
new.set_prefix(node.get_prefix())
|
|
return new
|
|
|
|
P1 = "power< func=NAME trailer< '(' node=any ')' > any* >"
|
|
p1 = patcomp.compile_pattern(P1)
|
|
|
|
P2 = """for_stmt< 'for' any 'in' node=any ':' any* >
|
|
| comp_for< 'for' any 'in' node=any any* >
|
|
"""
|
|
p2 = patcomp.compile_pattern(P2)
|
|
|
|
def in_special_context(self, node, isiter):
|
|
if node.parent is None:
|
|
return False
|
|
results = {}
|
|
if (node.parent.parent is not None and
|
|
self.p1.match(node.parent.parent, results) and
|
|
results["node"] is node):
|
|
if isiter:
|
|
# iter(d.iterkeys()) -> iter(d.keys()), etc.
|
|
return results["func"].value in iter_exempt
|
|
else:
|
|
# list(d.keys()) -> list(d.keys()), etc.
|
|
return results["func"].value in fixer_util.consuming_calls
|
|
if not isiter:
|
|
return False
|
|
# for ... in d.iterkeys() -> for ... in d.keys(), etc.
|
|
return self.p2.match(node.parent, results) and results["node"] is node
|