From 39d9f557ce5780305fdebb20b57425575b7f918c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Freitag?= Date: Tue, 11 Jan 2022 13:16:50 +0100 Subject: [PATCH] Implement CacheStatTracker.get_or_set (#1570) Capture the get_or_set() calls to the cache, keeping the tracker interface in line with django.core.cache.backends.BaseCache. --- debug_toolbar/panels/cache.py | 7 +++- docs/changes.rst | 1 + tests/panels/test_cache.py | 69 +++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) diff --git a/debug_toolbar/panels/cache.py b/debug_toolbar/panels/cache.py index 617c6e1ef..74a1155d9 100644 --- a/debug_toolbar/panels/cache.py +++ b/debug_toolbar/panels/cache.py @@ -88,6 +88,10 @@ def get(self, *args, **kwargs): def set(self, *args, **kwargs): return self.cache.set(*args, **kwargs) + @send_signal + def get_or_set(self, *args, **kwargs): + return self.cache.get_or_set(*args, **kwargs) + @send_signal def touch(self, *args, **kwargs): return self.cache.touch(*args, **kwargs) @@ -169,6 +173,7 @@ def __init__(self, *args, **kwargs): ("add", 0), ("get", 0), ("set", 0), + ("get_or_set", 0), ("touch", 0), ("delete", 0), ("clear", 0), @@ -197,7 +202,7 @@ def _store_call_info( backend=None, **kw, ): - if name == "get": + if name == "get" or name == "get_or_set": if return_value is None: self.misses += 1 else: diff --git a/docs/changes.rst b/docs/changes.rst index 9077d22c6..cacbfa5af 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -4,6 +4,7 @@ Change log Next version ------------ +* Track calls to :py:meth:`django.core.caches.cache.get_or_set`. * Removed support for Django < 3.2. * Updated check ``W006`` to look for ``django.template.loaders.app_directories.Loader``. diff --git a/tests/panels/test_cache.py b/tests/panels/test_cache.py index 1ffdddc97..d45eabb26 100644 --- a/tests/panels/test_cache.py +++ b/tests/panels/test_cache.py @@ -26,6 +26,75 @@ def test_recording_caches(self): second_cache.get("foo") self.assertEqual(len(self.panel.calls), 2) + def test_get_or_set_value(self): + cache.cache.get_or_set("baz", "val") + self.assertEqual(cache.cache.get("baz"), "val") + calls = [ + (call["name"], call["args"], call["kwargs"]) for call in self.panel.calls + ] + self.assertEqual( + calls, + [ + ("get_or_set", ("baz", "val"), {}), + ("get", ("baz",), {}), + ], + ) + self.assertEqual( + self.panel.counts, + { + "add": 0, + "get": 1, + "set": 0, + "get_or_set": 1, + "touch": 0, + "delete": 0, + "clear": 0, + "get_many": 0, + "set_many": 0, + "delete_many": 0, + "has_key": 0, + "incr": 0, + "decr": 0, + "incr_version": 0, + "decr_version": 0, + }, + ) + + def test_get_or_set_does_not_override_existing_value(self): + cache.cache.set("foo", "bar") + cached_value = cache.cache.get_or_set("foo", "other") + self.assertEqual(cached_value, "bar") + calls = [ + (call["name"], call["args"], call["kwargs"]) for call in self.panel.calls + ] + self.assertEqual( + calls, + [ + ("set", ("foo", "bar"), {}), + ("get_or_set", ("foo", "other"), {}), + ], + ) + self.assertEqual( + self.panel.counts, + { + "add": 0, + "get": 0, + "set": 1, + "get_or_set": 1, + "touch": 0, + "delete": 0, + "clear": 0, + "get_many": 0, + "set_many": 0, + "delete_many": 0, + "has_key": 0, + "incr": 0, + "decr": 0, + "incr_version": 0, + "decr_version": 0, + }, + ) + def test_insert_content(self): """ Test that the panel only inserts content after generate_stats and