diff options
| author | Jordan Cook <jordan.cook@pioneer.com> | 2021-08-25 15:31:05 -0500 |
|---|---|---|
| committer | Jordan Cook <jordan.cook@pioneer.com> | 2021-08-25 17:43:02 -0500 |
| commit | 20af95ca001110cf8df7d732526a3492cceba19f (patch) | |
| tree | 9ca505caa6f8a5e48b7e863b0ea25f419854e67c /requests_cache | |
| parent | 99282ad0d6df1444e43177cdac07e4af64ca2c84 (diff) | |
| download | requests-cache-20af95ca001110cf8df7d732526a3492cceba19f.tar.gz | |
Minor optimization: exclude redundant CachedResponse.cache_key and CachedHTTPResponse.headers from serialization, and set at runtime instead
Diffstat (limited to 'requests_cache')
| -rw-r--r-- | requests_cache/backends/base.py | 3 | ||||
| -rw-r--r-- | requests_cache/backends/mongodb.py | 7 | ||||
| -rw-r--r-- | requests_cache/models/raw_response.py | 10 | ||||
| -rwxr-xr-x | requests_cache/models/response.py | 15 | ||||
| -rw-r--r-- | requests_cache/serializers/cattrs.py | 8 |
5 files changed, 26 insertions, 17 deletions
diff --git a/requests_cache/backends/base.py b/requests_cache/backends/base.py index a5bc94f..e580d8b 100644 --- a/requests_cache/backends/base.py +++ b/requests_cache/backends/base.py @@ -74,6 +74,7 @@ class BaseCache: if key not in self.responses: key = self.redirects[key] response = self.responses[key] + response.cache_key = key # Set cache key here, since it's not serialized response.reset() # In case response was in memory and content has already been read return response except KeyError: @@ -92,7 +93,7 @@ class BaseCache: expire_after: Time in seconds until this cache item should expire """ cache_key = cache_key or self.create_key(response.request) - cached_response = CachedResponse.from_response(response, cache_key=cache_key, expires=expires) + cached_response = CachedResponse.from_response(response, expires=expires) cached_response.request = remove_ignored_params(cached_response.request, self.ignored_parameters) self.responses[cache_key] = cached_response for r in response.history: diff --git a/requests_cache/backends/mongodb.py b/requests_cache/backends/mongodb.py index 2924f52..07a91ab 100644 --- a/requests_cache/backends/mongodb.py +++ b/requests_cache/backends/mongodb.py @@ -3,12 +3,13 @@ ../_static/mongodb.png `MongoDB <https://www.mongodb.com>`_ is a NoSQL document database. It stores data in collections -of documents, which are more flexible and less strictly structured than a relational database. +of documents, which are more flexible and less strictly structured than tables in a relational +database. Connection Options ^^^^^^^^^^^^^^^^^^ -The MongoDB backend accepts any keyword arguments for :py:class:`pymongo.mongo_client.MongoClient`. These can be passed -via :py:class:`.CachedSession`: +The MongoDB backend accepts any keyword arguments for :py:class:`pymongo.mongo_client.MongoClient`. +These can be passed via :py:class:`.CachedSession`: >>> session = CachedSession('http_cache', backend='mongodb', host='192.168.1.63', port=27017) diff --git a/requests_cache/models/raw_response.py b/requests_cache/models/raw_response.py index 8275100..de2a8f6 100644 --- a/requests_cache/models/raw_response.py +++ b/requests_cache/models/raw_response.py @@ -1,5 +1,6 @@ from io import BytesIO from logging import getLogger +from typing import Mapping from attr import define, field, fields_dict from requests import Response @@ -18,18 +19,20 @@ class CachedHTTPResponse(HTTPResponse): """ decode_content: bool = field(default=None) - headers: HTTPHeaderDict = field(factory=dict) + headers: HTTPHeaderDict = None # Not serialized; set in either init or CachedResponse post-init reason: str = field(default=None) request_url: str = field(default=None) status: int = field(default=0) strict: int = field(default=0) version: int = field(default=0) - def __init__(self, *args, body: bytes = None, **kwargs): + def __init__(self, *args, body: bytes = None, headers: Mapping = None, **kwargs): """First initialize via HTTPResponse, then via attrs""" kwargs = {k: v for k, v in kwargs.items() if v is not None} super().__init__(body=BytesIO(body or b''), preload_content=False, **kwargs) + self._body = body + self.headers = HTTPHeaderDict(headers) self.__attrs_init__(*args, **kwargs) @classmethod @@ -37,7 +40,8 @@ class CachedHTTPResponse(HTTPResponse): """Create a CachedHTTPResponse based on an original response""" # Copy basic attributes raw = original_response.raw - kwargs = {k: getattr(raw, k, None) for k in fields_dict(cls).keys()} + copy_attrs = list(fields_dict(cls).keys()) + ['headers'] + kwargs = {k: getattr(raw, k, None) for k in copy_attrs} # Note: _request_url is not available in urllib <=1.21 kwargs['request_url'] = getattr(raw, '_request_url', None) diff --git a/requests_cache/models/response.py b/requests_cache/models/response.py index 229fd6a..d7fa3df 100755 --- a/requests_cache/models/response.py +++ b/requests_cache/models/response.py @@ -6,6 +6,7 @@ from attr import define, field from requests import PreparedRequest, Response from requests.cookies import RequestsCookieJar from requests.structures import CaseInsensitiveDict +from urllib3.response import HTTPHeaderDict from ..cache_control import ExpirationTime, get_expiration_datetime from . import CachedHTTPResponse, CachedRequest @@ -23,24 +24,26 @@ class CachedResponse(Response): _content: bytes = field(default=None) _next: Optional[CachedRequest] = field(default=None) - url: str = field(default=None) - status_code: int = field(default=0) - cache_key: str = field(default=None) + cache_key: Optional[str] = None # Not serialized; set by BaseCache.get_response() cookies: RequestsCookieJar = field(factory=RequestsCookieJar) created_at: datetime = field(factory=datetime.utcnow) elapsed: timedelta = field(factory=timedelta) - expires: Optional[datetime] = field(default=None) encoding: str = field(default=None) - headers: CaseInsensitiveDict = field(factory=dict) + expires: Optional[datetime] = field(default=None) + headers: CaseInsensitiveDict = field(factory=CaseInsensitiveDict) history: List['CachedResponse'] = field(factory=list) # type: ignore + raw: CachedHTTPResponse = field(factory=CachedHTTPResponse, repr=False) reason: str = field(default=None) request: CachedRequest = field(factory=CachedRequest) # type: ignore - raw: CachedHTTPResponse = field(factory=CachedHTTPResponse, repr=False) + status_code: int = field(default=0) + url: str = field(default=None) def __attrs_post_init__(self): """Re-initialize raw response body after deserialization""" if self.raw._body is None and self._content is not None: self.raw.reset(self._content) + if not self.raw.headers: + self.raw.headers = HTTPHeaderDict(self.headers) @classmethod def from_response(cls, original_response: Response, **kwargs): diff --git a/requests_cache/serializers/cattrs.py b/requests_cache/serializers/cattrs.py index 69dd7d4..522f0db 100644 --- a/requests_cache/serializers/cattrs.py +++ b/requests_cache/serializers/cattrs.py @@ -49,11 +49,11 @@ def init_converter(factory: Callable[..., GenConverter] = None): # Convert datetimes to and from iso-formatted strings converter.register_unstructure_hook(datetime, lambda obj: obj.isoformat() if obj else None) # type: ignore - converter.register_structure_hook(datetime, to_datetime) + converter.register_structure_hook(datetime, _to_datetime) # Convert timedeltas to and from float values in seconds converter.register_unstructure_hook(timedelta, lambda obj: obj.total_seconds() if obj else None) # type: ignore - converter.register_structure_hook(timedelta, to_timedelta) + converter.register_structure_hook(timedelta, _to_timedelta) # Convert dict-like objects to and from plain dicts converter.register_unstructure_hook(RequestsCookieJar, lambda obj: dict(obj.items())) # type: ignore @@ -72,13 +72,13 @@ def init_converter(factory: Callable[..., GenConverter] = None): return converter -def to_datetime(obj, cls) -> datetime: +def _to_datetime(obj, cls) -> datetime: if isinstance(obj, str): obj = datetime.fromisoformat(obj) return obj -def to_timedelta(obj, cls) -> timedelta: +def _to_timedelta(obj, cls) -> timedelta: if isinstance(obj, (int, float)): obj = timedelta(seconds=obj) return obj |
