Repository: timothycrosley/isort
Pull request #600 (2017-10-10 07:40:57)

Fix case-sensitive path existence check in Mac OS X
Mac OS X works in a case-insensitive manner when checking path existence. This PR applies the same logic for Mac OS X installations as isort has for windows


Patch:
diff --git a/.env b/.env
index 4f53fc5c..a7dbe409 100644
--- a/.env
+++ b/.env
@@ -16,18 +16,17 @@ if [ ! -d "venv" ]; then
      if ! hash pyvenv 2>/dev/null; then
         function pyvenv()
         {
-            if hash pyvenv-3.6 2>/dev/null; then
-                pyvenv-3.6 $@
-            elif hash pyvenv-3.5 2>/dev/null; then
+            if hash pyvenv-3.5 2>/dev/null; then
                 pyvenv-3.5 $@
-            elif hash pyvenv-3.4 2>/dev/null; then
+            fi
+            if hash pyvenv-3.4 2>/dev/null; then
                 pyvenv-3.4 $@
-            elif hash pyvenv-3.3 2>/dev/null; then
+            fi
+            if hash pyvenv-3.3 2>/dev/null; then
                 pyvenv-3.3 $@
-            elif hash pyvenv-3.2 2>/dev/null; then
+            fi
+            if hash pyvenv-3.2 2>/dev/null; then
                 pyvenv-3.2 $@
-            else
-                python3 -m venv $@
             fi
         }
     fi
@@ -86,12 +85,6 @@ function interact {
 }
 
 
-function open {
-    (root
-     $CODE_EDITOR isort/*.py setup.py test_*.py README.md tox.ini .gitignore CHANGELOG.md setup.cfg .editorconfig .env .coveragerc .travis.yml requirements.txt)
-}
-
-
 function _leave_project()
 {
     export PROJECT_NAME=""
@@ -106,7 +99,6 @@ function _leave_project()
 
     unset -f load
     unset -f interact
-    unset -f open
 
     deactivate
 }
diff --git a/.travis.yml b/.travis.yml
index d1cdbf23..6b23c0db 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,11 +1,10 @@
 sudo: false
 language: python
-cache: pip
 matrix:
   include:
   - env: TOXENV=isort-check
-  - python: 3.6
-    env: TOXENV=lint
+  - python: 2.6
+    env: TOXENV=py26
   - python: 2.7
     env: TOXENV=py27
   - python: 3.3
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ee8501fc..bd70e3e4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,11 +1,5 @@
 Changelog
 =========
-### 4.3.0 - In progress
-- Fixed #557: `force_alphabetical_sort` and `force_sort_within_sections` can now be utilized together without extra new lines
-- Implemented `--version-number` to retrieve just the version number without the isort logo
-- Breaking changes
-    - Python 2.7+ only (dropped 2.6) allowing various code simplifications and improvements.
-
 ### 4.2.15 - June 6, 2017 - hotfix release
 IMPORTANT NOTE: This will be the last release with Python 2.6 support, subsequent releases will be 2.7+ only
 - Fixed certain one line imports not being successfully wrapped
diff --git a/README.rst b/README.rst
index bc83c515..f185178d 100644
--- a/README.rst
+++ b/README.rst
@@ -4,7 +4,7 @@
 ########
 
 .. image:: https://badge.fury.io/py/isort.svg
-    :target: https://badge.fury.io/py/isort
+    :target: http://badge.fury.io/py/isort
     :alt: PyPI version
 
 .. image:: https://travis-ci.org/timothycrosley/isort.svg?branch=master
@@ -29,7 +29,7 @@ isort your python imports for you so you don't have to.
 
 isort is a Python utility / library to sort imports alphabetically, and automatically separated into sections.
 It provides a command line utility, Python library and `plugins for various editors <https://github.com/timothycrosley/isort/wiki/isort-Plugins>`_ to quickly sort all your imports.
-It currently cleanly supports Python 2.7 - 3.6 without any dependencies.
+It currently cleanly supports Python 2.6 - 3.5 without any dependencies.
 
 .. image:: https://raw.github.com/timothycrosley/isort/develop/example.gif
    :alt: Example Usage
diff --git a/appveyor.yml b/appveyor.yml
index 3b6746b7..003d2e58 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -9,4 +9,4 @@ install:
   - pip install tox
 
 test_script:
-  - tox -e isort-check,py27,py33,py34,py35,py36
+  - tox -e isort-check,py26,py27,py33,py34,py35,py36
diff --git a/isort/__init__.py b/isort/__init__.py
index 13a8549a..4dd2cd16 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.14"
diff --git a/isort/isort.py b/isort/isort.py
index b25318ed..e839635c 100644
--- a/isort/isort.py
+++ b/isort/isort.py
@@ -32,8 +32,7 @@ import itertools
 import os
 import re
 import sys
-import sysconfig
-from collections import OrderedDict, namedtuple
+from collections import namedtuple
 from datetime import datetime
 from difflib import unified_diff
 from fnmatch import fnmatch
@@ -41,7 +40,7 @@ from glob import glob
 
 from . import settings
 from .natural import nsorted
-from .pie_slice import OrderedSet, input, itemsview
+from .pie_slice import OrderedDict, OrderedSet, input, itemsview
 
 KNOWN_SECTION_MAPPING = {
     'STDLIB': 'STANDARD_LIBRARY',
@@ -88,8 +87,6 @@ class SortImports(object):
                 indent = "\t"
         self.config['indent'] = indent
 
-        self.config['comment_prefix'] = self.config['comment_prefix'].strip("'").strip('"')
-
         self.place_imports = {}
         self.import_placements = {}
         self.remove_imports = [self._format_simplified(removal) for removal in self.config['remove_imports']]
@@ -115,7 +112,6 @@ class SortImports(object):
                     file_contents = file_to_import_sort.read()
 
         if file_contents is None or ("isort:" + "skip_file") in file_contents:
-            self.skipped = True
             return
 
         self.in_lines = file_contents.split("\n")
@@ -166,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))
@@ -197,7 +193,7 @@ class SortImports(object):
                 self._show_diff(file_contents)
                 answer = None
                 while answer not in ('yes', 'y', 'no', 'n', 'quit', 'q'):
-                    answer = input("Apply suggested changes to '{0}' [y/n/q]? ".format(self.file_path)).lower()
+                    answer = input("Apply suggested changes to '{0}' [y/n/q]?".format(self.file_path)).lower()
                     if answer in ('no', 'n'):
                         return
                     if answer in ('quit', 'q'):
@@ -265,7 +261,7 @@ class SortImports(object):
             virtual_env_src = '{0}/src/'.format(virtual_env)
 
         # handle case-insensitive paths on windows
-        stdlib_lib_prefix = os.path.normcase(sysconfig.get_paths()['stdlib'])
+        stdlib_lib_prefix = os.path.normcase(get_stdlib_path())
 
         for prefix in paths:
             module_path = "/".join((prefix, module_name.replace(".", "/")))
@@ -327,8 +323,7 @@ class SortImports(object):
         """
             Returns a string with comments added
         """
-        return comments and "{0}{1} {2}".format(self._strip_comments(original_string)[0],
-                                                self.config['comment_prefix'],
+        return comments and "{0}  # {1}".format(self._strip_comments(original_string)[0],
                                                 "; ".join(comments)) or original_string
 
     def _wrap(self, line):
@@ -337,16 +332,10 @@ class SortImports(object):
         """
         wrap_mode = self.config['multi_line_output']
         if len(line) > self.config['line_length'] and wrap_mode != settings.WrapModes.NOQA:
-            line_without_comment = line
-            comment = None
-            if '#' in line:
-                line_without_comment, comment = line.split('#', 1)
-            for splitter in ("import ", ".", "as "):
+            for splitter in ("import", ".", "as"):
                 exp = r"\b" + re.escape(splitter) + r"\b"
-                if re.search(exp, line_without_comment) and not line_without_comment.strip().startswith(splitter):
-                    line_parts = re.split(exp, line_without_comment)
-                    if comment:
-                        line_parts[-1] = '{0}#{1}'.format(line_parts[-1], comment)
+                if re.search(exp, line) and not line.strip().startswith(splitter):
+                    line_parts = re.split(exp, line)
                     next_line = []
                     while (len(line) + 2) > (self.config['wrap_length'] or self.config['line_length']) and line_parts:
                         next_line.append(line_parts.pop())
@@ -356,7 +345,7 @@ class SortImports(object):
 
                     cont_line = self._wrap(self.config['indent'] + splitter.join(next_line).lstrip())
                     if self.config['use_parentheses']:
-                        output = "{0}{1}(\n{2}{3}{4})".format(
+                        output = "{0}{1} (\n{2}{3}{4})".format(
                             line, splitter, cont_line,
                             "," if self.config['include_trailing_comma'] else "",
                             "\n" if wrap_mode in (
@@ -364,14 +353,14 @@ class SortImports(object):
                                 settings.WrapModes.VERTICAL_GRID_GROUPED,
                             ) else "")
                         lines = output.split('\n')
-                        if self.config['comment_prefix'] in lines[-1] and lines[-1].endswith(')'):
-                            line, comment = lines[-1].split(self.config['comment_prefix'], 1)
-                            lines[-1] = line + ')' + self.config['comment_prefix'] + comment[:-1]
+                        if '  #' in lines[-1] and lines[-1].endswith(')'):
+                            line, comment = lines[-1].split('  #', 1)
+                            lines[-1] = line + ')  #' + comment[:-1]
                         return '\n'.join(lines)
-                    return "{0}{1}\\\n{2}".format(line, splitter, cont_line)
+                    return "{0}{1} \\\n{2}".format(line, splitter, cont_line)
         elif len(line) > self.config['line_length'] and wrap_mode == settings.WrapModes.NOQA:
             if "# NOQA" not in line:
-                return "{0}{1} NOQA".format(line, self.config['comment_prefix'])
+                return "{0}  # NOQA".format(line)
 
         return line
 
@@ -402,43 +391,38 @@ class SortImports(object):
                 from_imports = [line for line in from_imports if not "{0}.{1}".format(module, line) in
                                 self.remove_imports]
 
-            sub_modules = ['{0}.{1}'.format(module, from_import) for from_import in from_imports]
-            as_imports = dict((from_import, "{0} as {1}".format(from_import, self.as_map[sub_module])) for
-                              from_import, sub_module in zip(from_imports, sub_modules) if sub_module in self.as_map)
-            if self.config['combine_as_imports'] and not ("*" in from_imports and self.config['combine_star']):
-                for from_import in copy.copy(from_imports):
-                    if from_import in as_imports:
-                        from_imports[from_imports.index(from_import)] = as_imports.pop(from_import)
+            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 = import_start + import_definition
+                        force_grid_wrap = self.config['force_grid_wrap']
+                        comments = self.comments['straight'].get(submodule)
+                        import_statement = self._add_comments(comments, self._wrap(import_statement))
+                        from_imports.remove(from_import)
+                        section_output.append(import_statement)
+
 
-            while from_imports:
+            if from_imports:
                 comments = self.comments['from'].pop(module, ())
                 if "*" in from_imports and self.config['combine_star']:
                     import_statement = self._wrap(self._add_comments(comments, "{0}*".format(import_start)))
-                    from_imports = None
                 elif self.config['force_single_line']:
                     import_statements = []
-                    while from_imports:
-                        from_import = from_imports.pop(0)
-                        if from_import in as_imports:
-                            from_comments = self.comments['straight'].get('{}.{}'.format(module, from_import))
-                            import_statements.append(self._add_comments(from_comments,
-                                                     self._wrap(import_start + as_imports[from_import])))
-                            continue
+                    for from_import in from_imports:
                         single_import_line = self._add_comments(comments, import_start + from_import)
                         comment = self.comments['nested'].get(module, {}).pop(from_import, None)
                         if comment:
-                            single_import_line += "{0} {1}".format(comments and ";" or self.config['comment_prefix'],
-                                                                   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:
-                    while from_imports and from_imports[0] in as_imports:
-                        from_import = from_imports.pop(0)
-                        from_comments = self.comments['straight'].get('{}.{}'.format(module, from_import))
-                        section_output.append(self._add_comments(from_comments,
-                                                                 self._wrap(import_start + as_imports[from_import])))
-
                     star_import = False
                     if "*" in from_imports:
                         section_output.append(self._add_comments(comments, "{0}*".format(import_start)))
@@ -447,13 +431,10 @@ class SortImports(object):
                         comments = None
 
                     for from_import in copy.copy(from_imports):
-                        if from_import in as_imports:
-                            continue
                         comment = self.comments['nested'].get(module, {}).pop(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 self.config['comment_prefix'],
-                                                                   comment)
+                            single_import_line += "{0} {1}".format(comments and ";" or "  #", comment)
                             above_comments = self.comments['above']['from'].pop(module, None)
                             if above_comments:
                                 section_output.extend(above_comments)
@@ -461,32 +442,29 @@ class SortImports(object):
                             from_imports.remove(from_import)
                             comments = None
 
-                    from_import_section = []
-                    while from_imports and from_imports[0] not in as_imports:
-                        from_import_section.append(from_imports.pop(0))
                     if star_import:
-                        import_statement = import_start + (", ").join(from_import_section)
+                        import_statement = import_start + (", ").join(from_imports)
                     else:
-                        import_statement = self._add_comments(comments, import_start + (", ").join(from_import_section))
-                    if not from_import_section:
+                        import_statement = self._add_comments(comments, import_start + (", ").join(from_imports))
+                    if not from_imports:
                         import_statement = ""
 
                     do_multiline_reformat = False
 
                     force_grid_wrap = self.config['force_grid_wrap']
-                    if force_grid_wrap and len(from_import_section) >= force_grid_wrap:
+                    if force_grid_wrap and len(from_imports) >= force_grid_wrap:
                         do_multiline_reformat = True
 
-                    if len(import_statement) > self.config['line_length'] and len(from_import_section) > 1:
+                    if len(import_statement) > self.config['line_length'] and len(from_imports) > 1:
                         do_multiline_reformat = True
 
                     # If line too long AND have imports AND we are NOT using GRID or VERTICAL wrap modes
-                    if (len(import_statement) > self.config['line_length'] and len(from_import_section) > 0 and
+                    if (len(import_statement) > self.config['line_length'] and len(from_imports) > 0 and
                             self.config['multi_line_output'] not in (1, 0)):
                         do_multiline_reformat = True
 
                     if do_multiline_reformat:
-                        import_statement = self._multi_line_reformat(import_start, from_import_section, comments)
+                        import_statement = self._multi_line_reformat(import_start, from_imports, comments)
                     if not do_multiline_reformat and len(import_statement) > self.config['line_length']:
                         import_statement = self._wrap(import_statement)
 
@@ -508,7 +486,7 @@ class SortImports(object):
             lines = import_statement.split("\n")
             line_count = len(lines)
             if len(lines) > 1:
-                minimum_length = min(len(line) for line in lines[:-1])
+                minimum_length = min([len(line) for line in lines[:-1]])
             else:
                 minimum_length = 0
             new_import_statement = import_statement
@@ -572,6 +550,7 @@ 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:
@@ -581,14 +560,12 @@ 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 output and output[-1].strip() == '':
+        while [character.strip() for character in output[-1:]] == [""]:
             output.pop()
-        while output and output[0].strip() == '':
-            output.pop(0)
 
         output_at = 0
         if self.import_index < self.original_length:
@@ -703,18 +680,18 @@ class SortImports(object):
         retval = '{0}{1}'.format(statement, ', '.join(imports))
         comment_str = ' '.join(comments)
         if comments:
-            if len(retval) + len(self.config['comment_prefix']) + 1 + len(comment_str) <= line_length:
-                return '{0}{1} {2}'.format(retval, self.config['comment_prefix'], comment_str)
+            if len(retval) + 4 + len(comment_str) <= line_length:
+                return '{0}  # {1}'.format(retval, comment_str)
         else:
             if len(retval) <= line_length:
                 return retval
         if comments:
             if "NOQA" in comments:
-                return '{0}{1} {2}'.format(retval, self.config['comment_prefix'], comment_str)
+                return '{0}  # {1}'.format(retval, comment_str)
             else:
-                return '{0}{1} NOQA {2}'.format(retval, self.config['comment_prefix'], comment_str)
+                return '{0}  # NOQA {1}'.format(retval, comment_str)
         else:
-            return '{0}{1} NOQA'.format(retval, self.config['comment_prefix'])
+            return '{0}  # NOQA'.format(retval)
 
     @staticmethod
     def _strip_comments(line, comments=None):
@@ -746,7 +723,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)
@@ -851,14 +828,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
@@ -889,8 +866,6 @@ class SortImports(object):
                 if import_type == "from":
                     import_from = imports.pop(0)
                     placed_module = self.place_module(import_from)
-                    if self.config['verbose']:
-                        print("from-type place_module for %s returned %s" % (import_from, placed_module))
                     if placed_module == '':
                         print(
                             "WARNING: could not place module {0} of line {1} --"
@@ -907,8 +882,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()
@@ -931,7 +906,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:
@@ -941,8 +916,6 @@ class SortImports(object):
                             if self.index - 1 == self.import_index:
                                 self.import_index -= len(self.comments['above']['straight'].get(module, []))
                         placed_module = self.place_module(module)
-                        if self.config['verbose']:
-                            print("else-type place_module for %s returned %s" % (module, placed_module))
                         if placed_module == '':
                             print(
                                 "WARNING: could not place module {0} of line {1} --"
@@ -969,6 +942,18 @@ def coding_check(fname, default='utf-8'):
     return coding
 
 
+def get_stdlib_path():
+    """Returns the path to the standard lib for the current path installation.
+
+    This function can be dropped and "sysconfig.get_paths()" used directly once Python 2.6 support is dropped.
+    """
+    if sys.version_info >= (2, 7):
+        import sysconfig
+        return sysconfig.get_paths()['stdlib']
+    else:
+        return os.path.join(sys.prefix, 'lib')
+
+
 def exists_case_sensitive(path):
     """
     Returns if the given path exists and also matches the case on Windows.
@@ -978,7 +963,7 @@ def exists_case_sensitive(path):
     can only import using the case of the real file.
     """
     result = os.path.exists(path)
-    if sys.platform.startswith('win') and result:
+    if (sys.platform.startswith('win') or sys.platform == 'darwin') and result:
         directory, basename = os.path.split(path)
         result = basename in os.listdir(directory)
     return result
diff --git a/isort/main.py b/isort/main.py
index d950f77b..eae7afa5 100755
--- a/isort/main.py
+++ b/isort/main.py
@@ -211,8 +211,6 @@ def create_parser():
                         help="Combines as imports on the same line.")
     parser.add_argument('-tc', '--trailing-comma', dest='include_trailing_comma', action='store_true',
                         help='Includes a trailing comma on multi line imports that include parentheses.')
-    parser.add_argument('-vn', '--version-number', action='version', version=__version__,
-                        help='Returns just the current version number without the logo')
     parser.add_argument('-v', '--version', action='store_true', dest='show_version')
     parser.add_argument('-vb', '--verbose', action='store_true', dest="verbose",
                         help='Shows verbose output, such as when files are skipped or when a check is successful.')
@@ -235,11 +233,10 @@ def create_parser():
     parser.add_argument('-fss', '--force-sort-within-sections', action='store_true', dest="force_sort_within_sections",
                         help='Force imports to be sorted by module, independent of import_type')
     parser.add_argument('-lbt', '--lines-between-types', dest='lines_between_types', type=int)
-    parser.add_argument('-lai', '--lines-after-imports', dest='lines_after_imports', type=int)
     parser.add_argument('-up', '--use-parentheses', dest='use_parentheses', action='store_true',
-                        help='Use parenthesis for line continuation on length limit instead of slashes.')
+                        help='Use parenthesis for line continuation on lenght limit instead of slashes.')
 
-    arguments = {key: value for key, value in itemsview(vars(parser.parse_args())) if value}
+    arguments = dict((key, value) for (key, value) in itemsview(vars(parser.parse_args())) if value)
     if 'dont_order_by_type' in arguments:
         arguments['order_by_type'] = False
     return arguments
diff --git a/isort/natural.py b/isort/natural.py
index c02b42c3..aac8c4a3 100644
--- a/isort/natural.py
+++ b/isort/natural.py
@@ -8,7 +8,7 @@ usage:
 Copyright (C) 2013  Timothy Edmund Crosley
 
 Implementation originally from @HappyLeapSecond stack overflow user in response to:
-   https://stackoverflow.com/questions/5967500/how-to-correctly-sort-a-string-with-a-number-inside
+   http://stackoverflow.com/questions/5967500/how-to-correctly-sort-a-string-with-a-number-inside
 
 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 documentation files (the "Software"), to deal in the Software without restriction, including without limitation
diff --git a/isort/pie_slice.py b/isort/pie_slice.py
index 178cf33e..bfb341a7 100644
--- a/isort/pie_slice.py
+++ b/isort/pie_slice.py
@@ -21,8 +21,11 @@ OTHER DEALINGS IN THE SOFTWARE.
 """
 from __future__ import absolute_import
 
+import abc
 import collections
+import functools
 import sys
+from numbers import Integral
 
 __version__ = "1.1.0"
 
@@ -44,7 +47,7 @@ native_object = object
 
 common = ['native_dict', 'native_round', 'native_filter', 'native_map', 'native_range', 'native_str', 'native_chr',
           'native_input', 'PY2', 'PY3', 'u', 'itemsview', 'valuesview', 'keysview', 'execute', 'integer_types',
-          'native_next', 'native_object', 'with_metaclass', 'lru_cache']
+          'native_next', 'native_object', 'with_metaclass', 'OrderedDict', 'lru_cache']
 
 
 def with_metaclass(meta, *bases):
@@ -82,12 +85,32 @@ def unmodified_isinstance(*bases):
 
     """
     class UnmodifiedIsInstance(type):
-        @classmethod
-        def __instancecheck__(cls, instance):
-            if cls.__name__ in (str(base.__name__) for base in bases):
-                return isinstance(instance, bases)
+        if sys.version_info[0] == 2 and sys.version_info[1] <= 6:
+
+            @classmethod
+            def __instancecheck__(cls, instance):
+                if cls.__name__ in (str(base.__name__) for base in bases):
+                    return isinstance(instance, bases)
+
+                subclass = getattr(instance, '__class__', None)
+                subtype = type(instance)
+                instance_type = getattr(abc, '_InstanceType', None)
+                if not instance_type:
+                    class test_object:
+                        pass
+                    instance_type = type(test_object)
+                if subtype is instance_type:
+                    subtype = subclass
+                if subtype is subclass or subclass is None:
+                    return cls.__subclasscheck__(subtype)
+                return (cls.__subclasscheck__(subclass) or cls.__subclasscheck__(subtype))
+        else:
+            @classmethod
+            def __instancecheck__(cls, instance):
+                if cls.__name__ in (str(base.__name__) for base in bases):
+                    return isinstance(instance, bases)
 
-            return type.__instancecheck__(cls, instance)
+                return type.__instancecheck__(cls, instance)
 
     return with_metaclass(UnmodifiedIsInstance, *bases)
 
@@ -125,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 izip as zip  # 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
@@ -257,10 +281,28 @@ else:
             dct['__str__'] = lambda self: self.__unicode__().encode('utf-8')
             return type.__new__(cls, name, bases, dct)
 
-        def __instancecheck__(cls, instance):
-            if cls.__name__ == "object":
-                return isinstance(instance, native_object)
-            return type.__instancecheck__(cls, instance)
+        if sys.version_info[1] <= 6:
+            def __instancecheck__(cls, instance):
+                if cls.__name__ == "object":
+                    return isinstance(instance, native_object)
+
+                subclass = getattr(instance, '__class__', None)
+                subtype = type(instance)
+                instance_type = getattr(abc, '_InstanceType', None)
+                if not instance_type:
+                    class test_object:
+                        pass
+                    instance_type = type(test_object)
+                if subtype is instance_type:
+                    subtype = subclass
+                if subtype is subclass or subclass is None:
+                    return cls.__subclasscheck__(subtype)
+                return (cls.__subclasscheck__(subclass) or cls.__subclasscheck__(subtype))
+        else:
+            def __instancecheck__(cls, instance):
+                if cls.__name__ == "object":
+                    return isinstance(instance, native_object)
+                return type.__instancecheck__(cls, instance)
 
     class object(with_metaclass(FixStr, object)):
         pass
@@ -268,6 +310,138 @@ else:
     __all__ = common + ['round', 'dict', 'apply', 'cmp', 'coerce', 'execfile', 'raw_input', 'unpacks', 'str', 'chr',
                         'input', 'range', 'filter', 'map', 'zip', 'object']
 
+if sys.version_info[0] == 2 and sys.version_info[1] < 7:
+    # OrderedDict
+    # Copyright (c) 2009 Raymond Hettinger
+    #
+    # Permission is hereby granted, free of charge, to any person
+    # obtaining a copy of this software and associated documentation files
+    # (the "Software"), to deal in the Software without restriction,
+    # including without limitation the rights to use, copy, modify, merge,
+    # publish, distribute, sublicense, and/or sell copies of the Software,
+    # and to permit persons to whom the Software is furnished to do so,
+    # subject to the following conditions:
+    #
+    #     The above copyright notice and this permission notice shall be
+    #     included in all copies or substantial portions of the Software.
+    #
+    #     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    #     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+    #     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    #     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+    #     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+    #     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    #     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+    #     OTHER DEALINGS IN THE SOFTWARE.
+
+    from UserDict import DictMixin
+
+    class OrderedDict(dict, DictMixin):
+
+        def __init__(self, *args, **kwds):
+            if len(args) > 1:
+                raise TypeError('expected at most 1 arguments, got %d' % len(args))
+            try:
+                self.__end
+            except AttributeError:
+                self.clear()
+            self.update(*args, **kwds)
+
+        def clear(self):
+            self.__end = end = []
+            end += [None, end, end]         # sentinel node for doubly linked list
+            self.__map = {}                 # key --> [key, prev, next]
+            dict.clear(self)
+
+        def __setitem__(self, key, value):
+            if key not in self:
+                end = self.__end
+                curr = end[1]
+                curr[2] = end[1] = self.__map[key] = [key, curr, end]
+            dict.__setitem__(self, key, value)
+
+        def __delitem__(self, key):
+            dict.__delitem__(self, key)
+            key, prev, next = self.__map.pop(key)
+            prev[2] = next
+            next[1] = prev
+
+        def __iter__(self):
+            end = self.__end
+            curr = end[2]
+            while curr is not end:
+                yield curr[0]
+                curr = curr[2]
+
+        def __reversed__(self):
+            end = self.__end
+            curr = end[1]
+            while curr is not end:
+                yield curr[0]
+                curr = curr[1]
+
+        def popitem(self, last=True):
+            if not self:
+                raise KeyError('dictionary is empty')
+            if last:
+                key = reversed(self).next()
+            else:
+                key = iter(self).next()
+            value = self.pop(key)
+            return key, value
+
+        def __reduce__(self):
+            items = [[k, self[k]] for k in self]
+            tmp = self.__map, self.__end
+            del self.__map, self.__end
+            inst_dict = vars(self).copy()
+            self.__map, self.__end = tmp
+            if inst_dict:
+                return (self.__class__, (items,), inst_dict)
+            return self.__class__, (items,)
+
+        def keys(self):
+            return list(self)
+
+        setdefault = DictMixin.setdefault
+        update = DictMixin.update
+        pop = DictMixin.pop
+        values = DictMixin.values
+        items = DictMixin.items
+        iterkeys = DictMixin.iterkeys
+        itervalues = DictMixin.itervalues
+        iteritems = DictMixin.iteritems
+
+        def __repr__(self):
+            if not self:
+                return '%s()' % (self.__class__.__name__,)
+            return '%s(%r)' % (self.__class__.__name__, self.items())
+
+        def copy(self):
+            return self.__class__(self)
+
+        @classmethod
+        def fromkeys(cls, iterable, value=None):
+            d = cls()
+            for key in iterable:
+                d[key] = value
+            return d
+
+        def __eq__(self, other):
+            if isinstance(other, OrderedDict):
+                if len(self) != len(other):
+                    return False
+                for p, q in zip(self.items(), other.items()):
+                    if p != q:
+                        return False
+                return True
+            return dict.__eq__(self, other)
+
+        def __ne__(self, other):
+            return not self == other
+else:
+    from collections import OrderedDict
+
 
 if sys.version_info < (3, 2):
     try:
@@ -277,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
@@ -289,7 +461,7 @@ if sys.version_info < (3, 2):
         View the cache statistics named tuple (hits, misses, maxsize, currsize) with
         f.cache_info().  Clear the cache and statistics with f.cache_clear().
         Access the underlying function with f.__wrapped__.
-        See: https://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used
+        See:  http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used
 
         """
         def decorating_function(user_function, tuple=tuple, sorted=sorted, len=len, KeyError=KeyError):
@@ -298,7 +470,7 @@ if sys.version_info < (3, 2):
             lock = Lock()
 
             if maxsize is None:
-                CACHE = {}
+                CACHE = dict()
 
                 @wraps(user_function)
                 def wrapper(*args, **kwds):
@@ -316,7 +488,7 @@ if sys.version_info < (3, 2):
                     misses[0] += 1
                     return result
             else:
-                CACHE = collections.OrderedDict()
+                CACHE = OrderedDict()
 
                 @wraps(user_function)
                 def wrapper(*args, **kwds):
@@ -356,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 66155e08..15cdb210 100644
--- a/isort/settings.py
+++ b/isort/settings.py
@@ -25,7 +25,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 from __future__ import absolute_import, division, print_function, unicode_literals
 
 import fnmatch
-import io
 import os
 import posixpath
 from collections import namedtuple
@@ -37,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')
@@ -102,7 +101,6 @@ default = {'force_to_top': [],
            'multi_line_output': WrapModes.GRID,
            'forced_separate': [],
            'indent': ' ' * 4,
-           'comment_prefix': '  #',
            'length_sort': False,
            'add_imports': [],
            'remove_imports': [],
@@ -216,7 +214,7 @@ def _as_list(value):
 
 @lru_cache()
 def _get_config_data(file_path, sections):
-    with io.open(file_path, 'r') as config_file:
+    with open(file_path, 'rU') as config_file:
         if file_path.endswith('.editorconfig'):
             line = '\n'
             last_position = config_file.tell()
@@ -229,7 +227,7 @@ def _get_config_data(file_path, sections):
 
         config = configparser.SafeConfigParser()
         config.readfp(config_file)
-        settings = {}
+        settings = dict()
         for section in sections:
             if config.has_section(section):
                 settings.update(dict(config.items(section)))
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/setup.py b/setup.py
index eb266a34..59008570 100755
--- a/setup.py
+++ b/setup.py
@@ -63,6 +63,7 @@ setup(name='isort',
                    'License :: OSI Approved :: MIT License',
                    'Programming Language :: Python',
                    'Programming Language :: Python :: 2',
+                   'Programming Language :: Python :: 2.6',
                    'Programming Language :: Python :: 2.7',
                    'Programming Language :: Python :: 3',
                    'Programming Language :: Python :: 3.3',
diff --git a/tox.ini b/tox.ini
index 7c70f99e..1ee185be 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,17 +1,22 @@
+# 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 =
     isort-check,
-    py27, py33, py34, py35, py36, pypy,
-    lint
+    py26, py27, py33, py34, py35, py36, pypy
 
 [testenv]
-deps = pytest
-commands = py.test test_isort.py {posargs}
+commands =
+    py.test test_isort.py {posargs}
+deps =
+    six
+    pytest
 
 [testenv:isort-check]
-commands = python setup.py isort
-
-[testenv:lint]
-basepython = python2.7
-deps = flake8==3.3.0
-commands = flake8
+commands =
+    python setup.py isort
+deps =
+    six


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 2b792abd..2114619f 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"
@@ -506,15 +506,6 @@ def test_skip_with_file_name():
     assert skipped
 
 
-def test_skip_within_file():
-    """Ensure skipping a whole file works."""
-    test_input = ("# isort:skip_file\n"
-                  "import django\n"
-                  "import myproject\n")
-
-    assert SortImports(file_contents=test_input, known_third_party=['django']).skipped
-
-
 def test_force_to_top():
     """Ensure forcing a single import to the top of its category works as expected."""
     test_input = ("import lib6\n"
@@ -772,12 +763,10 @@ def test_thirdy_party_overrides_standard_section():
     """Test to ensure changing the default section works as expected."""
     test_input = ("import sys\n"
                   "import os\n"
-                  "import this\n"
                   "import profile.test\n")
     test_output = SortImports(file_contents=test_input, known_third_party=['profile']).output
     assert test_output == ("import os\n"
                            "import sys\n"
-                           "import this\n"
                            "\n"
                            "import profile.test\n")
 
@@ -903,7 +892,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
 
 
@@ -1017,7 +1006,7 @@ def test_settings_combine_instead_of_overwrite():
            set(SortImports().config['known_standard_library'] + ['not_std_library'])
 
     assert set(SortImports(not_known_standard_library=['thread']).config['known_standard_library']) == \
-           {item for item in SortImports().config['known_standard_library'] if item != 'thread'}
+           set(item for item in SortImports().config['known_standard_library'] if item != 'thread')
 
 
 def test_combined_from_and_as_imports():
@@ -1034,8 +1023,8 @@ def test_as_imports_with_line_length():
                   "from translate.storage.placeables import general, parse as rich_parse\n")
     assert SortImports(file_contents=test_input, combine_as_imports=False, line_length=40).output == \
                   ("from translate.storage import \\\n    base as storage_base\n"
-                   "from translate.storage.placeables import \\\n    general\n"
-                   "from translate.storage.placeables import \\\n    parse as rich_parse\n")
+                   "from translate.storage.placeables import \\\n    parse as rich_parse\n"
+                   "from translate.storage.placeables import \\\n    general\n")
 
 
 def test_keep_comments():
@@ -1351,6 +1340,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"
@@ -1635,7 +1625,7 @@ def test_comment_at_top_of_file():
 
 
 def test_alphabetic_sorting():
-    """Test to ensure isort correctly handles top of file comments"""
+    """Test to ensure isort correctly handles single line imports"""
     test_input = ("import unittest\n"
                   "\n"
                   "import ABC\n"
@@ -1803,7 +1793,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'
@@ -2039,7 +2028,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():
@@ -2047,14 +2035,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):
@@ -2079,8 +2068,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():
@@ -2149,53 +2138,8 @@ def test_future_below_encoding_issue_545():
     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
-
-
 def test_long_import_wrap_support_with_mode_2():
     """Test to ensure mode 2 still allows wrapped imports with slash"""
     test_input = ('from foobar.foobar.foobar.foobar import \\\n'
                   '    an_even_longer_function_name_over_80_characters\n')
     assert SortImports(file_contents=test_input, multi_line_output=2, line_length=80).output == test_input
-
-
-def test_pylint_comments_incorrectly_wrapped_issue_571():
-    """Test to ensure pylint comments don't get wrapped"""
-    test_input = ('from PyQt5.QtCore import QRegExp  # @UnresolvedImport pylint: disable=import-error,'
-                  'useless-suppression\n')
-    expected_output = ('from PyQt5.QtCore import \\\n'
-                       '    QRegExp  # @UnresolvedImport pylint: disable=import-error,useless-suppression\n')
-    assert SortImports(file_contents=test_input, line_length=60).output == expected_output
-
-
-def test_ensure_async_methods_work_issue_537():
-    """Test to ensure async methods are correctly identified"""
-    test_input = ('from myapp import myfunction\n'
-                  '\n'
-                  '\n'
-                  'async def test_myfunction(test_client, app):\n'
-                  '    a = await myfunction(test_client, app)\n')
-    assert SortImports(file_contents=test_input).output == test_input
-
-
-def test_ensure_as_imports_sort_correctly_within_from_imports_issue_590():
-    """Test to ensure combination from and as import statements are sorted correct"""
-    test_input = ('from os import defpath\n'
-                  'from os import pathsep as separator\n')
-    assert SortImports(file_contents=test_input, force_sort_within_sections=True).output == test_input
-
-    test_input = ('from os import defpath\n'
-                  'from os import pathsep as separator\n')
-    assert SortImports(file_contents=test_input).output == test_input
-
-    test_input = ('from os import defpath\n'
-                  'from os import pathsep as separator\n')
-    assert SortImports(file_contents=test_input, force_single_line=True).output == test_input