1ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh""" 2ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehMain program for 2to3. 3ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh""" 4ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 5ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom __future__ import with_statement 6ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 7ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport sys 8ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport os 9ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport difflib 10ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport logging 11ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport shutil 12ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport optparse 13ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 14ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom . import refactor 15ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 16ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 17ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef diff_texts(a, b, filename): 18ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Return a unified diff of two strings.""" 19ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh a = a.splitlines() 20ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh b = b.splitlines() 21ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return difflib.unified_diff(a, b, filename, filename, 22ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "(original)", "(refactored)", 23ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh lineterm="") 24ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 25ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 26ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass StdoutRefactoringTool(refactor.MultiprocessRefactoringTool): 27ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 28ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh A refactoring tool that can avoid overwriting its input files. 29ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh Prints output to stdout. 30ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 31ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh Output files can optionally be written to a different directory and or 32ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh have an extra file suffix appended to their name for use in situations 33ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh where you do not want to replace the input files. 34ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 35ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 36ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self, fixers, options, explicit, nobackups, show_diffs, 37ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh input_base_dir='', output_dir='', append_suffix=''): 38ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 39ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh Args: 40ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fixers: A list of fixers to import. 41ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh options: A dict with RefactoringTool configuration. 42ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh explicit: A list of fixers to run even if they are explicit. 43ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh nobackups: If true no backup '.bak' files will be created for those 44ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh files that are being refactored. 45ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh show_diffs: Should diffs of the refactoring be printed to stdout? 46ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh input_base_dir: The base directory for all input files. This class 47ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh will strip this path prefix off of filenames before substituting 48ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh it with output_dir. Only meaningful if output_dir is supplied. 49ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh All files processed by refactor() must start with this path. 50ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh output_dir: If supplied, all converted files will be written into 51ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh this directory tree instead of input_base_dir. 52ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh append_suffix: If supplied, all files output by this tool will have 53ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh this appended to their filename. Useful for changing .py to 54ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh .py3 for example by passing append_suffix='3'. 55ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 56ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.nobackups = nobackups 57ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.show_diffs = show_diffs 58ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if input_base_dir and not input_base_dir.endswith(os.sep): 59ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh input_base_dir += os.sep 60ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self._input_base_dir = input_base_dir 61ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self._output_dir = output_dir 62ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self._append_suffix = append_suffix 63ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh super(StdoutRefactoringTool, self).__init__(fixers, options, explicit) 64ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 65ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def log_error(self, msg, *args, **kwargs): 66ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.errors.append((msg, args, kwargs)) 67ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.logger.error(msg, *args, **kwargs) 68ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 69ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def write_file(self, new_text, filename, old_text, encoding): 70ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh orig_filename = filename 71ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self._output_dir: 72ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if filename.startswith(self._input_base_dir): 73ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename = os.path.join(self._output_dir, 74ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename[len(self._input_base_dir):]) 75ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 76ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raise ValueError('filename %s does not start with the ' 77ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'input_base_dir %s' % ( 78ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename, self._input_base_dir)) 79ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self._append_suffix: 80ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename += self._append_suffix 81ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if orig_filename != filename: 82ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh output_dir = os.path.dirname(filename) 83ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not os.path.isdir(output_dir): 84ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh os.makedirs(output_dir) 85ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.log_message('Writing converted %s to %s.', orig_filename, 86ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh filename) 87ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not self.nobackups: 88ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Make backup 89ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh backup = filename + ".bak" 90ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if os.path.lexists(backup): 91ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 92ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh os.remove(backup) 93ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except os.error, err: 94ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.log_message("Can't remove backup %s", backup) 95ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 96ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh os.rename(filename, backup) 97ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except os.error, err: 98ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.log_message("Can't rename %s to %s", filename, backup) 99ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Actually write the new file 100ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh write = super(StdoutRefactoringTool, self).write_file 101ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh write(new_text, filename, old_text, encoding) 102ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not self.nobackups: 103ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh shutil.copymode(backup, filename) 104ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if orig_filename != filename: 105ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Preserve the file mode in the new output directory. 106ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh shutil.copymode(orig_filename, filename) 107ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 108ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def print_output(self, old, new, filename, equal): 109ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if equal: 110ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.log_message("No changes to %s", filename) 111ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 112ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.log_message("Refactored %s", filename) 113ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.show_diffs: 114ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh diff_lines = diff_texts(old, new, filename) 115ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 116ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.output_lock is not None: 117ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh with self.output_lock: 118ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for line in diff_lines: 119ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print line 120ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh sys.stdout.flush() 121ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 122ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for line in diff_lines: 123ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print line 124ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except UnicodeEncodeError: 125ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh warn("couldn't encode %s's diff for your terminal" % 126ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (filename,)) 127ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 128ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 129ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 130ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef warn(msg): 131ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print >> sys.stderr, "WARNING: %s" % (msg,) 132ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 133ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 134ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef main(fixer_pkg, args=None): 135ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Main program. 136ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 137ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh Args: 138ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fixer_pkg: the name of a package where the fixers are located. 139ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh args: optional; a list of command line arguments. If omitted, 140ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh sys.argv[1:] is used. 141ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 142ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh Returns a suggested exit status (0, 1, 2). 143ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 144ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Set up option parser 145ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parser = optparse.OptionParser(usage="2to3 [options] file|dir ...") 146ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parser.add_option("-d", "--doctests_only", action="store_true", 147ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh help="Fix up doctests only") 148ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parser.add_option("-f", "--fix", action="append", default=[], 149ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh help="Each FIX specifies a transformation; default: all") 150ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parser.add_option("-j", "--processes", action="store", default=1, 151ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh type="int", help="Run 2to3 concurrently") 152ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parser.add_option("-x", "--nofix", action="append", default=[], 153ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh help="Prevent a transformation from being run") 154ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parser.add_option("-l", "--list-fixes", action="store_true", 155ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh help="List available transformations") 156ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parser.add_option("-p", "--print-function", action="store_true", 157ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh help="Modify the grammar so that print() is a function") 158ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parser.add_option("-v", "--verbose", action="store_true", 159ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh help="More verbose logging") 160ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parser.add_option("--no-diffs", action="store_true", 161ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh help="Don't show diffs of the refactoring") 162ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parser.add_option("-w", "--write", action="store_true", 163ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh help="Write back modified files") 164ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parser.add_option("-n", "--nobackups", action="store_true", default=False, 165ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh help="Don't write backups for modified files") 166ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parser.add_option("-o", "--output-dir", action="store", type="str", 167ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh default="", help="Put output files in this directory " 168ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "instead of overwriting the input files. Requires -n.") 169ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parser.add_option("-W", "--write-unchanged-files", action="store_true", 170ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh help="Also write files even if no changes were required" 171ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh " (useful with --output-dir); implies -w.") 172ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parser.add_option("--add-suffix", action="store", type="str", default="", 173ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh help="Append this string to all output filenames." 174ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh " Requires -n if non-empty. " 175ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "ex: --add-suffix='3' will generate .py3 files.") 176ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 177ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Parse command line arguments 178ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh refactor_stdin = False 179ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh flags = {} 180ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh options, args = parser.parse_args(args) 181ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if options.write_unchanged_files: 182ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh flags["write_unchanged_files"] = True 183ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not options.write: 184ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh warn("--write-unchanged-files/-W implies -w.") 185ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh options.write = True 186ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # If we allowed these, the original files would be renamed to backup names 187ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # but not replaced. 188ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if options.output_dir and not options.nobackups: 189ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parser.error("Can't use --output-dir/-o without -n.") 190ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if options.add_suffix and not options.nobackups: 191ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parser.error("Can't use --add-suffix without -n.") 192ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 193ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not options.write and options.no_diffs: 194ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh warn("not writing files and not printing diffs; that's not very useful") 195ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not options.write and options.nobackups: 196ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh parser.error("Can't use -n without -w") 197ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if options.list_fixes: 198ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print "Available transformations for the -f/--fix option:" 199ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for fixname in refactor.get_all_fix_names(fixer_pkg): 200ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print fixname 201ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not args: 202ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 0 203ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not args: 204ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print >> sys.stderr, "At least one file or directory argument required." 205ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print >> sys.stderr, "Use --help to show usage." 206ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 2 207ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if "-" in args: 208ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh refactor_stdin = True 209ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if options.write: 210ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print >> sys.stderr, "Can't write to stdin." 211ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 2 212ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if options.print_function: 213ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh flags["print_function"] = True 214ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 215ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Set up logging handler 216ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh level = logging.DEBUG if options.verbose else logging.INFO 217ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh logging.basicConfig(format='%(name)s: %(message)s', level=level) 218ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh logger = logging.getLogger('lib2to3.main') 219ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 220ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Initialize the refactoring tool 221ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh avail_fixes = set(refactor.get_fixers_from_package(fixer_pkg)) 222ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh unwanted_fixes = set(fixer_pkg + ".fix_" + fix for fix in options.nofix) 223ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh explicit = set() 224ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if options.fix: 225ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh all_present = False 226ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for fix in options.fix: 227ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if fix == "all": 228ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh all_present = True 229ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 230ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh explicit.add(fixer_pkg + ".fix_" + fix) 231ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh requested = avail_fixes.union(explicit) if all_present else explicit 232ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 233ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh requested = avail_fixes.union(explicit) 234ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fixer_names = requested.difference(unwanted_fixes) 235ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh input_base_dir = os.path.commonprefix(args) 236ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if (input_base_dir and not input_base_dir.endswith(os.sep) 237ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh and not os.path.isdir(input_base_dir)): 238ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # One or more similar names were passed, their directory is the base. 239ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # os.path.commonprefix() is ignorant of path elements, this corrects 240ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # for that weird API. 241ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh input_base_dir = os.path.dirname(input_base_dir) 242ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if options.output_dir: 243ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh input_base_dir = input_base_dir.rstrip(os.sep) 244ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh logger.info('Output in %r will mirror the input directory %r layout.', 245ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh options.output_dir, input_base_dir) 246ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rt = StdoutRefactoringTool( 247ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh sorted(fixer_names), flags, sorted(explicit), 248ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh options.nobackups, not options.no_diffs, 249ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh input_base_dir=input_base_dir, 250ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh output_dir=options.output_dir, 251ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh append_suffix=options.add_suffix) 252ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 253ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Refactor all files and directories passed as arguments 254ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not rt.errors: 255ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if refactor_stdin: 256ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rt.refactor_stdin() 257ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 258ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 259ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rt.refactor(args, options.write, options.doctests_only, 260ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh options.processes) 261ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except refactor.MultiprocessingUnsupported: 262ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh assert options.processes > 1 263ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh print >> sys.stderr, "Sorry, -j isn't " \ 264ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh "supported on this platform." 265ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 1 266ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh rt.summarize() 267ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 268ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Return error status (0 if rt.errors is zero) 269ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return int(bool(rt.errors)) 270