-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathorganize_python_imports.py
87 lines (71 loc) · 3.39 KB
/
organize_python_imports.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import _ast
import ast
import pyflakes.checker as pyflakes
import sublime
import sublime_plugin
class ImportGroup(object):
def __init__(self, start, end):
self.start = start
self.end = end
self.imports = []
class OrganizePythonImportsCommand(sublime_plugin.TextCommand):
def run(self, edit):
import_groups = []
code_lines = []
line_offset = 0
filename = sublime.Window.active_view(sublime.active_window()).file_name()
for line in self.view.lines(sublime.Region(0, self.view.size())):
line = self.view.substr(line)
if not line.strip().startswith('# -*- '):
code_lines.append(line)
else:
line_offset += 1
code = '\n'.join(code_lines)
try:
tree = compile(code, filename, 'exec', _ast.PyCF_ONLY_AST)
except:
tree = None
else:
unused_imports = set()
# for error in pyflakes.Checker(tree, filename).messages:
# if isinstance(error, pyflakes.messages.UnusedImport):
# print type(error)
# unused_imports.add(error.name)
st = ast.parse(code)
current_group = None
for stmt in st.body:
if stmt.__class__ in [ast.Import, ast.ImportFrom]:
line_region = self.view.full_line(self.view.text_point(stmt.lineno - 1 + line_offset, 0))
if not current_group:
current_group = ImportGroup(line_region.a, line_region.b)
import_groups.append(current_group)
current_group.imports.append(stmt)
current_group.end = max(line_region.b, current_group.end)
else:
current_group = None
edit = self.view.begin_edit('OrganizePythonImportsCommand')
for g in import_groups[-1::-1]:
imports, from_imports = set(), {}
for imp in g.imports:
if isinstance(imp, ast.Import):
for alias in imp.names:
if alias.asname:
if alias.asname not in unused_imports:
imports.add('import {0} as {1}'.format(alias.name, alias.asname))
elif alias.name not in unused_imports:
imports.add('import {0}'.format(alias.name))
else:
from_imports.setdefault(imp.module, set())
for alias in imp.names:
if alias.asname:
if alias.asname not in unused_imports:
from_imports[imp.module].add('{0} as {1}'.format(alias.name, alias.asname))
elif alias.name not in unused_imports:
from_imports[imp.module].add('{0}'.format(alias.name))
import_str = '\n'.join(sorted(imports)) + '\n'
for p in sorted(from_imports.keys()):
v = from_imports[p]
if v:
import_str += 'from {0} import {1}'.format(p, ', '.join(sorted(v))) + '\n'
self.view.replace(edit, sublime.Region(g.start, g.end), import_str.strip('\n') + '\n')
self.view.end_edit(edit)