Thanks Carlton Gibson, Chris Jerdonek, David Smith, Keryn Knight,
Mariusz Felisiak, and Nick Pope for reviews and mentoring this
Google Summer of Code 2021 project.
The validate_key() function should be called after make_key() to ensure
that the validation is performed on the key that will actually be
stored in the cache.
Co-authored-by: Mariusz Felisiak <felisiak.mariusz@gmail.com>
Many of the cache operations make use of the default argument to the
.get() operation to determine whether the key was found in the cache.
The default value of the default argument is None, so this results in
these operations assuming that None is not stored in the cache when it
actually is. Adding a sentinel object solves this issue.
Unfortunately the unmaintained python-memcached library does not support
a default argument to .get(), so the previous behavior is preserved for
the deprecated MemcachedCache backend.
There are 8 cache backends to test and each test of touch() takes
~7s → ~56s. This seems excessive and it feels like we should be able
to reduce this significantly. time.sleep() accepts floating point
values and is guaranteed to sleep for at least the number of seconds
specified as of Python 3.5.
We do run the risk that there may be spurious test failures from this,
but that already seemed to be the case anyway.
The servers property can be overridden to allow memcached backends to
alter the server configuration prior to it being passed to instantiate
the client. This allows avoidance of documentation for per-backend
differences, e.g. stripping the 'unix:' prefix for pylibmc.
DatabaseCache._cull implementation could fail if no key was found to
perform a deletion in the table. This prevented the new cache key/value
from being correctly added.
This is the new contract since middleware refactoring in Django 1.10.
Co-authored-by: Carlton Gibson <carlton.gibson@noumenal.es>
Co-authored-by: Mariusz Felisiak <felisiak.mariusz@gmail.com>
Added assertions to compare results of .add(), .delete(), .touch(),
.incr(), .decr(), and .get_or_set() methods.
Made tests use assertIs() rather than assertTrue/False().
* assertIsNone()/assertIsNotNone() instead of comparing to None.
* assertLess() for < comparisons.
* assertIs() for 'is' expressions.
* assertIsInstance() for isinstance() expressions.
* rounding of assertAlmostEqual() for round() expressions.
* assertIs(..., True/False) instead of comparing to True/False.
* assertIs()/assertIsNot() for ==/!= comparisons.
* assertNotEqual() for == comparisons.
* assertTrue()/assertFalse() instead of comparing to True/False.