diff options
author | Timothy Crosley <timothy.crosley@gmail.com> | 2014-03-07 02:10:53 -0500 |
---|---|---|
committer | Timothy Crosley <timothy.crosley@gmail.com> | 2014-03-07 02:10:53 -0500 |
commit | 4201b4fc15ddfe330f19216a8956e1f9a9ceeb59 (patch) | |
tree | 3b6cdd5cb470fec58f5d2941446e2952fbdaf7e0 | |
parent | 184287555f89c2e4c35ca4300e0ea6554baae3e8 (diff) | |
parent | 5aa7e1465b928a1317359316511431c4efecb025 (diff) | |
download | isort-3.6.2.tar.gz |
Merge branch 'release/3.6.2'3.6.2
-rw-r--r-- | .travis.yml | 3 | ||||
-rw-r--r-- | ACKNOWLEDGEMENTS.md | 40 | ||||
-rw-r--r-- | isort/__init__.py | 2 | ||||
-rw-r--r-- | isort/isort.py | 66 | ||||
-rw-r--r-- | isort/settings.py | 2 | ||||
-rwxr-xr-x | setup.py | 4 | ||||
-rw-r--r-- | test_isort.py | 9 | ||||
-rw-r--r-- | tox.ini | 12 |
8 files changed, 111 insertions, 27 deletions
diff --git a/.travis.yml b/.travis.yml index 1e66aee5..12bbf4c0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,8 @@ language: python python: + - "pypy" - "2.6" - "2.7" - "3.2" - "3.3" -script: python setup.py test
\ No newline at end of file +script: python setup.py test diff --git a/ACKNOWLEDGEMENTS.md b/ACKNOWLEDGEMENTS.md new file mode 100644 index 00000000..785e5ebb --- /dev/null +++ b/ACKNOWLEDGEMENTS.md @@ -0,0 +1,40 @@ +Original Creator & Maintainer +=================== +- Timothy Edmund Crosley (@timothycrosley) + +Plugin Writers +=================== +- *VIM* - Juan Pedro Fisanotti (@fisadev) +- *Emacs* - Friedrich Paetzke (@paetzke) +- *Sublime* - Thijs de Zoute (@thijsdezoete) + +Notable Bug Reporters +=================== +- Bengt Lüers (@Bengt) +- Chris Adams (@acdha) + +Code Contributors +=================== +- Aaron Gallagher (@habnabit) +- Thomas Grainger (@graingert) +- Thijs de Zoute (@thijsdezoete) +- Marc Abramowitz (@msabramo) +- Daniel Cowgill (@dcowgill) +- Francois Lebel (@flebel) +- Antoni Segura Puimedon (@celebdor) +- Pablo (@oubiga) +- Oskar Hahn (@ostcar) +- @wimglenn +- Matt Caldwell (@mattcaldwell) +- Dwayne Bailey (@dwaynebailey) +- Ionel Cristian Mărieș (@ionelmc) +- Chris Adams (@acdha) +- GuoJing (@GuoJing) + +-------------------------------------------- + +A sincere thanks to everyone who has helped isort be the great utility it is today! +It would not be one-hundredth as useful and consistent as it is now without the help of your bug reports, +commits, and suggestions. You guys rock! + +~Timothy Crosley diff --git a/isort/__init__.py b/isort/__init__.py index 0c8be9b5..541b2034 100644 --- a/isort/__init__.py +++ b/isort/__init__.py @@ -25,4 +25,4 @@ from __future__ import absolute_import, division, print_function, unicode_litera from . import settings from .isort import SECTION_NAMES, SECTIONS, SortImports -__version__ = "3.6.1" +__version__ = "3.6.2" diff --git a/isort/isort.py b/isort/isort.py index 9870725e..4ba0ff5a 100644 --- a/isort/isort.py +++ b/isort/isort.py @@ -250,6 +250,20 @@ class SortImports(object): return comments and "{0} # {1}".format(self._strip_comments(original_string)[0], "; ".join(comments)) or original_string + def _wrap(self, line): + """ + Returns an import wrapped to the specified line-length, if possible. + """ + if len(line) > self.config['line_length'] and "." in line: + line_parts = line.split(".") + next_line = [] + while (len(line) + 2) > self.config['line_length'] and line_parts: + next_line.append(line_parts.pop()) + line = ".".join(line_parts) + return "{0}. \\\n{1}".format(line, self._wrap(self.config['indent'] + ".".join(next_line))) + + return line + def _add_formatted_imports(self): """Adds the imports back to the file. @@ -299,33 +313,38 @@ class SortImports(object): if from_imports: comments = self.comments['from'].get(module) if "*" in from_imports: - import_statement = self._add_comments(comments, "{0}*".format(import_start)) + import_statement = self._wrap(self._add_comments(comments, "{0}*".format(import_start))) elif self.config['force_single_line']: - import_statement = self._add_comments(comments, import_start + from_imports.pop(0)) + import_statement = self._wrap(self._add_comments(comments, import_start + from_imports.pop(0))) for from_import in from_imports: import_statement += "\n{0}{1}".format(import_start, from_import) comments = None else: import_statement = self._add_comments(comments, import_start + (", ").join(from_imports)) - if len(import_statement) > self.config['line_length'] and 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) - minimum_length = min([len(line) for line in lines[:-1]]) - 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") + 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) + minimum_length = min([len(line) for line in lines[:-1]]) + 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) section_output.append(import_statement) @@ -496,7 +515,10 @@ class SortImports(object): else: while line.strip().endswith("\\"): line, comments = self._strip_comments(self._get_line(), comments) - import_string += "\n" + line + if import_string.strip().endswith(" import") or line.strip().startswith("import "): + import_string += "\n" + line + else: + import_string = import_string.rstrip().rstrip("\\") + line.lstrip() if import_type == "from": parts = import_string.split(" import ") diff --git a/isort/settings.py b/isort/settings.py index 0393b149..a94c622c 100644 --- a/isort/settings.py +++ b/isort/settings.py @@ -3,7 +3,7 @@ Defines how the default settings for isort should be loaded (First from the default setting dictionary at the top of the file, then overridden by any settings - in ~/.isort.conf if there are any) + in ~/.isort.cfg if there are any) Copyright (C) 2013 Timothy Edmund Crosley @@ -42,13 +42,13 @@ except (IOError, ImportError, OSError, RuntimeError): readme = '' setup(name='isort', - version='3.6.1', + version='3.6.2', description='A Python utility / library to sort Python imports.', long_description=readme, author='Timothy Crosley', author_email='timothy.crosley@gmail.com', url='https://github.com/timothycrosley/isort', - download_url='https://github.com/timothycrosley/isort/archive/3.6.1.tar.gz', + download_url='https://github.com/timothycrosley/isort/archive/3.6.2.tar.gz', license="MIT", entry_points={ 'console_scripts': [ diff --git a/test_isort.py b/test_isort.py index f66dca2f..4a581b59 100644 --- a/test_isort.py +++ b/test_isort.py @@ -825,3 +825,12 @@ def test_keep_comments(): assert SortImports(file_contents=test_input, combine_as_imports=True, line_length=45).output == \ ("from a import (b, # My Comment1; My Comment2 is really really really really long\n" " c, d)\n") + + +def test_multiline_split_on_dot(): + """Test to ensure isort correctly handles multiline imports, even when split right after a '.'""" + test_input = ("from my_lib.my_package.test.level_1.level_2.level_3.level_4.level_5.\\\n" + " my_module import my_function") + assert SortImports(file_contents=test_input, line_length=70).output == \ + ("from my_lib.my_package.test.level_1.level_2.level_3.level_4.level_5. \\\n" + " my_module import my_function\n") diff --git a/tox.ini b/tox.ini new file mode 100644 index 00000000..dac85a39 --- /dev/null +++ b/tox.ini @@ -0,0 +1,12 @@ +# Tox (http://tox.testrun.org/) is a tool for running tests +# in multiple virtualenvs. This configuration file will run the +# test suite on all supported python versions. To use it, "pip install tox" +# and then run "tox" from this directory. + +[tox] +envlist = py26, py27, py32, py33, pypy + +[testenv] +commands = py.test {posargs} +deps = + pytest |