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

Include subdirectory URL fragments in cache keys #7335

Merged
merged 4 commits into from
Nov 15, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions news/7333.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Include ``subdirectory`` URL fragments in cache keys.
10 changes: 10 additions & 0 deletions src/pip/_internal/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ def _get_cache_path_parts(self, link):
key_parts = [link.url_without_fragment]
if link.hash_name is not None and link.hash is not None:
key_parts.append("=".join([link.hash_name, link.hash]))
if link.subdirectory_fragment:
key_parts.append(
"=".join(["subdirectory", link.subdirectory_fragment])
)
key_url = "#".join(key_parts)
chrahunt marked this conversation as resolved.
Show resolved Hide resolved

# Encode our key url with sha224, we'll use this because it has similar
Expand Down Expand Up @@ -168,11 +172,17 @@ def get(
# type: (...) -> Link
candidates = []

canonical_package_name = None
if package_name:
canonical_package_name = canonicalize_name(package_name)
for wheel_name in self._get_candidates(link, package_name):
try:
wheel = Wheel(wheel_name)
except InvalidWheelFilename:
continue
assert canonical_package_name
pradyunsg marked this conversation as resolved.
Show resolved Hide resolved
if wheel.name != canonical_package_name:
xavfernandez marked this conversation as resolved.
Show resolved Hide resolved
continue
if not wheel.supported(supported_tags):
# Built for a different python/arch/etc
continue
Expand Down
45 changes: 38 additions & 7 deletions tests/unit/test_cache.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,44 @@
import os

from pip._internal.cache import WheelCache
from pip._internal.models.format_control import FormatControl
from pip._internal.models.link import Link
from pip._internal.utils.compat import expanduser
from pip._internal.utils.misc import ensure_dir


def test_expands_path():
wc = WheelCache("~/.foo/", None)
assert wc.cache_dir == expanduser("~/.foo/")


def test_falsey_path_none():
wc = WheelCache(False, None)
assert wc.cache_dir is None


class TestWheelCache:
def test_subdirectory_fragment():
"""
Test the subdirectory URL fragment is part of the cache key.
"""
wc = WheelCache("~/.foo/", None)
link1 = Link("git+https://g.c/o/r#subdirectory=d1")
link2 = Link("git+https://g.c/o/r#subdirectory=d2")
assert wc.get_path_for_link(link1) != wc.get_path_for_link(link2)

def test_expands_path(self):
wc = WheelCache("~/.foo/", None)
assert wc.cache_dir == expanduser("~/.foo/")

def test_falsey_path_none(self):
wc = WheelCache(False, None)
assert wc.cache_dir is None
def test_wheel_name_filter(tmpdir):
"""
Test the wheel cache filters on wheel name when several wheels
for different package are stored under the same cache directory.
"""
wc = WheelCache(tmpdir, FormatControl())
link = Link("https://g.c/package.tar.gz")
cache_path = wc.get_path_for_link(link)
ensure_dir(cache_path)
with open(os.path.join(cache_path, "package-1.0-py3-none-any.whl"), "w"):
pass
# package matches wheel name
assert wc.get(link, "package", [("py3", "none", "any")]) is not link
# package2 does not match wheel name
assert wc.get(link, "package2", [("py3", "none", "any")]) is link