Skip to content

Commit c1ead0a

Browse files
itamarstpythonspeed
authored andcommitted
Switch to new cache format and new cache location.
1 parent 9f72cd0 commit c1ead0a

File tree

5 files changed

+43
-17
lines changed

5 files changed

+43
-17
lines changed

news/2984.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pip uses less memory when caching large packages. As a result, there is a new on-disk cache format stored in a new directory ($PIP_CACHE_DIR/http-v2).

src/pip/_internal/cli/req_command.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ def _build_session(
123123
ssl_context = None
124124

125125
session = PipSession(
126-
cache=os.path.join(cache_dir, "http") if cache_dir else None,
126+
cache=os.path.join(cache_dir, "http-v2") if cache_dir else None,
127127
retries=retries if retries is not None else options.retries,
128128
trusted_hosts=options.trusted_hosts,
129129
index_urls=self._get_index_urls(options),

src/pip/_internal/commands/cache.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,25 +93,31 @@ def get_cache_info(self, options: Values, args: List[Any]) -> None:
9393
num_http_files = len(self._find_http_files(options))
9494
num_packages = len(self._find_wheels(options, "*"))
9595

96-
http_cache_location = self._cache_dir(options, "http")
96+
http_cache_location = self._cache_dir(options, "http-v2")
97+
old_http_cache_location = self._cache_dir(options, "http")
9798
wheels_cache_location = self._cache_dir(options, "wheels")
9899
http_cache_size = filesystem.format_directory_size(http_cache_location)
100+
old_http_cache_size = filesystem.format_directory_size(old_http_cache_location)
99101
wheels_cache_size = filesystem.format_directory_size(wheels_cache_location)
100102

101103
message = (
102104
textwrap.dedent(
103105
"""
104-
Package index page cache location: {http_cache_location}
105-
Package index page cache size: {http_cache_size}
106-
Number of HTTP files: {num_http_files}
106+
Package index page cache location (new): {http_cache_location}
107+
Package index page cache location (old): {old_http_cache_location}
108+
Package index page cache size (new): {http_cache_size}
109+
Package index page cache size (old): {old_http_cache_size}
110+
Number of HTTP files (old+new cache): {num_http_files}
107111
Locally built wheels location: {wheels_cache_location}
108112
Locally built wheels size: {wheels_cache_size}
109113
Number of locally built wheels: {package_count}
110114
"""
111115
)
112116
.format(
113117
http_cache_location=http_cache_location,
118+
old_http_cache_location=old_http_cache_location,
114119
http_cache_size=http_cache_size,
120+
old_http_cache_size=old_http_cache_size,
115121
num_http_files=num_http_files,
116122
wheels_cache_location=wheels_cache_location,
117123
package_count=num_packages,
@@ -195,8 +201,11 @@ def _cache_dir(self, options: Values, subdir: str) -> str:
195201
return os.path.join(options.cache_dir, subdir)
196202

197203
def _find_http_files(self, options: Values) -> List[str]:
198-
http_dir = self._cache_dir(options, "http")
199-
return filesystem.find_files(http_dir, "*")
204+
old_http_dir = self._cache_dir(options, "http")
205+
new_http_dir = self._cache_dir(options, "http-v2")
206+
return filesystem.find_files(old_http_dir, "*") + filesystem.find_files(
207+
new_http_dir, "*"
208+
)
200209

201210
def _find_wheels(self, options: Values, pattern: str) -> List[str]:
202211
wheel_dir = self._cache_dir(options, "wheels")

src/pip/_internal/network/cache.py

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33

44
import os
55
from contextlib import contextmanager
6-
from typing import Generator, Optional
6+
from typing import BinaryIO, Generator, Optional
77

8-
from pip._vendor.cachecontrol.cache import BaseCache
9-
from pip._vendor.cachecontrol.caches import FileCache
8+
from pip._vendor.cachecontrol.cache import SeparateBodyBaseCache
9+
from pip._vendor.cachecontrol.caches import SeparateBodyFileCache
1010
from pip._vendor.requests.models import Response
1111

1212
from pip._internal.utils.filesystem import adjacent_tmp_file, replace
@@ -28,7 +28,7 @@ def suppressed_cache_errors() -> Generator[None, None, None]:
2828
pass
2929

3030

31-
class SafeFileCache(BaseCache):
31+
class SafeFileCache(SeparateBodyBaseCache):
3232
"""
3333
A file based cache which is safe to use even when the target directory may
3434
not be accessible or writable.
@@ -43,7 +43,7 @@ def _get_cache_path(self, name: str) -> str:
4343
# From cachecontrol.caches.file_cache.FileCache._fn, brought into our
4444
# class for backwards-compatibility and to avoid using a non-public
4545
# method.
46-
hashed = FileCache.encode(name)
46+
hashed = SeparateBodyFileCache.encode(name)
4747
parts = list(hashed[:5]) + [hashed]
4848
return os.path.join(self.directory, *parts)
4949

@@ -53,17 +53,33 @@ def get(self, key: str) -> Optional[bytes]:
5353
with open(path, "rb") as f:
5454
return f.read()
5555

56-
def set(self, key: str, value: bytes, expires: Optional[int] = None) -> None:
57-
path = self._get_cache_path(key)
56+
def _write(self, path: str, data: bytes) -> None:
5857
with suppressed_cache_errors():
5958
ensure_dir(os.path.dirname(path))
6059

6160
with adjacent_tmp_file(path) as f:
62-
f.write(value)
61+
f.write(data)
6362

6463
replace(f.name, path)
6564

65+
def set(self, key: str, value: bytes, expires: Optional[int] = None) -> None:
66+
path = self._get_cache_path(key)
67+
self._write(path, value)
68+
6669
def delete(self, key: str) -> None:
6770
path = self._get_cache_path(key)
6871
with suppressed_cache_errors():
6972
os.remove(path)
73+
os.remove(path + ".body")
74+
75+
def get_body(self, key: str) -> Optional[BinaryIO]:
76+
path = self._get_cache_path(key) + ".body"
77+
with suppressed_cache_errors():
78+
return open(path, "rb")
79+
80+
def set_body(self, key: str, body: Optional[bytes]) -> None:
81+
if body is None:
82+
# Workaround for https://github.com/ionrock/cachecontrol/issues/276
83+
return
84+
path = self._get_cache_path(key) + ".body"
85+
self._write(path, body)

tests/functional/test_cache.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def cache_dir(script: PipTestEnvironment) -> str:
2020

2121
@pytest.fixture
2222
def http_cache_dir(cache_dir: str) -> str:
23-
return os.path.normcase(os.path.join(cache_dir, "http"))
23+
return os.path.normcase(os.path.join(cache_dir, "http-v2"))
2424

2525

2626
@pytest.fixture
@@ -211,7 +211,7 @@ def test_cache_info(
211211
) -> None:
212212
result = script.pip("cache", "info")
213213

214-
assert f"Package index page cache location: {http_cache_dir}" in result.stdout
214+
assert f"Package index page cache location (new): {http_cache_dir}" in result.stdout
215215
assert f"Locally built wheels location: {wheel_cache_dir}" in result.stdout
216216
num_wheels = len(wheel_cache_files)
217217
assert f"Number of locally built wheels: {num_wheels}" in result.stdout

0 commit comments

Comments
 (0)