summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy Crosley <timothy.crosley@gmail.com>2014-03-07 02:10:53 -0500
committerTimothy Crosley <timothy.crosley@gmail.com>2014-03-07 02:10:53 -0500
commit4201b4fc15ddfe330f19216a8956e1f9a9ceeb59 (patch)
tree3b6cdd5cb470fec58f5d2941446e2952fbdaf7e0
parent184287555f89c2e4c35ca4300e0ea6554baae3e8 (diff)
parent5aa7e1465b928a1317359316511431c4efecb025 (diff)
downloadisort-3.6.2.tar.gz
Merge branch 'release/3.6.2'3.6.2
-rw-r--r--.travis.yml3
-rw-r--r--ACKNOWLEDGEMENTS.md40
-rw-r--r--isort/__init__.py2
-rw-r--r--isort/isort.py66
-rw-r--r--isort/settings.py2
-rwxr-xr-xsetup.py4
-rw-r--r--test_isort.py9
-rw-r--r--tox.ini12
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
diff --git a/setup.py b/setup.py
index 94ccea71..1273ced8 100755
--- a/setup.py
+++ b/setup.py
@@ -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