Kaydet (Commit) 4eb5fa56 authored tarafından Benjamin Peterson's avatar Benjamin Peterson

Merged revisions…

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

........
  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
........
üst bf4cc5d4
"""Utility functions, node construction macros, etc.""" """Utility functions, node construction macros, etc."""
# Author: Collin Winter # Author: Collin Winter
from itertools import islice
# Local imports # Local imports
from .pgen2 import token from .pgen2 import token
from .pytree import Leaf, Node from .pytree import Leaf, Node
...@@ -14,7 +16,7 @@ from . import patcomp ...@@ -14,7 +16,7 @@ from . import patcomp
def KeywordArg(keyword, value): def KeywordArg(keyword, value):
return Node(syms.argument, return Node(syms.argument,
[keyword, Leaf(token.EQUAL, '='), value]) [keyword, Leaf(token.EQUAL, "="), value])
def LParen(): def LParen():
return Leaf(token.LPAR, "(") return Leaf(token.LPAR, "(")
...@@ -76,9 +78,9 @@ def Number(n, prefix=None): ...@@ -76,9 +78,9 @@ def Number(n, prefix=None):
def Subscript(index_node): def Subscript(index_node):
"""A numeric or string subscript""" """A numeric or string subscript"""
return Node(syms.trailer, [Leaf(token.LBRACE, '['), return Node(syms.trailer, [Leaf(token.LBRACE, "["),
index_node, index_node,
Leaf(token.RBRACE, ']')]) Leaf(token.RBRACE, "]")])
def String(string, prefix=None): def String(string, prefix=None):
"""A string leaf""" """A string leaf"""
...@@ -120,9 +122,9 @@ def FromImport(package_name, name_leafs): ...@@ -120,9 +122,9 @@ def FromImport(package_name, name_leafs):
# Pull the leaves out of their old tree # Pull the leaves out of their old tree
leaf.remove() leaf.remove()
children = [Leaf(token.NAME, 'from'), children = [Leaf(token.NAME, "from"),
Leaf(token.NAME, package_name, prefix=" "), Leaf(token.NAME, package_name, prefix=" "),
Leaf(token.NAME, 'import', prefix=" "), Leaf(token.NAME, "import", prefix=" "),
Node(syms.import_as_names, name_leafs)] Node(syms.import_as_names, name_leafs)]
imp = Node(syms.import_from, children) imp = Node(syms.import_from, children)
return imp return imp
...@@ -245,6 +247,16 @@ def is_probably_builtin(node): ...@@ -245,6 +247,16 @@ def is_probably_builtin(node):
return False return False
return True 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 ""
########################################################### ###########################################################
### The following functions are to find bindings in a suite ### The following functions are to find bindings in a suite
########################################################### ###########################################################
...@@ -314,11 +326,11 @@ def touch_import(package, name, node): ...@@ -314,11 +326,11 @@ def touch_import(package, name, node):
if package is None: if package is None:
import_ = Node(syms.import_name, [ import_ = Node(syms.import_name, [
Leaf(token.NAME, 'import'), Leaf(token.NAME, "import"),
Leaf(token.NAME, name, prefix=' ') Leaf(token.NAME, name, prefix=" ")
]) ])
else: else:
import_ = FromImport(package, [Leaf(token.NAME, name, prefix=' ')]) import_ = FromImport(package, [Leaf(token.NAME, name, prefix=" ")])
children = [import_, Newline()] children = [import_, Newline()]
root.insert_child(insert_pos, Node(syms.simple_stmt, children)) root.insert_child(insert_pos, Node(syms.simple_stmt, children))
...@@ -404,7 +416,7 @@ def _is_import_binding(node, name, package=None): ...@@ -404,7 +416,7 @@ def _is_import_binding(node, name, package=None):
if package and str(node.children[1]).strip() != package: if package and str(node.children[1]).strip() != package:
return None return None
n = node.children[3] n = node.children[3]
if package and _find('as', n): if package and _find("as", n):
# See test_from_import_as for explanation # See test_from_import_as for explanation
return None return None
elif n.type == syms.import_as_names and _find(name, n): elif n.type == syms.import_as_names and _find(name, n):
......
...@@ -43,8 +43,8 @@ class FixItertoolsImports(fixer_base.BaseFix): ...@@ -43,8 +43,8 @@ class FixItertoolsImports(fixer_base.BaseFix):
else: else:
remove_comma ^= True remove_comma ^= True
if children[-1].type == token.COMMA: while children and children[-1].type == token.COMMA:
children[-1].remove() children.pop().remove()
# If there are no imports left, just get rid of the entire statement # If there are no imports left, just get rid of the entire statement
if (not (imports.children or getattr(imports, 'value', None)) or if (not (imports.children or getattr(imports, 'value', None)) or
......
"""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.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)
""" """
import collections
# Local imports # Local imports
from .. import fixer_base from lib2to3 import fixer_base
from ..fixer_util import Call, Name, String from lib2to3.fixer_util import Call, Name, String, touch_import
class FixOperator(fixer_base.BaseFix): class FixOperator(fixer_base.BaseFix):
methods = "method=('isCallable'|'sequenceIncludes')" methods = """
func = "'(' func=any ')'" method=('isCallable'|'sequenceIncludes'
|'isSequenceType'|'isMappingType'|'isNumberType'
|'repeat'|'irepeat')
"""
obj = "'(' obj=any ')'"
PATTERN = """ PATTERN = """
power< module='operator' power< module='operator'
trailer< '.' %(methods)s > trailer< %(func)s > > trailer< '.' %(methods)s > trailer< %(obj)s > >
| |
power< %(methods)s trailer< %(func)s > > power< %(methods)s trailer< %(obj)s > >
""" % dict(methods=methods, func=func) """ % dict(methods=methods, obj=obj)
def transform(self, node, results): 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, "contains")
def _isCallable(self, node, results):
"""hasattr(%s, '__call__')"""
obj = results["obj"]
args = [obj.clone(), String(", "), String("'__call__'")]
return Call(Name("hasattr"), args, prefix=node.prefix)
def _repeat(self, node, results):
"""operator.mul(%s)"""
return self._handle_rename(node, results, "mul")
def _irepeat(self, node, results):
"""operator.imul(%s)"""
return self._handle_rename(node, results, "imul")
def _isSequenceType(self, node, results):
"""isinstance(%s, collections.Sequence)"""
return self._handle_type2abc(node, results, "collections", "Sequence")
def _isMappingType(self, node, results):
"""isinstance(%s, collections.Mapping)"""
return self._handle_type2abc(node, results, "collections", "Mapping")
def _isNumberType(self, node, results):
"""isinstance(%s, numbers.Number)"""
return self._handle_type2abc(node, results, "numbers", "Number")
def _handle_rename(self, node, results, name):
method = results["method"][0] method = results["method"][0]
method.value = name
method.changed()
if method.value == "sequenceIncludes": def _handle_type2abc(self, node, results, module, abc):
if "module" not in results: touch_import(None, module, node)
# operator may not be in scope, so we can't make a change. obj = results["obj"]
self.warning(node, "You should use operator.contains here.") args = [obj.clone(), String(", " + ".".join([module, abc]))]
else: return Call(Name("isinstance"), args, prefix=node.prefix)
method.value = "contains"
method.changed() def _check_method(self, node, results):
elif method.value == "isCallable": method = getattr(self, "_" + results["method"][0].value)
if "module" not in results: if isinstance(method, collections.Callable):
self.warning(node, if "module" in results:
"You should use hasattr(%s, '__call__') here." % return method
results["func"].value)
else: else:
func = results["func"] sub = (str(results["obj"]),)
args = [func.clone(), String(", "), String("'__call__'")] invocation_str = str(method.__doc__) % sub
return Call(Name("hasattr"), args, prefix=node.prefix) self.warning(node, "You should use '%s' here." % invocation_str)
return None
...@@ -5,39 +5,40 @@ ...@@ -5,39 +5,40 @@
# Author: Nick Edds # Author: Nick Edds
# Local imports # Local imports
from .fix_imports import alternates, FixImports from lib2to3.fixes.fix_imports import alternates, FixImports
from .. import fixer_base from lib2to3 import fixer_base
from ..fixer_util import Name, Comma, FromImport, Newline, attr_chain from lib2to3.fixer_util import (Name, Comma, FromImport, Newline,
find_indentation)
MAPPING = {'urllib': [
('urllib.request', MAPPING = {"urllib": [
['URLOpener', 'FancyURLOpener', 'urlretrieve', ("urllib.request",
'_urlopener', 'urlopen', 'urlcleanup', ["URLOpener", "FancyURLOpener", "urlretrieve",
'pathname2url', 'url2pathname']), "_urlopener", "urlopen", "urlcleanup",
('urllib.parse', "pathname2url", "url2pathname"]),
['quote', 'quote_plus', 'unquote', 'unquote_plus', ("urllib.parse",
'urlencode', 'splitattr', 'splithost', 'splitnport', ["quote", "quote_plus", "unquote", "unquote_plus",
'splitpasswd', 'splitport', 'splitquery', 'splittag', "urlencode", "splitattr", "splithost", "splitnport",
'splittype', 'splituser', 'splitvalue', ]), "splitpasswd", "splitport", "splitquery", "splittag",
('urllib.error', "splittype", "splituser", "splitvalue", ]),
['ContentTooShortError'])], ("urllib.error",
'urllib2' : [ ["ContentTooShortError"])],
('urllib.request', "urllib2" : [
['urlopen', 'install_opener', 'build_opener', ("urllib.request",
'Request', 'OpenerDirector', 'BaseHandler', ["urlopen", "install_opener", "build_opener",
'HTTPDefaultErrorHandler', 'HTTPRedirectHandler', "Request", "OpenerDirector", "BaseHandler",
'HTTPCookieProcessor', 'ProxyHandler', "HTTPDefaultErrorHandler", "HTTPRedirectHandler",
'HTTPPasswordMgr', "HTTPCookieProcessor", "ProxyHandler",
'HTTPPasswordMgrWithDefaultRealm', "HTTPPasswordMgr",
'AbstractBasicAuthHandler', "HTTPPasswordMgrWithDefaultRealm",
'HTTPBasicAuthHandler', 'ProxyBasicAuthHandler', "AbstractBasicAuthHandler",
'AbstractDigestAuthHandler', "HTTPBasicAuthHandler", "ProxyBasicAuthHandler",
'HTTPDigestAuthHandler', 'ProxyDigestAuthHandler', "AbstractDigestAuthHandler",
'HTTPHandler', 'HTTPSHandler', 'FileHandler', "HTTPDigestAuthHandler", "ProxyDigestAuthHandler",
'FTPHandler', 'CacheFTPHandler', "HTTPHandler", "HTTPSHandler", "FileHandler",
'UnknownHandler']), "FTPHandler", "CacheFTPHandler",
('urllib.error', "UnknownHandler"]),
['URLError', 'HTTPError']), ("urllib.error",
["URLError", "HTTPError"]),
] ]
} }
...@@ -78,7 +79,7 @@ class FixUrllib(FixImports): ...@@ -78,7 +79,7 @@ class FixUrllib(FixImports):
import name with a comma separated list of its import name with a comma separated list of its
replacements. replacements.
""" """
import_mod = results.get('module') import_mod = results.get("module")
pref = import_mod.prefix pref = import_mod.prefix
names = [] names = []
...@@ -94,9 +95,9 @@ class FixUrllib(FixImports): ...@@ -94,9 +95,9 @@ class FixUrllib(FixImports):
the module to be imported from with the appropriate new the module to be imported from with the appropriate new
module. module.
""" """
mod_member = results.get('mod_member') mod_member = results.get("mod_member")
pref = mod_member.prefix pref = mod_member.prefix
member = results.get('member') member = results.get("member")
# Simple case with only a single member being imported # Simple case with only a single member being imported
if member: if member:
...@@ -111,19 +112,18 @@ class FixUrllib(FixImports): ...@@ -111,19 +112,18 @@ class FixUrllib(FixImports):
if new_name: if new_name:
mod_member.replace(Name(new_name, prefix=pref)) mod_member.replace(Name(new_name, prefix=pref))
else: else:
self.cannot_convert(node, self.cannot_convert(node, "This is an invalid module element")
'This is an invalid module element')
# Multiple members being imported # Multiple members being imported
else: else:
# a dictionary for replacements, order matters # a dictionary for replacements, order matters
modules = [] modules = []
mod_dict = {} mod_dict = {}
members = results.get('members') members = results["members"]
for member in members: for member in members:
member = member.value member = member.value
# we only care about the actual members # we only care about the actual members
if member != ',': if member != ",":
for change in MAPPING[mod_member.value]: for change in MAPPING[mod_member.value]:
if member in change[1]: if member in change[1]:
if change[0] in mod_dict: if change[0] in mod_dict:
...@@ -133,13 +133,19 @@ class FixUrllib(FixImports): ...@@ -133,13 +133,19 @@ class FixUrllib(FixImports):
modules.append(change[0]) modules.append(change[0])
new_nodes = [] new_nodes = []
indentation = find_indentation(node)
first = True
for module in modules: for module in modules:
elts = mod_dict[module] elts = mod_dict[module]
names = [] names = []
for elt in elts[:-1]: for elt in elts[:-1]:
names.extend([Name(elt, prefix=pref), Comma()]) names.extend([Name(elt, prefix=pref), Comma()])
names.append(Name(elts[-1], prefix=pref)) 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: if new_nodes:
nodes = [] nodes = []
for new_node in new_nodes[:-1]: for new_node in new_nodes[:-1]:
...@@ -147,12 +153,12 @@ class FixUrllib(FixImports): ...@@ -147,12 +153,12 @@ class FixUrllib(FixImports):
nodes.append(new_nodes[-1]) nodes.append(new_nodes[-1])
node.replace(nodes) node.replace(nodes)
else: 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): def transform_dot(self, node, results):
"""Transform for calls to module members in code.""" """Transform for calls to module members in code."""
module_dot = results.get('bare_with_attr') module_dot = results.get("bare_with_attr")
member = results.get('member') member = results.get("member")
new_name = None new_name = None
if isinstance(member, list): if isinstance(member, list):
member = member[0] member = member[0]
...@@ -164,17 +170,17 @@ class FixUrllib(FixImports): ...@@ -164,17 +170,17 @@ class FixUrllib(FixImports):
module_dot.replace(Name(new_name, module_dot.replace(Name(new_name,
prefix=module_dot.prefix)) prefix=module_dot.prefix))
else: 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): def transform(self, node, results):
if results.get('module'): if results.get("module"):
self.transform_import(node, results) self.transform_import(node, results)
elif results.get('mod_member'): elif results.get("mod_member"):
self.transform_member(node, results) self.transform_member(node, results)
elif results.get('bare_with_attr'): elif results.get("bare_with_attr"):
self.transform_dot(node, results) self.transform_dot(node, results)
# Renaming and star imports are not supported for these modules. # Renaming and star imports are not supported for these modules.
elif results.get('module_star'): elif results.get("module_star"):
self.cannot_convert(node, 'Cannot handle star imports.') self.cannot_convert(node, "Cannot handle star imports.")
elif results.get('module_as'): elif results.get("module_as"):
self.cannot_convert(node, 'This module is now multiple modules') self.cannot_convert(node, "This module is now multiple modules")
...@@ -286,7 +286,7 @@ class Node(Base): ...@@ -286,7 +286,7 @@ class Node(Base):
"""Return a pre-order iterator for the tree.""" """Return a pre-order iterator for the tree."""
yield self yield self
for child in self.children: for child in self.children:
for node in child.post_order(): for node in child.pre_order():
yield node yield node
def _prefix_getter(self): def _prefix_getter(self):
......
...@@ -517,7 +517,7 @@ class RefactoringTool(object): ...@@ -517,7 +517,7 @@ class RefactoringTool(object):
try: try:
tree = self.parse_block(block, lineno, indent) tree = self.parse_block(block, lineno, indent)
except Exception as err: except Exception as err:
if self.log.isEnabledFor(logging.DEBUG): if self.logger.isEnabledFor(logging.DEBUG):
for line in block: for line in block:
self.log_debug("Source: %s", line.rstrip("\n")) self.log_debug("Source: %s", line.rstrip("\n"))
self.log_error("Can't parse docstring in %s line %s: %s: %s", self.log_error("Can't parse docstring in %s line %s: %s: %s",
......
...@@ -1818,6 +1818,33 @@ class Test_urllib(FixerTestCase): ...@@ -1818,6 +1818,33 @@ class Test_urllib(FixerTestCase):
s = "from %s import *" % old s = "from %s import *" % old
self.warns_unchanged(s, "Cannot handle star imports") 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): def test_import_module_usage(self):
for old, changes in self.modules.items(): for old, changes in self.modules.items():
for new, members in changes: for new, members in changes:
...@@ -3623,6 +3650,10 @@ class Test_itertools_imports(FixerTestCase): ...@@ -3623,6 +3650,10 @@ class Test_itertools_imports(FixerTestCase):
a = "from itertools import bar, foo" a = "from itertools import bar, foo"
self.check(b, a) self.check(b, a)
b = "from itertools import chain, imap, izip"
a = "from itertools import chain"
self.check(b, a)
def test_comments(self): def test_comments(self):
b = "#foo\nfrom itertools import imap, izip" b = "#foo\nfrom itertools import imap, izip"
a = "#foo\n" a = "#foo\n"
...@@ -4303,13 +4334,89 @@ class Test_operator(FixerTestCase): ...@@ -4303,13 +4334,89 @@ class Test_operator(FixerTestCase):
a = "operator.contains(x, y)" a = "operator.contains(x, y)"
self.check(b, a) 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): def test_bare_isCallable(self):
s = "isCallable(x)" 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): def test_bare_sequenceIncludes(self):
s = "sequenceIncludes(x, y)" 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): class Test_exitfunc(FixerTestCase):
......
...@@ -181,14 +181,18 @@ class TestNodes(support.TestCase): ...@@ -181,14 +181,18 @@ class TestNodes(support.TestCase):
def test_post_order(self): def test_post_order(self):
l1 = pytree.Leaf(100, "foo") l1 = pytree.Leaf(100, "foo")
l2 = pytree.Leaf(100, "bar") l2 = pytree.Leaf(100, "bar")
n1 = pytree.Node(1000, [l1, l2]) l3 = pytree.Leaf(100, "fooey")
self.assertEqual(list(n1.post_order()), [l1, l2, n1]) 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): def test_pre_order(self):
l1 = pytree.Leaf(100, "foo") l1 = pytree.Leaf(100, "foo")
l2 = pytree.Leaf(100, "bar") l2 = pytree.Leaf(100, "bar")
n1 = pytree.Node(1000, [l1, l2]) l3 = pytree.Leaf(100, "fooey")
self.assertEqual(list(n1.pre_order()), [n1, l1, l2]) 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): def test_changed(self):
l1 = pytree.Leaf(100, "f") l1 = pytree.Leaf(100, "f")
......
...@@ -575,3 +575,20 @@ class Test_touch_import(support.TestCase): ...@@ -575,3 +575,20 @@ class Test_touch_import(support.TestCase):
node = parse('bar()') node = parse('bar()')
fixer_util.touch_import(None, "cgi", node) fixer_util.touch_import(None, "cgi", node)
self.assertEqual(str(node), 'import cgi\nbar()\n\n') 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), "")
node = parse("")
self.assertEqual(fi(node), "")
def test_simple(self):
fi = fixer_util.find_indentation
node = parse("def f():\n x()")
self.assertEqual(fi(node), "")
self.assertEqual(fi(node.children[0].children[4].children[2]), " ")
node = parse("def f():\n x()\n y()")
self.assertEqual(fi(node.children[0].children[4].children[4]), " ")
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment