Simplifies cachalot_settings and forbids its modification.

This commit is contained in:
Bertrand Bordage 2014-12-08 19:43:43 +01:00
parent 4770df8798
commit d84783b0f1
5 changed files with 26 additions and 60 deletions

View file

@ -17,8 +17,7 @@ master
- Adds 2 settings to customize how cache keys are generated
- Adds a benchmark
- Adds file-based cache support for Django 1.7
- Fixes overridden settings not working when they are already defined in
Django settings
- Simplifies cachalot_settings and forbids its modification
0.8.1

View file

@ -13,12 +13,11 @@ from django.conf import settings
from django.contrib.auth.models import User, Group
from django.core.cache import get_cache
from django.db import connections, connection
from django.test.utils import CaptureQueriesContext
from django.test.utils import CaptureQueriesContext, override_settings
import matplotlib.pyplot as plt
import pandas as pd
from cachalot.api import invalidate_all
from cachalot.settings import cachalot_settings
from cachalot.tests.models import Test
@ -71,7 +70,7 @@ class Benchmark(object):
query_str = 'list(%s)' % query_str
self.query_function = eval('lambda using: ' + query_str)
with cachalot_settings(CACHALOT_ENABLED=False):
with override_settings(CACHALOT_ENABLED=False):
self.bench_once(CONTEXTS[0], num_queries)
self.bench_once(CONTEXTS[1], num_queries, invalidate_before=True)
@ -97,7 +96,7 @@ class Benchmark(object):
for cache_alias in settings.CACHES:
cache = get_cache(cache_alias)
self.cache_name = cache.__class__.__name__[:-5].lower()
with cachalot_settings(CACHALOT_CACHE=cache_alias):
with override_settings(CACHALOT_CACHE=cache_alias):
self.execute_benchmark()
self.df = pd.DataFrame.from_records(self.data)

View file

@ -1,32 +1,6 @@
from functools import wraps
from django.conf import settings
class SettingsOverrider(object):
def __init__(self, settings, overrides):
self.settings = settings
self.overrides = overrides
self.originals = [(k, getattr(settings, k)) for k in overrides]
self.overridden = set(overrides) - settings.overridden
def __enter__(self):
self.settings.overridden.update(self.overridden)
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:
setattr(self.settings, k, v)
self.settings.overridden.difference_update(self.overridden)
def __call__(self, func):
@wraps(func)
def inner(*args, **kwargs):
with self:
return func(*args, **kwargs)
return inner
class Settings(object):
CACHALOT_ENABLED = True
CACHALOT_CACHE = 'default'
@ -35,17 +9,16 @@ class Settings(object):
CACHALOT_QUERY_KEYGEN = 'cachalot.utils.get_query_cache_key'
CACHALOT_TABLE_KEYGEN = 'cachalot.utils.get_table_cache_key'
def __init__(self):
self.overridden = set()
def __getattribute__(self, item):
overridden = super(Settings, self).__getattribute__('overridden')
if hasattr(settings, item) and item not in overridden:
if hasattr(settings, item):
return getattr(settings, item)
return super(Settings, self).__getattribute__(item)
def __call__(self, **kwargs):
return SettingsOverrider(self, kwargs)
def __setattr__(self, key, value):
raise AttributeError(
"Don't modify `cachalot_settings`, use "
"`django.test.utils.override_settings` or "
"`django.conf.settings` instead.")
cachalot_settings = Settings()

View file

@ -10,13 +10,13 @@ from django.conf import settings
from django.core.cache import DEFAULT_CACHE_ALIAS
from django.db import connection
from django.test import TransactionTestCase
from django.test.utils import override_settings
from ..settings import cachalot_settings
from .models import Test
class SettingsTestCase(TransactionTestCase):
@cachalot_settings(CACHALOT_ENABLED=False)
@override_settings(CACHALOT_ENABLED=False)
def test_decorator(self):
with self.assertNumQueries(1):
list(Test.objects.all())
@ -36,13 +36,13 @@ class SettingsTestCase(TransactionTestCase):
list(Test.objects.all())
def test_enabled(self):
with cachalot_settings(CACHALOT_ENABLED=True):
with self.settings(CACHALOT_ENABLED=True):
with self.assertNumQueries(1):
list(Test.objects.all())
with self.assertNumQueries(0):
list(Test.objects.all())
with cachalot_settings(CACHALOT_ENABLED=False):
with self.settings(CACHALOT_ENABLED=False):
with self.assertNumQueries(1):
list(Test.objects.all())
with self.assertNumQueries(1):
@ -53,7 +53,7 @@ class SettingsTestCase(TransactionTestCase):
is_sqlite = connection.vendor == 'sqlite'
with cachalot_settings(CACHALOT_ENABLED=False):
with self.settings(CACHALOT_ENABLED=False):
with self.assertNumQueries(2 if is_sqlite else 1):
t = Test.objects.create(name='test')
with self.assertNumQueries(1):
@ -63,7 +63,7 @@ class SettingsTestCase(TransactionTestCase):
@skipIf(len(settings.CACHES) == 1,
'We cant change the cache used since theres only one configured')
def test_cache(self):
with cachalot_settings(CACHALOT_CACHE=DEFAULT_CACHE_ALIAS):
with self.settings(CACHALOT_CACHE=DEFAULT_CACHE_ALIAS):
with self.assertNumQueries(1):
list(Test.objects.all())
with self.assertNumQueries(0):
@ -72,7 +72,7 @@ class SettingsTestCase(TransactionTestCase):
other_cache_alias = [alias for alias in settings.CACHES
if alias != DEFAULT_CACHE_ALIAS][0]
with cachalot_settings(CACHALOT_CACHE=other_cache_alias):
with self.settings(CACHALOT_CACHE=other_cache_alias):
with self.assertNumQueries(1):
list(Test.objects.all())
with self.assertNumQueries(0):
@ -84,7 +84,7 @@ class SettingsTestCase(TransactionTestCase):
with self.assertNumQueries(1):
list(Test.objects.order_by('?'))
with cachalot_settings(CACHALOT_CACHE_RANDOM=True):
with self.settings(CACHALOT_CACHE_RANDOM=True):
with self.assertNumQueries(1):
list(Test.objects.order_by('?'))
with self.assertNumQueries(0):

View file

@ -81,26 +81,21 @@ Settings
Dynamic overriding
~~~~~~~~~~~~~~~~~~
Obviously, you can set these settings in your Django settings.
But you can also change them whenever you want!
Simply use ``cachalot_settings`` as a context manager, a decorator,
or simply by changing its attributes:
Django-cachalot is built so that its settings can be dynamically changed.
For example:
.. code:: python
from cachalot.settings import cachalot_settings
from django.conf import settings
from django.test.utils import override_settings
with cachalot_settings(CACHALOT_ENABLED=False):
with override_settings(CACHALOT_ENABLED=False):
# SQL queries are not cached in this block
@cachalot_settings(CACHALOT_CACHE='another_alias')
@override_settings(CACHALOT_CACHE='another_alias')
def your_function():
# Whats 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
`Djangos testing tools <https://docs.djangoproject.com/en/1.7/topics/testing/tools/#overriding-settings>`_
as well as ``cachalot_settings``. The only difference is that you cant use
``cachalot_settings`` to decorate a class.
settings.CACHALOT_ENABLED = False