Ignore:
Timestamp:
Mar 19, 2014, 11:31:01 PM (11 years ago)
Author:
dmik
Message:

python: Merge vendor 2.7.6 to trunk.

Location:
python/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • python/trunk

  • python/trunk/Lib/lib2to3/main.py

    r2 r391  
    22Main program for 2to3.
    33"""
     4
     5from __future__ import with_statement
    46
    57import sys
     
    2426class StdoutRefactoringTool(refactor.MultiprocessRefactoringTool):
    2527    """
     28    A refactoring tool that can avoid overwriting its input files.
    2629    Prints output to stdout.
     30
     31    Output files can optionally be written to a different directory and or
     32    have an extra file suffix appended to their name for use in situations
     33    where you do not want to replace the input files.
    2734    """
    2835
    29     def __init__(self, fixers, options, explicit, nobackups, show_diffs):
     36    def __init__(self, fixers, options, explicit, nobackups, show_diffs,
     37                 input_base_dir='', output_dir='', append_suffix=''):
     38        """
     39        Args:
     40            fixers: A list of fixers to import.
     41            options: A dict with RefactoringTool configuration.
     42            explicit: A list of fixers to run even if they are explicit.
     43            nobackups: If true no backup '.bak' files will be created for those
     44                files that are being refactored.
     45            show_diffs: Should diffs of the refactoring be printed to stdout?
     46            input_base_dir: The base directory for all input files.  This class
     47                will strip this path prefix off of filenames before substituting
     48                it with output_dir.  Only meaningful if output_dir is supplied.
     49                All files processed by refactor() must start with this path.
     50            output_dir: If supplied, all converted files will be written into
     51                this directory tree instead of input_base_dir.
     52            append_suffix: If supplied, all files output by this tool will have
     53                this appended to their filename.  Useful for changing .py to
     54                .py3 for example by passing append_suffix='3'.
     55        """
    3056        self.nobackups = nobackups
    3157        self.show_diffs = show_diffs
     58        if input_base_dir and not input_base_dir.endswith(os.sep):
     59            input_base_dir += os.sep
     60        self._input_base_dir = input_base_dir
     61        self._output_dir = output_dir
     62        self._append_suffix = append_suffix
    3263        super(StdoutRefactoringTool, self).__init__(fixers, options, explicit)
    3364
     
    3768
    3869    def write_file(self, new_text, filename, old_text, encoding):
     70        orig_filename = filename
     71        if self._output_dir:
     72            if filename.startswith(self._input_base_dir):
     73                filename = os.path.join(self._output_dir,
     74                                        filename[len(self._input_base_dir):])
     75            else:
     76                raise ValueError('filename %s does not start with the '
     77                                 'input_base_dir %s' % (
     78                                         filename, self._input_base_dir))
     79        if self._append_suffix:
     80            filename += self._append_suffix
     81        if orig_filename != filename:
     82            output_dir = os.path.dirname(filename)
     83            if not os.path.isdir(output_dir):
     84                os.makedirs(output_dir)
     85            self.log_message('Writing converted %s to %s.', orig_filename,
     86                             filename)
    3987        if not self.nobackups:
    4088            # Make backup
     
    54102        if not self.nobackups:
    55103            shutil.copymode(backup, filename)
     104        if orig_filename != filename:
     105            # Preserve the file mode in the new output directory.
     106            shutil.copymode(orig_filename, filename)
    56107
    57108    def print_output(self, old, new, filename, equal):
     
    63114                diff_lines = diff_texts(old, new, filename)
    64115                try:
    65                     for line in diff_lines:
    66                         print line
     116                    if self.output_lock is not None:
     117                        with self.output_lock:
     118                            for line in diff_lines:
     119                                print line
     120                            sys.stdout.flush()
     121                    else:
     122                        for line in diff_lines:
     123                            print line
    67124                except UnicodeEncodeError:
    68125                    warn("couldn't encode %s's diff for your terminal" %
     
    94151                      type="int", help="Run 2to3 concurrently")
    95152    parser.add_option("-x", "--nofix", action="append", default=[],
    96                       help="Prevent a fixer from being run.")
     153                      help="Prevent a transformation from being run")
    97154    parser.add_option("-l", "--list-fixes", action="store_true",
    98                       help="List available transformations (fixes/fix_*.py)")
     155                      help="List available transformations")
    99156    parser.add_option("-p", "--print-function", action="store_true",
    100157                      help="Modify the grammar so that print() is a function")
     
    106163                      help="Write back modified files")
    107164    parser.add_option("-n", "--nobackups", action="store_true", default=False,
    108                       help="Don't write backups for modified files.")
     165                      help="Don't write backups for modified files")
     166    parser.add_option("-o", "--output-dir", action="store", type="str",
     167                      default="", help="Put output files in this directory "
     168                      "instead of overwriting the input files.  Requires -n.")
     169    parser.add_option("-W", "--write-unchanged-files", action="store_true",
     170                      help="Also write files even if no changes were required"
     171                      " (useful with --output-dir); implies -w.")
     172    parser.add_option("--add-suffix", action="store", type="str", default="",
     173                      help="Append this string to all output filenames."
     174                      " Requires -n if non-empty.  "
     175                      "ex: --add-suffix='3' will generate .py3 files.")
    109176
    110177    # Parse command line arguments
     
    112179    flags = {}
    113180    options, args = parser.parse_args(args)
     181    if options.write_unchanged_files:
     182        flags["write_unchanged_files"] = True
     183        if not options.write:
     184            warn("--write-unchanged-files/-W implies -w.")
     185        options.write = True
     186    # If we allowed these, the original files would be renamed to backup names
     187    # but not replaced.
     188    if options.output_dir and not options.nobackups:
     189        parser.error("Can't use --output-dir/-o without -n.")
     190    if options.add_suffix and not options.nobackups:
     191        parser.error("Can't use --add-suffix without -n.")
     192
    114193    if not options.write and options.no_diffs:
    115194        warn("not writing files and not printing diffs; that's not very useful")
     
    137216    level = logging.DEBUG if options.verbose else logging.INFO
    138217    logging.basicConfig(format='%(name)s: %(message)s', level=level)
     218    logger = logging.getLogger('lib2to3.main')
    139219
    140220    # Initialize the refactoring tool
     
    153233        requested = avail_fixes.union(explicit)
    154234    fixer_names = requested.difference(unwanted_fixes)
    155     rt = StdoutRefactoringTool(sorted(fixer_names), flags, sorted(explicit),
    156                                options.nobackups, not options.no_diffs)
     235    input_base_dir = os.path.commonprefix(args)
     236    if (input_base_dir and not input_base_dir.endswith(os.sep)
     237        and not os.path.isdir(input_base_dir)):
     238        # One or more similar names were passed, their directory is the base.
     239        # os.path.commonprefix() is ignorant of path elements, this corrects
     240        # for that weird API.
     241        input_base_dir = os.path.dirname(input_base_dir)
     242    if options.output_dir:
     243        input_base_dir = input_base_dir.rstrip(os.sep)
     244        logger.info('Output in %r will mirror the input directory %r layout.',
     245                    options.output_dir, input_base_dir)
     246    rt = StdoutRefactoringTool(
     247            sorted(fixer_names), flags, sorted(explicit),
     248            options.nobackups, not options.no_diffs,
     249            input_base_dir=input_base_dir,
     250            output_dir=options.output_dir,
     251            append_suffix=options.add_suffix)
    157252
    158253    # Refactor all files and directories passed as arguments
Note: See TracChangeset for help on using the changeset viewer.