Commit 8ed6503e authored by Jason R. Coombs's avatar Jason R. Coombs Committed by Paul Ganssle

bpo-38121: Sync importlib.metadata with 0.22 backport (GH-15993)

* bpo-38121: Sync importlib.metadata with 0.22 backport

* 📜🤖 Added by blurb_it.
parent 421a72af
...@@ -1370,7 +1370,7 @@ class PathFinder: ...@@ -1370,7 +1370,7 @@ class PathFinder:
return spec.loader return spec.loader
@classmethod @classmethod
def find_distributions(self, context=None): def find_distributions(cls, *args, **kwargs):
""" """
Find distributions. Find distributions.
...@@ -1379,54 +1379,8 @@ class PathFinder: ...@@ -1379,54 +1379,8 @@ class PathFinder:
(or all names if ``None`` indicated) along the paths in the list (or all names if ``None`` indicated) along the paths in the list
of directories ``context.path``. of directories ``context.path``.
""" """
from importlib.metadata import PathDistribution, DistributionFinder from importlib.metadata import MetadataPathFinder
if context is None: return MetadataPathFinder.find_distributions(*args, **kwargs)
context = DistributionFinder.Context()
found = self._search_paths(context.pattern, context.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
import pathlib
PYPY_OPEN_BUG = False
if not PYPY_OPEN_BUG or os.path.isfile(path): # pragma: no branch
with suppress(Exception):
return zipfile.Path(path)
return pathlib.Path(path)
@classmethod
def _matches_info(cls, normalized, item):
import re
template = r'{pattern}(-.*)?\.(dist|egg)-info'
manifest = template.format(pattern=normalized)
return re.match(manifest, item.name, flags=re.IGNORECASE)
@classmethod
def _matches_legacy(cls, normalized, item):
import re
template = r'{pattern}-.*\.egg[\\/]EGG-INFO'
manifest = template.format(pattern=normalized)
return re.search(manifest, str(item), flags=re.IGNORECASE)
@classmethod
def _search_path(cls, root, pattern):
if not root.is_dir():
return ()
normalized = pattern.replace('-', '_')
return (item for item in root.iterdir()
if cls._matches_info(normalized, item)
or cls._matches_legacy(normalized, item))
class FileFinder: class FileFinder:
......
import io import io
import os
import re import re
import abc import abc
import csv import csv
import sys import sys
import email import email
import pathlib import pathlib
import zipfile
import operator import operator
import functools import functools
import itertools import itertools
...@@ -363,6 +365,58 @@ class DistributionFinder(MetaPathFinder): ...@@ -363,6 +365,58 @@ class DistributionFinder(MetaPathFinder):
""" """
class MetadataPathFinder(DistributionFinder):
@classmethod
def find_distributions(cls, context=DistributionFinder.Context()):
"""
Find distributions.
Return an iterable of all Distribution instances capable of
loading the metadata for packages matching ``context.name``
(or all names if ``None`` indicated) along the paths in the list
of directories ``context.path``.
"""
found = cls._search_paths(context.pattern, context.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):
PYPY_OPEN_BUG = False
if not PYPY_OPEN_BUG or os.path.isfile(path): # pragma: no branch
with suppress(Exception):
return zipfile.Path(path)
return pathlib.Path(path)
@classmethod
def _matches_info(cls, normalized, item):
template = r'{pattern}(-.*)?\.(dist|egg)-info'
manifest = template.format(pattern=normalized)
return re.match(manifest, item.name, flags=re.IGNORECASE)
@classmethod
def _matches_legacy(cls, normalized, item):
template = r'{pattern}-.*\.egg[\\/]EGG-INFO'
manifest = template.format(pattern=normalized)
return re.search(manifest, str(item), flags=re.IGNORECASE)
@classmethod
def _search_path(cls, root, pattern):
if not root.is_dir():
return ()
normalized = pattern.replace('-', '_')
return (item for item in root.iterdir()
if cls._matches_info(normalized, item)
or cls._matches_legacy(normalized, item))
class PathDistribution(Distribution): class PathDistribution(Distribution):
def __init__(self, path): def __init__(self, path):
"""Construct a distribution from a path to the metadata directory. """Construct a distribution from a path to the metadata directory.
...@@ -382,13 +436,13 @@ class PathDistribution(Distribution): ...@@ -382,13 +436,13 @@ class PathDistribution(Distribution):
return self._path.parent / path return self._path.parent / path
def distribution(package): def distribution(distribution_name):
"""Get the ``Distribution`` instance for the given package. """Get the ``Distribution`` instance for the named package.
:param package: The name of the package as a string. :param distribution_name: The name of the distribution package as a string.
:return: A ``Distribution`` instance (or subclass thereof). :return: A ``Distribution`` instance (or subclass thereof).
""" """
return Distribution.from_name(package) return Distribution.from_name(distribution_name)
def distributions(**kwargs): def distributions(**kwargs):
...@@ -399,23 +453,23 @@ def distributions(**kwargs): ...@@ -399,23 +453,23 @@ def distributions(**kwargs):
return Distribution.discover(**kwargs) return Distribution.discover(**kwargs)
def metadata(package): def metadata(distribution_name):
"""Get the metadata for the package. """Get the metadata for the named package.
:param package: The name of the distribution package to query. :param distribution_name: The name of the distribution package to query.
:return: An email.Message containing the parsed metadata. :return: An email.Message containing the parsed metadata.
""" """
return Distribution.from_name(package).metadata return Distribution.from_name(distribution_name).metadata
def version(package): def version(distribution_name):
"""Get the version string for the named package. """Get the version string for the named package.
:param package: The name of the distribution package to query. :param distribution_name: The name of the distribution package to query.
:return: The version string for the package as defined in the package's :return: The version string for the package as defined in the package's
"Version" metadata key. "Version" metadata key.
""" """
return distribution(package).version return distribution(distribution_name).version
def entry_points(): def entry_points():
...@@ -434,15 +488,20 @@ def entry_points(): ...@@ -434,15 +488,20 @@ def entry_points():
} }
def files(package): def files(distribution_name):
return distribution(package).files """Return a list of files for the named package.
:param distribution_name: The name of the distribution package to query.
:return: List of files composing the distribution.
"""
return distribution(distribution_name).files
def requires(package): def requires(distribution_name):
""" """
Return a list of requirements for the indicated distribution. Return a list of requirements for the named package.
:return: An iterator of requirements, suitable for :return: An iterator of requirements, suitable for
packaging.requirement.Requirement. packaging.requirement.Requirement.
""" """
return distribution(package).requires return distribution(distribution_name).requires
Update parameter names on functions in importlib.metadata matching the changes in the 0.22 release of importlib_metadata.
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment