mirror of
https://github.com/jazzband/django-constance.git
synced 2026-03-16 22:40:24 +00:00
Fixed latent none return bug (#658)
Some checks failed
Docs / docs (push) Has been cancelled
Test / ruff-format (push) Has been cancelled
Test / ruff-lint (push) Has been cancelled
Test / build (3.10) (push) Has been cancelled
Test / build (3.11) (push) Has been cancelled
Test / build (3.12) (push) Has been cancelled
Test / build (3.13) (push) Has been cancelled
Test / build (3.14) (push) Has been cancelled
Test / build (3.8) (push) Has been cancelled
Test / build (3.9) (push) Has been cancelled
Some checks failed
Docs / docs (push) Has been cancelled
Test / ruff-format (push) Has been cancelled
Test / ruff-lint (push) Has been cancelled
Test / build (3.10) (push) Has been cancelled
Test / build (3.11) (push) Has been cancelled
Test / build (3.12) (push) Has been cancelled
Test / build (3.13) (push) Has been cancelled
Test / build (3.14) (push) Has been cancelled
Test / build (3.8) (push) Has been cancelled
Test / build (3.9) (push) Has been cancelled
This commit is contained in:
parent
4ac1e546c7
commit
7e75db3ebc
8 changed files with 28 additions and 31 deletions
|
|
@ -24,16 +24,18 @@ class Backend(ABC):
|
|||
@abstractmethod
|
||||
def mget(self, keys):
|
||||
"""
|
||||
Get the keys from the backend store and return a list of the values.
|
||||
Return an empty list if not found.
|
||||
Get the keys from the backend store and return a dict mapping
|
||||
each found key to its value. Return an empty dict if no keys
|
||||
are provided or none are found.
|
||||
"""
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
async def amget(self, keys):
|
||||
"""
|
||||
Get the keys from the backend store and return a list of the values.
|
||||
Return an empty list if not found.
|
||||
Get the keys from the backend store and return a dict mapping
|
||||
each found key to its value. Return an empty dict if no keys
|
||||
are provided or none are found.
|
||||
"""
|
||||
...
|
||||
|
||||
|
|
|
|||
|
|
@ -54,20 +54,22 @@ class DatabaseBackend(Backend):
|
|||
if self._cache.get(full_cachekey):
|
||||
return
|
||||
autofill_values = {full_cachekey: 1}
|
||||
for key, value in self.mget(settings.CONFIG):
|
||||
for key, value in self.mget(settings.CONFIG).items():
|
||||
autofill_values[self.add_prefix(key)] = value
|
||||
self._cache.set_many(autofill_values, timeout=self._autofill_timeout)
|
||||
|
||||
def mget(self, keys):
|
||||
result = {}
|
||||
if not keys:
|
||||
return
|
||||
return result
|
||||
keys = {self.add_prefix(key): key for key in keys}
|
||||
try:
|
||||
stored = self._model._default_manager.filter(key__in=keys)
|
||||
for const in stored:
|
||||
yield keys[const.key], loads(const.value)
|
||||
result[keys[const.key]] = loads(const.value)
|
||||
except (OperationalError, ProgrammingError):
|
||||
pass
|
||||
return result
|
||||
|
||||
def get(self, key):
|
||||
key = self.add_prefix(key)
|
||||
|
|
|
|||
|
|
@ -25,14 +25,9 @@ class MemoryBackend(Backend):
|
|||
|
||||
def mget(self, keys):
|
||||
if not keys:
|
||||
return None
|
||||
result = []
|
||||
return {}
|
||||
with self._lock:
|
||||
for key in keys:
|
||||
value = self._storage.get(key)
|
||||
if value is not None:
|
||||
result.append((key, value))
|
||||
return result
|
||||
return {key: self._storage[key] for key in keys if key in self._storage}
|
||||
|
||||
async def amget(self, keys):
|
||||
if not keys:
|
||||
|
|
|
|||
|
|
@ -73,11 +73,9 @@ class RedisBackend(Backend):
|
|||
|
||||
def mget(self, keys):
|
||||
if not keys:
|
||||
return
|
||||
return {}
|
||||
prefixed_keys = [self.add_prefix(key) for key in keys]
|
||||
for key, value in zip(keys, self._rd.mget(prefixed_keys)):
|
||||
if value:
|
||||
yield key, loads(value)
|
||||
return {key: loads(value) for key, value in zip(keys, self._rd.mget(prefixed_keys)) if value}
|
||||
|
||||
async def amget(self, keys):
|
||||
if not keys:
|
||||
|
|
@ -177,11 +175,13 @@ class CachingRedisBackend(RedisBackend):
|
|||
|
||||
def mget(self, keys):
|
||||
if not keys:
|
||||
return
|
||||
return {}
|
||||
result = {}
|
||||
for key in keys:
|
||||
value = self.get(key)
|
||||
if value is not None:
|
||||
yield key, value
|
||||
result[key] = value
|
||||
return result
|
||||
|
||||
async def amget(self, keys):
|
||||
if not keys:
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ def get_values():
|
|||
# First load a mapping between config name and default value
|
||||
default_initial = ((name, options[0]) for name, options in settings.CONFIG.items())
|
||||
# Then update the mapping with actually values from the backend
|
||||
return dict(default_initial, **dict(config._backend.mget(settings.CONFIG)))
|
||||
return dict(default_initial, **config._backend.mget(settings.CONFIG))
|
||||
|
||||
|
||||
async def aget_values():
|
||||
|
|
@ -52,7 +52,7 @@ def get_values_for_keys(keys):
|
|||
raise AttributeError(f'"{", ".join(missing_keys)}" keys not found in configuration.')
|
||||
|
||||
# Merge default values and backend values, prioritizing backend values
|
||||
return dict(default_initial, **dict(config._backend.mget(keys)))
|
||||
return dict(default_initial, **config._backend.mget(keys))
|
||||
|
||||
|
||||
async def aget_values_for_keys(keys):
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class TestMemory(StorageTestsMixin, TestCase):
|
|||
|
||||
def test_mget_empty_keys(self):
|
||||
result = self.config._backend.mget([])
|
||||
self.assertIsNone(result)
|
||||
self.assertEqual(result, {})
|
||||
|
||||
|
||||
class TestMemoryAsync(TransactionTestCase):
|
||||
|
|
|
|||
|
|
@ -24,18 +24,16 @@ class TestRedis(StorageTestsMixin, TestCase):
|
|||
settings.BACKEND = self.old_backend
|
||||
|
||||
def test_mget_empty_keys(self):
|
||||
# Test that mget returns None for empty keys
|
||||
result = list(self.config._backend.mget([]) or [])
|
||||
self.assertEqual(result, [])
|
||||
result = self.config._backend.mget([])
|
||||
self.assertEqual(result, {})
|
||||
|
||||
|
||||
class TestCachingRedis(TestRedis):
|
||||
_BACKEND = "constance.backends.redisd.CachingRedisBackend"
|
||||
|
||||
def test_mget_empty_keys(self):
|
||||
# Test that mget returns None for empty keys
|
||||
result = list(self.config._backend.mget([]) or [])
|
||||
self.assertEqual(result, [])
|
||||
result = self.config._backend.mget([])
|
||||
self.assertEqual(result, {})
|
||||
|
||||
|
||||
class TestRedisAsync(TransactionTestCase):
|
||||
|
|
|
|||
|
|
@ -98,11 +98,11 @@ class StorageTestsMixin:
|
|||
self.config.BOOL_VALUE = False
|
||||
self.config.STRING_VALUE = ""
|
||||
|
||||
values = dict(self.config._backend.mget(settings.CONFIG))
|
||||
values = self.config._backend.mget(settings.CONFIG)
|
||||
self.assertEqual(values["INT_VALUE"], 0)
|
||||
self.assertEqual(values["BOOL_VALUE"], False)
|
||||
self.assertEqual(values["STRING_VALUE"], "")
|
||||
|
||||
def test_backend_does_not_return_none_values(self):
|
||||
result = dict(self.config._backend.mget(settings.CONFIG))
|
||||
result = self.config._backend.mget(settings.CONFIG)
|
||||
self.assertEqual(result, {})
|
||||
|
|
|
|||
Loading…
Reference in a new issue