summaryrefslogtreecommitdiffstats
path: root/Lib/importlib/_bootstrap_external.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/importlib/_bootstrap_external.py')
-rw-r--r--Lib/importlib/_bootstrap_external.py52
1 files changed, 52 insertions, 0 deletions
diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py
index 7da0cd0..9b5db81 100644
--- a/Lib/importlib/_bootstrap_external.py
+++ b/Lib/importlib/_bootstrap_external.py
@@ -1363,6 +1363,58 @@ class PathFinder:
return None
return spec.loader
+ search_template = r'(?:{pattern}(-.*)?\.(dist|egg)-info|EGG-INFO)'
+
+ @classmethod
+ def find_distributions(cls, name=None, path=None):
+ """
+ Find distributions.
+
+ Return an iterable of all Distribution instances capable of
+ loading the metadata for packages matching the ``name``
+ (or all names if not supplied) along the paths in the list
+ of directories ``path`` (defaults to sys.path).
+ """
+ import re
+ from importlib.metadata import PathDistribution
+ if path is None:
+ path = sys.path
+ pattern = '.*' if name is None else re.escape(name)
+ found = cls._search_paths(pattern, path)
+ return map(PathDistribution, found)
+
+ @classmethod
+ def _search_paths(cls, pattern, paths):
+ """Find metadata directories in paths heuristically."""
+ import itertools
+ return itertools.chain.from_iterable(
+ cls._search_path(path, pattern)
+ for path in map(cls._switch_path, paths)
+ )
+
+ @staticmethod
+ def _switch_path(path):
+ from contextlib import suppress
+ import zipfile
+ from pathlib import Path
+ with suppress(Exception):
+ return zipfile.Path(path)
+ return Path(path)
+
+ @classmethod
+ def _predicate(cls, pattern, root, item):
+ import re
+ return re.match(pattern, str(item.name), flags=re.IGNORECASE)
+
+ @classmethod
+ def _search_path(cls, root, pattern):
+ if not root.is_dir():
+ return ()
+ normalized = pattern.replace('-', '_')
+ matcher = cls.search_template.format(pattern=normalized)
+ return (item for item in root.iterdir()
+ if cls._predicate(matcher, root, item))
+
class FileFinder: