Skip to content
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

Infer top-level names for a package #340

Merged
merged 5 commits into from Aug 26, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGES.rst
@@ -1,3 +1,10 @@
v4.7.0
======

* #330: In ``packages_distributions``, now infer top-level
names from ``.files()`` when a ``top-level.txt``
(Setuptools-specific metadata) is not present.

v4.6.4
======

Expand Down
14 changes: 13 additions & 1 deletion importlib_metadata/__init__.py
Expand Up @@ -1013,6 +1013,18 @@ def packages_distributions() -> Mapping[str, List[str]]:
"""
pkg_to_dist = collections.defaultdict(list)
for dist in distributions():
for pkg in (dist.read_text('top_level.txt') or '').split():
for pkg in _top_level_declared(dist) or _top_level_inferred(dist):
pkg_to_dist[pkg].append(dist.metadata['Name'])
return dict(pkg_to_dist)


def _top_level_declared(dist):
return (dist.read_text('top_level.txt') or '').split()


def _top_level_inferred(dist):
return {
f.parts[0] if len(f.parts) > 1 else f.with_suffix('').name
for f in dist.files
Copy link

@harupy harupy Aug 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @jaraco, does this line throw when dist.files returns None? In our repo, we observed an issue that seems related to this line:

https://github.com/mlflow/mlflow/runs/3428616955#step:5:7078

  File "/miniconda/lib/python3.9/site-packages/importlib_metadata/__init__.py", line 1016, in packages_distributions
    for pkg in _top_level_declared(dist) or _top_level_inferred(dist):
  File "/miniconda/lib/python3.9/site-packages/importlib_metadata/__init__.py", line 1026, in _top_level_inferred
    return {
TypeError: 'NoneType' object is not iterable

if f.suffix == ".py"
}
2 changes: 2 additions & 0 deletions prepare/example2/example2/__init__.py
@@ -0,0 +1,2 @@
def main():
return "example"
10 changes: 10 additions & 0 deletions prepare/example2/pyproject.toml
@@ -0,0 +1,10 @@
[build-system]
build-backend = 'trampolim'
requires = ['trampolim']

[project]
name = 'example2'
version = '1.0.0'

[project.scripts]
example = 'example2:main'
Binary file added tests/data/example2-1.0.0-py3-none-any.whl
Binary file not shown.
2 changes: 1 addition & 1 deletion tests/fixtures.py
Expand Up @@ -301,7 +301,7 @@ class ZipFixtures:
def _fixture_on_path(self, filename):
pkg_file = resources.files(self.root).joinpath(filename)
file = self.resources.enter_context(resources.as_file(pkg_file))
assert file.name.startswith('example-'), file.name
assert file.name.startswith('example'), file.name
sys.path.insert(0, str(file))
self.resources.callback(sys.path.pop, 0)

Expand Down
15 changes: 15 additions & 0 deletions tests/test_main.py
Expand Up @@ -17,6 +17,7 @@
distributions,
entry_points,
metadata,
packages_distributions,
version,
)

Expand Down Expand Up @@ -282,3 +283,17 @@ def test_unicode_dir_on_sys_path(self):
prefix=self.site_dir,
)
list(distributions())


class PackagesDistributionsTest(fixtures.ZipFixtures, unittest.TestCase):
def test_packages_distributions_example(self):
self._fixture_on_path('example-21.12-py3-none-any.whl')
assert packages_distributions()['example'] == ['example']

def test_packages_distributions_example2(self):
"""
Test packages_distributions on a wheel built
by trampolim.
"""
self._fixture_on_path('example2-1.0.0-py3-none-any.whl')
assert packages_distributions()['example2'] == ['example2']