[Python-checkins] r66653 - in python/trunk/Lib/lib2to3: main.py refactor.py tests/data/fixers tests/test_refactor.py

benjamin.peterson python-checkins at python.org
Sat Sep 27 23:09:10 CEST 2008


Author: benjamin.peterson
Date: Sat Sep 27 23:09:10 2008
New Revision: 66653

Log:
Merged revisions 66511,66548-66549,66644,66646-66652 via svnmerge from 
svn+ssh://pythondev@svn.python.org/sandbox/trunk/2to3/lib2to3

........
  r66511 | benjamin.peterson | 2008-09-18 21:49:27 -0500 (Thu, 18 Sep 2008) | 1 line
  
  remove a  useless if __name__ == '__main__'
........
  r66548 | benjamin.peterson | 2008-09-21 21:14:14 -0500 (Sun, 21 Sep 2008) | 1 line
  
  avoid the perils of mutable default arguments
........
  r66549 | benjamin.peterson | 2008-09-21 21:26:11 -0500 (Sun, 21 Sep 2008) | 1 line
  
  some places in RefactoringTool should raise an error instead of logging it
........
  r66644 | benjamin.peterson | 2008-09-27 10:45:10 -0500 (Sat, 27 Sep 2008) | 1 line
  
  fix doctest refactoring
........
  r66646 | benjamin.peterson | 2008-09-27 11:40:13 -0500 (Sat, 27 Sep 2008) | 1 line
  
  don't print to stdout when 2to3 is used as a library
........
  r66647 | benjamin.peterson | 2008-09-27 12:28:28 -0500 (Sat, 27 Sep 2008) | 1 line
  
  let fixer modules and classes have different prefixes
........
  r66648 | benjamin.peterson | 2008-09-27 14:02:13 -0500 (Sat, 27 Sep 2008) | 1 line
  
  raise errors when 2to3 is used as a library
........
  r66649 | benjamin.peterson | 2008-09-27 14:03:38 -0500 (Sat, 27 Sep 2008) | 1 line
  
  fix docstring
........
  r66650 | benjamin.peterson | 2008-09-27 14:22:21 -0500 (Sat, 27 Sep 2008) | 1 line
  
  make use of enumerate
........
  r66651 | benjamin.peterson | 2008-09-27 14:24:13 -0500 (Sat, 27 Sep 2008) | 1 line
  
  revert last revision; it breaks things
........
  r66652 | benjamin.peterson | 2008-09-27 16:03:06 -0500 (Sat, 27 Sep 2008) | 1 line
  
  add tests for lib2to3.refactor
........


Added:
   python/trunk/Lib/lib2to3/tests/data/fixers/
      - copied from r66652, /sandbox/trunk/2to3/lib2to3/tests/data/fixers/
   python/trunk/Lib/lib2to3/tests/test_refactor.py
      - copied unchanged from r66652, /sandbox/trunk/2to3/lib2to3/tests/test_refactor.py
Modified:
   python/trunk/Lib/lib2to3/   (props changed)
   python/trunk/Lib/lib2to3/main.py
   python/trunk/Lib/lib2to3/refactor.py

Modified: python/trunk/Lib/lib2to3/main.py
==============================================================================
--- python/trunk/Lib/lib2to3/main.py	(original)
+++ python/trunk/Lib/lib2to3/main.py	Sat Sep 27 23:09:10 2008
@@ -10,6 +10,20 @@
 from . import refactor
 
 
+class StdoutRefactoringTool(refactor.RefactoringTool):
+    """
+    Prints output to stdout.
+    """
+
+    def log_error(self, msg, *args, **kwargs):
+        self.errors.append((msg, args, kwargs))
+        self.logger.error(msg, *args, **kwargs)
+
+    def print_output(self, lines):
+        for line in lines:
+            print line
+
+
 def main(fixer_pkg, args=None):
     """Main program.
 
@@ -68,7 +82,7 @@
         fixer_names = avail_names if "all" in options.fix else explicit
     else:
         fixer_names = avail_names
-    rt = refactor.RefactoringTool(fixer_names, rt_opts, explicit=explicit)
+    rt = StdoutRefactoringTool(fixer_names, rt_opts, explicit=explicit)
 
     # Refactor all files and directories passed as arguments
     if not rt.errors:
@@ -80,7 +94,3 @@
 
     # Return error status (0 if rt.errors is zero)
     return int(bool(rt.errors))
-
-
-if __name__ == "__main__":
-    sys.exit(main())

Modified: python/trunk/Lib/lib2to3/refactor.py
==============================================================================
--- python/trunk/Lib/lib2to3/refactor.py	(original)
+++ python/trunk/Lib/lib2to3/refactor.py	Sat Sep 27 23:09:10 2008
@@ -90,11 +90,18 @@
             for fix_name in get_all_fix_names(pkg_name, False)]
 
 
+class FixerError(Exception):
+    """A fixer could not be loaded."""
+
+
 class RefactoringTool(object):
 
     _default_options = {"print_function": False}
 
-    def __init__(self, fixer_names, options=None, explicit=[]):
+    CLASS_PREFIX = "Fix" # The prefix for fixer classes
+    FILE_PREFIX = "fix_" # The prefix for modules with a fixer within
+
+    def __init__(self, fixer_names, options=None, explicit=None):
         """Initializer.
 
         Args:
@@ -103,7 +110,7 @@
             explicit: a list of fixers to run even if they are explicit.
         """
         self.fixers = fixer_names
-        self.explicit = explicit
+        self.explicit = explicit or []
         self.options = self._default_options.copy()
         if options is not None:
             self.options.update(options)
@@ -134,29 +141,17 @@
         pre_order_fixers = []
         post_order_fixers = []
         for fix_mod_path in self.fixers:
-            try:
-                mod = __import__(fix_mod_path, {}, {}, ["*"])
-            except ImportError:
-                self.log_error("Can't load transformation module %s",
-                               fix_mod_path)
-                continue
+            mod = __import__(fix_mod_path, {}, {}, ["*"])
             fix_name = fix_mod_path.rsplit(".", 1)[-1]
-            if fix_name.startswith("fix_"):
-                fix_name = fix_name[4:]
+            if fix_name.startswith(self.FILE_PREFIX):
+                fix_name = fix_name[len(self.FILE_PREFIX):]
             parts = fix_name.split("_")
-            class_name = "Fix" + "".join([p.title() for p in parts])
+            class_name = self.CLASS_PREFIX + "".join([p.title() for p in parts])
             try:
                 fix_class = getattr(mod, class_name)
             except AttributeError:
-                self.log_error("Can't find %s.%s",
-                               fix_name, class_name)
-                continue
-            try:
-                fixer = fix_class(self.options, self.fixer_log)
-            except Exception, err:
-                self.log_error("Can't instantiate fixes.fix_%s.%s()",
-                               fix_name, class_name, exc_info=True)
-                continue
+                raise FixerError("Can't find %s.%s" % (fix_name, class_name))
+            fixer = fix_class(self.options, self.fixer_log)
             if fixer.explicit and self.explicit is not True and \
                     fix_mod_path not in self.explicit:
                 self.log_message("Skipping implicit fixer: %s", fix_name)
@@ -168,7 +163,7 @@
             elif fixer.order == "post":
                 post_order_fixers.append(fixer)
             else:
-                raise ValueError("Illegal fixer order: %r" % fixer.order)
+                raise FixerError("Illegal fixer order: %r" % fixer.order)
 
         key_func = operator.attrgetter("run_order")
         pre_order_fixers.sort(key=key_func)
@@ -176,9 +171,8 @@
         return (pre_order_fixers, post_order_fixers)
 
     def log_error(self, msg, *args, **kwds):
-        """Increments error count and log a message."""
-        self.errors.append((msg, args, kwds))
-        self.logger.error(msg, *args, **kwds)
+        """Called when an error occurs."""
+        raise
 
     def log_message(self, msg, *args):
         """Hook to log a message."""
@@ -191,13 +185,17 @@
             msg = msg % args
         self.logger.debug(msg)
 
+    def print_output(self, lines):
+        """Called with lines of output to give to the user."""
+        pass
+
     def refactor(self, items, write=False, doctests_only=False):
         """Refactor a list of files and directories."""
         for dir_or_file in items:
             if os.path.isdir(dir_or_file):
-                self.refactor_dir(dir_or_file, write)
+                self.refactor_dir(dir_or_file, write, doctests_only)
             else:
-                self.refactor_file(dir_or_file, write)
+                self.refactor_file(dir_or_file, write, doctests_only)
 
     def refactor_dir(self, dir_name, write=False, doctests_only=False):
         """Descends down a directory and refactor every Python file found.
@@ -348,12 +346,11 @@
         if old_text == new_text:
             self.log_debug("No changes to %s", filename)
             return
-        diff_texts(old_text, new_text, filename)
-        if not write:
-            self.log_debug("Not writing changes to %s", filename)
-            return
+        self.print_output(diff_texts(old_text, new_text, filename))
         if write:
             self.write_file(new_text, filename, old_text)
+        else:
+            self.log_debug("Not writing changes to %s", filename)
 
     def write_file(self, new_text, filename, old_text=None):
         """Writes a string to a file.
@@ -528,10 +525,9 @@
 
 
 def diff_texts(a, b, filename):
-    """Prints a unified diff of two strings."""
+    """Return a unified diff of two strings."""
     a = a.splitlines()
     b = b.splitlines()
-    for line in difflib.unified_diff(a, b, filename, filename,
-                                     "(original)", "(refactored)",
-                                     lineterm=""):
-        print line
+    return difflib.unified_diff(a, b, filename, filename,
+                                "(original)", "(refactored)",
+                                lineterm="")


More information about the Python-checkins mailing list