75
75
self.config['indent'] = indent
77
self.place_imports = {}
78
self.import_placements = {}
77
79
self.remove_imports = [self._format_simplified(removal) for removal in self.config.get('remove_imports', [])]
78
80
self.add_imports = [self._format_natural(addition) for addition in self.config.get('add_imports', [])]
79
81
self._section_comments = ["# " + value for key, value in itemsview(self.config) if
146
148
print("ERROR: {0} Imports are incorrectly sorted.".format(self.file_path))
147
149
self.incorrectly_sorted = True
150
if show_diff or self.config.get('show_diff', False) is True:
151
self._show_diff(file_contents)
151
for line in unified_diff(file_contents.splitlines(1), self.output.splitlines(1),
152
fromfile=self.file_path + ':before', tofile=self.file_path + ':after'):
154
if show_diff or self.config.get('show_diff', False) is True:
155
self._show_diff(file_contents)
154
156
elif write_to_stdout:
155
157
stdout.write(self.output)
157
159
with codecs.open(self.file_path, encoding='utf-8', mode='w') as output_file:
158
160
output_file.write(self.output)
162
def _show_diff(self, file_contents):
163
for line in unified_diff(file_contents.splitlines(1), self.output.splitlines(1),
164
fromfile=self.file_path + ':before', tofile=self.file_path + ':after'):
161
168
def _strip_top_comments(lines):
162
169
"""Strips # comments that exist at the top of the given lines"""
182
189
if it can't determine - it assumes it is project code
192
for forced_separate in self.config['forced_separate']:
193
if moduleName.startswith(forced_separate) or moduleName.startswith("." + forced_separate):
194
return forced_separate
185
196
if moduleName.startswith("."):
186
197
return SECTIONS.LOCALFOLDER
190
201
except IndexError:
193
for forced_separate in self.config['forced_separate']:
194
if moduleName.startswith(forced_separate):
195
return forced_separate
197
if moduleName == "__future__" or (firstPart == "__future__"):
204
if (moduleName in self.config['known_future_library'] or
205
firstPart in self.config['known_future_library']):
198
206
return SECTIONS.FUTURE
199
207
elif moduleName in self.config['known_standard_library'] or \
200
208
(firstPart in self.config['known_standard_library']):
265
273
Returns an import wrapped to the specified line-length, if possible.
267
if len(line) > self.config['line_length'] and "." in line:
268
line_parts = line.split(".")
270
while (len(line) + 2) > self.config['line_length'] and line_parts:
271
next_line.append(line_parts.pop())
272
line = ".".join(line_parts)
273
return "{0}. \\\n{1}".format(line, self._wrap(self.config['indent'] + ".".join(next_line)))
275
if len(line) > self.config['line_length']:
276
for splitter in ("import", "."):
277
if splitter in line and not line.strip().startswith(splitter):
278
line_parts = line.split(splitter)
280
while (len(line) + 2) > self.config['line_length'] and line_parts:
281
next_line.append(line_parts.pop())
282
line = splitter.join(line_parts)
284
line = next_line.pop()
285
return "{0}{1} \\\n{2}".format(line, splitter,
286
self._wrap(self.config['indent'] + splitter.join(next_line).lstrip()))
311
324
self.remove_imports]
313
326
for from_import in copy.copy(from_imports):
314
import_as = self.as_map.get(module + "." + from_import, False)
327
submodule = module + "." + from_import
328
import_as = self.as_map.get(submodule, False)
316
330
import_definition = "{0} as {1}".format(from_import, import_as)
317
331
if self.config['combine_as_imports'] and not ("*" in from_imports and
319
333
from_imports[from_imports.index(from_import)] = import_definition
321
335
import_statement = self._wrap(import_start + import_definition)
336
comments = self.comments['straight'].get(submodule)
337
import_statement = self._add_comments(comments, import_statement)
322
338
section_output.append(import_statement)
323
339
from_imports.remove(from_import)
372
388
if self.config['balanced_wrapping']:
373
389
lines = import_statement.split("\n")
374
390
line_count = len(lines)
375
minimum_length = min([len(line) for line in lines[:-1]])
392
minimum_length = min([len(line) for line in lines[:-1]])
376
395
new_import_statement = import_statement
377
396
while (len(lines[-1]) < minimum_length and
378
397
len(lines) == line_count and line_length > 10):
391
410
section_name = section
392
411
if section in SECTIONS:
393
412
section_name = SECTION_NAMES[section]
413
if section_name in self.place_imports:
414
self.place_imports[section_name] = section_output
394
417
section_title = self.config.get('import_heading_' + str(section_name).lower(), '')
395
418
if section_title:
396
419
section_output.insert(0, "# " + section_title)
427
450
self.out_lines[imports_tail:0] = [""]
452
if self.place_imports:
454
for index, line in enumerate(self.out_lines):
455
new_out_lines.append(line)
456
if line in self.import_placements:
457
new_out_lines.extend(self.place_imports[self.import_placements[line]])
458
if len(self.out_lines) <= index or self.out_lines[index + 1].strip() != "":
459
new_out_lines.append("")
460
self.out_lines = new_out_lines
429
463
def _output_grid(self, statement, imports, white_space, indent, line_length, comments):
430
464
statement += "(" + imports.pop(0)
432
466
next_import = imports.pop(0)
433
467
next_statement = self._add_comments(comments, statement + ", " + next_import)
434
468
if len(next_statement.split("\n")[-1]) + 1 > line_length:
435
next_statement = (self._add_comments(comments, "{0},".format(statement)) +
436
"\n{0}{1}".format(white_space, next_import))
469
statement = (self._add_comments(comments, "{0},".format(statement)) +
470
"\n{0}{1}".format(white_space, next_import))
438
statement = next_statement
473
statement += ", " + next_import
439
474
return statement + ")"
441
476
def _output_vertical(self, statement, imports, white_space, indent, line_length, comments):
558
593
self.import_index = self.index - 1
596
if "isort:imports-" in line:
597
section = line.split("isort:imports-")[-1].split()[0]
598
self.place_imports[section.upper()] = []
599
self.import_placements[line] = section.upper()
562
602
for part in (part.strip() for part in line.split(";")):
563
603
if part and not part.startswith("from ") and not part.startswith("import "):
573
613
if not import_type:
574
614
self.out_lines.append(line)
617
line = line.replace("\t", " ")
576
618
if self.import_index == -1:
577
619
self.import_index = self.index - 1
611
653
while "as" in imports:
612
654
index = imports.index('as')
613
655
if import_type == "from":
614
self.as_map[imports[0] + "." + imports[index - 1]] = imports[index + 1]
656
module = imports[0] + "." + imports[index - 1]
657
self.as_map[module] = imports[index + 1]
616
self.as_map[imports[index - 1]] = imports[index + 1]
659
module = imports[index - 1]
660
self.as_map[module] = imports[index + 1]
661
if not self.config['combine_as_imports']:
662
self.comments['straight'][module] = comments
617
664
del imports[index:index + 2]
618
665
if import_type == "from":
619
666
import_from = imports.pop(0)