diff options
author | Timothy Edmund Crosley <timothy.crosley@gmail.com> | 2015-02-05 11:10:16 -0500 |
---|---|---|
committer | Timothy Edmund Crosley <timothy.crosley@gmail.com> | 2015-02-05 11:10:16 -0500 |
commit | 24809bb5378bc1c4c5e0526a35f1d54221772cd0 (patch) | |
tree | 215f55be60a7cfbb3b20cf0dc164b519a54ccc5b | |
parent | 24fb4c6701545e3f0a173ae356ca1c6a045c9f06 (diff) | |
parent | 1a7cf453d11b5b06a399f5b183646e1fbe13005a (diff) | |
download | isort-24809bb5378bc1c4c5e0526a35f1d54221772cd0.tar.gz |
Merge pull request #239 from timothycrosley/feature/fix-issue-234
Feature/fix issue 234
-rw-r--r-- | isort/isort.py | 238 | ||||
-rwxr-xr-x | isort/main.py | 2 | ||||
-rw-r--r-- | isort/settings.py | 1 | ||||
-rw-r--r-- | test_isort.py | 7 |
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 + |