Repository: timothycrosley/isort
Pull request #1050 (2019-10-31 18:25:27)

Issue #1051: find extension suffixes from importlib.machinery
Thanks for considering my pull request!

This addresses https://github.com/timothycrosley/isort/issues/1051.

In PR https://github.com/timothycrosley/isort/pull/813 earlier this year, I tried to solve a problem with loading compiled extensions by populating an `ext_suffix` instance variable. While my solution worked for OS X and Linux, it unfortunately didn’t work for Windows, where compiled libraries will end with `.pyd` or with an architecture string and `.pyd`.

This PR changes the behavior to use the extension suffixes from Python’s `importlib.machinery` directly.


Patch:
diff --git a/isort/finders.py b/isort/finders.py
index 4ba20314..dda24dfb 100644
--- a/isort/finders.py
+++ b/isort/finders.py
@@ -1,4 +1,5 @@
 """Finders try to find right section for passed module name"""
+import importlib.machinery
 import inspect
 import os
 import os.path
@@ -162,9 +163,6 @@ class PathFinder(BaseFinder):
         if self.stdlib_lib_prefix not in self.paths:
             self.paths.append(self.stdlib_lib_prefix)
 
-        # handle compiled libraries
-        self.ext_suffix = sysconfig.get_config_var("EXT_SUFFIX") or ".so"
-
         # add system paths
         for path in sys.path[1:]:
             if path not in self.paths:
@@ -175,8 +173,10 @@ class PathFinder(BaseFinder):
             package_path = "/".join((prefix, module_name.split(".")[0]))
             is_module = (
                 exists_case_sensitive(package_path + ".py")
-                or exists_case_sensitive(package_path + ".so")
-                or exists_case_sensitive(package_path + self.ext_suffix)
+                or any(
+                    exists_case_sensitive(package_path + ext_suffix)
+                    for ext_suffix in importlib.machinery.EXTENSION_SUFFIXES
+                )
                 or exists_case_sensitive(package_path + "/__init__.py")
             )
             is_package = exists_case_sensitive(package_path) and os.path.isdir(package_path)


Test patch:
diff --git a/tests/test_isort.py b/tests/test_isort.py
index dcc65b53..3e85b15a 100644
--- a/tests/test_isort.py
+++ b/tests/test_isort.py
@@ -2,6 +2,7 @@
 
 Should be ran using py.test by simply running py.test in the isort project directory
 """
+import importlib.machinery
 import os
 import os.path
 import posixpath
@@ -3098,21 +3099,27 @@ def test_path_finder(monkeypatch) -> None:
     si = SortImports(file_contents="")
     finder = finders.PathFinder(config=si.config, sections=si.sections)
     third_party_prefix = next(path for path in finder.paths if "site-packages" in path)
-    ext_suffix = sysconfig.get_config_var("EXT_SUFFIX") or ".so"
-    imaginary_paths = {
-        posixpath.join(finder.stdlib_lib_prefix, "example_1.py"),
-        posixpath.join(third_party_prefix, "example_2.py"),
-        posixpath.join(third_party_prefix, "example_3.so"),
-        posixpath.join(third_party_prefix, "example_4" + ext_suffix),
-        posixpath.join(os.getcwd(), "example_5.py"),
-    }
+    ext_suffixes = importlib.machinery.EXTENSION_SUFFIXES
+    imaginary_paths = set(
+        [
+            posixpath.join(finder.stdlib_lib_prefix, "example_1.py"),
+            posixpath.join(third_party_prefix, "example_2.py"),
+            posixpath.join(os.getcwd(), "example_3.py"),
+        ]
+    )
+    imaginary_paths.update(
+        {
+            posixpath.join(third_party_prefix, "example_" + str(i) + ext_suffix)
+            for i, ext_suffix in enumerate(ext_suffixes, 4)
+        }
+    )
 
     monkeypatch.setattr("isort.finders.exists_case_sensitive", lambda p: p in imaginary_paths)
     assert finder.find("example_1") == finder.sections.STDLIB
     assert finder.find("example_2") == finder.sections.THIRDPARTY
-    assert finder.find("example_3") == finder.sections.THIRDPARTY
-    assert finder.find("example_4") == finder.sections.THIRDPARTY
-    assert finder.find("example_5") == finder.sections.FIRSTPARTY
+    assert finder.find("example_3") == finder.sections.FIRSTPARTY
+    for i, _ in enumerate(ext_suffixes, 4):
+        assert finder.find("example_" + str(i)) == finder.sections.THIRDPARTY
 
 
 def test_argument_parsing() -> None: