[Python-checkins] r83847 - in python/branches/release27-maint/Lib/lib2to3: fixer_util.py fixes/fix_itertools_imports.py fixes/fix_operator.py fixes/fix_urllib.py pytree.py refactor.py tests/test_fixers.py tests/test_pytree.py tests/test_util.py

benjamin.peterson python-checkins at python.org
Sun Aug 8 21:13:06 CEST 2010


Author: benjamin.peterson
Date: Sun Aug  8 21:13:06 2010
New Revision: 83847

Log:
Merged revisions 82530-82531,82779,82855,83740,83789-83791,83797-83801,83803,83811,83827,83844 via svnmerge from 
svn+ssh://pythondev@svn.python.org/sandbox/trunk/2to3/lib2to3

........
  r82530 | benjamin.peterson | 2010-07-04 11:11:41 -0500 (Sun, 04 Jul 2010) | 1 line
  
  simplify ignore star imports from itertools #8892
........
  r82531 | benjamin.peterson | 2010-07-04 11:13:20 -0500 (Sun, 04 Jul 2010) | 1 line
  
  wrap with parenthesis not \
........
  r82779 | benjamin.peterson | 2010-07-10 14:45:08 -0500 (Sat, 10 Jul 2010) | 1 line
  
  typo in attribute name #9217
........
  r82855 | benjamin.peterson | 2010-07-13 16:27:38 -0500 (Tue, 13 Jul 2010) | 1 line
  
  remove more extraneous commas #9245
........
  r83740 | alexandre.vassalotti | 2010-08-05 01:58:36 -0500 (Thu, 05 Aug 2010) | 4 lines
  
  Issue 5077: Update fixer for the other functions gone from the operator module.
  
  Patch by Meador Inge.
........
  r83789 | benjamin.peterson | 2010-08-07 17:45:14 -0500 (Sat, 07 Aug 2010) | 1 line
  
  cleanup and use unicode consistently
........
  r83790 | benjamin.peterson | 2010-08-07 17:52:06 -0500 (Sat, 07 Aug 2010) | 1 line
  
  unicode literal
........
  r83791 | benjamin.peterson | 2010-08-07 17:52:55 -0500 (Sat, 07 Aug 2010) | 1 line
  
  .get() is pointless here
........
  r83797 | benjamin.peterson | 2010-08-07 18:54:51 -0500 (Sat, 07 Aug 2010) | 1 line
  
  add a function to find how a node is indented
........
  r83798 | benjamin.peterson | 2010-08-07 18:55:28 -0500 (Sat, 07 Aug 2010) | 1 line
  
  when splitting import statements, use correct indentation #9386
........
  r83799 | benjamin.peterson | 2010-08-07 18:57:43 -0500 (Sat, 07 Aug 2010) | 1 line
  
  double quotes
........
  r83800 | benjamin.peterson | 2010-08-07 18:58:52 -0500 (Sat, 07 Aug 2010) | 1 line
  
  add another test
........
  r83801 | benjamin.peterson | 2010-08-07 19:02:10 -0500 (Sat, 07 Aug 2010) | 1 line
  
  cleanup; style-nits
........
  r83803 | benjamin.peterson | 2010-08-07 19:05:08 -0500 (Sat, 07 Aug 2010) | 1 line
  
  slightly more explicit
........
  r83811 | benjamin.peterson | 2010-08-07 22:56:44 -0500 (Sat, 07 Aug 2010) | 4 lines
  
  Fix node.pre_order() to call the right method on its children.
  
  This was a rather tragic copy-paste error.
........
  r83827 | benjamin.peterson | 2010-08-08 08:12:48 -0500 (Sun, 08 Aug 2010) | 1 line
  
  cause test to actually run and fix it
........
  r83844 | benjamin.peterson | 2010-08-08 13:46:37 -0500 (Sun, 08 Aug 2010) | 1 line
  
  fix whitespace
........


Modified:
   python/branches/release27-maint/Lib/lib2to3/   (props changed)
   python/branches/release27-maint/Lib/lib2to3/fixer_util.py
   python/branches/release27-maint/Lib/lib2to3/fixes/fix_itertools_imports.py
   python/branches/release27-maint/Lib/lib2to3/fixes/fix_operator.py
   python/branches/release27-maint/Lib/lib2to3/fixes/fix_urllib.py
   python/branches/release27-maint/Lib/lib2to3/pytree.py
   python/branches/release27-maint/Lib/lib2to3/refactor.py
   python/branches/release27-maint/Lib/lib2to3/tests/test_fixers.py
   python/branches/release27-maint/Lib/lib2to3/tests/test_pytree.py
   python/branches/release27-maint/Lib/lib2to3/tests/test_util.py

Modified: python/branches/release27-maint/Lib/lib2to3/fixer_util.py
==============================================================================
--- python/branches/release27-maint/Lib/lib2to3/fixer_util.py	(original)
+++ python/branches/release27-maint/Lib/lib2to3/fixer_util.py	Sun Aug  8 21:13:06 2010
@@ -1,6 +1,8 @@
 """Utility functions, node construction macros, etc."""
 # Author: Collin Winter
 
+from itertools import islice
+
 # Local imports
 from .pgen2 import token
 from .pytree import Leaf, Node
@@ -14,7 +16,7 @@
 
 def KeywordArg(keyword, value):
     return Node(syms.argument,
-                [keyword, Leaf(token.EQUAL, u'='), value])
+                [keyword, Leaf(token.EQUAL, u"="), value])
 
 def LParen():
     return Leaf(token.LPAR, u"(")
@@ -76,9 +78,9 @@
 
 def Subscript(index_node):
     """A numeric or string subscript"""
-    return Node(syms.trailer, [Leaf(token.LBRACE, u'['),
+    return Node(syms.trailer, [Leaf(token.LBRACE, u"["),
                                index_node,
-                               Leaf(token.RBRACE, u']')])
+                               Leaf(token.RBRACE, u"]")])
 
 def String(string, prefix=None):
     """A string leaf"""
@@ -120,9 +122,9 @@
         # Pull the leaves out of their old tree
         leaf.remove()
 
-    children = [Leaf(token.NAME, u'from'),
+    children = [Leaf(token.NAME, u"from"),
                 Leaf(token.NAME, package_name, prefix=u" "),
-                Leaf(token.NAME, u'import', prefix=u" "),
+                Leaf(token.NAME, u"import", prefix=u" "),
                 Node(syms.import_as_names, name_leafs)]
     imp = Node(syms.import_from, children)
     return imp
@@ -245,6 +247,16 @@
         return False
     return True
 
+def find_indentation(node):
+    """Find the indentation of *node*."""
+    while node is not None:
+        if node.type == syms.suite and len(node.children) > 2:
+            indent = node.children[1]
+            if indent.type == token.INDENT:
+                return indent.value
+        node = node.parent
+    return u""
+
 ###########################################################
 ### The following functions are to find bindings in a suite
 ###########################################################
@@ -314,11 +326,11 @@
 
     if package is None:
         import_ = Node(syms.import_name, [
-            Leaf(token.NAME, u'import'),
-            Leaf(token.NAME, name, prefix=u' ')
+            Leaf(token.NAME, u"import"),
+            Leaf(token.NAME, name, prefix=u" ")
         ])
     else:
-        import_ = FromImport(package, [Leaf(token.NAME, name, prefix=u' ')])
+        import_ = FromImport(package, [Leaf(token.NAME, name, prefix=u" ")])
 
     children = [import_, Newline()]
     root.insert_child(insert_pos, Node(syms.simple_stmt, children))
@@ -404,7 +416,7 @@
         if package and unicode(node.children[1]).strip() != package:
             return None
         n = node.children[3]
-        if package and _find(u'as', n):
+        if package and _find(u"as", n):
             # See test_from_import_as for explanation
             return None
         elif n.type == syms.import_as_names and _find(name, n):

Modified: python/branches/release27-maint/Lib/lib2to3/fixes/fix_itertools_imports.py
==============================================================================
--- python/branches/release27-maint/Lib/lib2to3/fixes/fix_itertools_imports.py	(original)
+++ python/branches/release27-maint/Lib/lib2to3/fixes/fix_itertools_imports.py	Sun Aug  8 21:13:06 2010
@@ -43,8 +43,8 @@
             else:
                 remove_comma ^= True
 
-        if children[-1].type == token.COMMA:
-            children[-1].remove()
+        while children and children[-1].type == token.COMMA:
+            children.pop().remove()
 
         # If there are no imports left, just get rid of the entire statement
         if (not (imports.children or getattr(imports, 'value', None)) or

Modified: python/branches/release27-maint/Lib/lib2to3/fixes/fix_operator.py
==============================================================================
--- python/branches/release27-maint/Lib/lib2to3/fixes/fix_operator.py	(original)
+++ python/branches/release27-maint/Lib/lib2to3/fixes/fix_operator.py	Sun Aug  8 21:13:06 2010
@@ -1,40 +1,87 @@
-"""Fixer for operator.{isCallable,sequenceIncludes}
+"""Fixer for operator functions.
 
-operator.isCallable(obj) -> hasattr(obj, '__call__')
+operator.isCallable(obj)       -> hasattr(obj, '__call__')
 operator.sequenceIncludes(obj) -> operator.contains(obj)
+operator.isSequenceType(obj)   -> isinstance(obj, collections.Sequence)
+operator.isMappingType(obj)    -> isinstance(obj, collections.Mapping)
+operator.isNumberType(obj)     -> isinstance(obj, numbers.Number)
+operator.repeat(obj, n)        -> operator.mul(obj, n)
+operator.irepeat(obj, n)       -> operator.imul(obj, n)
 """
 
 # Local imports
-from .. import fixer_base
-from ..fixer_util import Call, Name, String
+from lib2to3 import fixer_base
+from lib2to3.fixer_util import Call, Name, String, touch_import
+
 
 class FixOperator(fixer_base.BaseFix):
 
-    methods = "method=('isCallable'|'sequenceIncludes')"
-    func = "'(' func=any ')'"
+    methods = """
+              method=('isCallable'|'sequenceIncludes'
+                     |'isSequenceType'|'isMappingType'|'isNumberType'
+                     |'repeat'|'irepeat')
+              """
+    obj = "'(' obj=any ')'"
     PATTERN = """
               power< module='operator'
-                trailer< '.' %(methods)s > trailer< %(func)s > >
+                trailer< '.' %(methods)s > trailer< %(obj)s > >
               |
-              power< %(methods)s trailer< %(func)s > >
-              """ % dict(methods=methods, func=func)
+              power< %(methods)s trailer< %(obj)s > >
+              """ % dict(methods=methods, obj=obj)
 
     def transform(self, node, results):
+        method = self._check_method(node, results)
+        if method is not None:
+            return method(node, results)
+
+    def _sequenceIncludes(self, node, results):
+        """operator.contains(%s)"""
+        return self._handle_rename(node, results, u"contains")
+
+    def _isCallable(self, node, results):
+        """hasattr(%s, '__call__')"""
+        obj = results["obj"]
+        args = [obj.clone(), String(u", "), String(u"'__call__'")]
+        return Call(Name(u"hasattr"), args, prefix=node.prefix)
+
+    def _repeat(self, node, results):
+        """operator.mul(%s)"""
+        return self._handle_rename(node, results, u"mul")
+
+    def _irepeat(self, node, results):
+        """operator.imul(%s)"""
+        return self._handle_rename(node, results, u"imul")
+
+    def _isSequenceType(self, node, results):
+        """isinstance(%s, collections.Sequence)"""
+        return self._handle_type2abc(node, results, u"collections", u"Sequence")
+
+    def _isMappingType(self, node, results):
+        """isinstance(%s, collections.Mapping)"""
+        return self._handle_type2abc(node, results, u"collections", u"Mapping")
+
+    def _isNumberType(self, node, results):
+        """isinstance(%s, numbers.Number)"""
+        return self._handle_type2abc(node, results, u"numbers", u"Number")
+
+    def _handle_rename(self, node, results, name):
         method = results["method"][0]
+        method.value = name
+        method.changed()
 
-        if method.value == u"sequenceIncludes":
-            if "module" not in results:
-                # operator may not be in scope, so we can't make a change.
-                self.warning(node, "You should use operator.contains here.")
-            else:
-                method.value = u"contains"
-                method.changed()
-        elif method.value == u"isCallable":
-            if "module" not in results:
-                self.warning(node,
-                             "You should use hasattr(%s, '__call__') here." %
-                             results["func"].value)
+    def _handle_type2abc(self, node, results, module, abc):
+        touch_import(None, module, node)
+        obj = results["obj"]
+        args = [obj.clone(), String(u", " + u".".join([module, abc]))]
+        return Call(Name(u"isinstance"), args, prefix=node.prefix)
+
+    def _check_method(self, node, results):
+        method = getattr(self, "_" + results["method"][0].value.encode("ascii"))
+        if callable(method):
+            if "module" in results:
+                return method
             else:
-                func = results["func"]
-                args = [func.clone(), String(u", "), String(u"'__call__'")]
-                return Call(Name(u"hasattr"), args, prefix=node.prefix)
+                sub = (unicode(results["obj"]),)
+                invocation_str = unicode(method.__doc__) % sub
+                self.warning(node, u"You should use '%s' here." % invocation_str)
+        return None

Modified: python/branches/release27-maint/Lib/lib2to3/fixes/fix_urllib.py
==============================================================================
--- python/branches/release27-maint/Lib/lib2to3/fixes/fix_urllib.py	(original)
+++ python/branches/release27-maint/Lib/lib2to3/fixes/fix_urllib.py	Sun Aug  8 21:13:06 2010
@@ -5,39 +5,40 @@
 # Author: Nick Edds
 
 # Local imports
-from .fix_imports import alternates, FixImports
-from .. import fixer_base
-from ..fixer_util import Name, Comma, FromImport, Newline, attr_chain
-
-MAPPING = {'urllib':  [
-                ('urllib.request',
-                    ['URLOpener', 'FancyURLOpener', 'urlretrieve',
-                     '_urlopener', 'urlopen', 'urlcleanup',
-                     'pathname2url', 'url2pathname']),
-                ('urllib.parse',
-                    ['quote', 'quote_plus', 'unquote', 'unquote_plus',
-                     'urlencode', 'splitattr', 'splithost', 'splitnport',
-                     'splitpasswd', 'splitport', 'splitquery', 'splittag',
-                     'splittype', 'splituser', 'splitvalue', ]),
-                ('urllib.error',
-                    ['ContentTooShortError'])],
-           'urllib2' : [
-                ('urllib.request',
-                    ['urlopen', 'install_opener', 'build_opener',
-                     'Request', 'OpenerDirector', 'BaseHandler',
-                     'HTTPDefaultErrorHandler', 'HTTPRedirectHandler',
-                     'HTTPCookieProcessor', 'ProxyHandler',
-                     'HTTPPasswordMgr',
-                     'HTTPPasswordMgrWithDefaultRealm',
-                     'AbstractBasicAuthHandler',
-                     'HTTPBasicAuthHandler', 'ProxyBasicAuthHandler',
-                     'AbstractDigestAuthHandler',
-                     'HTTPDigestAuthHandler', 'ProxyDigestAuthHandler',
-                     'HTTPHandler', 'HTTPSHandler', 'FileHandler',
-                     'FTPHandler', 'CacheFTPHandler',
-                     'UnknownHandler']),
-                ('urllib.error',
-                    ['URLError', 'HTTPError']),
+from lib2to3.fixes.fix_imports import alternates, FixImports
+from lib2to3 import fixer_base
+from lib2to3.fixer_util import (Name, Comma, FromImport, Newline,
+                                find_indentation)
+
+MAPPING = {"urllib":  [
+                ("urllib.request",
+                    ["URLOpener", "FancyURLOpener", "urlretrieve",
+                     "_urlopener", "urlopen", "urlcleanup",
+                     "pathname2url", "url2pathname"]),
+                ("urllib.parse",
+                    ["quote", "quote_plus", "unquote", "unquote_plus",
+                     "urlencode", "splitattr", "splithost", "splitnport",
+                     "splitpasswd", "splitport", "splitquery", "splittag",
+                     "splittype", "splituser", "splitvalue", ]),
+                ("urllib.error",
+                    ["ContentTooShortError"])],
+           "urllib2" : [
+                ("urllib.request",
+                    ["urlopen", "install_opener", "build_opener",
+                     "Request", "OpenerDirector", "BaseHandler",
+                     "HTTPDefaultErrorHandler", "HTTPRedirectHandler",
+                     "HTTPCookieProcessor", "ProxyHandler",
+                     "HTTPPasswordMgr",
+                     "HTTPPasswordMgrWithDefaultRealm",
+                     "AbstractBasicAuthHandler",
+                     "HTTPBasicAuthHandler", "ProxyBasicAuthHandler",
+                     "AbstractDigestAuthHandler",
+                     "HTTPDigestAuthHandler", "ProxyDigestAuthHandler",
+                     "HTTPHandler", "HTTPSHandler", "FileHandler",
+                     "FTPHandler", "CacheFTPHandler",
+                     "UnknownHandler"]),
+                ("urllib.error",
+                    ["URLError", "HTTPError"]),
            ]
 }
 
@@ -78,7 +79,7 @@
            import name with a comma separated list of its
            replacements.
         """
-        import_mod = results.get('module')
+        import_mod = results.get("module")
         pref = import_mod.prefix
 
         names = []
@@ -94,9 +95,9 @@
            the module to be imported from with the appropriate new
            module.
         """
-        mod_member = results.get('mod_member')
+        mod_member = results.get("mod_member")
         pref = mod_member.prefix
-        member = results.get('member')
+        member = results.get("member")
 
         # Simple case with only a single member being imported
         if member:
@@ -111,19 +112,18 @@
             if new_name:
                 mod_member.replace(Name(new_name, prefix=pref))
             else:
-                self.cannot_convert(node,
-                                    'This is an invalid module element')
+                self.cannot_convert(node, "This is an invalid module element")
 
         # Multiple members being imported
         else:
             # a dictionary for replacements, order matters
             modules = []
             mod_dict = {}
-            members = results.get('members')
+            members = results["members"]
             for member in members:
                 member = member.value
                 # we only care about the actual members
-                if member != ',':
+                if member != u",":
                     for change in MAPPING[mod_member.value]:
                         if member in change[1]:
                             if change[0] in mod_dict:
@@ -133,13 +133,19 @@
                                 modules.append(change[0])
 
             new_nodes = []
+            indentation = find_indentation(node)
+            first = True
             for module in modules:
                 elts = mod_dict[module]
                 names = []
                 for elt in elts[:-1]:
                     names.extend([Name(elt, prefix=pref), Comma()])
                 names.append(Name(elts[-1], prefix=pref))
-                new_nodes.append(FromImport(module, names))
+                new = FromImport(module, names)
+                if not first or node.parent.prefix.endswith(indentation):
+                    new.prefix = indentation
+                new_nodes.append(new)
+                first = False
             if new_nodes:
                 nodes = []
                 for new_node in new_nodes[:-1]:
@@ -147,12 +153,12 @@
                 nodes.append(new_nodes[-1])
                 node.replace(nodes)
             else:
-                self.cannot_convert(node, 'All module elements are invalid')
+                self.cannot_convert(node, "All module elements are invalid")
 
     def transform_dot(self, node, results):
         """Transform for calls to module members in code."""
-        module_dot = results.get('bare_with_attr')
-        member = results.get('member')
+        module_dot = results.get("bare_with_attr")
+        member = results.get("member")
         new_name = None
         if isinstance(member, list):
             member = member[0]
@@ -164,17 +170,17 @@
             module_dot.replace(Name(new_name,
                                     prefix=module_dot.prefix))
         else:
-            self.cannot_convert(node, 'This is an invalid module element')
+            self.cannot_convert(node, "This is an invalid module element")
 
     def transform(self, node, results):
-        if results.get('module'):
+        if results.get("module"):
             self.transform_import(node, results)
-        elif results.get('mod_member'):
+        elif results.get("mod_member"):
             self.transform_member(node, results)
-        elif results.get('bare_with_attr'):
+        elif results.get("bare_with_attr"):
             self.transform_dot(node, results)
         # Renaming and star imports are not supported for these modules.
-        elif results.get('module_star'):
-            self.cannot_convert(node, 'Cannot handle star imports.')
-        elif results.get('module_as'):
-            self.cannot_convert(node, 'This module is now multiple modules')
+        elif results.get("module_star"):
+            self.cannot_convert(node, "Cannot handle star imports.")
+        elif results.get("module_as"):
+            self.cannot_convert(node, "This module is now multiple modules")

Modified: python/branches/release27-maint/Lib/lib2to3/pytree.py
==============================================================================
--- python/branches/release27-maint/Lib/lib2to3/pytree.py	(original)
+++ python/branches/release27-maint/Lib/lib2to3/pytree.py	Sun Aug  8 21:13:06 2010
@@ -286,7 +286,7 @@
         """Return a pre-order iterator for the tree."""
         yield self
         for child in self.children:
-            for node in child.post_order():
+            for node in child.pre_order():
                 yield node
 
     def _prefix_getter(self):

Modified: python/branches/release27-maint/Lib/lib2to3/refactor.py
==============================================================================
--- python/branches/release27-maint/Lib/lib2to3/refactor.py	(original)
+++ python/branches/release27-maint/Lib/lib2to3/refactor.py	Sun Aug  8 21:13:06 2010
@@ -517,7 +517,7 @@
         try:
             tree = self.parse_block(block, lineno, indent)
         except Exception, err:
-            if self.log.isEnabledFor(logging.DEBUG):
+            if self.logger.isEnabledFor(logging.DEBUG):
                 for line in block:
                     self.log_debug("Source: %s", line.rstrip(u"\n"))
             self.log_error("Can't parse docstring in %s line %s: %s: %s",

Modified: python/branches/release27-maint/Lib/lib2to3/tests/test_fixers.py
==============================================================================
--- python/branches/release27-maint/Lib/lib2to3/tests/test_fixers.py	(original)
+++ python/branches/release27-maint/Lib/lib2to3/tests/test_fixers.py	Sun Aug  8 21:13:06 2010
@@ -1818,6 +1818,33 @@
             s = "from %s import *" % old
             self.warns_unchanged(s, "Cannot handle star imports")
 
+    def test_indented(self):
+        b = """
+def foo():
+    from urllib import urlencode, urlopen
+"""
+        a = """
+def foo():
+    from urllib.parse import urlencode
+    from urllib.request import urlopen
+"""
+        self.check(b, a)
+
+        b = """
+def foo():
+    other()
+    from urllib import urlencode, urlopen
+"""
+        a = """
+def foo():
+    other()
+    from urllib.parse import urlencode
+    from urllib.request import urlopen
+"""
+        self.check(b, a)
+
+
+
     def test_import_module_usage(self):
         for old, changes in self.modules.items():
             for new, members in changes:
@@ -3623,6 +3650,10 @@
         a = "from itertools import bar, foo"
         self.check(b, a)
 
+        b = "from itertools import chain, imap, izip"
+        a = "from itertools import chain"
+        self.check(b, a)
+
     def test_comments(self):
         b = "#foo\nfrom itertools import imap, izip"
         a = "#foo\n"
@@ -4303,13 +4334,89 @@
         a = "operator.contains(x, y)"
         self.check(b, a)
 
+        b = "operator .sequenceIncludes(x, y)"
+        a = "operator .contains(x, y)"
+        self.check(b, a)
+
+        b = "operator.  sequenceIncludes(x, y)"
+        a = "operator.  contains(x, y)"
+        self.check(b, a)
+
+    def test_operator_isSequenceType(self):
+        b = "operator.isSequenceType(x)"
+        a = "import collections\nisinstance(x, collections.Sequence)"
+        self.check(b, a)
+
+    def test_operator_isMappingType(self):
+        b = "operator.isMappingType(x)"
+        a = "import collections\nisinstance(x, collections.Mapping)"
+        self.check(b, a)
+
+    def test_operator_isNumberType(self):
+        b = "operator.isNumberType(x)"
+        a = "import numbers\nisinstance(x, numbers.Number)"
+        self.check(b, a)
+
+    def test_operator_repeat(self):
+        b = "operator.repeat(x, n)"
+        a = "operator.mul(x, n)"
+        self.check(b, a)
+
+        b = "operator .repeat(x, n)"
+        a = "operator .mul(x, n)"
+        self.check(b, a)
+
+        b = "operator.  repeat(x, n)"
+        a = "operator.  mul(x, n)"
+        self.check(b, a)
+
+    def test_operator_irepeat(self):
+        b = "operator.irepeat(x, n)"
+        a = "operator.imul(x, n)"
+        self.check(b, a)
+
+        b = "operator .irepeat(x, n)"
+        a = "operator .imul(x, n)"
+        self.check(b, a)
+
+        b = "operator.  irepeat(x, n)"
+        a = "operator.  imul(x, n)"
+        self.check(b, a)
+
     def test_bare_isCallable(self):
         s = "isCallable(x)"
-        self.warns_unchanged(s, "You should use hasattr(x, '__call__') here.")
+        t = "You should use 'hasattr(x, '__call__')' here."
+        self.warns_unchanged(s, t)
 
     def test_bare_sequenceIncludes(self):
         s = "sequenceIncludes(x, y)"
-        self.warns_unchanged(s, "You should use operator.contains here.")
+        t = "You should use 'operator.contains(x, y)' here."
+        self.warns_unchanged(s, t)
+
+    def test_bare_operator_isSequenceType(self):
+        s = "isSequenceType(z)"
+        t = "You should use 'isinstance(z, collections.Sequence)' here."
+        self.warns_unchanged(s, t)
+
+    def test_bare_operator_isMappingType(self):
+        s = "isMappingType(x)"
+        t = "You should use 'isinstance(x, collections.Mapping)' here."
+        self.warns_unchanged(s, t)
+
+    def test_bare_operator_isNumberType(self):
+        s = "isNumberType(y)"
+        t = "You should use 'isinstance(y, numbers.Number)' here."
+        self.warns_unchanged(s, t)
+
+    def test_bare_operator_repeat(self):
+        s = "repeat(x, n)"
+        t = "You should use 'operator.mul(x, n)' here."
+        self.warns_unchanged(s, t)
+
+    def test_bare_operator_irepeat(self):
+        s = "irepeat(y, 187)"
+        t = "You should use 'operator.imul(y, 187)' here."
+        self.warns_unchanged(s, t)
 
 
 class Test_exitfunc(FixerTestCase):

Modified: python/branches/release27-maint/Lib/lib2to3/tests/test_pytree.py
==============================================================================
--- python/branches/release27-maint/Lib/lib2to3/tests/test_pytree.py	(original)
+++ python/branches/release27-maint/Lib/lib2to3/tests/test_pytree.py	Sun Aug  8 21:13:06 2010
@@ -181,14 +181,18 @@
     def test_post_order(self):
         l1 = pytree.Leaf(100, "foo")
         l2 = pytree.Leaf(100, "bar")
-        n1 = pytree.Node(1000, [l1, l2])
-        self.assertEqual(list(n1.post_order()), [l1, l2, n1])
+        l3 = pytree.Leaf(100, "fooey")
+        c1 = pytree.Node(1000, [l1, l2])
+        n1 = pytree.Node(1000, [c1, l3])
+        self.assertEqual(list(n1.post_order()), [l1, l2, c1, l3, n1])
 
     def test_pre_order(self):
         l1 = pytree.Leaf(100, "foo")
         l2 = pytree.Leaf(100, "bar")
-        n1 = pytree.Node(1000, [l1, l2])
-        self.assertEqual(list(n1.pre_order()), [n1, l1, l2])
+        l3 = pytree.Leaf(100, "fooey")
+        c1 = pytree.Node(1000, [l1, l2])
+        n1 = pytree.Node(1000, [c1, l3])
+        self.assertEqual(list(n1.pre_order()), [n1, c1, l1, l2, l3])
 
     def test_changed(self):
         l1 = pytree.Leaf(100, "f")

Modified: python/branches/release27-maint/Lib/lib2to3/tests/test_util.py
==============================================================================
--- python/branches/release27-maint/Lib/lib2to3/tests/test_util.py	(original)
+++ python/branches/release27-maint/Lib/lib2to3/tests/test_util.py	Sun Aug  8 21:13:06 2010
@@ -575,3 +575,20 @@
         node = parse('bar()')
         fixer_util.touch_import(None, "cgi", node)
         self.assertEqual(str(node), 'import cgi\nbar()\n\n')
+
+class Test_find_indentation(support.TestCase):
+
+    def test_nothing(self):
+        fi = fixer_util.find_indentation
+        node = parse("node()")
+        self.assertEqual(fi(node), u"")
+        node = parse("")
+        self.assertEqual(fi(node), u"")
+
+    def test_simple(self):
+        fi = fixer_util.find_indentation
+        node = parse("def f():\n    x()")
+        self.assertEqual(fi(node), u"")
+        self.assertEqual(fi(node.children[0].children[4].children[2]), u"    ")
+        node = parse("def f():\n    x()\n    y()")
+        self.assertEqual(fi(node.children[0].children[4].children[4]), u"    ")


More information about the Python-checkins mailing list