summaryrefslogtreecommitdiff
path: root/requests_cache
diff options
context:
space:
mode:
authorJordan Cook <jordan.cook@pioneer.com>2021-08-25 15:31:05 -0500
committerJordan Cook <jordan.cook@pioneer.com>2021-08-25 17:43:02 -0500
commit20af95ca001110cf8df7d732526a3492cceba19f (patch)
tree9ca505caa6f8a5e48b7e863b0ea25f419854e67c /requests_cache
parent99282ad0d6df1444e43177cdac07e4af64ca2c84 (diff)
downloadrequests-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.py3
-rw-r--r--requests_cache/backends/mongodb.py7
-rw-r--r--requests_cache/models/raw_response.py10
-rwxr-xr-xrequests_cache/models/response.py15
-rw-r--r--requests_cache/serializers/cattrs.py8
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