Skip to content

Commit

Permalink
Update WorkingSet.find to consider standardised .dist-info directory …
Browse files Browse the repository at this point in the history
…names (#4856)
  • Loading branch information
abravalheri committed Feb 26, 2025
2 parents 56c055b + edca181 commit c0f39c0
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 6 deletions.
2 changes: 2 additions & 0 deletions newsfragments/4856.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fixed ``pkg_resources.require(...)`` to also consider standardised
``dist-info`` directories.
17 changes: 11 additions & 6 deletions pkg_resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -708,14 +708,19 @@ def find(self, req: Requirement) -> Distribution | None:
If there is no active distribution for the requested project, ``None``
is returned.
"""
dist = self.by_key.get(req.key)
dist: Distribution | None = None

if dist is None:
canonical_key = self.normalized_to_canonical_keys.get(req.key)
candidates = (
req.key,
self.normalized_to_canonical_keys.get(req.key),
safe_name(req.key).replace(".", "-"),
)

if canonical_key is not None:
req.key = canonical_key
dist = self.by_key.get(canonical_key)
for candidate in filter(None, candidates):
dist = self.by_key.get(candidate)
if dist:
req.key = candidate
break

if dist is not None and dist not in req:
# XXX add more info
Expand Down
58 changes: 58 additions & 0 deletions pkg_resources/tests/test_pkg_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import builtins
import datetime
import inspect
import os
import plistlib
import stat
Expand Down Expand Up @@ -425,3 +426,60 @@ def test_normalize_path_backslash_sep(self, unnormalized, expected):
"""Ensure path seps are cleaned on backslash path sep systems."""
result = pkg_resources.normalize_path(unnormalized)
assert result.endswith(expected)


class TestWorkdirRequire:
def fake_site_packages(self, tmp_path, monkeypatch, dist_files):
site_packages = tmp_path / "site-packages"
site_packages.mkdir()
for file, content in self.FILES.items():
path = site_packages / file
path.parent.mkdir(exist_ok=True, parents=True)
path.write_text(inspect.cleandoc(content), encoding="utf-8")

monkeypatch.setattr(sys, "path", [site_packages])
return os.fspath(site_packages)

FILES = {
"pkg1_mod-1.2.3.dist-info/METADATA": """
Metadata-Version: 2.4
Name: pkg1.mod
Version: 1.2.3
""",
"pkg2.mod-0.42.dist-info/METADATA": """
Metadata-Version: 2.1
Name: pkg2.mod
Version: 0.42
""",
"pkg3_mod.egg-info/PKG-INFO": """
Name: pkg3.mod
Version: 1.2.3.4
""",
"pkg4.mod.egg-info/PKG-INFO": """
Name: pkg4.mod
Version: 0.42.1
""",
}

@pytest.mark.parametrize(
("version", "requirement"),
[
("1.2.3", "pkg1.mod>=1"),
("0.42", "pkg2.mod>=0.4"),
("1.2.3.4", "pkg3.mod<=2"),
("0.42.1", "pkg4.mod>0.2,<1"),
],
)
def test_require_non_normalised_name(
self, tmp_path, monkeypatch, version, requirement
):
# https://github.com/pypa/setuptools/issues/4853
site_packages = self.fake_site_packages(tmp_path, monkeypatch, self.FILES)
ws = pkg_resources.WorkingSet([site_packages])

for req in [requirement, requirement.replace(".", "-")]:
[dist] = ws.require(req)
assert dist.version == version
assert os.path.samefile(
os.path.commonpath([dist.location, site_packages]), site_packages
)

0 comments on commit c0f39c0

Please sign in to comment.