Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-django-cacheops for openSUSE:Factory checked in at 2023-05-10 16:18:10 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-django-cacheops (Old) and /work/SRC/openSUSE:Factory/.python-django-cacheops.new.1533 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-django-cacheops" Wed May 10 16:18:10 2023 rev:9 rq:1085792 version:7.0.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-django-cacheops/python-django-cacheops.changes 2023-05-08 17:24:20.372714947 +0200 +++ /work/SRC/openSUSE:Factory/.python-django-cacheops.new.1533/python-django-cacheops.changes 2023-05-10 16:18:14.086871882 +0200 @@ -1,0 +2,8 @@ +Tue May 9 19:26:45 UTC 2023 - Dirk Müller <dmuel...@suse.com> + +- update to 7.0.1: + * made it work with Redis 6.x and older again + * handle abstract models better + * some docs improvements + +------------------------------------------------------------------- Old: ---- django-cacheops-7.0.tar.gz New: ---- django-cacheops-7.0.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-django-cacheops.spec ++++++ --- /var/tmp/diff_new_pack.MoRD2j/_old 2023-05-10 16:18:14.606874958 +0200 +++ /var/tmp/diff_new_pack.MoRD2j/_new 2023-05-10 16:18:14.614875005 +0200 @@ -19,7 +19,7 @@ %define skip_python2 1 %define skip_python36 1 Name: python-django-cacheops -Version: 7.0 +Version: 7.0.1 Release: 0 Summary: Django ORM cache with automatic granular event-driven invalidation License: BSD-3-Clause ++++++ django-cacheops-7.0.tar.gz -> django-cacheops-7.0.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-cacheops-7.0/CHANGELOG new/django-cacheops-7.0.1/CHANGELOG --- old/django-cacheops-7.0/CHANGELOG 2023-03-11 10:08:54.000000000 +0100 +++ new/django-cacheops-7.0.1/CHANGELOG 2023-05-09 09:41:55.000000000 +0200 @@ -1,3 +1,8 @@ +7.0.1 +- made it work with Redis 6.x and older again +- handle abstract models better +- some docs improvements + 7.0 - support Django 4.2b and 5.0a - added a new insideout mode @@ -5,6 +10,7 @@ Backwards incompatible changes: - dropped Python 3.5, 3.6 and Django 2.1, 2.2, 3.0 and 3.1 support - removed CACHEOPS_LRU +- removed CacheopsRedis, should inherit redis.Redis instead 6.2 - support Python 3.11 and Django 4.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-cacheops-7.0/MANIFEST.in new/django-cacheops-7.0.1/MANIFEST.in --- old/django-cacheops-7.0/MANIFEST.in 2021-05-24 11:36:10.000000000 +0200 +++ new/django-cacheops-7.0.1/MANIFEST.in 2023-03-16 07:31:03.000000000 +0100 @@ -2,7 +2,7 @@ include README.rst include CHANGELOG include cacheops/lua/* -include manage.py run_tests.py bench.py +include manage.py bench.py include requirements-test.txt include tox.ini recursive-include tests *.json diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-cacheops-7.0/PKG-INFO new/django-cacheops-7.0.1/PKG-INFO --- old/django-cacheops-7.0/PKG-INFO 2023-03-15 11:03:10.339889800 +0100 +++ new/django-cacheops-7.0.1/PKG-INFO 2023-05-09 09:49:47.681410600 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: django-cacheops -Version: 7.0 +Version: 7.0.1 Summary: A slick ORM cache with automatic granular event-driven invalidation for Django. Home-page: http://github.com/Suor/django-cacheops Author: Alexander Schepanovski @@ -105,7 +105,7 @@ ... # everything else is passed to Sentinel() } - # Use your own redis client class, should be compatible or subclass redis.StrictRedis + # Use your own redis client class, should be compatible or subclass redis.Redis CACHEOPS_CLIENT_CLASS = 'your.redis.ClientClass' CACHEOPS = { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-cacheops-7.0/README.rst new/django-cacheops-7.0.1/README.rst --- old/django-cacheops-7.0/README.rst 2023-03-11 10:05:57.000000000 +0100 +++ new/django-cacheops-7.0.1/README.rst 2023-03-17 16:09:39.000000000 +0100 @@ -75,7 +75,7 @@ ... # everything else is passed to Sentinel() } - # Use your own redis client class, should be compatible or subclass redis.StrictRedis + # Use your own redis client class, should be compatible or subclass redis.Redis CACHEOPS_CLIENT_CLASS = 'your.redis.ClientClass' CACHEOPS = { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-cacheops-7.0/cacheops/__init__.py new/django-cacheops-7.0.1/cacheops/__init__.py --- old/django-cacheops-7.0/cacheops/__init__.py 2023-03-11 10:09:11.000000000 +0100 +++ new/django-cacheops-7.0.1/cacheops/__init__.py 2023-05-09 09:42:08.000000000 +0200 @@ -1,4 +1,4 @@ -__version__ = '7.0' +__version__ = '7.0.1' VERSION = tuple(map(int, __version__.split('.'))) from .simple import * # noqa diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-cacheops-7.0/cacheops/conf.py new/django-cacheops-7.0.1/cacheops/conf.py --- old/django-cacheops-7.0/cacheops/conf.py 2023-02-25 06:59:13.000000000 +0100 +++ new/django-cacheops-7.0.1/cacheops/conf.py 2023-05-05 13:51:50.000000000 +0200 @@ -96,7 +96,8 @@ """ Returns cacheops profile for a model """ - # Django migrations these fake models, we don't want to cache them + assert not model._meta.abstract, "This should be handled by caller" + # Django migrations create lots of fake models, just skip them if model.__module__ == '__fake__': return None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-cacheops-7.0/cacheops/lua/cache_thing.lua new/django-cacheops-7.0.1/cacheops/lua/cache_thing.lua --- old/django-cacheops-7.0/cacheops/lua/cache_thing.lua 2023-02-25 06:59:13.000000000 +0100 +++ new/django-cacheops-7.0.1/cacheops/lua/cache_thing.lua 2023-04-03 13:32:23.000000000 +0200 @@ -47,6 +47,16 @@ redis.call('sadd', conj_key, key) -- NOTE: an invalidator should live longer than any key it references. -- So we update its ttl on every key if needed. + -- REDIS_7 redis.call('expire', conj_key, timeout, 'gt') + -- /REDIS_7 + -- REDIS_6 + local conj_ttl = redis.call('ttl', conj_key) + if conj_ttl < timeout then + -- We set conj_key life with a margin over key life to call expire rarer + -- And add few extra seconds to be extra safe + redis.call('expire', conj_key, timeout * 2 + 10) + end + -- /REDIS_6 end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-cacheops-7.0/cacheops/lua/cache_thing_insideout.lua new/django-cacheops-7.0.1/cacheops/lua/cache_thing_insideout.lua --- old/django-cacheops-7.0/cacheops/lua/cache_thing_insideout.lua 2023-02-25 06:58:23.000000000 +0100 +++ new/django-cacheops-7.0.1/cacheops/lua/cache_thing_insideout.lua 2023-04-03 13:31:30.000000000 +0200 @@ -19,7 +19,17 @@ table.insert(stamps, stamp) -- NOTE: an invalidator should live longer than any key it references. -- So we update its ttl on every key if needed. + -- REDIS_7 redis.call('expire', conj_key, timeout, 'gt') + -- /REDIS_7 + -- REDIS_6 + local conj_ttl = redis.call('ttl', conj_key) + if conj_ttl < timeout then + -- We set conj_key life with a margin over key life to call expire rarer + -- And add few extra seconds to be extra safe + redis.call('expire', conj_key, timeout * 2 + 10) + end + -- /REDIS_6 end -- Write data to cache along with a checksum of the stamps to see if any of them changed diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-cacheops-7.0/cacheops/query.py new/django-cacheops-7.0.1/cacheops/query.py --- old/django-cacheops-7.0/cacheops/query.py 2023-03-11 10:02:52.000000000 +0100 +++ new/django-cacheops-7.0.1/cacheops/query.py 2023-05-05 13:51:50.000000000 +0200 @@ -393,13 +393,12 @@ if not hasattr(module, cls.__name__): setattr(module, cls.__name__, cls) - # This is probably still needed if models are created dynamically + # This is probably still needed if models are created dynamically or imported late def contribute_to_class(self, cls, name): self._no_monkey.contribute_to_class(self, cls, name) - # Django migrations create lots of fake models, just skip them - # NOTE: we make it here rather then inside _install_cacheops() + # NOTE: we check it here rather then inside _install_cacheops() # because we don't want @once_per() to hold refs to all of them. - if cls.__module__ != '__fake__' and family_has_profile(cls): + if family_has_profile(cls): self._install_cacheops(cls) @skip_on_no_invalidation diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-cacheops-7.0/cacheops/redis.py new/django-cacheops-7.0.1/cacheops/redis.py --- old/django-cacheops-7.0/cacheops/redis.py 2023-02-25 06:59:13.000000000 +0100 +++ new/django-cacheops-7.0.1/cacheops/redis.py 2023-04-04 12:55:06.000000000 +0200 @@ -27,7 +27,7 @@ if settings.CACHEOPS_REDIS and settings.CACHEOPS_SENTINEL: raise ImproperlyConfigured("CACHEOPS_REDIS and CACHEOPS_SENTINEL are mutually exclusive") - client_class = redis.StrictRedis + client_class = redis.Redis if settings.CACHEOPS_CLIENT_CLASS: client_class = import_string(settings.CACHEOPS_CLIENT_CLASS) @@ -54,6 +54,7 @@ ### Lua script loader import os.path +import re @memoize @@ -61,4 +62,14 @@ filename = os.path.join(os.path.dirname(__file__), 'lua/%s.lua' % name) with open(filename) as f: code = f.read() + if is_redis_7(): + code = re.sub(r'REDIS_6.*?/REDIS_6', '', code, flags=re.S) + else: + code = re.sub(r'REDIS_7.*?/REDIS_7', '', code, flags=re.S) return redis_client.register_script(code) + + +@memoize +def is_redis_7(): + redis_version = redis_client.info('server')['redis_version'] + return int(redis_version.split('.')[0]) >= 7 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-cacheops-7.0/cacheops/utils.py new/django-cacheops-7.0.1/cacheops/utils.py --- old/django-cacheops-7.0/cacheops/utils.py 2023-03-02 15:50:46.000000000 +0100 +++ new/django-cacheops-7.0.1/cacheops/utils.py 2023-05-05 13:51:50.000000000 +0200 @@ -9,22 +9,24 @@ from .conf import model_profile -def get_concrete_model(model): +def get_table_model(model): return next((b for b in model.__mro__ if issubclass(b, models.Model) and b is not models.Model and not b._meta.proxy and not b._meta.abstract), None) def model_family(model): """ - Returns a list of all proxy models, including subclasess, superclasses and siblings. + The family is models sharing a database table, events on one should affect each other. + + We simply collect a list of all proxy models, including subclasess, superclasses and siblings. + Two descendants of an abstract model are not family - they cannot affect each other. """ def class_tree(cls): return [cls] + lmapcat(class_tree, cls.__subclasses__()) # NOTE: we also list multitable submodels here, we just don't care. # Cacheops doesn't support them anyway. - # NOTE: when this is called in Manager.contribute_to_class() - # ._meta.concrete_model might still be None - return class_tree(model._meta.concrete_model or get_concrete_model(model) or model) + table_model = get_table_model(model) + return class_tree(table_model) if table_model else [] @memoize diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-cacheops-7.0/django_cacheops.egg-info/PKG-INFO new/django-cacheops-7.0.1/django_cacheops.egg-info/PKG-INFO --- old/django-cacheops-7.0/django_cacheops.egg-info/PKG-INFO 2023-03-15 11:03:10.000000000 +0100 +++ new/django-cacheops-7.0.1/django_cacheops.egg-info/PKG-INFO 2023-05-09 09:49:47.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: django-cacheops -Version: 7.0 +Version: 7.0.1 Summary: A slick ORM cache with automatic granular event-driven invalidation for Django. Home-page: http://github.com/Suor/django-cacheops Author: Alexander Schepanovski @@ -105,7 +105,7 @@ ... # everything else is passed to Sentinel() } - # Use your own redis client class, should be compatible or subclass redis.StrictRedis + # Use your own redis client class, should be compatible or subclass redis.Redis CACHEOPS_CLIENT_CLASS = 'your.redis.ClientClass' CACHEOPS = { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-cacheops-7.0/setup.py new/django-cacheops-7.0.1/setup.py --- old/django-cacheops-7.0/setup.py 2023-03-11 10:09:49.000000000 +0100 +++ new/django-cacheops-7.0.1/setup.py 2023-05-09 09:42:03.000000000 +0200 @@ -7,7 +7,7 @@ setup( name='django-cacheops', - version='7.0', + version='7.0.1', author='Alexander Schepanovski', author_email='suor....@gmail.com', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-cacheops-7.0/tests/models.py new/django-cacheops-7.0.1/tests/models.py --- old/django-cacheops-7.0/tests/models.py 2023-03-11 10:02:54.000000000 +0100 +++ new/django-cacheops-7.0.1/tests/models.py 2023-05-05 13:51:50.000000000 +0200 @@ -307,3 +307,8 @@ setattr(self, '_get_private_data', curry(sum, [1, 2, 3, 4])) name = models.CharField(max_length=255) + + +class Abs(models.Model): + class Meta: + abstract = True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-cacheops-7.0/tests/test_extras.py new/django-cacheops-7.0.1/tests/test_extras.py --- old/django-cacheops-7.0/tests/test_extras.py 2021-05-24 11:36:10.000000000 +0200 +++ new/django-cacheops-7.0.1/tests/test_extras.py 2023-05-05 13:51:50.000000000 +0200 @@ -6,7 +6,7 @@ from cacheops.signals import cache_read, cache_invalidated from .utils import BaseTestCase, make_inc -from .models import Post, Category, Local, DbAgnostic, DbBinded +from .models import Post, Category, Local, DbAgnostic, DbBinded, Abs class SettingsTests(TestCase): @@ -104,7 +104,7 @@ def second_thread(): def _target(): try: - with before('redis.StrictRedis.brpoplpush', lambda *a, **kw: locked.set()): + with before('redis.Redis.brpoplpush', lambda *a, **kw: locked.set()): results.append(func()) except Exception: locked.set() @@ -183,3 +183,9 @@ with self.assertNumQueries(1, using='slave'): list(DbBinded.objects.cache().using('slave')) + + +def test_abstract_family(): + from cacheops.utils import model_family + + assert model_family(Abs) == [] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/django-cacheops-7.0/tests/tests.py new/django-cacheops-7.0.1/tests/tests.py --- old/django-cacheops-7.0/tests/tests.py 2023-02-27 05:15:02.000000000 +0100 +++ new/django-cacheops-7.0.1/tests/tests.py 2023-05-05 13:51:50.000000000 +0200 @@ -961,6 +961,13 @@ with self.assertRaises(NonCachedMedia.DoesNotExist): MediaProxy.objects.cache().get(title=media.title) + def test_siblings(self): + list(VideoProxy.objects.cache()) + NonCachedVideoProxy.objects.create(title='Pulp Fiction') + + with self.assertNumQueries(1): + list(VideoProxy.objects.cache()) + def test_proxy_caching(self): video = Video.objects.create(title='Pulp Fiction') self.assertEqual(type(Video.objects.cache().get(pk=video.pk)),