Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-django-redis for openSUSE:Factory checked in at 2023-07-03 17:42:15 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-django-redis (Old) and /work/SRC/openSUSE:Factory/.python-django-redis.new.13546 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-django-redis" Mon Jul 3 17:42:15 2023 rev:12 rq:1096317 version:5.3.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-django-redis/python-django-redis.changes 2023-06-26 18:17:01.802719908 +0200 +++ /work/SRC/openSUSE:Factory/.python-django-redis.new.13546/python-django-redis.changes 2023-07-03 17:42:17.280542871 +0200 @@ -1,0 +2,19 @@ +Sat Jul 1 20:30:43 UTC 2023 - Dirk Müller <dmuel...@suse.com> + +- update to 5.3.0: + * Add support for django 4 + * Access `django_redis.cache.DJANGO_REDIS_SCAN_ITERSIZE` and + `django_redis.client.herd.CACHE_HERD_TIMEOUT` in runtime to + not read Django settings in import time. + * Skipping pickle serializer test for django >= 4.2 + * Speed up deleting multiple keys by a pattern with pipelines + and larger itersize + * Print full exception traceback when logging ignored + exceptions + * Fix mypy linting + * Added support for python 3.11 + * Fix CI, running tox<4 to still support Python 3.6. + * Dropped support for django 2.2 and 3.1 + * Run actions & tox against Django 4..2 + +------------------------------------------------------------------- Old: ---- django-redis-5.2.0.tar.gz New: ---- django-redis-5.3.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-django-redis.spec ++++++ --- /var/tmp/diff_new_pack.BWqMFN/_old 2023-07-03 17:42:17.968546922 +0200 +++ /var/tmp/diff_new_pack.BWqMFN/_new 2023-07-03 17:42:17.972546945 +0200 @@ -18,7 +18,7 @@ %{?sle15_python_module_pythons} Name: python-django-redis -Version: 5.2.0 +Version: 5.3.0 Release: 0 Summary: A redis cache backend for Django License: BSD-3-Clause ++++++ django-redis-5.2.0.tar.gz -> django-redis-5.3.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-redis-5.2.0/AUTHORS.rst new/django-redis-5.3.0/AUTHORS.rst --- old/django-redis-5.2.0/AUTHORS.rst 2021-12-22 16:08:32.000000000 +0100 +++ new/django-redis-5.3.0/AUTHORS.rst 2023-06-16 14:12:53.000000000 +0200 @@ -1,10 +1,10 @@ Andrei Antoukh / niwibe <https://github.com/niwibe> -Sean Bleier <http://github.com/sebleier> -Matt Dennewitz <http://github.com/blackbrrr> -Jannis Leidel <http://github.com/jezdez> -S. Angel / Twidi <http://github.com/twidi> -Noah Kantrowitz / coderanger <http://github.com/coderanger> -Martin Mahner / bartTC <http://github.com/bartTC> +Sean Bleier <https://github.com/sebleier> +Matt Dennewitz <https://github.com/blackbrrr> +Jannis Leidel <https://github.com/jezdez> +S. Angel / Twidi <https://github.com/twidi> +Noah Kantrowitz / coderanger <https://github.com/coderanger> +Martin Mahner / bartTC <https://github.com/bartTC> Timothée Peignier / cyberdelia <https://github.com/cyberdelia> Lior Sion / liorsion <https://github.com/liorsion> Ales Zoulek / aleszoulek <https://github.com/aleszoulek> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-redis-5.2.0/PKG-INFO new/django-redis-5.3.0/PKG-INFO --- old/django-redis-5.2.0/PKG-INFO 2021-12-22 16:08:41.102405300 +0100 +++ new/django-redis-5.3.0/PKG-INFO 2023-06-16 14:13:06.367214400 +0200 @@ -1,19 +1,18 @@ Metadata-Version: 2.1 Name: django-redis -Version: 5.2.0 +Version: 5.3.0 Summary: Full featured redis cache backend for Django. Home-page: https://github.com/jazzband/django-redis Author: Andrei Antoukh Author-email: n...@niwi.nz License: BSD-3-Clause -Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Framework :: Django -Classifier: Framework :: Django :: 2.2 -Classifier: Framework :: Django :: 3.1 Classifier: Framework :: Django :: 3.2 Classifier: Framework :: Django :: 4.0 +Classifier: Framework :: Django :: 4.1 +Classifier: Framework :: Django :: 4.2 Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent @@ -25,6 +24,7 @@ Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 Classifier: Topic :: Software Development :: Libraries Classifier: Topic :: Utilities Requires-Python: >=3.6 @@ -518,6 +518,15 @@ >>> from django.core.cache import cache >>> cache.delete_pattern("foo_*") +To achieve the best performance while deleting many keys, you should set ``DJANGO_REDIS_SCAN_ITERSIZE`` to a relatively +high number (e.g., 100_000) by default in Django settings or pass it directly to the ``delete_pattern``. + + +.. code-block:: pycon + + >>> from django.core.cache import cache + >>> cache.delete_pattern("foo_*", itersize=100_000) + Redis native commands ~~~~~~~~~~~~~~~~~~~~~ @@ -837,7 +846,7 @@ ^^^^^^^^^^^ This pluggable client helps dealing with the thundering herd problem. You can read more about it -on link: `Wikipedia <http://en.wikipedia.org/wiki/Thundering_herd_problem>`_ +on link: `Wikipedia <https://en.wikipedia.org/wiki/Thundering_herd_problem>`_ Like previous pluggable clients, it inherits all functionality from the default client, adding some additional methods for getting/setting keys. @@ -897,7 +906,7 @@ } } -.. _MsgPack: http://msgpack.org/ +.. _MsgPack: https://msgpack.org/ Pluggable Redis client ~~~~~~~~~~~~~~~~~~~~~~ @@ -997,5 +1006,3 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-redis-5.2.0/README.rst new/django-redis-5.3.0/README.rst --- old/django-redis-5.2.0/README.rst 2021-12-22 16:08:32.000000000 +0100 +++ new/django-redis-5.3.0/README.rst 2023-06-16 14:12:53.000000000 +0200 @@ -483,6 +483,15 @@ >>> from django.core.cache import cache >>> cache.delete_pattern("foo_*") +To achieve the best performance while deleting many keys, you should set ``DJANGO_REDIS_SCAN_ITERSIZE`` to a relatively +high number (e.g., 100_000) by default in Django settings or pass it directly to the ``delete_pattern``. + + +.. code-block:: pycon + + >>> from django.core.cache import cache + >>> cache.delete_pattern("foo_*", itersize=100_000) + Redis native commands ~~~~~~~~~~~~~~~~~~~~~ @@ -802,7 +811,7 @@ ^^^^^^^^^^^ This pluggable client helps dealing with the thundering herd problem. You can read more about it -on link: `Wikipedia <http://en.wikipedia.org/wiki/Thundering_herd_problem>`_ +on link: `Wikipedia <https://en.wikipedia.org/wiki/Thundering_herd_problem>`_ Like previous pluggable clients, it inherits all functionality from the default client, adding some additional methods for getting/setting keys. @@ -862,7 +871,7 @@ } } -.. _MsgPack: http://msgpack.org/ +.. _MsgPack: https://msgpack.org/ Pluggable Redis client ~~~~~~~~~~~~~~~~~~~~~~ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-redis-5.2.0/django_redis/__init__.py new/django-redis-5.3.0/django_redis/__init__.py --- old/django-redis-5.2.0/django_redis/__init__.py 2021-12-22 16:08:32.000000000 +0100 +++ new/django-redis-5.3.0/django_redis/__init__.py 2023-06-16 14:12:53.000000000 +0200 @@ -1,4 +1,4 @@ -VERSION = (5, 2, 0) +VERSION = (5, 3, 0) __version__ = ".".join(map(str, VERSION)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-redis-5.2.0/django_redis/cache.py new/django-redis-5.3.0/django_redis/cache.py --- old/django-redis-5.2.0/django_redis/cache.py 2021-12-22 16:08:32.000000000 +0100 +++ new/django-redis-5.3.0/django_redis/cache.py 2023-06-16 14:12:53.000000000 +0200 @@ -9,8 +9,6 @@ from .exceptions import ConnectionInterrupted -DJANGO_REDIS_SCAN_ITERSIZE = getattr(settings, "DJANGO_REDIS_SCAN_ITERSIZE", 10) - CONNECTION_INTERRUPTED = object() @@ -32,7 +30,7 @@ except ConnectionInterrupted as e: if self._ignore_exceptions: if self._log_ignored_exceptions: - self.logger.error(str(e)) + self.logger.exception("Exception ignored") return return_value raise e.__cause__ @@ -45,6 +43,9 @@ super().__init__(params) self._server = server self._params = params + self._default_scan_itersize = getattr( + settings, "DJANGO_REDIS_SCAN_ITERSIZE", 10 + ) options = params.get("OPTIONS", {}) self._client_cls = options.get( @@ -105,7 +106,7 @@ @omit_exception def delete_pattern(self, *args, **kwargs): - kwargs["itersize"] = kwargs.get("itersize", DJANGO_REDIS_SCAN_ITERSIZE) + kwargs.setdefault("itersize", self._default_scan_itersize) return self.client.delete_pattern(*args, **kwargs) @omit_exception diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-redis-5.2.0/django_redis/client/default.py new/django-redis-5.3.0/django_redis/client/default.py --- old/django-redis-5.2.0/django_redis/client/default.py 2021-12-22 16:08:32.000000000 +0100 +++ new/django-redis-5.3.0/django_redis/client/default.py 2023-06-16 14:12:53.000000000 +0200 @@ -393,9 +393,13 @@ try: count = 0 + pipeline = client.pipeline() + for key in client.scan_iter(match=pattern, count=itersize): - client.delete(key) + pipeline.delete(key) count += 1 + pipeline.execute() + return count except _main_exceptions as e: raise ConnectionInterrupted(connection=client) from e diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-redis-5.2.0/django_redis/client/herd.py new/django-redis-5.3.0/django_redis/client/herd.py --- old/django-redis-5.2.0/django_redis/client/herd.py 2021-12-22 16:08:32.000000000 +0100 +++ new/django-redis-5.3.0/django_redis/client/herd.py 2023-06-16 14:12:53.000000000 +0200 @@ -21,15 +21,12 @@ pass -CACHE_HERD_TIMEOUT = getattr(settings, "CACHE_HERD_TIMEOUT", 60) - - -def _is_expired(x): - if x >= CACHE_HERD_TIMEOUT: +def _is_expired(x, herd_timeout: int) -> bool: + if x >= herd_timeout: return True - val = x + random.randint(1, CACHE_HERD_TIMEOUT) + val = x + random.randint(1, herd_timeout) - if val >= CACHE_HERD_TIMEOUT: + if val >= herd_timeout: return True return False @@ -37,6 +34,7 @@ class HerdClient(DefaultClient): def __init__(self, *args, **kwargs): self._marker = Marker() + self._herd_timeout = getattr(settings, "CACHE_HERD_TIMEOUT", 60) super().__init__(*args, **kwargs) def _pack(self, value, timeout): @@ -55,7 +53,7 @@ now = int(time.time()) if herd_timeout < now: x = now - herd_timeout - return unpacked, _is_expired(x) + return unpacked, _is_expired(x, self._herd_timeout) return unpacked, False @@ -69,7 +67,6 @@ nx=False, xx=False, ): - if timeout is DEFAULT_TIMEOUT: timeout = self._backend.default_timeout @@ -85,7 +82,7 @@ ) packed = self._pack(value, timeout) - real_timeout = timeout + CACHE_HERD_TIMEOUT + real_timeout = timeout + self._herd_timeout return super().set( key, packed, timeout=real_timeout, version=version, client=client, nx=nx diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-redis-5.2.0/django_redis/client/sharded.py new/django-redis-5.3.0/django_redis/client/sharded.py --- old/django-redis-5.2.0/django_redis/client/sharded.py 2021-12-22 16:08:32.000000000 +0100 +++ new/django-redis-5.3.0/django_redis/client/sharded.py 2023-06-16 14:12:53.000000000 +0200 @@ -205,7 +205,6 @@ client=None, thread_local=True, ): - if client is None: key = self.make_key(key, version=version) client = self.get_server(key) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-redis-5.2.0/django_redis/pool.py new/django-redis-5.3.0/django_redis/pool.py --- old/django-redis-5.2.0/django_redis/pool.py 2021-12-22 16:08:32.000000000 +0100 +++ new/django-redis-5.3.0/django_redis/pool.py 2023-06-16 14:12:53.000000000 +0200 @@ -10,7 +10,6 @@ class ConnectionFactory: - # Store connection pool by cache backend options. # # _pools is a process-global, as otherwise _pools is cleared every time diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-redis-5.2.0/django_redis.egg-info/PKG-INFO new/django-redis-5.3.0/django_redis.egg-info/PKG-INFO --- old/django-redis-5.2.0/django_redis.egg-info/PKG-INFO 2021-12-22 16:08:41.000000000 +0100 +++ new/django-redis-5.3.0/django_redis.egg-info/PKG-INFO 2023-06-16 14:13:06.000000000 +0200 @@ -1,19 +1,18 @@ Metadata-Version: 2.1 Name: django-redis -Version: 5.2.0 +Version: 5.3.0 Summary: Full featured redis cache backend for Django. Home-page: https://github.com/jazzband/django-redis Author: Andrei Antoukh Author-email: n...@niwi.nz License: BSD-3-Clause -Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Framework :: Django -Classifier: Framework :: Django :: 2.2 -Classifier: Framework :: Django :: 3.1 Classifier: Framework :: Django :: 3.2 Classifier: Framework :: Django :: 4.0 +Classifier: Framework :: Django :: 4.1 +Classifier: Framework :: Django :: 4.2 Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent @@ -25,6 +24,7 @@ Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 Classifier: Topic :: Software Development :: Libraries Classifier: Topic :: Utilities Requires-Python: >=3.6 @@ -518,6 +518,15 @@ >>> from django.core.cache import cache >>> cache.delete_pattern("foo_*") +To achieve the best performance while deleting many keys, you should set ``DJANGO_REDIS_SCAN_ITERSIZE`` to a relatively +high number (e.g., 100_000) by default in Django settings or pass it directly to the ``delete_pattern``. + + +.. code-block:: pycon + + >>> from django.core.cache import cache + >>> cache.delete_pattern("foo_*", itersize=100_000) + Redis native commands ~~~~~~~~~~~~~~~~~~~~~ @@ -837,7 +846,7 @@ ^^^^^^^^^^^ This pluggable client helps dealing with the thundering herd problem. You can read more about it -on link: `Wikipedia <http://en.wikipedia.org/wiki/Thundering_herd_problem>`_ +on link: `Wikipedia <https://en.wikipedia.org/wiki/Thundering_herd_problem>`_ Like previous pluggable clients, it inherits all functionality from the default client, adding some additional methods for getting/setting keys. @@ -897,7 +906,7 @@ } } -.. _MsgPack: http://msgpack.org/ +.. _MsgPack: https://msgpack.org/ Pluggable Redis client ~~~~~~~~~~~~~~~~~~~~~~ @@ -997,5 +1006,3 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-redis-5.2.0/django_redis.egg-info/requires.txt new/django-redis-5.3.0/django_redis.egg-info/requires.txt --- old/django-redis-5.2.0/django_redis.egg-info/requires.txt 2021-12-22 16:08:41.000000000 +0100 +++ new/django-redis-5.3.0/django_redis.egg-info/requires.txt 2023-06-16 14:13:06.000000000 +0200 @@ -1,4 +1,4 @@ -Django>=2.2 +Django>=3.2 redis!=4.0.0,!=4.0.1,>=3 [hiredis] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-redis-5.2.0/setup.cfg new/django-redis-5.3.0/setup.cfg --- old/django-redis-5.2.0/setup.cfg 2021-12-22 16:08:41.102405300 +0100 +++ new/django-redis-5.3.0/setup.cfg 2023-06-16 14:13:06.371214400 +0200 @@ -12,10 +12,10 @@ Development Status :: 5 - Production/Stable Environment :: Web Environment Framework :: Django - Framework :: Django :: 2.2 - Framework :: Django :: 3.1 Framework :: Django :: 3.2 Framework :: Django :: 4.0 + Framework :: Django :: 4.1 + Framework :: Django :: 4.2 Intended Audience :: Developers License :: OSI Approved :: BSD License Operating System :: OS Independent @@ -27,6 +27,7 @@ Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 + Programming Language :: Python :: 3.11 Topic :: Software Development :: Libraries Topic :: Utilities @@ -38,7 +39,7 @@ django_redis.serializers django_redis.compressors install_requires = - Django>=2.2 + Django>=3.2 redis>=3,!=4.0.0,!=4.0.1 [options.extras_require] @@ -70,9 +71,9 @@ flake8 isort mypy - py{36,37,38,39,310}-dj{22,31,32,40}-redislatest - py310-dj40-redismaster - py310-djmain-redis{latest,master} + py{36,37,38,39,310,311}-dj{22,31,32,40,41,42}-redislatest + py311-dj42-redismaster + py311-djmain-redis{latest,master} [gh-actions] python = @@ -81,13 +82,14 @@ 3.8: py38, black, flake8, isort, mypy 3.9: py39 3.10: py310 + 3.11: py311 [gh-actions:env] DJANGO = - 2.2: dj22 - 3.1: dj31 3.2: dj32 4.0: dj40 + 4.1: dj41 + 4.2: dj42 main: djmain REDIS = latest: redislatest @@ -97,6 +99,7 @@ passenv = CI GITHUB* commands = {envpython} -m pytest --cov-report= --ds=settings.sqlite {posargs} + {envpython} -m pytest --cov-append --cov-report= --ds=settings.sqlite_herd {posargs} {envpython} -m pytest --cov-append --cov-report= --ds=settings.sqlite_json {posargs} {envpython} -m pytest --cov-append --cov-report= --ds=settings.sqlite_lz4 {posargs} {envpython} -m pytest --cov-append --cov-report= --ds=settings.sqlite_msgpack {posargs} @@ -108,10 +111,10 @@ {envpython} -m coverage report {envpython} -m coverage xml deps = - dj22: Django>=2.2,<2.3 - dj31: Django>=3.1,<3.2 dj32: Django>=3.2,<3.3 dj40: Django>=4.0,<4.1 + dj41: Django>=4.1,<4.2 + dj42: Django>=4.2,<5.0 djmain: https://github.com/django/django/archive/main.tar.gz msgpack>=0.6.0 pytest diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-redis-5.2.0/tests/conftest.py new/django-redis-5.3.0/tests/conftest.py --- old/django-redis-5.2.0/tests/conftest.py 2021-12-22 16:08:32.000000000 +0100 +++ new/django-redis-5.3.0/tests/conftest.py 2023-06-16 14:12:53.000000000 +0200 @@ -3,10 +3,10 @@ import pytest from django.core.cache import cache as default_cache -from django_redis.cache import RedisCache +from django_redis.cache import BaseCache @pytest.fixture -def cache() -> Iterable[RedisCache]: +def cache() -> Iterable[BaseCache]: yield default_cache default_cache.clear() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-redis-5.2.0/tests/settings/sqlite_herd.py new/django-redis-5.3.0/tests/settings/sqlite_herd.py --- old/django-redis-5.2.0/tests/settings/sqlite_herd.py 2021-12-22 16:08:32.000000000 +0100 +++ new/django-redis-5.3.0/tests/settings/sqlite_herd.py 2023-06-16 14:12:53.000000000 +0200 @@ -27,3 +27,5 @@ INSTALLED_APPS = ["django.contrib.sessions"] USE_TZ = False + +CACHE_HERD_TIMEOUT = 2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-redis-5.2.0/tests/test_backend.py new/django-redis-5.3.0/tests/test_backend.py --- old/django-redis-5.2.0/tests/test_backend.py 2021-12-22 16:08:32.000000000 +0100 +++ new/django-redis-5.3.0/tests/test_backend.py 2023-06-16 14:12:53.000000000 +0200 @@ -2,21 +2,29 @@ import threading import time from datetime import timedelta -from typing import List, Union, cast +from typing import Iterable, List, Union, cast from unittest.mock import patch import pytest from django.core.cache import caches +from django.test import override_settings from pytest_django.fixtures import SettingsWrapper from pytest_mock import MockerFixture -import django_redis.cache from django_redis.cache import RedisCache from django_redis.client import ShardClient, herd from django_redis.serializers.json import JSONSerializer from django_redis.serializers.msgpack import MSGPackSerializer -herd.CACHE_HERD_TIMEOUT = 2 + +@pytest.fixture +def patch_itersize_setting() -> Iterable[None]: + # destroy cache to force recreation with overriden settings + del caches["default"] + with override_settings(DJANGO_REDIS_SCAN_ITERSIZE=30): + yield + # destroy cache to force recreation with original settings + del caches["default"] class TestDjangoRedisCache: @@ -199,7 +207,12 @@ res = cache.get_many(["a", "b", "c"]) assert res == {"a": 1, "b": 2, "c": 3} - def test_set_call_empty_pipeline(self, cache: RedisCache, mocker: MockerFixture): + def test_set_call_empty_pipeline( + self, + cache: RedisCache, + mocker: MockerFixture, + settings: SettingsWrapper, + ): if isinstance(cache.client, ShardClient): pytest.skip("ShardClient doesn't support get_client") @@ -212,7 +225,7 @@ if isinstance(cache.client, herd.HerdClient): default_timeout = cache.client._backend.default_timeout - herd_timeout = (default_timeout + herd.CACHE_HERD_TIMEOUT) * 1000 + herd_timeout = (default_timeout + settings.CACHE_HERD_TIMEOUT) * 1000 herd_pack_value = cache.client._pack(value, default_timeout) mocked_set.assert_called_once_with( cache.client.make_key(key, version=None), @@ -495,11 +508,15 @@ @patch("django_redis.cache.RedisCache.client") def test_delete_pattern_with_settings_default_scan_count( - self, client_mock, cache: RedisCache + self, + client_mock, + patch_itersize_setting, + cache: RedisCache, + settings: SettingsWrapper, ): for key in ["foo-aa", "foo-ab", "foo-bb", "foo-bc"]: cache.set(key, "foo") - expected_count = django_redis.cache.DJANGO_REDIS_SCAN_ITERSIZE + expected_count = settings.DJANGO_REDIS_SCAN_ITERSIZE cache.delete_pattern("*foo-a*") @@ -541,7 +558,6 @@ assert ttl == 0 def test_pttl(self, cache: RedisCache): - # Test pttl cache.set("foo", "bar", 10) ttl = cache.pttl("foo") @@ -599,7 +615,6 @@ assert cache.pexpire("not-existent-key", 20500) is False def test_pexpire_at(self, cache: RedisCache): - # Test settings expiration time 1 hour ahead by datetime. cache.set("foo", "bar", timeout=None) expiration_time = datetime.datetime.now() + timedelta(hours=1) @@ -625,7 +640,6 @@ assert cache.pexpire_at("not-existent-key", expiration_time) is False def test_expire_at(self, cache: RedisCache): - # Test settings expiration time 1 hour ahead by datetime. cache.set("foo", "bar", timeout=None) expiration_time = datetime.datetime.now() + timedelta(hours=1) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-redis-5.2.0/tests/test_cache_options.py new/django-redis-5.3.0/tests/test_cache_options.py --- old/django-redis-5.2.0/tests/test_cache_options.py 2021-12-22 16:08:32.000000000 +0100 +++ new/django-redis-5.3.0/tests/test_cache_options.py 2023-06-16 14:12:53.000000000 +0200 @@ -3,6 +3,7 @@ import pytest from django.core.cache import caches +from pytest import LogCaptureFixture from pytest_django.fixtures import SettingsWrapper from redis.exceptions import ConnectionError @@ -22,8 +23,10 @@ def ignore_exceptions_cache(settings: SettingsWrapper) -> RedisCache: caches_setting = copy.deepcopy(settings.CACHES) caches_setting["doesnotexist"]["OPTIONS"]["IGNORE_EXCEPTIONS"] = True + caches_setting["doesnotexist"]["OPTIONS"]["LOG_IGNORED_EXCEPTIONS"] = True settings.CACHES = caches_setting settings.DJANGO_REDIS_IGNORE_EXCEPTIONS = True + settings.DJANGO_REDIS_LOG_IGNORED_EXCEPTIONS = True return cast(RedisCache, caches["doesnotexist"]) @@ -34,12 +37,22 @@ assert ignore_exceptions_cache.get_many(["key1", "key2", "key3"]) == {} -def test_get_django_omit_exceptions(ignore_exceptions_cache: RedisCache): +def test_get_django_omit_exceptions( + caplog: LogCaptureFixture, ignore_exceptions_cache: RedisCache +): assert ignore_exceptions_cache._ignore_exceptions is True + assert ignore_exceptions_cache._log_ignored_exceptions is True + assert ignore_exceptions_cache.get("key") is None assert ignore_exceptions_cache.get("key", "default") == "default" assert ignore_exceptions_cache.get("key", default="default") == "default" + assert len(caplog.records) == 3 + assert all( + record.levelname == "ERROR" and record.msg == "Exception ignored" + for record in caplog.records + ) + def test_get_django_omit_exceptions_priority_1(settings: SettingsWrapper): caches_setting = copy.deepcopy(settings.CACHES) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-redis-5.2.0/tests/test_client.py new/django-redis-5.3.0/tests/test_client.py --- old/django-redis-5.2.0/tests/test_client.py 2021-12-22 16:08:32.000000000 +0100 +++ new/django-redis-5.3.0/tests/test_client.py 2023-06-16 14:12:53.000000000 +0200 @@ -1,5 +1,5 @@ from typing import Iterable -from unittest.mock import Mock, patch +from unittest.mock import Mock, call, patch import pytest from django.core.cache import DEFAULT_CACHE_ALIAS @@ -104,6 +104,28 @@ count=90210, match=make_pattern_mock.return_value ) + @patch("test_client.DefaultClient.make_pattern") + @patch("test_client.DefaultClient.get_client", return_value=Mock()) + @patch("test_client.DefaultClient.__init__", return_value=None) + def test_delete_pattern_calls_pipeline_delete_and_execute( + self, init_mock, get_client_mock, make_pattern_mock + ): + client = DefaultClient() + client._backend = Mock() + client._backend.key_prefix = "" + get_client_mock.return_value.scan_iter.return_value = [":1:foo", ":1:foo-a"] + get_client_mock.return_value.pipeline.return_value = Mock() + get_client_mock.return_value.pipeline.return_value.delete = Mock() + get_client_mock.return_value.pipeline.return_value.execute = Mock() + + client.delete_pattern(pattern="foo*") + + assert get_client_mock.return_value.pipeline.return_value.delete.call_count == 2 + get_client_mock.return_value.pipeline.return_value.delete.assert_has_calls( + [call(":1:foo"), call(":1:foo-a")] + ) + get_client_mock.return_value.pipeline.return_value.execute.assert_called_once() + class TestShardClient: @patch("test_client.DefaultClient.make_pattern") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-redis-5.2.0/tests/test_session.py new/django-redis-5.3.0/tests/test_session.py --- old/django-redis-5.2.0/tests/test_session.py 2021-12-22 16:08:32.000000000 +0100 +++ new/django-redis-5.3.0/tests/test_session.py 2023-06-16 14:12:53.000000000 +0200 @@ -3,6 +3,8 @@ from datetime import timedelta from typing import Optional, Type +import django +import pytest from django.conf import settings from django.contrib.sessions.backends.base import SessionBase from django.contrib.sessions.backends.cache import SessionStore as CacheSession @@ -365,6 +367,10 @@ class SessionTests(SessionTestsMixin, unittest.TestCase): backend = CacheSession + @pytest.mark.skipif( + django.VERSION >= (4, 2), + reason="PickleSerializer is removed as of https://code.djangoproject.com/ticket/29708", # noqa: E501 + ) def test_actual_expiry(self): if isinstance( caches[DEFAULT_CACHE_ALIAS].client._serializer, MSGPackSerializer