New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor cached response info & initialization into a separate class #189
Conversation
* Pass per-request expiration in request params instead of setting as a temporary instance variable * Make use of dict ordering from python3.6+ in _normalize_parameters() * Add some more type annotations to `CachedSession` methods * Remove `expires_before` param from remove_old_entries, and always use the current time * Remove `relative_to` param from `CachedSession._determine_expiration_datetime` and use mock values in unit tests instead
@shoeffner To make this work with the changes you added in PR #177, I needed to change a few things:
I hope you're okay with those changes. Let me know if you have any suggestions, or if one of those changes is inconvenient for the use cases you had in mind. |
I am completely fine with those changes, the 'default' etc. solution was just if someone would like to have some more custom control over when to cache what and when to reset it. But allowing None for that purpose and using the simpler semantics is definitely a plus. |
Overall this is a very good rewrite of multiple bits and pieces. It is a massive PR so there might be things I didn't see, but except for a few minor issues listed above I think this is really good. While going through the PR I found that the documentation on install_cache is a little bit short (no mention of the kwargs or how the default backend is chosen), but that is something for another PR. |
@shoeffner Thanks for reviewing the tests! That's super helpful.
Yeah, and after going through the backlog of issues, I've noticed several other things that should be explained more in the docs. Differences between using |
… logic into CachedResponse class: * Replace `_RawStore` with `CachedHTTPResponse` class to wrap raw responses * Maintain support for streaming requests (#68) * Improve handling for generator usage * Add support for use with `pandas.read_csv()` and similar readers (#148) * Add support for use as a context manager (#148) * Add support for `decode_content` arg * Fix streaming requests when used with memory backend (#188) * Verified that `PreparedRequest.body` is always encoded in utf-8, so no need to detect encoding (Re: TODO note) * Response creation time and expiration time are stored as CachedResponse, so the `(response, timestamp)` tuple is no longer necessary * Rename `response.expire_after` and `response.cache_date` to `expires` and `created_at`, respectively, based on browser cache directives * Add optional `expire_after` param to `CachedSession.remove_old_responses()` * Make `CachedSession` members `allowable_codes, allowable_methods, filter_fn, old_data_on_error` public, since they can safely be modified after initialization * More type annotations and docstring updates * Move main cache documentation from `CacheMixin` to CachedSession`, since that's probably where a user would look first * Wrap temporary `_request_expire_after` in a contextmanager * Add intersphinx links for `urllib` classes & methods * Fix linting issues raised by flake8 * Start adding some unit tests using requests-mock tmp
… requests-mock and fixtures
I'm going to go ahead and merge now this so I can start working on my next PR. If anyone has more comments or suggestions on this one, I can address them in a follow-up PR. |
Closes #99, #148, #186 , #187, #188, and does some of the work for #169 and #184.
Summary
The goal of this PR is to reduce code complexity, and hopefully make things a little easier for others who want to contribute. Some of the logic around getting and saving responses had gotten a bit complicated as more features have been added, mainly in:
CachedSession.request()
CachedSession.send()
BaseCache.set_response()
(and associated helper methods)BaseCache.get_response()
(and associated helper methods)I've consolidated most of the logic around expiration, serializiation compatibility, and other response object handling into a separate class,
CachedResponse
. This simplifies the above methods, removes most of the code duplication, and fixes a few other issues. According to radon, all classes/modules/methods except two have an 'A' maintainability rating (CC <= 5).Changes
Short version: Most of the important bits are here: requests_cache/response.py
Serialization/Deserialization
CachedResponse
, so the timestamp from the(response, timestamp)
tuple is no longer neededCachedResponse.is_expired
can be used to indicate if an old response was returned as the result of an error withold_data_on_error=True
(Detect when a cached response is returned because of an error #99)_RawStore
withCachedHTTPResponse
class to wrap raw responses, and:pandas.read_csv()
and similar readers (_RawStore
doesn’t behave likeurllib3.response.HTTPResponse
#148)_RawStore
doesn’t behave likeurllib3.response.HTTPResponse
#148)decode_content
paramPreparedRequest.body
is always encoded in utf-8, so no need to detect encodingExpiration
expire_after
param toCachedSession.remove_old_responses()
_request_expire_after
in a contextmanagerexpires_before
param from remove_old_entries, and always use the current timerelative_to
param fromCachedSession._determine_expiration_datetime
for unit testing and patchdatetime.now
in unit tests insteadresponse.expire_after
andresponse.cache_date
toexpires
andcreated_at
, respectively, based on browser cachingDocs
CachedSession
,CachedResponse
, andBaseCache
urllib
classes & methodsrequests_mock.Adapter
Tests
/tmp
test_cache
as pytest-style functions instead ofunittest.TestCase
methodsMisc
Backwards-compatibility
These changes don't break compatibility with code using requests-cache <= 0.5.2, but they aren't compatible with previously cached data due to the different serialization format. Retrieving a previously cached response will fail quietly and simply fetch and cache a new response. Since the docs already warn about this potentially happening with new releases, I don't think this is a problem.