summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy Edmund Crosley <timothy.crosley@gmail.com>2017-04-01 16:20:26 -0700
committerGitHub <noreply@github.com>2017-04-01 16:20:26 -0700
commit9a445f4e6f99411b587903a7b19f411d913bd208 (patch)
treecd7241e274c04ced67f415edcef1fd3c5f22aea4
parent6ac060f80b06bc0472cbf13ca276f8050873d4f3 (diff)
parent5d62a73b5b3edef073edf5e58c977c89ddd961f4 (diff)
downloadisort-9a445f4e6f99411b587903a7b19f411d913bd208.tar.gz
Merge pull request #465 from ESSS/stdlib-prefix-issue-464
Place modules found in sys.prefix/lib in stdlib section
-rw-r--r--isort/isort.py38
-rw-r--r--test_isort.py29
2 files changed, 63 insertions, 4 deletions
diff --git a/isort/isort.py b/isort/isort.py
index 0c8b9fdf..ea5402e8 100644
--- a/isort/isort.py
+++ b/isort/isort.py
@@ -251,15 +251,20 @@ class SortImports(object):
paths += [path for path in glob('{0}/src/*'.format(virtual_env)) if os.path.isdir(path)]
virtual_env_src = '{0}/src/'.format(virtual_env)
+ # handle case-insensitive paths on windows
+ stdlib_lib_prefix = os.path.normcase(get_stdlib_path())
+
for prefix in paths:
module_path = "/".join((prefix, module_name.replace(".", "/")))
package_path = "/".join((prefix, module_name.split(".")[0]))
- if (os.path.exists(module_path + ".py") or os.path.exists(module_path + ".so") or
- (os.path.exists(package_path) and os.path.isdir(package_path))):
+ is_module = (exists_case_sensitive(module_path + ".py") or
+ exists_case_sensitive(module_path + ".so"))
+ is_package = exists_case_sensitive(package_path) and os.path.isdir(package_path)
+ if is_module or is_package:
if ('site-packages' in prefix or 'dist-packages' in prefix or
(virtual_env and virtual_env_src in prefix)):
return self.sections.THIRDPARTY
- elif 'python2' in prefix.lower() or 'python3' in prefix.lower():
+ elif os.path.normcase(prefix).startswith(stdlib_lib_prefix):
return self.sections.STDLIB
else:
return self.config['default_section']
@@ -898,3 +903,30 @@ def coding_check(fname, default='utf-8'):
break
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.
+
+ When finding files that can be imported, it is important for the cases to match because while
+ file os.path.exists("module.py") and os.path.exists("MODULE.py") both return True on Windows, Python
+ can only import using the case of the real file.
+ """
+ result = os.path.exists(path)
+ if sys.platform.startswith('win') and result:
+ directory, basename = os.path.split(path)
+ result = basename in os.listdir(directory)
+ return result
diff --git a/test_isort.py b/test_isort.py
index 07efcd82..c0e13e9d 100644
--- a/test_isort.py
+++ b/test_isort.py
@@ -28,7 +28,7 @@ import os
import shutil
import tempfile
-from isort.isort import SortImports
+from isort.isort import exists_case_sensitive, SortImports
from isort.pie_slice import *
from isort.settings import WrapModes
@@ -1830,3 +1830,30 @@ def test_plone_style():
options = {'force_single_line': True,
'force_alphabetical_sort': True}
assert SortImports(file_contents=test_input, **options).output == test_input
+
+
+def test_third_party_case_sensitive():
+ """Modules which match builtins by name but not on case should not be picked up on Windows."""
+ test_input = ("import thirdparty\n"
+ "import os\n"
+ "import ABC\n")
+
+ expected_output = ('import os\n'
+ '\n'
+ 'import ABC\n'
+ 'import thirdparty\n')
+ assert SortImports(file_contents=test_input).output == expected_output
+
+
+def test_exists_case_sensitive_file(tmpdir):
+ """Test exists_case_sensitive function for a file."""
+ tmpdir.join('module.py').ensure(file=1)
+ assert exists_case_sensitive(str(tmpdir.join('module.py')))
+ assert not exists_case_sensitive(str(tmpdir.join('MODULE.py')))
+
+
+def test_exists_case_sensitive_directory(tmpdir):
+ """Test exists_case_sensitive function for a directory."""
+ tmpdir.join('pkg').ensure(dir=1)
+ assert exists_case_sensitive(str(tmpdir.join('pkg')))
+ assert not exists_case_sensitive(str(tmpdir.join('PKG')))