156 lines
6.9 KiB
Python
Executable file
156 lines
6.9 KiB
Python
Executable file
#!/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()
|