Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-CacheControl for 
openSUSE:Factory checked in at 2022-08-03 21:16:28
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-CacheControl (Old)
 and      /work/SRC/openSUSE:Factory/.python-CacheControl.new.1533 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-CacheControl"

Wed Aug  3 21:16:28 2022 rev:10 rq:992331 version:0.12.11

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-CacheControl/python-CacheControl.changes  
2021-12-09 19:45:19.281124939 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-CacheControl.new.1533/python-CacheControl.changes
        2022-08-03 21:16:37.163429690 +0200
@@ -1,0 +2,8 @@
+Tue Aug  2 10:26:39 UTC 2022 - Otto Hollmann <otto.hollm...@suse.com>
+
+- Update to v0.12.11
+  * Added new variant of FileCache, SeparateBodyFileCache, which uses
+    less memory by storing the body in a separate file than metadata,
+    and streaming data in and out directly to/from that file.
+
+-------------------------------------------------------------------

Old:
----
  CacheControl-0.12.10.tar.gz

New:
----
  CacheControl-0.12.11.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-CacheControl.spec ++++++
--- /var/tmp/diff_new_pack.5Vp38i/_old  2022-08-03 21:16:37.651430971 +0200
+++ /var/tmp/diff_new_pack.5Vp38i/_new  2022-08-03 21:16:37.655430981 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-CacheControl
 #
-# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2022 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -19,7 +19,7 @@
 %{?!python_module:%define python_module() python3-%{**}}
 %define skip_python2 1
 Name:           python-CacheControl
-Version:        0.12.10
+Version:        0.12.11
 Release:        0
 Summary:        Caching library for Python requests
 License:        Apache-2.0

++++++ CacheControl-0.12.10.tar.gz -> CacheControl-0.12.11.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cachecontrol-0.12.10/.bumpversion.cfg 
new/cachecontrol-0.12.11/.bumpversion.cfg
--- old/cachecontrol-0.12.10/.bumpversion.cfg   2021-11-05 18:07:09.000000000 
+0100
+++ new/cachecontrol-0.12.11/.bumpversion.cfg   2022-04-19 19:20:49.000000000 
+0200
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 0.12.10
+current_version = 0.12.11
 files = setup.py cachecontrol/__init__.py docs/conf.py
 commit = True
 tag = True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cachecontrol-0.12.10/.gitignore 
new/cachecontrol-0.12.11/.gitignore
--- old/cachecontrol-0.12.10/.gitignore 2021-11-05 18:07:09.000000000 +0100
+++ new/cachecontrol-0.12.11/.gitignore 2022-04-19 19:20:49.000000000 +0200
@@ -14,4 +14,6 @@
 .Python
 docs/_build
 build/
-.tox
\ No newline at end of file
+.tox
+.venv
+web_cache
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cachecontrol-0.12.10/cachecontrol/__init__.py 
new/cachecontrol-0.12.11/cachecontrol/__init__.py
--- old/cachecontrol-0.12.10/cachecontrol/__init__.py   2021-11-05 
18:07:09.000000000 +0100
+++ new/cachecontrol-0.12.11/cachecontrol/__init__.py   2022-04-19 
19:20:49.000000000 +0200
@@ -8,7 +8,7 @@
 """
 __author__ = "Eric Larson"
 __email__ = "e...@ionrock.org"
-__version__ = "0.12.10"
+__version__ = "0.12.11"
 
 from .wrapper import CacheControl
 from .adapter import CacheControlAdapter
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cachecontrol-0.12.10/cachecontrol/cache.py 
new/cachecontrol-0.12.11/cachecontrol/cache.py
--- old/cachecontrol-0.12.10/cachecontrol/cache.py      2021-11-05 
18:07:09.000000000 +0100
+++ new/cachecontrol-0.12.11/cachecontrol/cache.py      2022-04-19 
19:20:49.000000000 +0200
@@ -41,3 +41,25 @@
         with self.lock:
             if key in self.data:
                 self.data.pop(key)
+
+
+class SeparateBodyBaseCache(BaseCache):
+    """
+    In this variant, the body is not stored mixed in with the metadata, but is
+    passed in (as a bytes-like object) in a separate call to ``set_body()``.
+
+    That is, the expected interaction pattern is::
+
+        cache.set(key, serialized_metadata)
+        cache.set_body(key)
+
+    Similarly, the body should be loaded separately via ``get_body()``.
+    """
+    def set_body(self, key, body):
+        raise NotImplementedError()
+
+    def get_body(self, key):
+        """
+        Return the body as file-like object.
+        """
+        raise NotImplementedError()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cachecontrol-0.12.10/cachecontrol/caches/__init__.py 
new/cachecontrol-0.12.11/cachecontrol/caches/__init__.py
--- old/cachecontrol-0.12.10/cachecontrol/caches/__init__.py    2021-11-05 
18:07:09.000000000 +0100
+++ new/cachecontrol-0.12.11/cachecontrol/caches/__init__.py    2022-04-19 
19:20:49.000000000 +0200
@@ -2,5 +2,8 @@
 #
 # SPDX-License-Identifier: Apache-2.0
 
-from .file_cache import FileCache  # noqa
-from .redis_cache import RedisCache  # noqa
+from .file_cache import FileCache, SeparateBodyFileCache
+from .redis_cache import RedisCache
+
+
+__all__ = ["FileCache", "SeparateBodyFileCache", "RedisCache"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cachecontrol-0.12.10/cachecontrol/caches/file_cache.py 
new/cachecontrol-0.12.11/cachecontrol/caches/file_cache.py
--- old/cachecontrol-0.12.10/cachecontrol/caches/file_cache.py  2021-11-05 
18:07:09.000000000 +0100
+++ new/cachecontrol-0.12.11/cachecontrol/caches/file_cache.py  2022-04-19 
19:20:49.000000000 +0200
@@ -6,7 +6,7 @@
 import os
 from textwrap import dedent
 
-from ..cache import BaseCache
+from ..cache import BaseCache, SeparateBodyBaseCache
 from ..controller import CacheController
 
 try:
@@ -57,7 +57,8 @@
         raise
 
 
-class FileCache(BaseCache):
+class _FileCacheMixin:
+    """Shared implementation for both FileCache variants."""
 
     def __init__(
         self,
@@ -120,20 +121,25 @@
 
     def set(self, key, value, expires=None):
         name = self._fn(key)
+        self._write(name, value)
 
+    def _write(self, path, data: bytes):
+        """
+        Safely write the data to the given path.
+        """
         # Make sure the directory exists
         try:
-            os.makedirs(os.path.dirname(name), self.dirmode)
+            os.makedirs(os.path.dirname(path), self.dirmode)
         except (IOError, OSError):
             pass
 
-        with self.lock_class(name) as lock:
+        with self.lock_class(path) as lock:
             # Write our actual file
             with _secure_open_write(lock.path, self.filemode) as fh:
-                fh.write(value)
+                fh.write(data)
 
-    def delete(self, key):
-        name = self._fn(key)
+    def _delete(self, key, suffix):
+        name = self._fn(key) + suffix
         if not self.forever:
             try:
                 os.remove(name)
@@ -141,6 +147,38 @@
                 pass
 
 
+class FileCache(_FileCacheMixin, BaseCache):
+    """
+    Traditional FileCache: body is stored in memory, so not suitable for large
+    downloads.
+    """
+
+    def delete(self, key):
+        self._delete(key, "")
+
+
+class SeparateBodyFileCache(_FileCacheMixin, SeparateBodyBaseCache):
+    """
+    Memory-efficient FileCache: body is stored in a separate file, reducing
+    peak memory usage.
+    """
+
+    def get_body(self, key):
+        name = self._fn(key) + ".body"
+        try:
+            return open(name, "rb")
+        except FileNotFoundError:
+            return None
+
+    def set_body(self, key, body):
+        name = self._fn(key) + ".body"
+        self._write(name, body)
+
+    def delete(self, key):
+        self._delete(key, "")
+        self._delete(key, ".body")
+
+
 def url_to_file_path(url, filecache):
     """Return the file cache path based on the URL.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cachecontrol-0.12.10/cachecontrol/caches/redis_cache.py 
new/cachecontrol-0.12.11/cachecontrol/caches/redis_cache.py
--- old/cachecontrol-0.12.10/cachecontrol/caches/redis_cache.py 2021-11-05 
18:07:09.000000000 +0100
+++ new/cachecontrol-0.12.11/cachecontrol/caches/redis_cache.py 2022-04-19 
19:20:49.000000000 +0200
@@ -19,9 +19,11 @@
     def set(self, key, value, expires=None):
         if not expires:
             self.conn.set(key, value)
-        else:
+        elif isinstance(expires, datetime):
             expires = expires - datetime.utcnow()
             self.conn.setex(key, int(expires.total_seconds()), value)
+        else:
+            self.conn.setex(key, expires, value)
 
     def delete(self, key):
         self.conn.delete(key)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cachecontrol-0.12.10/cachecontrol/controller.py 
new/cachecontrol-0.12.11/cachecontrol/controller.py
--- old/cachecontrol-0.12.10/cachecontrol/controller.py 2021-11-05 
18:07:09.000000000 +0100
+++ new/cachecontrol-0.12.11/cachecontrol/controller.py 2022-04-19 
19:20:49.000000000 +0200
@@ -13,7 +13,7 @@
 
 from requests.structures import CaseInsensitiveDict
 
-from .cache import DictCache
+from .cache import DictCache, SeparateBodyBaseCache
 from .serialize import Serializer
 
 
@@ -27,15 +27,14 @@
 def parse_uri(uri):
     """Parses a URI using the regex given in Appendix B of RFC 3986.
 
-        (scheme, authority, path, query, fragment) = parse_uri(uri)
+    (scheme, authority, path, query, fragment) = parse_uri(uri)
     """
     groups = URI.match(uri).groups()
     return (groups[1], groups[3], groups[4], groups[6], groups[8])
 
 
 class CacheController(object):
-    """An interface to see if request should cached or not.
-    """
+    """An interface to see if request should cached or not."""
 
     def __init__(
         self, cache=None, cache_etags=True, serializer=None, status_codes=None
@@ -147,8 +146,13 @@
             logger.debug("No cache entry available")
             return False
 
+        if isinstance(self.cache, SeparateBodyBaseCache):
+            body_file = self.cache.get_body(cache_url)
+        else:
+            body_file = None
+
         # Check whether it can be deserialized
-        resp = self.serializer.loads(request, cache_data)
+        resp = self.serializer.loads(request, cache_data, body_file)
         if not resp:
             logger.warning("Cache entry deserialization failed, entry ignored")
             return False
@@ -251,6 +255,26 @@
 
         return new_headers
 
+    def _cache_set(self, cache_url, request, response, body=None, 
expires_time=None):
+        """
+        Store the data in the cache.
+        """
+        if isinstance(self.cache, SeparateBodyBaseCache):
+            # We pass in the body separately; just put a placeholder empty
+            # string in the metadata.
+            self.cache.set(
+                cache_url,
+                self.serializer.dumps(request, response, b""),
+                expires=expires_time,
+            )
+            self.cache.set_body(cache_url, body)
+        else:
+            self.cache.set(
+                cache_url,
+                self.serializer.dumps(request, response, body),
+                expires=expires_time,
+            )
+
     def cache_response(self, request, response, body=None, status_codes=None):
         """
         Algorithm for caching requests.
@@ -326,17 +350,13 @@
 
             logger.debug("etag object cached for {0} 
seconds".format(expires_time))
             logger.debug("Caching due to etag")
-            self.cache.set(
-                cache_url,
-                self.serializer.dumps(request, response, body),
-                expires=expires_time,
-            )
+            self._cache_set(cache_url, request, response, body, expires_time)
 
         # Add to the cache any permanent redirects. We do this before looking
         # that the Date headers.
         elif int(response.status) in PERMANENT_REDIRECT_STATUSES:
             logger.debug("Caching permanent redirect")
-            self.cache.set(cache_url, self.serializer.dumps(request, response, 
b""))
+            self._cache_set(cache_url, request, response, b"")
 
         # Add to the cache if the response headers demand it. If there
         # is no date header then we can't do anything about expiring
@@ -347,10 +367,12 @@
             if "max-age" in cc and cc["max-age"] > 0:
                 logger.debug("Caching b/c date exists and max-age > 0")
                 expires_time = cc["max-age"]
-                self.cache.set(
+                self._cache_set(
                     cache_url,
-                    self.serializer.dumps(request, response, body),
-                    expires=expires_time,
+                    request,
+                    response,
+                    body,
+                    expires_time,
                 )
 
             # If the request can expire, it means we should cache it
@@ -368,10 +390,12 @@
                             expires_time
                         )
                     )
-                    self.cache.set(
+                    self._cache_set(
                         cache_url,
-                        self.serializer.dumps(request, response, body=body),
-                        expires=expires_time,
+                        request,
+                        response,
+                        body,
+                        expires_time,
                     )
 
     def update_cached_response(self, request, response):
@@ -410,6 +434,6 @@
         cached_response.status = 200
 
         # update our cache
-        self.cache.set(cache_url, self.serializer.dumps(request, 
cached_response))
+        self._cache_set(cache_url, request, cached_response)
 
         return cached_response
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cachecontrol-0.12.10/cachecontrol/serialize.py 
new/cachecontrol-0.12.11/cachecontrol/serialize.py
--- old/cachecontrol-0.12.10/cachecontrol/serialize.py  2021-11-05 
18:07:09.000000000 +0100
+++ new/cachecontrol-0.12.11/cachecontrol/serialize.py  2022-04-19 
19:20:49.000000000 +0200
@@ -44,7 +44,7 @@
         #       enough to have msgpack know the difference.
         data = {
             u"response": {
-                u"body": body,
+                u"body": body,  # Empty bytestring if body is stored separately
                 u"headers": dict(
                     (text_type(k), text_type(v)) for k, v in 
response.headers.items()
                 ),
@@ -69,7 +69,7 @@
 
         return b",".join([b"cc=4", msgpack.dumps(data, use_bin_type=True)])
 
-    def loads(self, request, data):
+    def loads(self, request, data, body_file=None):
         # Short circuit if we've been given an empty set of data
         if not data:
             return
@@ -92,14 +92,14 @@
 
         # Dispatch to the actual load method for the given version
         try:
-            return getattr(self, "_loads_v{}".format(ver))(request, data)
+            return getattr(self, "_loads_v{}".format(ver))(request, data, 
body_file)
 
         except AttributeError:
             # This is a version we don't have a loads function for, so we'll
             # just treat it as a miss and return None
             return
 
-    def prepare_response(self, request, cached):
+    def prepare_response(self, request, cached, body_file=None):
         """Verify our vary headers match and construct a real urllib3
         HTTPResponse object.
         """
@@ -125,7 +125,10 @@
         cached["response"]["headers"] = headers
 
         try:
-            body = io.BytesIO(body_raw)
+            if body_file is None:
+                body = io.BytesIO(body_raw)
+            else:
+                body = body_file
         except TypeError:
             # This can happen if cachecontrol serialized to v1 format (pickle)
             # using Python 2. A Python 2 str(byte string) will be unpickled as
@@ -137,21 +140,22 @@
 
         return HTTPResponse(body=body, preload_content=False, 
**cached["response"])
 
-    def _loads_v0(self, request, data):
+    def _loads_v0(self, request, data, body_file=None):
         # The original legacy cache data. This doesn't contain enough
         # information to construct everything we need, so we'll treat this as
         # a miss.
         return
 
-    def _loads_v1(self, request, data):
+    def _loads_v1(self, request, data, body_file=None):
         try:
             cached = pickle.loads(data)
         except ValueError:
             return
 
-        return self.prepare_response(request, cached)
+        return self.prepare_response(request, cached, body_file)
 
-    def _loads_v2(self, request, data):
+    def _loads_v2(self, request, data, body_file=None):
+        assert body_file is None
         try:
             cached = json.loads(zlib.decompress(data).decode("utf8"))
         except (ValueError, zlib.error):
@@ -169,18 +173,18 @@
             for k, v in cached["vary"].items()
         )
 
-        return self.prepare_response(request, cached)
+        return self.prepare_response(request, cached, body_file)
 
-    def _loads_v3(self, request, data):
+    def _loads_v3(self, request, data, body_file):
         # Due to Python 2 encoding issues, it's impossible to know for sure
         # exactly how to load v3 entries, thus we'll treat these as a miss so
         # that they get rewritten out as v4 entries.
         return
 
-    def _loads_v4(self, request, data):
+    def _loads_v4(self, request, data, body_file=None):
         try:
             cached = msgpack.loads(data, raw=False)
         except ValueError:
             return
 
-        return self.prepare_response(request, cached)
+        return self.prepare_response(request, cached, body_file)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cachecontrol-0.12.10/docs/conf.py 
new/cachecontrol-0.12.11/docs/conf.py
--- old/cachecontrol-0.12.10/docs/conf.py       2021-11-05 18:07:09.000000000 
+0100
+++ new/cachecontrol-0.12.11/docs/conf.py       2022-04-19 19:20:49.000000000 
+0200
@@ -52,9 +52,9 @@
 # built documents.
 #
 # The short X.Y version.
-version = "0.12.10"
+version = "0.12.11"
 # The full version, including alpha/beta/rc tags.
-release = "0.12.10"
+release = "0.12.11"
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cachecontrol-0.12.10/docs/release_notes.rst 
new/cachecontrol-0.12.11/docs/release_notes.rst
--- old/cachecontrol-0.12.10/docs/release_notes.rst     2021-11-05 
18:07:09.000000000 +0100
+++ new/cachecontrol-0.12.11/docs/release_notes.rst     2022-04-19 
19:20:49.000000000 +0200
@@ -7,7 +7,12 @@
  Release Notes
 ===============
 
-0.13.0
+0.12.11
+=======
+
+* Added new variant of ``FileCache``, ``SeparateBodyFileCache``, which uses 
less memory by storing the body in a separate file than metadata, and streaming 
data in and out directly to/from that file. Implemented by [Itamar 
Turner-Trauring](https://pythonspeed.com), work sponsored by 
[G-Research](https://www.gresearch.co.uk/technology-innovation-and-open-source/).
+
+0.12.7
 ======
 
 * Dropped support for Python 2.7, 3.4, 3.5.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cachecontrol-0.12.10/docs/storage.rst 
new/cachecontrol-0.12.11/docs/storage.rst
--- old/cachecontrol-0.12.10/docs/storage.rst   2021-11-05 18:07:09.000000000 
+0100
+++ new/cachecontrol-0.12.11/docs/storage.rst   2022-04-19 19:20:49.000000000 
+0200
@@ -56,17 +56,33 @@
   forever_cache = FileCache('.web_cache', forever=True)
   sess = CacheControl(requests.Session(), forever_cache)
 
+SeparateBodyFileCache
+=====================
 
-:A Note About Pickle:
+This is similar to ``FileCache``, but far more memory efficient, and therefore 
recommended if you expect to be caching large downloads.
+``FileCache`` results in memory usage that can be 2?? or 3?? of the downloaded 
file, whereas ``SeparateBodyFileCache`` should have fixed memory usage.
 
-  It should be noted that the `FileCache` uses pickle to store the
-  cached response. Prior to `requests 2.1`_, `requests.Response`
-  objects were not 'pickleable' due to the use of `IOBase` base
-  classes in `urllib3` `HTTPResponse` objects. In CacheControl we work
-  around this by patching the Response objects with the appropriate
-  `__getstate__` and `__setstate__` methods when the requests version
-  doesn't natively support Response pickling.
+The body of the request is stored in a separate file than metadata, and 
streamed in and out.
 
+It requires `lockfile`_ be installed as it prevents multiple threads from 
writing to the same file at the same time.
+
+.. note::
+
+  You can install this dependency automatically with pip
+  by requesting the *filecache* extra: ::
+
+    pip install cachecontrol[filecache]
+
+Here is an example of using the cache::
+
+  import requests
+  from cachecontrol import CacheControl
+  from cachecontrol.caches SeparateBodyFileCache
+
+  sess = CacheControl(requests.Session(),
+                      cache=SeparatedBodyFileCache('.web_cache'))
+
+``SeparateBodyFileCache`` supports the same options as ``FileCache``.
 
 
 RedisCache
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cachecontrol-0.12.10/setup.py 
new/cachecontrol-0.12.11/setup.py
--- old/cachecontrol-0.12.10/setup.py   2021-11-05 18:07:09.000000000 +0100
+++ new/cachecontrol-0.12.11/setup.py   2022-04-19 19:20:49.000000000 +0200
@@ -6,7 +6,7 @@
 
 long_description = open("README.rst").read()
 
-VERSION = "0.12.10"
+VERSION = "0.12.11"
 
 setup_params = dict(
     name="CacheControl",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cachecontrol-0.12.10/tests/test_cache_control.py 
new/cachecontrol-0.12.11/tests/test_cache_control.py
--- old/cachecontrol-0.12.10/tests/test_cache_control.py        2021-11-05 
18:07:09.000000000 +0100
+++ new/cachecontrol-0.12.11/tests/test_cache_control.py        2022-04-19 
19:20:49.000000000 +0200
@@ -21,7 +21,7 @@
     def dumps(self, request, response):
         return response
 
-    def loads(self, request, data):
+    def loads(self, request, data, body_file=None):
         return data
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cachecontrol-0.12.10/tests/test_etag.py 
new/cachecontrol-0.12.11/tests/test_etag.py
--- old/cachecontrol-0.12.10/tests/test_etag.py 2021-11-05 18:07:09.000000000 
+0100
+++ new/cachecontrol-0.12.11/tests/test_etag.py 2022-04-19 19:20:49.000000000 
+0200
@@ -18,7 +18,7 @@
     def dumps(self, request, response, body=None):
         return response
 
-    def loads(self, request, data):
+    def loads(self, request, data, body_file=None):
         if data and getattr(data, "chunked", False):
             data.chunked = False
         return data
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cachecontrol-0.12.10/tests/test_max_age.py 
new/cachecontrol-0.12.11/tests/test_max_age.py
--- old/cachecontrol-0.12.10/tests/test_max_age.py      2021-11-05 
18:07:09.000000000 +0100
+++ new/cachecontrol-0.12.11/tests/test_max_age.py      2022-04-19 
19:20:49.000000000 +0200
@@ -15,7 +15,7 @@
     def dumps(self, request, response, body=None):
         return response
 
-    def loads(self, request, data):
+    def loads(self, request, data, body_file=None):
         if data and getattr(data, "chunked", False):
             data.chunked = False
         return data
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cachecontrol-0.12.10/tests/test_storage_filecache.py 
new/cachecontrol-0.12.11/tests/test_storage_filecache.py
--- old/cachecontrol-0.12.10/tests/test_storage_filecache.py    2021-11-05 
18:07:09.000000000 +0100
+++ new/cachecontrol-0.12.11/tests/test_storage_filecache.py    2022-04-19 
19:20:49.000000000 +0200
@@ -13,7 +13,7 @@
 import pytest
 import requests
 from cachecontrol import CacheControl
-from cachecontrol.caches import FileCache
+from cachecontrol.caches import FileCache, SeparateBodyFileCache
 from lockfile import LockFile
 from lockfile.mkdirlockfile import MkdirLockFile
 
@@ -25,12 +25,14 @@
     return "&{}={}".format(key, val)
 
 
-class TestStorageFileCache(object):
+class FileCacheTestsMixin(object):
+
+    FileCacheClass = None  # Either FileCache or SeparateBodyFileCache
 
     @pytest.fixture()
     def sess(self, url, tmpdir):
         self.url = url
-        self.cache = FileCache(str(tmpdir))
+        self.cache = self.FileCacheClass(str(tmpdir))
         sess = CacheControl(requests.Session(), cache=self.cache)
         yield sess
 
@@ -94,7 +96,7 @@
 
     def test_cant_use_dir_and_lock_class(self, tmpdir):
         with pytest.raises(ValueError):
-            FileCache(str(tmpdir), use_dir_lock=True, lock_class=object())
+            self.FileCacheClass(str(tmpdir), use_dir_lock=True, 
lock_class=object())
 
     @pytest.mark.parametrize(
         ("value", "expected"),
@@ -102,16 +104,16 @@
     )
     def test_simple_lockfile_arg(self, tmpdir, value, expected):
         if value is not None:
-            cache = FileCache(str(tmpdir), use_dir_lock=value)
+            cache = self.FileCacheClass(str(tmpdir), use_dir_lock=value)
         else:
-            cache = FileCache(str(tmpdir))
+            cache = self.FileCacheClass(str(tmpdir))
 
         assert issubclass(cache.lock_class, expected)
         cache.close()
 
     def test_lock_class(self, tmpdir):
         lock_class = object()
-        cache = FileCache(str(tmpdir), lock_class=lock_class)
+        cache = self.FileCacheClass(str(tmpdir), lock_class=lock_class)
         assert cache.lock_class is lock_class
         cache.close()
 
@@ -126,3 +128,58 @@
         url = self.url + "".join(sample(string.ascii_lowercase, randint(2, 4)))
         sess.put(url)
         assert True  # test verifies no exceptions were raised
+
+
+class TestFileCache(FileCacheTestsMixin):
+    """
+    Tests for ``FileCache``.
+    """
+    
+    FileCacheClass = FileCache
+
+    def test_body_stored_inline(self, sess):
+        """The body is stored together with the metadata."""
+        url = self.url + "cache_60"
+        response = sess.get(url)
+        body = response.content
+        response2 = sess.get(url)
+        assert response2.from_cache
+        assert response2.content == body
+
+        # OK now let's violate some abstraction boundaries to make sure body
+        # was stored in metadata file.
+        with open(self.cache._fn(url), "rb") as f:
+            assert body in f.read()
+        assert not os.path.exists(self.cache._fn(url) + ".body")
+
+
+class TestSeparateBodyFileCache(FileCacheTestsMixin):
+    """
+    Tests for ``SeparateBodyFileCache``
+    """
+
+    FileCacheClass = SeparateBodyFileCache
+
+    def test_body_actually_stored_separately(self, sess):
+        """
+        Body is stored and can be retrieved from the SeparateBodyFileCache, 
with assurances
+        it's actually being loaded from separate file than metadata.
+        """
+        url = self.url + "cache_60"
+        response = sess.get(url)
+        body = response.content
+        response2 = sess.get(url)
+        assert response2.from_cache
+        assert response2.content == body
+
+        # OK now let's violate some abstraction boundaries to make sure body
+        # actually came from separate file.
+        with open(self.cache._fn(url), "rb") as f:
+            assert body not in f.read()
+        with open(self.cache._fn(url) + ".body", "rb") as f:
+            assert body == f.read()
+        with open(self.cache._fn(url) + ".body", "wb") as f:
+            f.write(b"CORRUPTED")
+        response2 = sess.get(url)
+        assert response2.from_cache
+        assert response2.content == b"CORRUPTED"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/cachecontrol-0.12.10/tests/test_storage_redis.py 
new/cachecontrol-0.12.11/tests/test_storage_redis.py
--- old/cachecontrol-0.12.10/tests/test_storage_redis.py        2021-11-05 
18:07:09.000000000 +0100
+++ new/cachecontrol-0.12.11/tests/test_storage_redis.py        2022-04-19 
19:20:49.000000000 +0200
@@ -14,6 +14,10 @@
         self.conn = Mock()
         self.cache = RedisCache(self.conn)
 
-    def test_set_expiration(self):
+    def test_set_expiration_datetime(self):
         self.cache.set("foo", "bar", expires=datetime(2014, 2, 2))
         assert self.conn.setex.called
+
+    def test_set_expiration_int(self):
+        self.cache.set("foo", "bar", expires=600)
+        assert self.conn.setex.called

Reply via email to