+++ /dev/null
-# Copyright 2007 Google, Inc. All Rights Reserved.\r
-# Licensed to PSF under a Contributor Agreement.\r
-\r
-"""Fixer for dict methods.\r
-\r
-d.keys() -> list(d.keys())\r
-d.items() -> list(d.items())\r
-d.values() -> list(d.values())\r
-\r
-d.iterkeys() -> iter(d.keys())\r
-d.iteritems() -> iter(d.items())\r
-d.itervalues() -> iter(d.values())\r
-\r
-d.viewkeys() -> d.keys()\r
-d.viewitems() -> d.items()\r
-d.viewvalues() -> d.values()\r
-\r
-Except in certain very specific contexts: the iter() can be dropped\r
-when the context is list(), sorted(), iter() or for...in; the list()\r
-can be dropped when the context is list() or sorted() (but not iter()\r
-or for...in!). Special contexts that apply to both: list(), sorted(), tuple()\r
-set(), any(), all(), sum().\r
-\r
-Note: iter(d.keys()) could be written as iter(d) but since the\r
-original d.iterkeys() was also redundant we don't fix this. And there\r
-are (rare) contexts where it makes a difference (e.g. when passing it\r
-as an argument to a function that introspects the argument).\r
-"""\r
-\r
-# Local imports\r
-from .. import pytree\r
-from .. import patcomp\r
-from ..pgen2 import token\r
-from .. import fixer_base\r
-from ..fixer_util import Name, Call, LParen, RParen, ArgList, Dot\r
-from .. import fixer_util\r
-\r
-\r
-iter_exempt = fixer_util.consuming_calls | set(["iter"])\r
-\r
-\r
-class FixDict(fixer_base.BaseFix):\r
- BM_compatible = True\r
-\r
- PATTERN = """\r
- power< head=any+\r
- trailer< '.' method=('keys'|'items'|'values'|\r
- 'iterkeys'|'iteritems'|'itervalues'|\r
- 'viewkeys'|'viewitems'|'viewvalues') >\r
- parens=trailer< '(' ')' >\r
- tail=any*\r
- >\r
- """\r
-\r
- def transform(self, node, results):\r
- head = results["head"]\r
- method = results["method"][0] # Extract node for method name\r
- tail = results["tail"]\r
- syms = self.syms\r
- method_name = method.value\r
- isiter = method_name.startswith(u"iter")\r
- isview = method_name.startswith(u"view")\r
- if isiter or isview:\r
- method_name = method_name[4:]\r
- assert method_name in (u"keys", u"items", u"values"), repr(method)\r
- head = [n.clone() for n in head]\r
- tail = [n.clone() for n in tail]\r
- special = not tail and self.in_special_context(node, isiter)\r
- args = head + [pytree.Node(syms.trailer,\r
- [Dot(),\r
- Name(method_name,\r
- prefix=method.prefix)]),\r
- results["parens"].clone()]\r
- new = pytree.Node(syms.power, args)\r
- if not (special or isview):\r
- new.prefix = u""\r
- new = Call(Name(u"iter" if isiter else u"list"), [new])\r
- if tail:\r
- new = pytree.Node(syms.power, [new] + tail)\r
- new.prefix = node.prefix\r
- return new\r
-\r
- P1 = "power< func=NAME trailer< '(' node=any ')' > any* >"\r
- p1 = patcomp.compile_pattern(P1)\r
-\r
- P2 = """for_stmt< 'for' any 'in' node=any ':' any* >\r
- | comp_for< 'for' any 'in' node=any any* >\r
- """\r
- p2 = patcomp.compile_pattern(P2)\r
-\r
- def in_special_context(self, node, isiter):\r
- if node.parent is None:\r
- return False\r
- results = {}\r
- if (node.parent.parent is not None and\r
- self.p1.match(node.parent.parent, results) and\r
- results["node"] is node):\r
- if isiter:\r
- # iter(d.iterkeys()) -> iter(d.keys()), etc.\r
- return results["func"].value in iter_exempt\r
- else:\r
- # list(d.keys()) -> list(d.keys()), etc.\r
- return results["func"].value in fixer_util.consuming_calls\r
- if not isiter:\r
- return False\r
- # for ... in d.iterkeys() -> for ... in d.keys(), etc.\r
- return self.p2.match(node.parent, results) and results["node"] is node\r