cpython: 4b791e513c2c (original) (raw)

Mercurial > cpython

changeset 74897:4b791e513c2c

Issue #13930: Adds ability for 2to3 to write its output to a different directory tree instead of overwriting the input files. Adds three command line options: -o/--output-dir, -W/--write-unchanged-files and --add-suffix. [#13930]

Gregory P. Smith greg@krypto.org
date Sun, 12 Feb 2012 15:56:49 -0800
parents 5d0f7b275fe9(current diff)ceea9ebfe003(diff)
children 0be50d7c4ae1
files Lib/lib2to3/refactor.py Misc/NEWS
diffstat 6 files changed, 274 insertions(+), 14 deletions(-)[+] [-] Doc/library/2to3.rst 32 Lib/lib2to3/main.py 93 Lib/lib2to3/refactor.py 20 Lib/lib2to3/tests/test_main.py 98 Lib/lib2to3/tests/test_refactor.py 36 Misc/NEWS 9

line wrap: on

line diff

--- a/Doc/library/2to3.rst +++ b/Doc/library/2to3.rst @@ -94,6 +94,38 @@ change can also be enabled manually with :option:-p to run fixers on code that already has had its print statements converted. +The :option:-o or :option:--output-dir option allows specification of an +alternate directory for processed output files to be written to. The +:option:-n flag is required when using this as backup files do not make sense +when not overwriting the input files. + +.. versionadded:: 3.2.3

+The :option:-W or :option:--write-unchanged-files flag tells 2to3 to always +write output files even if no changes were required to the file. This is most +useful with :option:-o so that an entire Python source tree is copied with +translation from one directory to another. +This option implies the :option:-w flag as it would not make sense otherwise. + +.. versionadded:: 3.2.3

+The :option:--add-suffix option specifies a string to append to all output +filenames. The :option:-n flag is required when specifying this as backups +are not necessary when writing to different filenames. Example:: +

+Will cause a converted file named example.py3 to be written. + +.. versionadded:: 3.2.3

+To translate an entire project from one directory tree to another use:: +

.. _2to3-fixers:

--- a/Lib/lib2to3/main.py +++ b/Lib/lib2to3/main.py @@ -25,12 +25,41 @@ def diff_texts(a, b, filename): class StdoutRefactoringTool(refactor.MultiprocessRefactoringTool): """

def log_error(self, msg, *args, **kwargs): @@ -38,6 +67,23 @@ class StdoutRefactoringTool(refactor.Mul self.logger.error(msg, *args, **kwargs) def write_file(self, new_text, filename, old_text, encoding):

@@ -55,6 +101,9 @@ class StdoutRefactoringTool(refactor.Mul write(new_text, filename, old_text, encoding) if not self.nobackups: shutil.copymode(backup, filename)

def print_output(self, old, new, filename, equal): if equal: @@ -113,11 +162,33 @@ def main(fixer_pkg, args=None): help="Write back modified files") parser.add_option("-n", "--nobackups", action="store_true", default=False, help="Don't write backups for modified files")

# Parse command line arguments refactor_stdin = False flags = {} options, args = parser.parse_args(args)

+ if not options.write and options.no_diffs: warn("not writing files and not printing diffs; that's not very useful") if not options.write and options.nobackups: @@ -143,6 +214,7 @@ def main(fixer_pkg, args=None): # Set up logging handler level = logging.DEBUG if options.verbose else logging.INFO logging.basicConfig(format='%(name)s: %(message)s', level=level)

# Initialize the refactoring tool avail_fixes = set(refactor.get_fixers_from_package(fixer_pkg)) @@ -159,8 +231,23 @@ def main(fixer_pkg, args=None): else: requested = avail_fixes.union(explicit) fixer_names = requested.difference(unwanted_fixes)

# Refactor all files and directories passed as arguments if not rt.errors:

--- a/Lib/lib2to3/refactor.py +++ b/Lib/lib2to3/refactor.py @@ -173,7 +173,8 @@ class FixerError(Exception): class RefactoringTool(object):

CLASS_PREFIX = "Fix" # The prefix for fixer classes FILE_PREFIX = "fix_" # The prefix for modules with a fixer within @@ -195,6 +196,10 @@ class RefactoringTool(object): self.grammar = pygram.python_grammar_no_print_statement else: self.grammar = pygram.python_grammar

@@ -341,13 +346,13 @@ class RefactoringTool(object): if doctests_only: self.log_debug("Refactoring doctests in %s", filename) output = self.refactor_docstring(input, filename)

@@ -386,13 +391,13 @@ class RefactoringTool(object): if doctests_only: self.log_debug("Refactoring doctests in stdin") output = self.refactor_docstring(input, "")

@@ -502,7 +507,7 @@ class RefactoringTool(object): def processed_file(self, new_text, filename, old_text=None, write=False, encoding=None): """

@@ -513,7 +518,8 @@ class RefactoringTool(object): self.print_output(old_text, new_text, filename, equal) if equal: self.log_debug("No changes to %s", filename)

--- a/Lib/lib2to3/tests/test_main.py +++ b/Lib/lib2to3/tests/test_main.py @@ -1,18 +1,30 @@

-- coding: utf-8 --

-import sys import codecs +import io import logging -import io +import os +import shutil +import sys +import tempfile import unittest from lib2to3 import main +TEST_DATA_DIR = os.path.join(os.path.dirname(file), "data") +PY2_TEST_MODULE = os.path.join(TEST_DATA_DIR, "py2_test_grammar.py") + + class TestMain(unittest.TestCase):

+ def tearDown(self): # Clean up logging configuration down by main. del logging.root.handlers[:]

def run_2to3_capture(self, args, in_capture, out_capture, err_capture): save_stdin = sys.stdin @@ -39,3 +51,85 @@ class TestMain(unittest.TestCase): self.assertTrue("-print 'nothing'" in output) self.assertTrue("WARNING: couldn't encode 's diff for " "your terminal" in err.getvalue()) +

+

+

+

+ + +if name == 'main':

--- a/Lib/lib2to3/tests/test_refactor.py +++ b/Lib/lib2to3/tests/test_refactor.py @@ -53,6 +53,12 @@ class TestRefactoringTool(unittest.TestC self.assertTrue(rt.driver.grammar is pygram.python_grammar_no_print_statement)

+ def test_fixer_loading_helpers(self): contents = ["explicit", "first", "last", "parrot", "preorder"] non_prefixed = refactor.get_all_fix_names("myfixes") @@ -176,7 +182,9 @@ from future import print_function""" "", False] self.assertEqual(results, expected)

@@ -189,11 +197,15 @@ from future import print_function""" return fp.read() old_contents = read_file()

rt.refactor_file(test_file) self.assertEqual(old_contents, read_file())

@@ -203,6 +215,26 @@ from future import print_function""" test_file = os.path.join(FIXER_DIR, "parrot_example.py") self.check_file_refactoring(test_file, _DEFAULT_FIXERS)

+ def test_refactor_dir(self): def check(structure, expected): def mock_refactor_file(self, f, *args):

--- a/Misc/NEWS +++ b/Misc/NEWS @@ -466,6 +466,10 @@ Core and Builtins Library ------- +- Issue #13930: lib2to3 now supports writing converted output files to another