Inline the find_distributions functionality on PathFinder.

This commit is contained in:
Jason R. Coombs 2019-05-10 14:55:40 -04:00
parent 58533a71b2
commit 3b19b9d823
4 changed files with 822 additions and 693 deletions

View file

@ -1359,6 +1359,57 @@ class PathFinder:
return None
return spec.loader
search_template = r'{pattern}(-.*)?\.(dist|egg)-info'
@classmethod
def find_distributions(cls, name=None, path=None):
"""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._hooks 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:

View file

@ -1,12 +1,8 @@
import re
import sys
import zipfile
import itertools
from .api import Distribution
from .abc import DistributionFinder
from contextlib import suppress
from pathlib import Path
def install(cls):
@ -25,57 +21,6 @@ class NullFinder(DistributionFinder):
return None
@install
class MetadataPathFinder(NullFinder):
"""A degenerate finder for distribution packages on the file system.
This finder supplies only a find_distributions() method for versions
of Python that do not have a PathFinder find_distributions().
"""
search_template = r'{pattern}(-.*)?\.(dist|egg)-info'
def find_distributions(self, name=None, path=None):
"""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).
"""
if path is None:
path = sys.path
pattern = '.*' if name is None else re.escape(name)
found = self._search_paths(pattern, path)
return map(PathDistribution, found)
@classmethod
def _search_paths(cls, pattern, paths):
"""
Find metadata directories in paths heuristically.
"""
return itertools.chain.from_iterable(
cls._search_path(path, pattern)
for path in map(cls._switch_path, paths)
)
@staticmethod
def _switch_path(path):
with suppress(Exception):
return zipfile.Path(path)
return Path(path)
@classmethod
def _predicate(cls, pattern, root, item):
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 PathDistribution(Distribution):
def __init__(self, path):
"""Construct a distribution from a path to the metadata directory."""

View file

@ -7,7 +7,7 @@ import importlib
from . import fixtures
from importlib.metadata import (
Distribution, PackageNotFoundError, _hooks, api, distributions,
Distribution, PackageNotFoundError, api, distributions,
entry_points, metadata, version)
@ -25,7 +25,6 @@ class BasicTests(fixtures.DistInfoPkg, unittest.TestCase):
def test_new_style_classes(self):
self.assertIsInstance(Distribution, type)
self.assertIsInstance(_hooks.MetadataPathFinder, type)
class ImportTests(fixtures.DistInfoPkg, unittest.TestCase):

File diff suppressed because it is too large Load diff