File: cacheops.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 (72 lines) | stat: -rw-r--r-- 2,311 bytes parent folder | download | duplicates (2)
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
from inspect import getfullargspec, unwrap
from functools import partial

from django.template import Library
from django.template.library import TagHelperNode, parse_bits

import cacheops
from cacheops.utils import carefully_strip_whitespace


__all__ = ['CacheopsLibrary', 'invalidate_fragment']


class CacheopsLibrary(Library):
    def decorator_tag(self, func=None, takes_context=False):
        if func is None:
            return partial(self.decorator_tag, takes_context=takes_context)

        name = func.__name__
        params, varargs, varkw, defaults, kwonly, kwonly_defaults, _ = getfullargspec(unwrap(func))

        def _compile(parser, token):
            # content
            nodelist = parser.parse(('end' + name,))
            parser.delete_first_token()

            # args
            bits = token.split_contents()[1:]
            args, kwargs = parse_bits(
                parser, bits, params, varargs, varkw, defaults,
                kwonly, kwonly_defaults, takes_context, name,
            )
            return CachedNode(func, takes_context, args, kwargs, nodelist)

        self.tag(name=name, compile_function=_compile)
        return func

register = CacheopsLibrary()


class CachedNode(TagHelperNode):
    def __init__(self, func, takes_context, args, kwargs, nodelist):
        super(CachedNode, self).__init__(func, takes_context, args, kwargs)
        self.nodelist = nodelist

    def render(self, context):
        args, kwargs = self.get_resolved_arguments(context)
        decorator = self.func(*args, **kwargs)
        render = _make_render(context, self.nodelist)
        return decorator(render)()


def _make_render(context, nodelist):
    def render():
        # TODO: make this cache preparation configurable
        return carefully_strip_whitespace(nodelist.render(context))
    return render


@register.decorator_tag
def cached(timeout, fragment_name, *extra):
    return cacheops.cached(timeout=timeout, extra=(fragment_name,) + extra)


def invalidate_fragment(fragment_name, *extra):
    render = _make_render(None, None)
    cached(None, fragment_name, *extra)(render).invalidate()


@register.decorator_tag
def cached_as(queryset, timeout, fragment_name, *extra):
    return cacheops.cached_as(queryset, timeout=timeout, extra=(fragment_name,) + extra)