creeper-adventure/.venv/bin/tidy-imports
2022-03-31 20:20:07 -05:00

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()