[Python-checkins] r73849 - in sandbox/trunk/2to3: README example.py lib2to3/fixes/fix_operator.py lib2to3/tests/test_fixers.py

alexandre.vassalotti python-checkins at python.org
Sun Jul 5 06:43:19 CEST 2009


Author: alexandre.vassalotti
Date: Sun Jul  5 06:43:18 2009
New Revision: 73849

Log:
Issue 2370: Add fixer for the removal of operator.isCallable() and
operator.sequenceIncludes().

Patch contributed by Jeff Balogh (and updated by me).


Added:
   sandbox/trunk/2to3/lib2to3/fixes/fix_operator.py
Modified:
   sandbox/trunk/2to3/README
   sandbox/trunk/2to3/example.py
   sandbox/trunk/2to3/lib2to3/tests/test_fixers.py

Modified: sandbox/trunk/2to3/README
==============================================================================
--- sandbox/trunk/2to3/README	(original)
+++ sandbox/trunk/2to3/README	Sun Jul  5 06:43:18 2009
@@ -93,6 +93,9 @@
 * **fix_paren** - Add parentheses to places where they are needed in list
     comprehensions and generator expressions.
 
+* **fix_operator** - "operator.isCallable(x)" -> "hasattr(x, '__call__')",
+  "operator.sequenceIncludes(x, y)" -> "operator.contains(a, b)"
+
 * **fix_print** - convert "print" statements to print() function calls.
 
 * **fix_raise** - convert "raise" statements to Python 3 syntax (PEP 3109).

Modified: sandbox/trunk/2to3/example.py
==============================================================================
--- sandbox/trunk/2to3/example.py	(original)
+++ sandbox/trunk/2to3/example.py	Sun Jul  5 06:43:18 2009
@@ -377,6 +377,16 @@
 def sys_exc_examples():
     print sys.exc_type, sys.exc_value, sys.exc_traceback
 
+def operator_examples():
+    import operator
+    operator.isCallable(foo)
+    operator.sequenceIncludes(foo, bar)
+
+    from operator import isCallable, sequenceIncludes
+    # These should produce warnings.
+    isCallable(foo)
+    sequenceIncludes(foo, bar)
+
 class X:
     def maximum(self):
         return max(self.data.values())

Added: sandbox/trunk/2to3/lib2to3/fixes/fix_operator.py
==============================================================================
--- (empty file)
+++ sandbox/trunk/2to3/lib2to3/fixes/fix_operator.py	Sun Jul  5 06:43:18 2009
@@ -0,0 +1,41 @@
+"""Fixer for operator.{isCallable,sequenceIncludes}
+
+operator.isCallable(obj) -> hasattr(obj, '__call__')
+operator.sequenceIncludes(obj) -> operator.contains(obj)
+"""
+
+# Local imports
+from .. import fixer_base
+from ..fixer_util import Call, Name, String
+
+class FixOperator(fixer_base.BaseFix):
+
+    methods = "method=('isCallable'|'sequenceIncludes')"
+    func = "'(' func=any ')'"
+    PATTERN = """
+              power< module='operator'
+                trailer< '.' %(methods)s > trailer< %(func)s > >
+              |
+              power< %(methods)s trailer< %(func)s > >
+              """ % locals()
+
+    def transform(self, node, results):
+        method = results["method"][0]
+
+        if method.value == "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 = "contains"
+                method.changed()
+                return node
+        elif method.value == "isCallable":
+            if "module" not in results:
+                self.warning(node,
+                             "You should use hasattr(%s, '__call__') here." %
+                             results["func"].value)
+            else:
+                func = results["func"]
+                args = [func.clone(), String(", "), String("'__call__'")]
+                return Call(Name("hasattr"), args, prefix=node.get_prefix())

Modified: sandbox/trunk/2to3/lib2to3/tests/test_fixers.py
==============================================================================
--- sandbox/trunk/2to3/lib2to3/tests/test_fixers.py	(original)
+++ sandbox/trunk/2to3/lib2to3/tests/test_fixers.py	Sun Jul  5 06:43:18 2009
@@ -4105,3 +4105,26 @@
         b = """os.getcwdu (  )"""
         a = """os.getcwd (  )"""
         self.check(b, a)
+
+
+class Test_operator(FixerTestCase):
+
+    fixer = "operator"
+
+    def test_operator_isCallable(self):
+        b = "operator.isCallable(x)"
+        a = "hasattr(x, '__call__')"
+        self.check(b, a)
+
+    def test_operator_sequenceIncludes(self):
+        b = "operator.sequenceIncludes(x, y)"
+        a = "operator.contains(x, y)"
+        self.check(b, a)
+
+    def test_bare_isCallable(self):
+        s = "isCallable(x)"
+        self.warns_unchanged(s, "You should use hasattr(x, '__call__') here.")
+
+    def test_bare_sequenceIncludes(self):
+        s = "sequenceIncludes(x, y)"
+        self.warns_unchanged(s, "You should use operator.contains here.")


More information about the Python-checkins mailing list