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 keyword 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(
... cache_name='http_cache',
... per_second=5,
... bucket_class=RedisBucket,
... backend=RedisCache(),
... )
Warning
When using mixins, use keyword arguments instead of positional arguments whenever possible. The order of positional arguments will change based on inheritance order, but keyword arguments can be passed in any order.
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.