Repository: timothycrosley/isort
Pull request #524 (2017-05-28 12:28:25)

Add support for glob in known modules listings.


Patch:
diff --git a/isort/isort.py b/isort/isort.py
index 8b237603..9c1241de 100644
--- a/isort/isort.py
+++ b/isort/isort.py
@@ -131,6 +131,14 @@ class SortImports(object):
         for section in itertools.chain(self.sections, self.config['forced_separate']):
             self.imports[section] = {'straight': set(), 'from': {}}
 
+        self.known_patterns = []
+        for placement in reversed(self.sections):
+            known_placement = KNOWN_SECTION_MAPPING.get(placement, placement)
+            config_key = 'known_{0}'.format(known_placement.lower())
+            known_patterns = self.config.get(config_key, [])
+            for known_pattern in known_patterns:
+                self.known_patterns.append((re.compile('^' + known_pattern.replace('*', '.*').replace('?', '.?') + '$'), placement))
+
         self.index = 0
         self.import_index = -1
         self._first_comment_index_start = -1
@@ -235,10 +243,8 @@ class SortImports(object):
         parts = module_name.split('.')
         module_names_to_check = ['.'.join(parts[:first_k]) for first_k in range(len(parts), 0, -1)]
         for module_name_to_check in module_names_to_check:
-            for placement in reversed(self.sections):
-                known_placement = KNOWN_SECTION_MAPPING.get(placement, placement)
-                config_key = 'known_{0}'.format(known_placement.lower())
-                if module_name_to_check in self.config.get(config_key, []):
+            for pattern, placement in self.known_patterns:
+                if pattern.match(module_name_to_check):
                     return placement
 
         # Use a copy of sys.path to avoid any unintended modifications


Test patch:
diff --git a/test_isort.py b/test_isort.py
index a757080d..e50256d0 100644
--- a/test_isort.py
+++ b/test_isort.py
@@ -1411,6 +1411,38 @@ def test_custom_sections():
                            "import p24.shared.media_wiki_syntax as syntax\n")
 
 
+def test_glob_known():
+    """Ensure that most specific placement control match wins"""
+    test_input = ("import os\n"
+                  "from django_whatever import whatever\n"
+                  "import sys\n"
+                  "from django.conf import settings\n"
+                  "from . import another\n")
+    test_output = SortImports(file_contents=test_input,
+                import_heading_stdlib='Standard Library',
+                import_heading_thirdparty='Third Party',
+                import_heading_firstparty='First Party',
+                import_heading_django='Django',
+                import_heading_djangoplugins='Django Plugins',
+                import_heading_localfolder='Local',
+                known_django=['django'],
+                known_djangoplugins=['django_*'],
+                default_section="THIRDPARTY",
+                sections=["FUTURE", "STDLIB", "DJANGO", "DJANGOPLUGINS", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"]).output
+    assert test_output == ("# Standard Library\n"
+                           "import os\n"
+                           "import sys\n"
+                           "\n"
+                           "# Django\n"
+                           "from django.conf import settings\n"
+                           "\n"
+                           "# Django Plugins\n"
+                           "from django_whatever import whatever\n"
+                           "\n"
+                           "# Local\n"
+                           "from . import another\n")
+
+
 def test_sticky_comments():
     """Test to ensure it is possible to make comments 'stick' above imports"""
     test_input = ("import os\n"