Skip to content
This repository has been archived by the owner on Feb 11, 2025. It is now read-only.
/ pip Public archive
forked from pypa/pip

Commit

Permalink
Merge pull request #7 from replit/th-ro-download-cache
Browse files Browse the repository at this point in the history
Use a read-only cache adapter for downloading files to workaround mem…
  • Loading branch information
airportyh authored Dec 1, 2022
2 parents ddb81e6 + 40cc19c commit aaef0bd
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 3 deletions.
68 changes: 68 additions & 0 deletions src/pip/_internal/network/ro_cache_adapter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import zlib

from pip._vendor.requests.adapters import HTTPAdapter

from pip._vendor.cachecontrol.controller import CacheController
from pip._vendor.cachecontrol.cache import DictCache
from pip._vendor.cachecontrol.filewrapper import CallbackFileWrapper


class ReadOnlyCacheControlAdapter(HTTPAdapter):
invalidating_methods = {"PUT", "DELETE"}

def __init__(
self,
cache=None,
cache_etags=True,
controller_class=None,
serializer=None,
heuristic=None,
cacheable_methods=None,
*args,
**kw
):
super(ReadOnlyCacheControlAdapter, self).__init__(*args, **kw)
self.cache = DictCache() if cache is None else cache
self.heuristic = heuristic
self.cacheable_methods = cacheable_methods or ("GET",)

controller_factory = controller_class or CacheController
self.controller = controller_factory(
self.cache, cache_etags=cache_etags, serializer=serializer
)

def send(self, request, cacheable_methods=None, **kw):
"""
Send a request. Use the request information to see if it
exists in the cache and cache the response if we need to and can.
"""
cacheable = cacheable_methods or self.cacheable_methods
if request.method in cacheable:
try:
cached_response = self.controller.cached_request(request)
except zlib.error:
cached_response = None
if cached_response:
return self.build_response(request, cached_response, from_cache=True)

resp = super(ReadOnlyCacheControlAdapter, self).send(request, **kw)

return resp

def build_response(
self, request, response, from_cache=False, cacheable_methods=None
):
"""
Build a response by making a request or using the cache.
"""

resp = super(ReadOnlyCacheControlAdapter, self).build_response(request, response)

# Give the request a from_cache attr to let people use it
resp.from_cache = from_cache

return resp

def close(self):
self.cache.close()
super(ReadOnlyCacheControlAdapter, self).close()
6 changes: 3 additions & 3 deletions src/pip/_internal/network/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
from typing import Any, Dict, Iterator, List, Mapping, Optional, Sequence, Tuple, Union

from pip._vendor import requests, urllib3
from pip._vendor.cachecontrol import CacheControlAdapter
from .ro_cache_adapter import ReadOnlyCacheControlAdapter
from pip._vendor.requests.adapters import BaseAdapter, HTTPAdapter
from pip._vendor.requests.models import PreparedRequest, Response
from pip._vendor.requests.structures import CaseInsensitiveDict
Expand Down Expand Up @@ -251,7 +251,7 @@ def cert_verify(
super().cert_verify(conn=conn, url=url, verify=False, cert=cert)


class InsecureCacheControlAdapter(CacheControlAdapter):
class InsecureCacheControlAdapter(ReadOnlyCacheControlAdapter):

def cert_verify(
self,
Expand Down Expand Up @@ -327,7 +327,7 @@ def __init__(
# origin, and we don't want someone to be able to poison the cache and
# require manual eviction from the cache to fix it.
if cache:
secure_adapter = CacheControlAdapter(
secure_adapter = ReadOnlyCacheControlAdapter(
cache=SafeFileCache(cache),
max_retries=retries,
)
Expand Down

0 comments on commit aaef0bd

Please sign in to comment.