Completed
Push — master ( 7e3137...04afa3 )
by Bertrand
01:27
created

CachalotExtension.parse_args()   B

Complexity

Conditions 6

Size

Total Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
c 1
b 0
f 0
dl 0
loc 27
rs 7.5384
1
from django.core.cache import caches, DEFAULT_CACHE_ALIAS
2
from django.core.cache.utils import make_template_fragment_key
3
from jinja2.nodes import Keyword, Const, CallBlock
4
from jinja2.ext import Extension
5
6
from .api import get_last_invalidation
7
8
9
class CachalotExtension(Extension):
10
    tags = {'cache'}
11
    allowed_kwargs = ('cache_key', 'timeout', 'cache_alias')
12
13
    def __init__(self, environment):
14
        super(CachalotExtension, self).__init__(environment)
15
16
        self.environment.globals.update(
17
            get_last_invalidation=get_last_invalidation)
18
19
    def parse_args(self, parser):
20
        args = []
21
        kwargs = []
22
23
        stream = parser.stream
24
25
        while stream.current.type != 'block_end':
26
            if stream.current.type == 'name' \
27
                    and stream.look().type == 'assign':
28
                key = stream.current.value
29
                if key not in self.allowed_kwargs:
30
                    parser.fail(
31
                        "'%s' is not a valid keyword argument "
32
                        "for {%% cache %%}" % key,
33
                        stream.current.lineno)
34
                stream.skip(2)
35
                value = parser.parse_expression()
36
                kwargs.append(Keyword(key, value, lineno=value.lineno))
37
            else:
38
                args.append(parser.parse_expression())
39
40
            if stream.current.type == 'block_end':
41
                break
42
43
            parser.stream.expect('comma')
44
45
        return args, kwargs
46
47
    def parse(self, parser):
48
        tag = parser.stream.current.value
49
        lineno = next(parser.stream).lineno
50
        args, kwargs = self.parse_args(parser)
51
        default_cache_key = (None if parser.filename is None
52
                             else '%s:%d' % (parser.filename, lineno))
53
        kwargs.append(Keyword('default_cache_key', Const(default_cache_key),
54
                              lineno=lineno))
55
        body = parser.parse_statements(['name:end' + tag], drop_needle=True)
56
57
        return CallBlock(self.call_method('cache', args, kwargs),
58
                         [], [], body).set_lineno(lineno)
59
60
    def cache(self, *args, **kwargs):
61
        cache_alias = kwargs.get('cache_alias', DEFAULT_CACHE_ALIAS)
62
        cache_key = kwargs.get('cache_key', kwargs['default_cache_key'])
63
        if cache_key is None:
64
            raise ValueError(
65
                'You must set `cache_key` when the template is not a file.')
66
        cache_key = make_template_fragment_key(cache_key, args)
67
68
        out = caches[cache_alias].get(cache_key)
69
        if out is None:
70
            out = kwargs['caller']()
71
            caches[cache_alias].set(cache_key, out, kwargs.get('timeout'))
72
        return out
73
74
75
ext = CachalotExtension
76