#!/home/walkers/git/creeper-adventure/.venv/bin/python3 """ tidy-imports *.py tidy-imports < foo.py Automatically improves python import statements. - Adds missing imports and mandatory imports. - Removes unused imports. - Nicely formats imports (sorts, aligns, wraps). If filenames are given on the command line, rewrites them. Otherwise, if stdin is not a tty, read from stdin and write to stdout. Only top-level import statements are touched. """ # pyflyby/tidy-imports # Copyright (C) 2011, 2012, 2014 Karl Chen. # License: MIT http://opensource.org/licenses/MIT from __future__ import print_function, absolute_import, division, with_statement from distutils.spawn import find_executable import subprocess import sys from pyflyby._cmdline import hfmt, parse_args, process_actions from pyflyby._imports2s import (canonicalize_imports, fix_unused_and_missing_imports, replace_star_imports, transform_imports) from pyflyby._log import logger def main(): def addopts(parser): parser.add_option('--add-missing', default=True, action='store_true', help=hfmt(''' (Default) Add missing imports.''')) parser.add_option('--no-add-missing', dest='add_missing', default=True, action='store_false', help=hfmt(''' Don't add missing imports.''')) parser.add_option('--remove-unused', default="AUTOMATIC", action='store_true', help=hfmt(''' Remove unused imports (default unless filename == __init__.py).''')) parser.add_option('--no-remove-unused', dest='remove_unused', action='store_false', help=hfmt(''' Don't remove unused imports (default if filename == __init__.py).''')) parser.add_option('--add-mandatory', default=True, action='store_true', help=hfmt(''' (Default) Add mandatory imports.''')) parser.add_option('--no-add-mandatory', dest='add_mandatory', default=True, action='store_false', help=hfmt(''' Don't add mandatory imports.''')) parser.add_option('--replace-star-imports', default=False, action='store_true', help=hfmt(''' Replace 'from foo.bar import *' with full list of imports before removing unused imports.''')) parser.add_option('--no-replace-star-imports', dest='replace_star_imports', action='store_false', help=hfmt(''' (Default) Don't replace 'from foo.bar import *'.''')) parser.add_option('--canonicalize', default=True, action='store_true', help=hfmt(''' (Default) Replace imports with canonical equivalent imports, according to database.''')) parser.add_option('--no-canonicalize', dest='canonicalize', default=True, action='store_false', help=hfmt(''' Don't canonicalize imports.''')) parser.add_option('--py23-fallback', dest='py23_fallback', default=True, action='store_true', help=hfmt(''' (Default) Automatically fallback to python2/python3 if the source file has a syntax error.''')) parser.add_option('--no-py23-fallback', dest='py23_fallback', default=True, action='store_false', help=hfmt(''' Do not automatically fallback to python2/python3 if the source file has a syntax error.''')) def transform_callback(option, opt_str, value, group): k, v = value.split("=", 1) group.values.transformations[k] = v parser.add_option("--transform", action='callback', type="string", callback=transform_callback, metavar="OLD=NEW", dest="transformations", default={}, help=hfmt(''' Replace OLD with NEW in imports. May be specified multiple times.''')) def no_add_callback(option, opt_str, value, group): group.values.add_missing = False group.values.add_mandatory = False parser.add_option('--no-add', action='callback', callback=no_add_callback, help=hfmt(''' Equivalent to --no-add-missing --no-add-mandatory.''')) options, args = parse_args( addopts, import_format_params=True, modify_action_params=True) def modify(x): if options.canonicalize: x = canonicalize_imports(x, params=options.params) if options.transformations: x = transform_imports(x, options.transformations, params=options.params) if options.replace_star_imports: x = replace_star_imports(x, params=options.params) return fix_unused_and_missing_imports( x, params=options.params, add_missing=options.add_missing, remove_unused=options.remove_unused, add_mandatory=options.add_mandatory, ) if options.py23_fallback: try: process_actions(args, options.actions, modify, reraise_exceptions=SyntaxError) except SyntaxError as e: python = 'python2' if sys.version_info[0] == 3 else 'python3' python_full = find_executable(python) if not python_full: logger.error("Fallback failed: could not find %s", python) raise logger.info("SyntaxError detected ({}), falling back to {}".format( e, python)) args = [python_full] + sys.argv + ['--no-py23-fallback'] try: raise SystemExit(subprocess.call(args)) except KeyboardInterrupt: sys.exit(1) else: process_actions(args, options.actions, modify) if __name__ == '__main__': main()