Compatibility with other libraries#
This library works by patching and/or extending requests.Session. Many other libraries
out there do the same thing, making it potentially difficult to combine them.
For that scenario, a mixin class is provided, so you can create a custom class with behavior from multiple Session-modifying libraries:
>>> from requests import Session
>>> from requests_cache import CacheMixin
>>> from some_other_lib import SomeOtherMixin
>>> class CustomSession(CacheMixin, SomeOtherMixin, Session):
...     """Session class with features from both some_other_lib and requests-cache"""
Requests-HTML#
requests-html is one library that works with this method:
>>> import requests
>>> from requests_cache import CacheMixin, install_cache
>>> from requests_html import HTMLSession
>>> class CachedHTMLSession(CacheMixin, HTMLSession):
...     """Session with features from both CachedSession and HTMLSession"""
>>> session = CachedHTMLSession()
>>> response = session.get('https://github.com/')
>>> print(response.from_cache, response.html.links)
Or if you are using install_cache(), you can use the session_factory argument:
>>> install_cache(session_factory=CachedHTMLSession)
>>> response = requests.get('https://github.com/')
>>> print(response.from_cache, response.html.links)
The same approach can be used with other libraries that subclass requests.Session.
Requests-Futures#
Some libraries, including requests-futures, support wrapping an existing session object:
>>> from requests_cache import CachedSession
>>> from requests_futures.sessions import FuturesSession
>>> session = FuturesSession(session=CachedSession())
In this case, FuturesSession must wrap CachedSession rather than the other way around, since
FuturesSession returns (as you might expect) futures rather than response objects.
See issue #135 for more notes on this.
Requests-OAuthlib#
Usage with requests-oauthlib is the same as other
libraries that subclass requests.Session:
>>> from requests_cache import CacheMixin
>>> from requests_oauthlib import OAuth2Session
>>> class CachedOAuth2Session(CacheMixin, OAuth2Session):
...     """Session with features from both CachedSession and OAuth2Session"""
>>> session = CachedOAuth2Session('my_client_id')
Requests-Ratelimiter#
requests-ratelimiter adds rate-limiting to requests via the pyrate-limiter library. It also provides a mixin, but note that the inheritance order is important: If rate-limiting is applied after caching, you get the added benefit of not counting cache hits against your rate limit.
>>> from pyrate_limiter import RedisBucket, RequestRate, Duration
>>> from requests import Session
>>> from requests_cache import CacheMixin, RedisCache
>>> from requests_ratelimiter import LimiterMixin
>>> class CachedLimiterSession(CacheMixin, LimiterMixin, Session):
...     """Session class with caching and rate-limiting behavior. Accepts arguments for both
...     LimiterSession and CachedSession.
...     """
>>> # Limit non-cached requests to 5 requests per second, with unlimited cached requests
>>> # Optionally use Redis as both the bucket backend and the cache backend
>>> session = CachedLimiterSession(
...     per_second=5,
...     bucket_class=RedisBucket,
...     backend=RedisCache(),
... )
Internet Archive#
Usage with internetarchive is the same as other libraries
that subclass requests.Session:
>>> from requests_cache import CacheMixin
>>> from internetarchive.session import ArchiveSession
>>> class CachedArchiveSession(CacheMixin, ArchiveSession):
...     """Session with features from both CachedSession and ArchiveSession"""
>>> session = CachedArchiveSession()
Requests-Mock#
requests-mock has multiple methods for mocking requests, including a contextmanager, decorator, fixture, and adapter. There are a few different options for using it with requests-cache, depending on how you want your tests to work.
Disabling requests-cache#
If you have an application that uses requests-cache and you just want to use requests-mock in your tests, the easiest thing to do is to disable requests-cache.
For example, if you are using install_cache() in your application and the
requests-mock pytest fixture in your
tests, you could wrap it in another fixture that uses uninstall_cache() or
disabled():
Or if you use a CachedSession object, you could replace it with a regular Session, for example:
>>> import unittest
>>> import pytest
>>> import requests
>>> @pytest.fixure(scope='function', autouse=True)
>>> def disable_requests_cache():
...     """Replace CachedSession with a regular Session for all test functions"""
...     with unittest.mock.patch('requests_cache.CachedSession', requests.Session):
...         yield
Combining requests-cache with requests-mock#
If you want both caching and mocking features at the same time, you can attach requests-mock’s
adapter to a CachedSession:
Building a mocker using requests-cache data#
Another approach is to use cached data to dynamically define mock requests + responses. This has the advantage of only using request-mock’s behavior for request matching.
@pytest.fixture(scope='session')
def mock_session():
    """Fixture that provides a session with mocked URLs and responses based on cache data"""
    adapter = Adapter()
    cache = CachedSession(TEST_DB).cache
    for response in cache.responses.values():
        adapter.register_uri(
            response.request.method,
            response.request.url,
            content=response.content,
            headers=response.headers,
            status_code=response.status_code,
        )
        print(f'Added mock response: {response}')
    session = Session()
    session.mount('http://', adapter)
    session.mount('https://', adapter)
    yield session
To turn that into a complete example:
Responses#
Usage with the responses library is similar to the requests-mock examples above.
VCR#
If you would like to reuse your cached response data for unit tests, one option is to convert your cache into a format compatible with VCR-vased libraries like vcrpy and betamax.