bpo-34632: Add importlib.metadata (GH-12547)

Add importlib.metadata module as forward port of the standalone importlib_metadata.
This commit is contained in:
Jason R. Coombs 2019-05-24 19:59:01 -04:00 committed by Barry Warsaw
parent 6dbbe748e1
commit 1bbf7b661f
15 changed files with 2049 additions and 639 deletions

View file

@ -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: