summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy Edmund Crosley <timothy.crosley@gmail.com>2015-02-05 11:10:16 -0500
committerTimothy Edmund Crosley <timothy.crosley@gmail.com>2015-02-05 11:10:16 -0500
commit24809bb5378bc1c4c5e0526a35f1d54221772cd0 (patch)
tree215f55be60a7cfbb3b20cf0dc164b519a54ccc5b
parent24fb4c6701545e3f0a173ae356ca1c6a045c9f06 (diff)
parent1a7cf453d11b5b06a399f5b183646e1fbe13005a (diff)
downloadisort-24809bb5378bc1c4c5e0526a35f1d54221772cd0.tar.gz
Merge pull request #239 from timothycrosley/feature/fix-issue-234
Feature/fix issue 234
-rw-r--r--isort/isort.py238
-rwxr-xr-xisort/main.py2
-rw-r--r--isort/settings.py1
-rw-r--r--test_isort.py7
4 files changed, 134 insertions, 114 deletions
diff --git a/isort/isort.py b/isort/isort.py
index 8fafd9d0..038cd3d0 100644
--- a/isort/isort.py
+++ b/isort/isort.py
@@ -284,6 +284,123 @@ class SortImports(object):
return line
+ def _add_straight_imports(self, straight_modules, section, section_output):
+ for module in straight_modules:
+ if module in self.remove_imports:
+ continue
+
+ if module in self.as_map:
+ import_definition = "import {0} as {1}".format(module, self.as_map[module])
+ else:
+ import_definition = "import {0}".format(module)
+
+ comments_above = self.comments['above']['straight'].get(module, None)
+ if comments_above:
+ section_output.append(comments_above)
+ section_output.append(self._add_comments(self.comments['straight'].get(module), import_definition))
+
+ def _add_from_imports(self, from_modules, section, section_output):
+ for module in from_modules:
+ if module in self.remove_imports:
+ continue
+
+ import_start = "from {0} import ".format(module)
+ from_imports = list(self.imports[section]['from'][module])
+ from_imports = natsorted(from_imports, key=lambda key: self._module_key(key, self.config, True))
+ if self.remove_imports:
+ from_imports = [line for line in from_imports if not "{0}.{1}".format(module, line) in
+ self.remove_imports]
+
+ for from_import in copy.copy(from_imports):
+ submodule = module + "." + from_import
+ import_as = self.as_map.get(submodule, False)
+ if import_as:
+ import_definition = "{0} as {1}".format(from_import, import_as)
+ if self.config['combine_as_imports'] and not ("*" in from_imports and
+ self.config['combine_star']):
+ from_imports[from_imports.index(from_import)] = import_definition
+ else:
+ import_statement = self._wrap(import_start + import_definition)
+ comments = self.comments['straight'].get(submodule)
+ import_statement = self._add_comments(comments, import_statement)
+ section_output.append(import_statement)
+ from_imports.remove(from_import)
+
+ if from_imports:
+ comments = self.comments['from'].get(module)
+ if "*" in from_imports and self.config['combine_star']:
+ import_statement = self._wrap(self._add_comments(comments, "{0}*".format(import_start)))
+ elif self.config['force_single_line']:
+ import_statements = []
+ for from_import in from_imports:
+ single_import_line = self._add_comments(comments, import_start + from_import)
+ comment = self.comments['nested'].get(module, {}).get(from_import, None)
+ if comment:
+ single_import_line += "{0} {1}".format(comments and ";" or " #", comment)
+ import_statements.append(self._wrap(single_import_line))
+ comments = None
+ import_statement = "\n".join(import_statements)
+ else:
+ star_import = False
+ if "*" in from_imports:
+ section_output.append(self._add_comments(comments, "{0}*".format(import_start)))
+ from_imports.remove('*')
+ star_import = True
+ comments = None
+
+ for from_import in copy.copy(from_imports):
+ comment = self.comments['nested'].get(module, {}).get(from_import, None)
+ if comment:
+ single_import_line = self._add_comments(comments, import_start + from_import)
+ single_import_line += "{0} {1}".format(comments and ";" or " #", comment)
+ above_comments = self.comments['above']['from'].get(module, None)
+ if above_comments:
+ section_output.extend(above_comments)
+ section_output.append(self._wrap(single_import_line))
+ from_imports.remove(from_import)
+ comments = None
+
+ if star_import:
+ import_statement = import_start + (", ").join(from_imports)
+ else:
+ import_statement = self._add_comments(comments, import_start + (", ").join(from_imports))
+ if not from_imports:
+ import_statement = ""
+ if len(import_statement) > self.config['line_length']:
+ if len(from_imports) > 1:
+ output_mode = settings.WrapModes._fields[self.config.get('multi_line_output',
+ 0)].lower()
+ formatter = getattr(self, "_output_" + output_mode, self._output_grid)
+ dynamic_indent = " " * (len(import_start) + 1)
+ indent = self.config['indent']
+ line_length = self.config['line_length']
+ import_statement = formatter(import_start, copy.copy(from_imports),
+ dynamic_indent, indent, line_length, comments)
+ if self.config['balanced_wrapping']:
+ lines = import_statement.split("\n")
+ line_count = len(lines)
+ if len(lines) > 1:
+ minimum_length = min([len(line) for line in lines[:-1]])
+ else:
+ minimum_length = 0
+ new_import_statement = import_statement
+ while (len(lines[-1]) < minimum_length and
+ len(lines) == line_count and line_length > 10):
+ import_statement = new_import_statement
+ line_length -= 1
+ new_import_statement = formatter(import_start, copy.copy(from_imports),
+ dynamic_indent, indent, line_length, comments)
+ lines = new_import_statement.split("\n")
+ else:
+ import_statement = self._wrap(import_statement)
+
+
+ if import_statement:
+ above_comments = self.comments['above']['from'].get(module, None)
+ if above_comments:
+ section_output.extend(above_comments)
+ section_output.append(import_statement)
+
def _add_formatted_imports(self):
"""Adds the imports back to the file.
@@ -294,124 +411,17 @@ class SortImports(object):
for section in itertools.chain(SECTIONS, self.config['forced_separate']):
straight_modules = list(self.imports[section]['straight'])
straight_modules = natsorted(straight_modules, key=lambda key: self._module_key(key, self.config))
- section_output = []
-
- for module in straight_modules:
- if module in self.remove_imports:
- continue
-
- if module in self.as_map:
- import_definition = "import {0} as {1}".format(module, self.as_map[module])
- else:
- import_definition = "import {0}".format(module)
-
- comments_above = self.comments['above']['straight'].get(module, None)
- if comments_above:
- section_output.append(comments_above)
- section_output.append(self._add_comments(self.comments['straight'].get(module), import_definition))
-
from_modules = list(self.imports[section]['from'].keys())
from_modules = natsorted(from_modules, key=lambda key: self._module_key(key, self.config))
- for module in from_modules:
- if module in self.remove_imports:
- continue
- import_start = "from {0} import ".format(module)
- from_imports = list(self.imports[section]['from'][module])
- from_imports = natsorted(from_imports, key=lambda key: self._module_key(key, self.config, True))
- if self.remove_imports:
- from_imports = [line for line in from_imports if not "{0}.{1}".format(module, line) in
- self.remove_imports]
-
- for from_import in copy.copy(from_imports):
- submodule = module + "." + from_import
- import_as = self.as_map.get(submodule, False)
- if import_as:
- import_definition = "{0} as {1}".format(from_import, import_as)
- if self.config['combine_as_imports'] and not ("*" in from_imports and
- self.config['combine_star']):
- from_imports[from_imports.index(from_import)] = import_definition
- else:
- import_statement = self._wrap(import_start + import_definition)
- comments = self.comments['straight'].get(submodule)
- import_statement = self._add_comments(comments, import_statement)
- section_output.append(import_statement)
- from_imports.remove(from_import)
-
- if from_imports:
- comments = self.comments['from'].get(module)
- if "*" in from_imports and self.config['combine_star']:
- import_statement = self._wrap(self._add_comments(comments, "{0}*".format(import_start)))
- elif self.config['force_single_line']:
- import_statements = []
- for from_import in from_imports:
- single_import_line = self._add_comments(comments, import_start + from_import)
- comment = self.comments['nested'].get(module, {}).get(from_import, None)
- if comment:
- single_import_line += "{0} {1}".format(comments and ";" or " #", comment)
- import_statements.append(self._wrap(single_import_line))
- comments = None
- import_statement = "\n".join(import_statements)
- else:
- star_import = False
- if "*" in from_imports:
- section_output.append(self._add_comments(comments, "{0}*".format(import_start)))
- from_imports.remove('*')
- star_import = True
- comments = None
+ section_output = []
+ if self.config.get('from_first', False):
+ self._add_from_imports(from_modules, section, section_output)
+ self._add_straight_imports(straight_modules, section, section_output)
+ else:
+ self._add_straight_imports(straight_modules, section, section_output)
+ self._add_from_imports(from_modules, section, section_output)
- for from_import in copy.copy(from_imports):
- comment = self.comments['nested'].get(module, {}).get(from_import, None)
- if comment:
- single_import_line = self._add_comments(comments, import_start + from_import)
- single_import_line += "{0} {1}".format(comments and ";" or " #", comment)
- above_comments = self.comments['above']['from'].get(module, None)
- if above_comments:
- section_output.extend(above_comments)
- section_output.append(self._wrap(single_import_line))
- from_imports.remove(from_import)
- comments = None
-
- if star_import:
- import_statement = import_start + (", ").join(from_imports)
- else:
- import_statement = self._add_comments(comments, import_start + (", ").join(from_imports))
- if not from_imports:
- import_statement = ""
- if len(import_statement) > self.config['line_length']:
- if len(from_imports) > 1:
- output_mode = settings.WrapModes._fields[self.config.get('multi_line_output',
- 0)].lower()
- formatter = getattr(self, "_output_" + output_mode, self._output_grid)
- dynamic_indent = " " * (len(import_start) + 1)
- indent = self.config['indent']
- line_length = self.config['line_length']
- import_statement = formatter(import_start, copy.copy(from_imports),
- dynamic_indent, indent, line_length, comments)
- if self.config['balanced_wrapping']:
- lines = import_statement.split("\n")
- line_count = len(lines)
- if len(lines) > 1:
- minimum_length = min([len(line) for line in lines[:-1]])
- else:
- minimum_length = 0
- new_import_statement = import_statement
- while (len(lines[-1]) < minimum_length and
- len(lines) == line_count and line_length > 10):
- import_statement = new_import_statement
- line_length -= 1
- new_import_statement = formatter(import_start, copy.copy(from_imports),
- dynamic_indent, indent, line_length, comments)
- lines = new_import_statement.split("\n")
- else:
- import_statement = self._wrap(import_statement)
-
-
- if import_statement:
- above_comments = self.comments['above']['from'].get(module, None)
- if above_comments:
- section_output.extend(above_comments)
- section_output.append(import_statement)
if section_output:
section_name = section
if section in SECTIONS:
diff --git a/isort/main.py b/isort/main.py
index 727f01a0..1ed1030e 100755
--- a/isort/main.py
+++ b/isort/main.py
@@ -106,6 +106,8 @@ def main():
help='Shows verbose output, such as when files are skipped or when a check is successful.')
parser.add_argument('-sp', '--settings-path', dest="settings_path",
help='Explicitly set the settings path instead of auto determining based on file location.')
+ parser.add_argument('-ff', '--from-first', dest='from_first',
+ help="Switches the typical ordering preference, showing from imports first then straight ones")
arguments = dict((key, value) for (key, value) in itemsview(vars(parser.parse_args())) if value)
file_names = arguments.pop('files', [])
diff --git a/isort/settings.py b/isort/settings.py
index 664267ba..cdb5cd74 100644
--- a/isort/settings.py
+++ b/isort/settings.py
@@ -87,6 +87,7 @@ default = {'force_to_top': [],
'combine_as_imports': False,
'combine_star': False,
'include_trailing_comma': False,
+ 'from_first': False,
'verbose': False}
diff --git a/test_isort.py b/test_isort.py
index 7fde1b43..f25ae5fb 100644
--- a/test_isort.py
+++ b/test_isort.py
@@ -1194,3 +1194,10 @@ def test_from_ending():
test_input = "from foo import get_foo_from, get_foo\n"
expected_output = "from foo import get_foo, get_foo_from\n"
assert SortImports(file_contents=test_input).output == expected_output
+
+
+def test_from_first():
+ """Tests the setting from_first works correctly"""
+ test_input = "from os import path\nimport os\n"
+ assert SortImports(file_contents=test_input, from_first=True).output == test_input
+