[Python-modules-commits] [python-requests-cache] 01/07: Import python-requests-cache_0.4.12.orig.tar.gz

Sandro Tosi morph at moszumanska.debian.org
Mon Apr 25 21:32:23 UTC 2016


This is an automated email from the git hooks/post-receive script.

morph pushed a commit to branch master
in repository python-requests-cache.

commit b7bf9ae0ce33f9ae11e559273f95ac3364541cd8
Author: Sandro Tosi <morph at debian.org>
Date:   Mon Apr 25 22:25:52 2016 +0100

    Import python-requests-cache_0.4.12.orig.tar.gz
---
 HISTORY.rst                         |  11 ++++
 PKG-INFO                            |  19 ++++--
 README.rst                          |   6 +-
 docs/index.rst                      |   3 +-
 docs/make.bat                       |   0
 docs/user_guide.rst                 |  43 ++++++++------
 requests_cache.egg-info/PKG-INFO    |  19 ++++--
 requests_cache.egg-info/SOURCES.txt |   1 +
 requests_cache/__init__.py          |   2 +-
 requests_cache/backends/__init__.py |  19 +++++-
 requests_cache/backends/base.py     |  50 +++++++++++++++-
 requests_cache/compat.py            |   4 +-
 requests_cache/core.py              |  30 ++++++----
 setup.cfg                           |   3 +
 setup.py                            |   2 +-
 tests/test_cache.py                 | 112 ++++++++++++++++++++++++++++++++++++
 tests/test_monkey_patch.py          |  14 +++++
 17 files changed, 288 insertions(+), 50 deletions(-)

diff --git a/HISTORY.rst b/HISTORY.rst
index 706d462..4e9fc21 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -3,6 +3,17 @@
 History
 -------
 
+0.4.12 (2016-03-19)
++++++++++++++++++++
+* Fix ability to pass backend instance in ``install_cache`` #61
+
+
+0.4.11 (2016-03-07)
++++++++++++++++++++
+* ``ignore_parameters`` feature, thanks to @themiurgo and @YetAnotherNerd (#52, #55)
+* More informative message for missing backend dependencies, thanks to @Garrett-R (#60)
+
+
 0.4.10 (2015-04-28)
 +++++++++++++++++++
 * Better transactional handling in sqlite #50, thanks to @rgant
diff --git a/PKG-INFO b/PKG-INFO
index 0255666..8bcc8bf 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: requests-cache
-Version: 0.4.10
+Version: 0.4.12
 Summary: Persistent cache for requests library
 Home-page: https://github.com/reclosedev/requests-cache
 Author: Roman Haritonov
@@ -16,9 +16,9 @@ Description: requests-cache
         .. image:: https://travis-ci.org/reclosedev/requests-cache.svg?branch=master
             :target: https://travis-ci.org/reclosedev/requests-cache
         
-        .. image:: https://pypip.in/version/requests-cache/badge.svg
-            :target: https://pypi.python.org/pypi/requests-cache/
-            :alt: Latest Version
+        .. image:: https://coveralls.io/repos/reclosedev/requests-cache/badge.svg?branch=master&service=github
+            :target: https://coveralls.io/github/reclosedev/requests-cache?branch=master
+        
         
         Usage example
         -------------
@@ -70,6 +70,17 @@ Description: requests-cache
         History
         -------
         
+        0.4.12 (2016-03-19)
+        +++++++++++++++++++
+        * Fix ability to pass backend instance in ``install_cache`` #61
+        
+        
+        0.4.11 (2016-03-07)
+        +++++++++++++++++++
+        * ``ignore_parameters`` feature, thanks to @themiurgo and @YetAnotherNerd (#52, #55)
+        * More informative message for missing backend dependencies, thanks to @Garrett-R (#60)
+        
+        
         0.4.10 (2015-04-28)
         +++++++++++++++++++
         * Better transactional handling in sqlite #50, thanks to @rgant
diff --git a/README.rst b/README.rst
index 818a24f..c749a1c 100644
--- a/README.rst
+++ b/README.rst
@@ -8,9 +8,9 @@ Requests-cache is a transparent persistent cache for requests_ (version >= 1.1.0
 .. image:: https://travis-ci.org/reclosedev/requests-cache.svg?branch=master
     :target: https://travis-ci.org/reclosedev/requests-cache
 
-.. image:: https://pypip.in/version/requests-cache/badge.svg
-    :target: https://pypi.python.org/pypi/requests-cache/
-    :alt: Latest Version
+.. image:: https://coveralls.io/repos/reclosedev/requests-cache/badge.svg?branch=master&service=github
+    :target: https://coveralls.io/github/reclosedev/requests-cache?branch=master
+
 
 Usage example
 -------------
diff --git a/docs/index.rst b/docs/index.rst
index dd75dea..ad390d1 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -7,8 +7,7 @@ Requests-cache documentation
 ============================
 
 `Requests-cache <http://pypi.python.org/pypi/requests-cache>`_
-is a transparent persistent cache for requests_ (version >= 1.1.0
-see :ref:`incompatible_changes`) library.
+is a transparent persistent cache for requests_ (version >= 1.1.0) library.
 
 Source code and issue tracking can be found at
 `GitHub <https://github.com/reclosedev/requests-cache>`_.
diff --git a/docs/make.bat b/docs/make.bat
old mode 100755
new mode 100644
diff --git a/docs/user_guide.rst b/docs/user_guide.rst
index 37580a8..56b148e 100644
--- a/docs/user_guide.rst
+++ b/docs/user_guide.rst
@@ -17,6 +17,12 @@ or download latest version from version control::
     cd requests-cache
     python setup.py install
 
+
+.. warning:: Version updates of ``requests``, ``urllib3`` or ``requests_cache`` itself can break existing
+            cache database (see https://github.com/reclosedev/requests-cache/issues/56 ).
+            So if your code relies on cache, or is expensive in terms of time and traffic, please be sure to use
+            something like ``virtualenv`` and pin your requirements.
+
 .. _pip: http://pypi.python.org/pypi/pip/
 .. _easy_install: http://pypi.python.org/pypi/setuptools
 
@@ -126,30 +132,33 @@ List of available backends:
 
 - ``'sqlite'``  - sqlite database (**default**)
 - ``'memory'``  - not persistent,  stores all data in Python ``dict`` in memory
-- ``'mongodb'`` - (**experimental**) MongoDB database (``pymongo`` required)
+- ``'mongodb'`` - (**experimental**) MongoDB database (``pymongo < 3.0`` required)
 - ``'redis'``   - stores all data on a redis data store (``redis`` required)
 
-  .. note:: ``pymongo`` doesn't work fine with `gevent <http://www.gevent.org/>`_ which powers `grequests <https://github.com/kennethreitz/grequests>`_,
-            but there is some workarounds, see question on
-            `StackOverflow <http://stackoverflow.com/questions/7166998/pymongo-gevent-throw-me-a-banana-and-just-monkey-patch>`_.
-
 You can write your own and pass instance to :func:`install_cache` or :class:`CachedSession` constructor.
 See :ref:`cache_backends` API documentation and sources.
 
+.. _expiration:
 
-.. _incompatible_changes:
+Expiration
+----------
 
-Backward incompatible changes
------------------------------
-
-There is backward incompatible changes introduced in version 0.3.0:
-
-* `expire_after` is now seconds
-* UTC time in cache
-* Storage backends are now using hash for keys
-* Renamed methods in backends
+If you are using cache with ``expire_after`` parameter set, responses are removed from the storage only when the same
+request is made. Since the store sizes can get out of control pretty quickly with expired items
+you can remove them using :func:`remove_expired_responses`
+or :meth:`BaseCache.remove_old_entries(created_before) <requests_cache.backends.base.BaseCache.remove_old_entries>`.
+::
 
+    expire_after = timedelta(hours=1)
+    requests_cache.install_cache(expire_after=expire_after)
+    ...
+    requests_cache.remove_expired_responses()
+    # or
+    remove_old_entries.get_cache().remove_old_entries(datetime.utcnow() - expire_after)
+    # when used as session
+    session = CachedSession(..., expire_after=expire_after)
+    ...
+    session.cache.remove_old_entries(datetime.utcnow() - expire_after)
 
-----------------------
 
-For more information see :doc:`API reference <api>` .
+For more information see :doc:`API reference <api>`.
diff --git a/requests_cache.egg-info/PKG-INFO b/requests_cache.egg-info/PKG-INFO
index 0255666..8bcc8bf 100644
--- a/requests_cache.egg-info/PKG-INFO
+++ b/requests_cache.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: requests-cache
-Version: 0.4.10
+Version: 0.4.12
 Summary: Persistent cache for requests library
 Home-page: https://github.com/reclosedev/requests-cache
 Author: Roman Haritonov
@@ -16,9 +16,9 @@ Description: requests-cache
         .. image:: https://travis-ci.org/reclosedev/requests-cache.svg?branch=master
             :target: https://travis-ci.org/reclosedev/requests-cache
         
-        .. image:: https://pypip.in/version/requests-cache/badge.svg
-            :target: https://pypi.python.org/pypi/requests-cache/
-            :alt: Latest Version
+        .. image:: https://coveralls.io/repos/reclosedev/requests-cache/badge.svg?branch=master&service=github
+            :target: https://coveralls.io/github/reclosedev/requests-cache?branch=master
+        
         
         Usage example
         -------------
@@ -70,6 +70,17 @@ Description: requests-cache
         History
         -------
         
+        0.4.12 (2016-03-19)
+        +++++++++++++++++++
+        * Fix ability to pass backend instance in ``install_cache`` #61
+        
+        
+        0.4.11 (2016-03-07)
+        +++++++++++++++++++
+        * ``ignore_parameters`` feature, thanks to @themiurgo and @YetAnotherNerd (#52, #55)
+        * More informative message for missing backend dependencies, thanks to @Garrett-R (#60)
+        
+        
         0.4.10 (2015-04-28)
         +++++++++++++++++++
         * Better transactional handling in sqlite #50, thanks to @rgant
diff --git a/requests_cache.egg-info/SOURCES.txt b/requests_cache.egg-info/SOURCES.txt
index b215e86..72ee778 100644
--- a/requests_cache.egg-info/SOURCES.txt
+++ b/requests_cache.egg-info/SOURCES.txt
@@ -7,6 +7,7 @@ example.py
 history_issue.py
 howdoi_issue.py
 sandbox.py
+setup.cfg
 setup.py
 docs/Makefile
 docs/api.rst
diff --git a/requests_cache/__init__.py b/requests_cache/__init__.py
index 368842e..eeaaae8 100644
--- a/requests_cache/__init__.py
+++ b/requests_cache/__init__.py
@@ -23,7 +23,7 @@
     :license: BSD, see LICENSE for more details.
 """
 __docformat__ = 'restructuredtext'
-__version__ = '0.4.10'
+__version__ = '0.4.12'
 
 from .core import(
     CachedSession, install_cache, uninstall_cache,
diff --git a/requests_cache/backends/__init__.py b/requests_cache/backends/__init__.py
index 29da672..3623e95 100644
--- a/requests_cache/backends/__init__.py
+++ b/requests_cache/backends/__init__.py
@@ -14,6 +14,12 @@ registry = {
     'memory': BaseCache,
 }
 
+_backend_dependencies = {
+    'sqlite': 'sqlite3',
+    'mongo': 'pymongo',
+    'redis': 'redis'
+}
+
 try:
     # Heroku doesn't allow the SQLite3 module to be installed
     from .sqlite import DbCache
@@ -35,16 +41,23 @@ except ImportError:
 
 
 def create_backend(backend_name, cache_name, options):
+    if isinstance(backend_name, BaseCache):
+        return backend_name
+
     if backend_name is None:
         backend_name = _get_default_backend_name()
     try:
         return registry[backend_name](cache_name, **options)
     except KeyError:
-        raise ValueError('Unsupported backend "%s" try one of: %s' %
-                         (backend_name, ', '.join(registry.keys())))
+        if backend_name in _backend_dependencies:
+            raise ImportError('You must install the python package: %s' %
+                              _backend_dependencies[backend_name])
+        else:
+            raise ValueError('Unsupported backend "%s" try one of: %s' %
+                             (backend_name, ', '.join(registry.keys())))
 
 
 def _get_default_backend_name():
     if 'sqlite' in registry:
         return 'sqlite'
-    return 'memory'
\ No newline at end of file
+    return 'memory'
diff --git a/requests_cache/backends/base.py b/requests_cache/backends/base.py
index 1a05037..2c61cf2 100644
--- a/requests_cache/backends/base.py
+++ b/requests_cache/backends/base.py
@@ -14,7 +14,7 @@ from io import BytesIO
 
 import requests
 
-from ..compat import is_py2
+from ..compat import is_py2, urlencode, urlparse, urlunparse, parse_qsl
 
 
 _DEFAULT_HEADERS = requests.utils.default_headers()
@@ -32,6 +32,7 @@ class BaseCache(object):
         #: `key_in_cache` -> `response` mapping
         self.responses = {}
         self._include_get_headers = kwargs.get("include_get_headers", False)
+        self._ignored_parameters = set(kwargs.get("ignored_parameters") or [])
 
     def save_response(self, key, response):
         """ Save response to cache
@@ -100,6 +101,21 @@ class BaseCache(object):
         self.responses.clear()
         self.keys_map.clear()
 
+    def remove_old_entries(self, created_before):
+        """ Deletes entries from cache with creation time older than ``created_before``
+        """
+        keys_to_delete = set()
+        for key in self.responses:
+            try:
+                response, created_at = self.responses[key]
+            except KeyError:
+                continue
+            if created_at < created_before:
+                keys_to_delete.add(key)
+
+        for key in keys_to_delete:
+            self.delete(key)
+
     def has_key(self, key):
         """ Returns `True` if cache has `key`, `False` otherwise
         """
@@ -170,12 +186,40 @@ class BaseCache(object):
         result.history = tuple(self.restore_response(r, seen) for r in response.history)
         return result
 
+    def _remove_ignored_parameters(self, request):
+
+        def filter_ignored_parameters(data):
+            return [(k, v) for k, v in data if k not in self._ignored_parameters]
+
+        url = urlparse(request.url)
+        query = parse_qsl(url.query)
+        query = filter_ignored_parameters(query)
+        query = urlencode(query)
+        url = urlunparse((url.scheme, url.netloc, url.path, url.params, query, url.fragment))
+        body = request.body
+        content_type = request.headers.get('content-type')
+        if body and content_type:
+            if content_type == 'application/x-www-form-urlencoded':
+                body = parse_qsl(body)
+                body = filter_ignored_parameters(body)
+                body = urlencode(body)
+            elif content_type == 'application/json':
+                import json
+                body = json.loads(body)
+                body = filter_ignored_parameters(sorted(body.items()))
+                body = json.dumps(body)
+        return url, body
+
     def create_key(self, request):
+        if self._ignored_parameters:
+            url, body = self._remove_ignored_parameters(request)
+        else:
+            url, body = request.url, request.body
         key = hashlib.sha256()
         key.update(_to_bytes(request.method.upper()))
-        key.update(_to_bytes(request.url))
+        key.update(_to_bytes(url))
         if request.body:
-            key.update(_to_bytes(request.body))
+            key.update(_to_bytes(body))
         else:
             if self._include_get_headers and request.headers != _DEFAULT_HEADERS:
                 for name, value in sorted(request.headers.items()):
diff --git a/requests_cache/compat.py b/requests_cache/compat.py
index daaf0bb..c0039a2 100644
--- a/requests_cache/compat.py
+++ b/requests_cache/compat.py
@@ -80,7 +80,7 @@ is_solaris = ('solar==' in str(sys.platform).lower())   # Complete guess.
 
 if is_py2:
     from urllib import quote, unquote, urlencode
-    from urlparse import urlparse, urlunparse, urljoin, urlsplit
+    from urlparse import urlparse, urlunparse, urljoin, urlsplit, parse_qsl
     from urllib2 import parse_http_list
     import cookielib
     from StringIO import StringIO
@@ -91,7 +91,7 @@ if is_py2:
 
 
 elif is_py3:
-    from urllib.parse import urlparse, urlunparse, urljoin, urlsplit, urlencode, quote, unquote
+    from urllib.parse import urlparse, urlunparse, urljoin, urlsplit, urlencode, quote, unquote, parse_qsl
     from urllib.request import parse_http_list
     from http import cookiejar as cookielib
     from http.cookies import SimpleCookie
diff --git a/requests_cache/core.py b/requests_cache/core.py
index 36e4d59..055eb06 100644
--- a/requests_cache/core.py
+++ b/requests_cache/core.py
@@ -34,8 +34,7 @@ class CachedSession(OriginalSession):
 
     def __init__(self, cache_name='cache', backend=None, expire_after=None,
                  allowable_codes=(200,), allowable_methods=('GET',),
-                 old_data_on_error=False,
-                 **backend_options):
+                 old_data_on_error=False, **backend_options):
         """
         :param cache_name: for ``sqlite`` backend: cache file will start with this prefix,
                            e.g ``cache.sqlite``
@@ -61,13 +60,12 @@ class CachedSession(OriginalSession):
         :param include_get_headers: If `True` headers will be part of cache key.
                                     E.g. after get('some_link', headers={'Accept':'application/json'})
                                     get('some_link', headers={'Accept':'application/xml'}) is not from cache.
+        :param ignored_parameters: List of parameters to be excluded from the cache key.
+                                   Useful when requesting the same resource through different
+                                   credentials or access tokens, passed as parameters.
         :param old_data_on_error: If `True` it will return expired cached response if update fails
         """
-        if backend is None or isinstance(backend, basestring):
-            self.cache = backends.create_backend(backend, cache_name,
-                                                 backend_options)
-        else:
-            self.cache = backend
+        self.cache = backends.create_backend(backend, cache_name, backend_options)
         self._cache_name = cache_name
 
         if expire_after is not None and not isinstance(expire_after, timedelta):
@@ -153,6 +151,13 @@ class CachedSession(OriginalSession):
         finally:
             self._is_cache_disabled = False
 
+    def remove_expired_responses(self):
+        """ Removes expired responses from storage
+        """
+        if not self._cache_expire_after:
+            return
+        self.cache.remove_old_entries(datetime.utcnow() - self._cache_expire_after)
+
     def __repr__(self):
         return (
             "<CachedSession(%s('%s', ...), expire_after=%s, "
@@ -164,8 +169,8 @@ class CachedSession(OriginalSession):
 
 
 def install_cache(cache_name='cache', backend=None, expire_after=None,
-                 allowable_codes=(200,), allowable_methods=('GET',),
-                 session_factory=CachedSession, **backend_options):
+                  allowable_codes=(200,), allowable_methods=('GET',),
+                  session_factory=CachedSession, **backend_options):
     """
     Installs cache for all ``Requests`` requests by monkey-patching ``Session``
 
@@ -256,6 +261,12 @@ def clear():
     get_cache().clear()
 
 
+def remove_expired_responses():
+    """ Removes expired responses from storage
+    """
+    return requests.Session().remove_expired_responses()
+
+
 def _patch_session_factory(session_factory=CachedSession):
     requests.Session = requests.sessions.Session = session_factory
 
@@ -264,7 +275,6 @@ def _normalize_parameters(params):
     """ If builtin dict is passed as parameter, returns sorted list
     of key-value pairs
     """
-
     if type(params) is dict:
         return sorted(params.items(), key=itemgetter(0))
     return params
diff --git a/setup.cfg b/setup.cfg
index b14b0bc..9ea0a41 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,3 +1,6 @@
+[bdist_wheel]
+universal = 1
+
 [egg_info]
 tag_build = 
 tag_date = 0
diff --git a/setup.py b/setup.py
index 78801dd..f959ce3 100644
--- a/setup.py
+++ b/setup.py
@@ -20,7 +20,7 @@ setup(
     packages=['requests_cache',
               'requests_cache.backends',
               'requests_cache.backends.storage'],
-    version='0.4.10',
+    version='0.4.12',
     description='Persistent cache for requests library',
     author='Roman Haritonov',
     author_email='reclosedev at gmail.com',
diff --git a/tests/test_cache.py b/tests/test_cache.py
index 56a2858..31dd671 100644
--- a/tests/test_cache.py
+++ b/tests/test_cache.py
@@ -70,6 +70,15 @@ class CacheTestCase(unittest.TestCase):
         with self.assertRaises(ValueError):
             CachedSession(CACHE_NAME, backend='nonexistent')
 
+    @mock.patch('requests_cache.backends.registry')
+    def test_missing_backend_dependency(self, mocked_registry):
+        # Testing that the correct error is thrown when a user does not have
+        # the Python package `redis` installed.  We mock out the registry
+        # to simulate `redis` not being installed.
+        mocked_registry.__getitem__.side_effect = KeyError
+        with self.assertRaises(ImportError):
+            CachedSession(CACHE_NAME, backend='redis')
+
     def test_hooks(self):
         state = defaultdict(int)
         for hook in ('response',):  # TODO it's only one hook here
@@ -343,6 +352,109 @@ class CacheTestCase(unittest.TestCase):
             with self.assertRaises(Exception):
                 s.get(url)
 
+    def test_ignore_parameters_get(self):
+        url = httpbin("get")
+        ignored_param = "ignored"
+        usual_param = "some"
+        params = {ignored_param: "1", usual_param: "1"}
+
+        s = CachedSession(CACHE_NAME, CACHE_BACKEND,
+                          ignored_parameters=[ignored_param])
+
+        r = s.get(url, params=params)
+        self.assertIn(ignored_param, r.json()['args'].keys())
+        self.assertFalse(r.from_cache)
+
+        self.assertTrue(s.get(url, params=params).from_cache)
+
+        params[ignored_param] = "new"
+        self.assertTrue(s.get(url, params=params).from_cache)
+
+        params[usual_param] = "new"
+        self.assertFalse(s.get(url, params=params).from_cache)
+
+    def test_ignore_parameters_post(self):
+        url = httpbin("post")
+        ignored_param = "ignored"
+        usual_param = "some"
+        d = {ignored_param: "1", usual_param: "1"}
+
+        s = CachedSession(CACHE_NAME, CACHE_BACKEND,
+                          allowable_methods=('POST'),
+                          ignored_parameters=[ignored_param])
+
+        r = s.post(url, data=d)
+        self.assertIn(ignored_param, r.json()['form'].keys())
+        self.assertFalse(r.from_cache)
+
+        self.assertTrue(s.post(url, data=d).from_cache)
+
+        d[ignored_param] = "new"
+        self.assertTrue(s.post(url, data=d).from_cache)
+
+        d[usual_param] = "new"
+        self.assertFalse(s.post(url, data=d).from_cache)
+
+    def test_ignore_parameters_post_json(self):
+        url = httpbin("post")
+        ignored_param = "ignored"
+        usual_param = "some"
+        d = {ignored_param: "1", usual_param: "1"}
+
+        s = CachedSession(CACHE_NAME, CACHE_BACKEND,
+                          allowable_methods=('POST'),
+                          ignored_parameters=[ignored_param])
+
+        r = s.post(url, json=d)
+        self.assertIn(ignored_param, json.loads(r.json()['data']).keys())
+        self.assertFalse(r.from_cache)
+
+        self.assertTrue(s.post(url, json=d).from_cache)
+
+        d[ignored_param] = "new"
+        self.assertTrue(s.post(url, json=d).from_cache)
+
+        d[usual_param] = "new"
+        self.assertFalse(s.post(url, json=d).from_cache)
+
+    def test_ignore_parameters_post_raw(self):
+        url = httpbin("post")
+        ignored_param = "ignored"
+        raw_data = "raw test data"
+
+        s = CachedSession(CACHE_NAME, CACHE_BACKEND,
+                          allowable_methods=('POST'),
+                          ignored_parameters=[ignored_param])
+
+        self.assertFalse(s.post(url, data=raw_data).from_cache)
+        self.assertTrue(s.post(url, data=raw_data).from_cache)
+
+        raw_data = "new raw data"
+        self.assertFalse(s.post(url, data=raw_data).from_cache)
+
+    @mock.patch("requests_cache.backends.base.datetime")
+    @mock.patch("requests_cache.core.datetime")
+    def test_remove_expired_entries(self, datetime_mock, datetime_mock2):
+        expire_after = timedelta(minutes=10)
+        start_time = datetime.utcnow().replace(year=2010, minute=0)
+        datetime_mock.utcnow.return_value = start_time
+        datetime_mock2.utcnow.return_value = start_time
+
+        s = CachedSession(CACHE_NAME, CACHE_BACKEND, expire_after=expire_after)
+        s.get(httpbin('get'))
+        s.get(httpbin('relative-redirect/3'))
+        datetime_mock.utcnow.return_value = start_time + expire_after * 2
+        datetime_mock2.utcnow.return_value = datetime_mock.utcnow.return_value
+
+        ok_url = 'get?x=1'
+        s.get(httpbin(ok_url))
+        self.assertEqual(len(s.cache.responses), 3)
+        self.assertEqual(len(s.cache.keys_map), 3)
+        s.remove_expired_responses()
+        self.assertEqual(len(s.cache.responses), 1)
+        self.assertEqual(len(s.cache.keys_map), 0)
+        self.assertIn(ok_url, list(s.cache.responses.values())[0][0].url)
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/test_monkey_patch.py b/tests/test_monkey_patch.py
index f944014..596544b 100644
--- a/tests/test_monkey_patch.py
+++ b/tests/test_monkey_patch.py
@@ -14,6 +14,8 @@ from requests.sessions import Session as OriginalSession
 
 import requests_cache
 from requests_cache import CachedSession
+from requests_cache.backends import BaseCache
+
 
 CACHE_NAME = 'requests_cache_test'
 CACHE_BACKEND = 'sqlite'
@@ -66,6 +68,18 @@ class MonkeyPatchTestCase(unittest.TestCase):
         self.assertIn("new_one", s.__attrs__)
         self.assertTrue(isinstance(s, CachedSession))
 
+    def test_passing_backend_instance_support(self):
+
+        class MyCache(BaseCache):
+            pass
+
+        backend = MyCache()
+        requests_cache.install_cache(name=CACHE_NAME, backend=backend)
+        self.assertIs(requests.Session().cache, backend)
+
+        session = CachedSession(backend=backend)
+        self.assertIs(session.cache, backend)
+
 
 if __name__ == '__main__':
     unittest.main()

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-requests-cache.git



More information about the Python-modules-commits mailing list