summaryrefslogtreecommitdiffstats
path: root/Lib/importlib/metadata.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/importlib/metadata.py')
-rw-r--r--Lib/importlib/metadata.py63
1 files changed, 51 insertions, 12 deletions
diff --git a/Lib/importlib/metadata.py b/Lib/importlib/metadata.py
index 3b46142..e230766 100644
--- a/Lib/importlib/metadata.py
+++ b/Lib/importlib/metadata.py
@@ -19,6 +19,7 @@ from itertools import starmap
__all__ = [
'Distribution',
+ 'DistributionFinder',
'PackageNotFoundError',
'distribution',
'distributions',
@@ -158,7 +159,7 @@ class Distribution:
metadata cannot be found.
"""
for resolver in cls._discover_resolvers():
- dists = resolver(name)
+ dists = resolver(DistributionFinder.Context(name=name))
dist = next(dists, None)
if dist is not None:
return dist
@@ -166,17 +167,34 @@ class Distribution:
raise PackageNotFoundError(name)
@classmethod
- def discover(cls):
+ def discover(cls, **kwargs):
"""Return an iterable of Distribution objects for all packages.
+ Pass a ``context`` or pass keyword arguments for constructing
+ a context.
+
+ :context: A ``DistributionFinder.Context`` object.
:return: Iterable of Distribution objects for all packages.
"""
+ context = kwargs.pop('context', None)
+ if context and kwargs:
+ raise ValueError("cannot accept context and kwargs")
+ context = context or DistributionFinder.Context(**kwargs)
return itertools.chain.from_iterable(
- resolver()
+ resolver(context)
for resolver in cls._discover_resolvers()
)
@staticmethod
+ def at(path):
+ """Return a Distribution for the indicated metadata path
+
+ :param path: a string or path-like object
+ :return: a concrete Distribution instance for the path
+ """
+ return PathDistribution(pathlib.Path(path))
+
+ @staticmethod
def _discover_resolvers():
"""Search the meta_path for resolvers."""
declared = (
@@ -215,7 +233,7 @@ class Distribution:
def files(self):
"""Files in this distribution.
- :return: Iterable of PackagePath for this distribution or None
+ :return: List of PackagePath for this distribution or None
Result is `None` if the metadata file that enumerates files
(i.e. RECORD for dist-info or SOURCES.txt for egg-info) is
@@ -231,7 +249,7 @@ class Distribution:
result.dist = self
return result
- return file_lines and starmap(make_file, csv.reader(file_lines))
+ return file_lines and list(starmap(make_file, csv.reader(file_lines)))
def _read_files_distinfo(self):
"""
@@ -251,7 +269,8 @@ class Distribution:
@property
def requires(self):
"""Generated requirements specified for this Distribution"""
- return self._read_dist_info_reqs() or self._read_egg_info_reqs()
+ reqs = self._read_dist_info_reqs() or self._read_egg_info_reqs()
+ return reqs and list(reqs)
def _read_dist_info_reqs(self):
return self.metadata.get_all('Requires-Dist')
@@ -312,15 +331,35 @@ class DistributionFinder(MetaPathFinder):
A MetaPathFinder capable of discovering installed distributions.
"""
+ class Context:
+
+ name = None
+ """
+ Specific name for which a distribution finder should match.
+ """
+
+ def __init__(self, **kwargs):
+ vars(self).update(kwargs)
+
+ @property
+ def path(self):
+ """
+ The path that a distribution finder should search.
+ """
+ return vars(self).get('path', sys.path)
+
+ @property
+ def pattern(self):
+ return '.*' if self.name is None else re.escape(self.name)
+
@abc.abstractmethod
- def find_distributions(self, name=None, path=None):
+ def find_distributions(self, context=Context()):
"""
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).
+ loading the metadata for packages matching the ``context``,
+ a DistributionFinder.Context instance.
"""
@@ -352,12 +391,12 @@ def distribution(package):
return Distribution.from_name(package)
-def distributions():
+def distributions(**kwargs):
"""Get all ``Distribution`` instances in the current environment.
:return: An iterable of ``Distribution`` instances.
"""
- return Distribution.discover()
+ return Distribution.discover(**kwargs)
def metadata(package):