From f1bb3ee001077db3905a2efe67e397be55818168 Mon Sep 17 00:00:00 2001 From: Bertrand Bordage Date: Sun, 5 Oct 2014 03:11:26 +0200 Subject: [PATCH] Adds a context manager & decorator to dynamically override settings. --- README.rst | 23 +++++++++++++++++++---- cachalot/settings.py | 24 ++++++++++++++++++++++++ cachalot/tests.py | 20 +++++++++++++++----- 3 files changed, 58 insertions(+), 9 deletions(-) diff --git a/README.rst b/README.rst index 3074fa4..edd56d0 100644 --- a/README.rst +++ b/README.rst @@ -53,12 +53,27 @@ Setting Default value Description .. |CACHES| replace:: ``CACHES`` .. _CACHES: https://docs.djangoproject.com/en/1.7/ref/settings/#std:setting-CACHES -.. note:: Settings can be changed at any moment during runtime like this: +These settings can be changed whenever you want. +You have to use ``cachalot_settings`` as a context manager, a decorator, +or simply by changing its attributes: - .. code:: python +.. code:: python - from cachalot.settings import cachalot_settings - cachalot_settings.CACHALOT_CACHE = 'another_cache' + from cachalot.settings import cachalot_settings + + with cachalot_settings(CACHALOT_ENABLED=False): + # SQL queries are not cached in this block + + @cachalot_settings(CACHALOT_CACHE='another_cache') + def your_function(): + # What’s in this function uses another cache + + # Globally disables SQL caching until you set it back to True + cachalot_settings.CACHALOT_ENABLED = False + +In tests, you can use +`Django’s testing tools `_ +as well as ``cachalot_settings``. They will both work the same. Limits diff --git a/cachalot/settings.py b/cachalot/settings.py index 9c79eaf..e383508 100644 --- a/cachalot/settings.py +++ b/cachalot/settings.py @@ -1,6 +1,27 @@ from django.conf import settings +class SettingsOverrider(object): + def __init__(self, settings, overrides): + self.settings = settings + self.overrides = overrides + self.originals = {k: getattr(self.settings, k) for k in self.overrides} + + def __enter__(self): + for k, v in self.overrides.items(): + setattr(self.settings, k, v) + + def __exit__(self, exc_type, exc_val, exc_tb): + for k, v in self.originals.items(): + setattr(self.settings, k, v) + + def __call__(self, func): + def inner(*args, **kwargs): + with self: + return func(*args, **kwargs) + return inner + + class Settings(object): CACHALOT_ENABLED = True CACHALOT_CACHE = 'default' @@ -10,5 +31,8 @@ class Settings(object): return getattr(settings, item) return super(Settings, self).__getattribute__(item) + def __call__(self, **kwargs): + return SettingsOverrider(self, kwargs) + cachalot_settings = Settings() diff --git a/cachalot/tests.py b/cachalot/tests.py index 574544f..d6a2cd0 100644 --- a/cachalot/tests.py +++ b/cachalot/tests.py @@ -1,6 +1,9 @@ # coding: utf-8 from __future__ import unicode_literals +from cachalot.settings import cachalot_settings + + try: from unittest import skip, skipIf except ImportError: # For Python 2.6 @@ -1178,14 +1181,21 @@ class AtomicTestCase(TestCase): class SettingsTestCase(TestCase): + @cachalot_settings(CACHALOT_ENABLED=False) + def test_decorator(self): + with self.assertNumQueries(1): + list(Test.objects.all()) + with self.assertNumQueries(1): + list(Test.objects.all()) + def test_enabled(self): - with self.settings(CACHALOT_ENABLED=True): + with cachalot_settings(CACHALOT_ENABLED=True): with self.assertNumQueries(1): list(Test.objects.all()) with self.assertNumQueries(0): list(Test.objects.all()) - with self.settings(CACHALOT_ENABLED=False): + with cachalot_settings(CACHALOT_ENABLED=False): with self.assertNumQueries(1): list(Test.objects.all()) with self.assertNumQueries(1): @@ -1194,7 +1204,7 @@ class SettingsTestCase(TestCase): with self.assertNumQueries(0): list(Test.objects.all()) - with self.settings(CACHALOT_ENABLED=False): + with cachalot_settings(CACHALOT_ENABLED=False): with self.assertNumQueries(1): t = Test.objects.create(name='test') with self.assertNumQueries(1): @@ -1204,7 +1214,7 @@ class SettingsTestCase(TestCase): @skipIf(len(settings.CACHES) == 1, 'We can’t change the cache used since there’s only one configured') def test_cache(self): - with self.settings(CACHALOT_CACHE='default'): + with cachalot_settings(CACHALOT_CACHE='default'): with self.assertNumQueries(1): list(Test.objects.all()) with self.assertNumQueries(0): @@ -1212,7 +1222,7 @@ class SettingsTestCase(TestCase): other_cache = [k for k in settings.CACHES if k != 'default'][0] - with self.settings(CACHALOT_CACHE=other_cache): + with cachalot_settings(CACHALOT_CACHE=other_cache): with self.assertNumQueries(1): list(Test.objects.all()) with self.assertNumQueries(0):