Skip to content

bpo-38010 Sync importlib.metadata with importlib_metadata 0.20. #15646

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Doc/library/importlib.metadata.rst
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,13 @@ Once you have the file, you can also read its contents::
return s.encode('utf-8')
return s

In the case where the metadata file listing files
(RECORD or SOURCES.txt) is missing, ``files()`` will
return ``None``. The caller may wish to wrap calls to
``files()`` in `always_iterable
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.always_iterable>`_
or otherwise guard against this condition if the target
distribution is not known to have the metadata present.

.. _requirements:

Expand Down
18 changes: 15 additions & 3 deletions Lib/importlib/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,15 @@ def entry_points(self):

@property
def files(self):
"""Files in this distribution.

:return: Iterable 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
missing.
Result may be empty if the metadata exists but is empty.
"""
file_lines = self._read_files_distinfo() or self._read_files_egginfo()

def make_file(name, hash=None, size_str=None):
Expand Down Expand Up @@ -245,8 +254,7 @@ def requires(self):
return self._read_dist_info_reqs() or self._read_egg_info_reqs()

def _read_dist_info_reqs(self):
spec = self.metadata['Requires-Dist']
return spec and filter(None, spec.splitlines())
return self.metadata.get_all('Requires-Dist')

def _read_egg_info_reqs(self):
source = self.read_text('requires.txt')
Expand Down Expand Up @@ -318,7 +326,11 @@ def find_distributions(self, name=None, path=None):

class PathDistribution(Distribution):
def __init__(self, path):
"""Construct a distribution from a path to the metadata directory."""
"""Construct a distribution from a path to the metadata directory.

:param path: A pathlib.Path or similar object supporting
.joinpath(), __div__, .parent, and .read_text().
"""
self._path = path

def read_text(self, filename):
Expand Down
2 changes: 2 additions & 0 deletions Lib/test/test_importlib/test_metadata_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ def test_requires(self):
def test_requires_dist_info(self):
deps = list(requires('distinfo-pkg'))
assert deps and all(deps)
assert 'wheel >= 1.0' in deps
assert "pytest; extra == 'test'" in deps

def test_more_complex_deps_requires_text(self):
requires = textwrap.dedent("""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
In ``importlib.metadata`` sync with ``importlib_metadata`` 0.20, clarifying behavior of ``files()`` and fixing issue where only one requirement was returned for ``requires()`` on ``dist-info`` packages.