diff options
author | Timothy Edmund Crosley <timothy.crosley@gmail.com> | 2017-04-01 16:20:26 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-01 16:20:26 -0700 |
commit | 9a445f4e6f99411b587903a7b19f411d913bd208 (patch) | |
tree | cd7241e274c04ced67f415edcef1fd3c5f22aea4 | |
parent | 6ac060f80b06bc0472cbf13ca276f8050873d4f3 (diff) | |
parent | 5d62a73b5b3edef073edf5e58c977c89ddd961f4 (diff) | |
download | isort-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.py | 38 | ||||
-rw-r--r-- | test_isort.py | 29 |
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'))) |