Skip to content

Commit c260ecc

Browse files
authored
Merge pull request #11217 from uranusjr/importlib-metadata-ignore-dist-info-in-wheel
2 parents 06f79b8 + 6eaa8e9 commit c260ecc

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed

news/11217.bugfix.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Do not consider a ``.dist-info`` directory found inside a wheel-like zip file
2+
as metadata for an installed distribution. A package in a wheel is (by
3+
definition) not installed, and is not guaranteed to work due to how a wheel is
4+
structured.

src/pip/_internal/metadata/importlib/_envs.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,24 @@
1010
from pip._vendor.packaging.utils import NormalizedName, canonicalize_name
1111

1212
from pip._internal.metadata.base import BaseDistribution, BaseEnvironment
13+
from pip._internal.models.wheel import Wheel
1314
from pip._internal.utils.deprecation import deprecated
15+
from pip._internal.utils.filetypes import WHEEL_EXTENSION
1416

1517
from ._compat import BasePath, get_dist_name, get_info_location
1618
from ._dists import Distribution
1719

1820

21+
def _looks_like_wheel(location: str) -> bool:
22+
if not location.endswith(WHEEL_EXTENSION):
23+
return False
24+
if not os.path.isfile(location):
25+
return False
26+
if not Wheel.wheel_file_re.match(os.path.basename(location)):
27+
return False
28+
return zipfile.is_zipfile(location)
29+
30+
1931
class _DistributionFinder:
2032
"""Finder to locate distributions.
2133
@@ -36,6 +48,11 @@ def __init__(self) -> None:
3648

3749
def _find_impl(self, location: str) -> Iterator[FoundResult]:
3850
"""Find distributions in a location."""
51+
# Skip looking inside a wheel. Since a package inside a wheel is not
52+
# always valid (due to .data directories etc.), its .dist-info entry
53+
# should not be considered an installed distribution.
54+
if _looks_like_wheel(location):
55+
return
3956
# To know exactly where we find a distribution, we have to feed in the
4057
# paths one by one, instead of dumping the list to importlib.metadata.
4158
for dist in importlib.metadata.distributions(path=[location]):

tests/unit/metadata/test_metadata.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
import os
23
from pathlib import Path
34
from typing import cast
45
from unittest import mock
@@ -9,6 +10,7 @@
910
from pip._internal.metadata import (
1011
BaseDistribution,
1112
get_directory_distribution,
13+
get_environment,
1214
get_wheel_distribution,
1315
)
1416
from pip._internal.metadata.base import FilesystemWheel
@@ -102,3 +104,28 @@ def test_metadata_dict(tmp_path: Path) -> None:
102104
metadata_dict = dist.metadata_dict
103105
assert metadata_dict["name"] == "pkga"
104106
assert metadata_dict["version"] == "1.0.1"
107+
108+
109+
def test_no_dist_found_in_wheel(tmp_path: Path) -> None:
110+
location = os.fspath(tmp_path.joinpath("pkg-1-py3-none-any.whl"))
111+
make_wheel(name="pkg", version="1").save_to(location)
112+
assert get_environment([location]).get_distribution("pkg") is None
113+
114+
115+
def test_dist_found_in_directory_named_whl(tmp_path: Path) -> None:
116+
dir_path = tmp_path.joinpath("pkg-1-py3-none-any.whl")
117+
info_path = dir_path.joinpath("pkg-1.dist-info")
118+
info_path.mkdir(parents=True)
119+
info_path.joinpath("METADATA").write_text("Name: pkg")
120+
location = os.fspath(dir_path)
121+
dist = get_environment([location]).get_distribution("pkg")
122+
assert dist is not None and dist.location is not None
123+
assert Path(dist.location) == Path(location)
124+
125+
126+
def test_dist_found_in_zip(tmp_path: Path) -> None:
127+
location = os.fspath(tmp_path.joinpath("pkg.zip"))
128+
make_wheel(name="pkg", version="1").save_to(location)
129+
dist = get_environment([location]).get_distribution("pkg")
130+
assert dist is not None and dist.location is not None
131+
assert Path(dist.location) == Path(location)

0 commit comments

Comments
 (0)