Repository: timothycrosley/isort
Pull request #558 (2017-06-03 00:37:21)

Add test to demonstrate no extra line is prepended


Patch:
diff --git a/.travis.yml b/.travis.yml
index e79ee219..6b23c0db 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,8 +3,6 @@ language: python
 matrix:
   include:
   - env: TOXENV=isort-check
-  - python: 3.6
-    env: TOXENV=lint
   - python: 2.6
     env: TOXENV=py26
   - python: 2.7
diff --git a/isort/__init__.py b/isort/__init__.py
index 6501ebd2..2969988f 100644
--- a/isort/__init__.py
+++ b/isort/__init__.py
@@ -22,7 +22,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 from __future__ import absolute_import, division, print_function, unicode_literals
 
-from . import settings  # noqa: F401
-from .isort import SortImports  # noqa: F401
+from . import settings
+from .isort import SortImports
 
 __version__ = "4.2.13"
diff --git a/isort/isort.py b/isort/isort.py
index 6055a57f..546d0722 100644
--- a/isort/isort.py
+++ b/isort/isort.py
@@ -162,7 +162,7 @@ class SortImports(object):
                 self.incorrectly_sorted = True
                 try:
                     compile(self._strip_top_comments(self.in_lines), self.file_path, 'exec', 0, 1)
-                    print("ERROR: {0} isort would have introduced syntax errors, please report to the project!".
+                    print("ERROR: {0} isort would have introduced syntax errors, please report to the project!". \
                           format(self.file_path))
                 except SyntaxError:
                     print("ERROR: {0} File contains syntax errors.".format(self.file_path))
@@ -407,6 +407,7 @@ class SortImports(object):
                         from_imports.remove(from_import)
                         section_output.append(import_statement)
 
+
             if from_imports:
                 comments = self.comments['from'].pop(module, ())
                 if "*" in from_imports and self.config['combine_star']:
@@ -547,7 +548,6 @@ class SortImports(object):
                         line = line.lower()
                     return '{0}{1}'.format(section, line)
                 section_output = nsorted(section_output, key=by_module)
-
             if section_output:
                 section_name = section
                 if section_name in self.place_imports:
@@ -557,12 +557,14 @@ class SortImports(object):
                 section_title = self.config.get('import_heading_' + str(section_name).lower(), '')
                 if section_title:
                     section_comment = "# {0}".format(section_title)
-                    if section_comment not in self.out_lines[0:1] and section_comment not in self.in_lines[0:1]:
+                    if not section_comment in self.out_lines[0:1] and not section_comment in self.in_lines[0:1]:
                         section_output.insert(0, section_comment)
                 output += section_output + ([''] * self.config['lines_between_sections'])
 
-        while [character.strip() for character in output[-1:]] == [""]:
+        while output and output[-1].strip() == '':
             output.pop()
+        while output and output[0].strip() == '':
+            output.pop(0)
 
         output_at = 0
         if self.import_index < self.original_length:
@@ -720,7 +722,7 @@ class SortImports(object):
     def _format_natural(import_line):
         import_line = import_line.strip()
         if not import_line.startswith("from ") and not import_line.startswith("import "):
-            if "." not in import_line:
+            if not "." in import_line:
                 return "import {0}".format(import_line)
             parts = import_line.split(".")
             end = parts.pop(-1)
@@ -825,14 +827,14 @@ class SortImports(object):
                     while not line.strip().endswith(")") and not self._at_end():
                         line, comments, new_comments = self._strip_comments(self._get_line(), comments)
                         stripped_line = self._strip_syntax(line).strip()
-                        if import_type == "from" and stripped_line and " " not in stripped_line and new_comments:
+                        if import_type == "from" and stripped_line and not " " in stripped_line and new_comments:
                             nested_comments[stripped_line] = comments[-1]
                         import_string += "\n" + line
                 else:
                     while line.strip().endswith("\\"):
                         line, comments, new_comments = self._strip_comments(self._get_line(), comments)
                         stripped_line = self._strip_syntax(line).strip()
-                        if import_type == "from" and stripped_line and " " not in stripped_line and new_comments:
+                        if import_type == "from" and stripped_line and not " " in stripped_line and new_comments:
                             nested_comments[stripped_line] = comments[-1]
                         if import_string.strip().endswith(" import") or line.strip().startswith("import "):
                             import_string += "\n" + line
@@ -879,8 +881,8 @@ class SortImports(object):
 
                     if len(self.out_lines) > max(self.import_index, self._first_comment_index_end + 1, 1) - 1:
                         last = self.out_lines and self.out_lines[-1].rstrip() or ""
-                        while (last.startswith("#") and not last.endswith('"""') and not last.endswith("'''") and
-                               'isort:imports-' not in last):
+                        while (last.startswith("#") and not last.endswith('"""') and not last.endswith("'''") and not
+                               'isort:imports-' in last):
                             self.comments['above']['from'].setdefault(import_from, []).insert(0, self.out_lines.pop(-1))
                             if len(self.out_lines) > max(self.import_index - 1, self._first_comment_index_end + 1, 1) - 1:
                                 last = self.out_lines[-1].rstrip()
@@ -903,7 +905,7 @@ class SortImports(object):
 
                             last = self.out_lines and self.out_lines[-1].rstrip() or ""
                             while (last.startswith("#") and not last.endswith('"""') and not last.endswith("'''") and
-                                   'isort:imports-' not in last):
+                                   not 'isort:imports-' in last):
                                 self.comments['above']['straight'].setdefault(module, []).insert(0,
                                                                                                  self.out_lines.pop(-1))
                                 if len(self.out_lines) > 0:
diff --git a/isort/pie_slice.py b/isort/pie_slice.py
index 0122a484..bfb341a7 100644
--- a/isort/pie_slice.py
+++ b/isort/pie_slice.py
@@ -23,7 +23,9 @@ from __future__ import absolute_import
 
 import abc
 import collections
+import functools
 import sys
+from numbers import Integral
 
 __version__ = "1.1.0"
 
@@ -146,11 +148,12 @@ if PY3:
 
     __all__ = common + ['urllib']
 else:
-    from itertools import ifilter as filter  # noqa: F401
-    from itertools import imap as map  # noqa: F401
+    from itertools import ifilter as filter
+    from itertools import imap as map
     from itertools import izip as zip
     from decimal import Decimal, ROUND_HALF_EVEN
 
+    import codecs
     str = unicode
     chr = unichr
     input = raw_input
@@ -448,8 +451,6 @@ if sys.version_info < (3, 2):
 
     from functools import wraps
 
-    _CacheInfo = collections.namedtuple("CacheInfo", "hits misses maxsize currsize")
-
     def lru_cache(maxsize=100):
         """Least-recently-used cache decorator.
         Taking from: https://github.com/MiCHiLU/python-functools32/blob/master/functools32/functools32.py
@@ -527,7 +528,7 @@ if sys.version_info < (3, 2):
         return decorating_function
 
 else:
-    from functools import lru_cache  # noqa: F401
+    from functools import lru_cache
 
 
 class OrderedSet(collections.MutableSet):
diff --git a/isort/settings.py b/isort/settings.py
index 267eb6f4..c60bd786 100644
--- a/isort/settings.py
+++ b/isort/settings.py
@@ -36,7 +36,7 @@ try:
 except ImportError:
     import ConfigParser as configparser
 
-MAX_CONFIG_SEARCH_DEPTH = 25  # The number of parent directories isort will look for a config file within
+MAX_CONFIG_SEARCH_DEPTH = 25 # The number of parent directories isort will look for a config file within
 DEFAULT_SECTIONS = ('FUTURE', 'STDLIB', 'THIRDPARTY', 'FIRSTPARTY', 'LOCALFOLDER')
 
 WrapModes = ('GRID', 'VERTICAL', 'HANGING_INDENT', 'VERTICAL_HANGING_INDENT', 'VERTICAL_GRID', 'VERTICAL_GRID_GROUPED', 'NOQA')
diff --git a/setup.cfg b/setup.cfg
index 4ec6f561..85548bf5 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -2,11 +2,5 @@
 universal = 1
 
 [flake8]
+ignore = F401,F403,E502,E123,E127,E128,E303,E713,E111,E241,E302,E121,E261,W391
 max-line-length = 160
-ignore =
-    # The default ignore list:
-    E121,E123,E126,E226,E24,E704,
-    # Our additions:
-    # E127: continuation line over-indented for visual indent
-    # E128: continuation line under-indented for visual indent
-    E127,E128
diff --git a/tox.ini b/tox.ini
index b5996f69..1ee185be 100644
--- a/tox.ini
+++ b/tox.ini
@@ -6,8 +6,7 @@
 [tox]
 envlist =
     isort-check,
-    py26, py27, py33, py34, py35, py36, pypy,
-    lint
+    py26, py27, py33, py34, py35, py36, pypy
 
 [testenv]
 commands =
@@ -21,8 +20,3 @@ commands =
     python setup.py isort
 deps =
     six
-
-[testenv:lint]
-basepython = python2.7
-deps = flake8==3.3.0
-commands = flake8


Test patch:
diff --git a/runtests.py b/runtests.py
index b699f5e7..4109bde0 100644
--- a/runtests.py
+++ b/runtests.py
@@ -1,9 +1,5 @@
 #!/usr/bin/env python
 
-# Skip linting this file until it's cleaned up:
-# https://github.com/timothycrosley/isort/issues/554
-# flake8: noqa
-
 sources = """
 eNrcvWmXG1l2INYzY1tjeGYk2ePtg32iQVGIKCKDSXZpyylUqVRFqqmuYvFwUVPOSoGRQGRmNJER
 YESAiVSrz/Ev8Dn+Bf4p/mu+29tfAMjqKo3PlNTMTOC9+7b77rv7/T//9e8+/Cx980fr23y+ai7z
diff --git a/test_isort.py b/test_isort.py
index fbac9528..efdc7a2e 100644
--- a/test_isort.py
+++ b/test_isort.py
@@ -30,6 +30,7 @@ import sys
 import tempfile
 
 from isort.isort import SortImports, exists_case_sensitive
+from isort.pie_slice import *
 from isort.settings import WrapModes
 
 SHORT_IMPORT = "from third_party import lib1, lib2, lib3, lib4"
@@ -362,7 +363,6 @@ def test_qa_comment_case():
     test_output = SortImports(file_contents=test_input, line_length=40, multi_line_output=WrapModes.NOQA).output
     assert test_output == "import veryveryveryveryveryveryveryveryveryveryvery  # NOQA\n"
 
-
 def test_length_sort():
     """Test setting isort to sort on length instead of alphabetically."""
     test_input = ("import medium_sizeeeeeeeeeeeeee\n"
@@ -888,7 +888,7 @@ def test_atomic_mode():
                                                                           "from b import c, d\n")
 
     # with syntax error content is not changed
-    test_input += "while True print 'Hello world'"  # blatant syntax error
+    test_input += "while True print 'Hello world'" # blatant syntax error
     assert SortImports(file_contents=test_input, atomic=True).output == test_input
 
 
@@ -1336,6 +1336,7 @@ def test_place_comments():
     assert test_output == expected_output
 
 
+
 def test_placement_control():
     """Ensure that most specific placement control match wins"""
     test_input = ("import os\n"
@@ -1788,7 +1789,6 @@ def test_lines_between_sections():
     assert SortImports(file_contents=test_input, lines_between_sections=2).output == ('import os\n\n\n'
                                                                                       'from bar import baz\n')
 
-
 def test_forced_sepatate_globs():
     """Test to ensure that forced_separate glob matches lines"""
     test_input = ('import os\n'
@@ -2024,7 +2024,6 @@ def test_import_line_mangles_issues_439():
     """Test to ensure comment on import with parens doesn't cause issues"""
     test_input = ('import a  # () import\n'
                   'from b import b\n')
-    assert SortImports(file_contents=test_input).output == test_input
 
 
 def test_alias_using_paren_issue_466():
@@ -2032,14 +2031,15 @@ def test_alias_using_paren_issue_466():
     test_input = 'from django.db.backends.mysql.base import DatabaseWrapper as MySQLDatabaseWrapper\n'
     expected_output = ('from django.db.backends.mysql.base import (\n'
                        '    DatabaseWrapper as MySQLDatabaseWrapper)\n')
-    assert SortImports(file_contents=test_input, line_length=50, use_parentheses=True).output == expected_output
+    assert  SortImports(file_contents=test_input, line_length=50, use_parentheses=True).output == expected_output
+
 
     test_input = 'from django.db.backends.mysql.base import DatabaseWrapper as MySQLDatabaseWrapper\n'
     expected_output = ('from django.db.backends.mysql.base import (\n'
                        '    DatabaseWrapper as MySQLDatabaseWrapper\n'
                        ')\n')
-    assert SortImports(file_contents=test_input, line_length=50, multi_line_output=5,
-                       use_parentheses=True).output == expected_output
+    assert  SortImports(file_contents=test_input, line_length=50, multi_line_output=5,
+                        use_parentheses=True).output == expected_output
 
 
 def test_strict_whitespace_by_default(capsys):
@@ -2064,8 +2064,8 @@ def test_import_wraps_with_comment_issue_471():
                   ' -- long string of comments which wrap over')
     expected_output = ('from very_long_module_name import (\n'
                        '    SuperLongClassName)  # @UnusedImport -- long string of comments which wrap over\n')
-    assert SortImports(file_contents=test_input, line_length=50, multi_line_output=1,
-                       use_parentheses=True).output == expected_output
+    assert  SortImports(file_contents=test_input, line_length=50, multi_line_output=1,
+                        use_parentheses=True).output == expected_output
 
 
 def test_import_case_produces_inconsistent_results_issue_472():
@@ -2132,3 +2132,14 @@ def test_future_below_encoding_issue_545():
                        '\n'
                        'print("hello")\n')
     assert SortImports(file_contents=test_input).output == expected_output
+
+
+def test_no_extra_lines_issue_557():
+    """Test to ensure no extra lines are prepended"""
+    test_input = ('import os\n'
+                  '\n'
+                  'from scrapy.core.downloader.handlers.http import HttpDownloadHandler, HTTPDownloadHandler\n')
+    expected_output = ('import os\n'
+                       'from scrapy.core.downloader.handlers.http import HttpDownloadHandler, HTTPDownloadHandler\n')
+    assert SortImports(file_contents=test_input, force_alphabetical_sort=True,
+                       force_sort_within_sections=True).output == expected_output