This commit is contained in:
H. White 2025-11-15 23:59:32 +01:00 committed by GitHub
commit c6e56b764c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 103 additions and 2 deletions

View file

@ -208,6 +208,10 @@ class BaseCache:
async def aget_many(self, keys, version=None):
"""See get_many()."""
if self.get_many.__func__ is not BaseCache.get_many:
return await sync_to_async(self.get_many, thread_sensitive=True)(
keys, version=version
)
d = {}
for k in keys:
val = await self.aget(k, self._missing_key, version=version)
@ -236,6 +240,10 @@ class BaseCache:
async def aget_or_set(self, key, default, timeout=DEFAULT_TIMEOUT, version=None):
"""See get_or_set()."""
if self.get_or_set.__func__ is not BaseCache.get_or_set:
return await sync_to_async(self.get_or_set, thread_sensitive=True)(
key, default, timeout=timeout, version=version
)
val = await self.aget(key, self._missing_key, version=version)
if val is self._missing_key:
if callable(default):
@ -255,6 +263,10 @@ class BaseCache:
)
async def ahas_key(self, key, version=None):
if self.has_key.__func__ is not BaseCache.has_key:
return await sync_to_async(self.has_key, thread_sensitive=True)(
key, version=version
)
return (
await self.aget(key, self._missing_key, version=version)
is not self._missing_key
@ -274,6 +286,10 @@ class BaseCache:
async def aincr(self, key, delta=1, version=None):
"""See incr()."""
if self.incr.__func__ is not BaseCache.incr:
return await sync_to_async(self.incr, thread_sensitive=True)(
key, delta=delta, version=version
)
value = await self.aget(key, self._missing_key, version=version)
if value is self._missing_key:
raise ValueError("Key '%s' not found" % key)
@ -317,6 +333,10 @@ class BaseCache:
return []
async def aset_many(self, data, timeout=DEFAULT_TIMEOUT, version=None):
if self.set_many.__func__ is not BaseCache.set_many:
return await sync_to_async(self.set_many, thread_sensitive=True)(
data, timeout=timeout, version=version
)
for key, value in data.items():
await self.aset(key, value, timeout=timeout, version=version)
return []
@ -331,6 +351,10 @@ class BaseCache:
self.delete(key, version=version)
async def adelete_many(self, keys, version=None):
if self.delete_many.__func__ is not BaseCache.delete_many:
return await sync_to_async(self.delete_many, thread_sensitive=True)(
keys, version=version
)
for key in keys:
await self.adelete(key, version=version)
@ -361,6 +385,10 @@ class BaseCache:
async def aincr_version(self, key, delta=1, version=None):
"""See incr_version()."""
if self.incr_version.__func__ is not BaseCache.incr_version:
return await sync_to_async(self.incr_version, thread_sensitive=True)(
key, delta=delta, version=version
)
if version is None:
version = self.version
@ -387,7 +415,7 @@ class BaseCache:
pass
async def aclose(self, **kwargs):
pass
return await sync_to_async(self.close, thread_sensitive=True)(**kwargs)
memcached_error_chars_re = _lazy_re_compile(r"[\x00-\x20\x7f]")

75
tests/cache/tests.py vendored
View file

@ -25,7 +25,7 @@ from django.core.cache import (
cache,
caches,
)
from django.core.cache.backends.base import InvalidCacheBackendError
from django.core.cache.backends.base import BaseCache, InvalidCacheBackendError
from django.core.cache.backends.redis import RedisCacheClient
from django.core.cache.utils import make_template_fragment_key
from django.db import close_old_connections, connection, connections
@ -1165,6 +1165,79 @@ class BaseCacheTests:
cache_add.return_value = False
self.assertEqual(cache.get_or_set("key", "default"), "default")
def test_aget_many_uses_specialized_implementation(self):
meth = getattr(cache, "aget_many")
overridden = False if "BaseCache" in meth.__repr__() else True
if overridden is False and cache.get_many.__func__ is not BaseCache.get_many:
self.assertIs(cache.aget_many.__func__, BaseCache.aget_many)
elif overridden is True:
self.assertIsNot(cache.aget_many.__func__, BaseCache.aget_many)
def test_aset_many_uses_specialized_implementation(self):
meth = getattr(cache, "aset_many")
overridden = False if "BaseCache" in meth.__repr__() else True
if overridden is False and cache.set_many.__func__ is not BaseCache.set_many:
self.assertIs(cache.aset_many.__func__, BaseCache.aset_many)
elif overridden is True:
self.assertIsNot(cache.aset_many.__func__, BaseCache.aset_many)
def test_adelete_many_uses_specialized_implementation(self):
meth = getattr(cache, "adelete_many")
overridden = False if "BaseCache" in meth.__repr__() else True
if (
overridden is False
and cache.delete_many.__func__ is not BaseCache.delete_many
):
self.assertIs(cache.adelete_many.__func__, BaseCache.adelete_many)
elif overridden is True:
self.assertIsNot(cache.adelete_many.__func__, BaseCache.adelete_many)
def test_aget_or_set_uses_specialized_implementation(self):
meth = getattr(cache, "aget_or_set")
overridden = False if "BaseCache" in meth.__repr__() else True
if (
overridden is False
and cache.get_or_set.__func__ is not BaseCache.get_or_set
):
self.assertIs(cache.aget_or_set.__func__, BaseCache.aget_or_set)
elif overridden is True:
self.assertIsNot(cache.aget_or_set.__func__, BaseCache.aget_or_set)
def test_ahas_key_uses_specialized_implementation(self):
meth = getattr(cache, "ahas_key")
overridden = False if "BaseCache" in meth.__repr__() else True
if overridden is False and cache.has_key.__func__ is not BaseCache.has_key:
self.assertIs(cache.ahas_key.__func__, BaseCache.ahas_key)
elif overridden is True:
self.assertIsNot(cache.ahas_key.__func__, BaseCache.ahas_key)
def test_aincr_version_uses_specialized_implementation(self):
meth = getattr(cache, "aincr_version")
overridden = False if "BaseCache" in meth.__repr__() else True
if (
overridden is False
and cache.incr_version.__func__ is not BaseCache.incr_version
):
self.assertIs(cache.aincr_version.__func__, BaseCache.aincr_version)
elif overridden is True:
self.assertIsNot(cache.aincr_version.__func__, BaseCache.aincr_version)
def test_aincr_uses_specialized_implementation(self):
meth = getattr(cache, "aincr")
overridden = False if "BaseCache" in meth.__repr__() else True
if overridden is False and cache.incr.__func__ is not BaseCache.incr:
self.assertIs(cache.aincr.__func__, BaseCache.aincr)
elif overridden is True:
self.assertIsNot(cache.aincr.__func__, BaseCache.aincr)
def test_aclose_uses_specialized_implementation(self):
meth = getattr(cache, "aclose")
overridden = False if "BaseCache" in meth.__repr__() else True
if overridden is False and cache.close.__func__ is not BaseCache.close:
self.assertIs(cache.aclose.__func__, BaseCache.aclose)
elif overridden is True:
self.assertIsNot(cache.aclose.__func__, BaseCache.aclose)
@override_settings(
CACHES=caches_setting_for_tests(