File: conf.py

package info (click to toggle)
django-cacheops 7.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 404 kB
  • sloc: python: 3,189; sh: 7; makefile: 4
file content (112 lines) | stat: -rw-r--r-- 3,608 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
from importlib import import_module
from funcy import memoize, merge

from django.conf import settings as base_settings
from django.core.exceptions import ImproperlyConfigured
from django.core.signals import setting_changed


ALL_OPS = {'get', 'fetch', 'count', 'aggregate', 'exists'}


class Defaults:
    CACHEOPS_ENABLED = True
    CACHEOPS_REDIS = {}
    CACHEOPS_DEFAULTS = {}
    CACHEOPS = {}
    CACHEOPS_PREFIX = lambda query: ''
    CACHEOPS_INSIDEOUT = False
    CACHEOPS_CLIENT_CLASS = None
    CACHEOPS_DEGRADE_ON_FAILURE = False
    CACHEOPS_SENTINEL = {}
    # NOTE: we don't use this fields in invalidator conditions since their values could be very long
    #       and one should not filter by their equality anyway.
    CACHEOPS_SKIP_FIELDS = "FileField", "TextField", "BinaryField", "JSONField", "ArrayField"
    CACHEOPS_LONG_DISJUNCTION = 8
    CACHEOPS_SERIALIZER = 'pickle'

    FILE_CACHE_DIR = '/tmp/cacheops_file_cache'
    FILE_CACHE_TIMEOUT = 60*60*24*30


class Settings(object):
    def __getattr__(self, name):
        res = getattr(base_settings, name, getattr(Defaults, name))
        if name in ['CACHEOPS_PREFIX', 'CACHEOPS_SERIALIZER']:
            res = import_string(res) if isinstance(res, str) else res

        # Convert old list of classes to list of strings
        if name == 'CACHEOPS_SKIP_FIELDS':
            res = [f if isinstance(f, str) else f.get_internal_type(res) for f in res]

        # Save to dict to speed up next access, __getattr__ won't be called
        self.__dict__[name] = res
        return res

settings = Settings()
setting_changed.connect(lambda setting, **kw: settings.__dict__.pop(setting, None), weak=False)


def import_string(path):
    if "." in path:
        module, attr = path.rsplit(".", 1)
        return getattr(import_module(module), attr)
    else:
        return import_module(path)


@memoize
def prepare_profiles():
    """
    Prepares a dict 'app.model' -> profile, for use in model_profile()
    """
    profile_defaults = {
        'ops': (),
        'local_get': False,
        'db_agnostic': True,
        'lock': False,
    }
    profile_defaults.update(settings.CACHEOPS_DEFAULTS)

    model_profiles = {}
    for app_model, profile in settings.CACHEOPS.items():
        if profile is None:
            model_profiles[app_model.lower()] = None
            continue

        model_profiles[app_model.lower()] = mp = merge(profile_defaults, profile)
        if mp['ops'] == 'all':
            mp['ops'] = ALL_OPS
        # People will do that anyway :)
        if isinstance(mp['ops'], str):
            mp['ops'] = {mp['ops']}
        mp['ops'] = set(mp['ops'])

        if 'timeout' not in mp:
            raise ImproperlyConfigured(
                'You must specify "timeout" option in "%s" CACHEOPS profile' % app_model)
        if not isinstance(mp['timeout'], int):
            raise ImproperlyConfigured(
                '"timeout" option in "%s" CACHEOPS profile should be an integer' % app_model)

    return model_profiles


def model_profile(model):
    """
    Returns cacheops profile for a model
    """
    assert not model._meta.abstract, "Can't get profile for %s" % model
    # Django migrations create lots of fake models, just skip them
    if model.__module__ == '__fake__':
        return None

    model_profiles = prepare_profiles()

    app = model._meta.app_label.lower()
    model_name = model._meta.model_name
    for guess in ('%s.%s' % (app, model_name), '%s.*' % app, '*.*'):
        if guess in model_profiles:
            return model_profiles[guess]
    else:
        return None