File: tagged_cache.py

package info (click to toggle)
cachy 0.3.0-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 264 kB
  • sloc: python: 1,319; sh: 6; makefile: 4
file content (243 lines) | stat: -rw-r--r-- 5,835 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
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# -*- coding: utf-8 -*-

import hashlib
import datetime
import math
from .contracts.store import Store
from .helpers import value
from .utils import encode


class TaggedCache(Store):
    """

    """
    def __init__(self, store, tags):
        """
        :param store: The cache store implementation
        :type store: cachy.contracts.store.Store

        :param tags: The tag set
        :type tags: cachy.tag_set.TagSet
        """
        self._store = store
        self._tags = tags

    def has(self, key):
        """
        Determine if an item exists in the cache.

        :param key: The cache key
        :type key: str

        :rtype: bool
        """
        return self.get(key) is not None

    def get(self, key, default=None):
        """
        Retrieve an item from the cache by key.

        :param key: The cache key
        :type key: str

        :param default: The default value
        :type default: mixed

        :return: The cache value
        """
        val = self._store.get(self.tagged_item_key(key))

        if val is not None:
            return val

        return value(default)

    def put(self, key, value, minutes):
        """
        Store an item in the cache for a given number of minutes.

        :param key: The cache key
        :type key: str

        :param value: The cache value
        :type value: mixed

        :param minutes: The lifetime in minutes of the cached value
        :type minutes: int or datetime
        """
        minutes = self._get_minutes(minutes)

        if minutes is not None:
            return self._store.put(self.tagged_item_key(key), value, minutes)

    def add(self, key, val, minutes):
        """
        Store an item in the cache if it does not exist.

        :param key: The cache key
        :type key: str

        :param val: The cache value
        :type val: mixed

        :param minutes: The lifetime in minutes of the cached value
        :type minutes: int|datetime

        :rtype: bool
        """
        if not self.has(key):
            self.put(key, val, minutes)

            return True

        return False

    def increment(self, key, value=1):
        """
        Increment the value of an item in the cache.

        :param key: The cache key
        :type key: str

        :param value: The increment value
        :type value: int

        :rtype: int or bool
        """
        self._store.increment(self.tagged_item_key(key), value)

    def decrement(self, key, value=1):
        """
        Decrement the value of an item in the cache.

        :param key: The cache key
        :type key: str

        :param value: The decrement value
        :type value: int

        :rtype: int or bool
        """
        self._store.decrement(self.tagged_item_key(key), value)

    def forever(self, key, value):
        """
        Store an item in the cache indefinitely.

        :param key: The cache key
        :type key: str

        :param value: The value
        :type value: mixed
        """
        self._store.forever(self.tagged_item_key(key), value)

    def forget(self, key):
        """
        Remove an item from the cache.

        :param key: The cache key
        :type key: str

        :rtype: bool
        """
        self._store.forget(self.tagged_item_key(key))

    def flush(self):
        """
        Remove all items from the cache.
        """
        self._tags.reset()

    def remember(self, key, minutes, callback):
        """
        Get an item from the cache, or store the default value.

        :param key: The cache key
        :type key: str

        :param minutes: The lifetime in minutes of the cached value
        :type minutes: int or datetime

        :param callback: The default function
        :type callback: mixed

        :rtype: mixed
        """
        # If the item exists in the cache we will just return this immediately
        # otherwise we will execute the given callback and cache the result
        # of that execution for the given number of minutes in storage.
        val = self.get(key)
        if val is not None:
            return val

        val = value(callback)

        self.put(key, val, minutes)

        return val

    def remember_forever(self, key, callback):
        """
        Get an item from the cache, or store the default value forever.

        :param key: The cache key
        :type key: str

        :param callback: The default function
        :type callback: mixed

        :rtype: mixed
        """
        # If the item exists in the cache we will just return this immediately
        # otherwise we will execute the given callback and cache the result
        # of that execution forever.
        val = self.get(key)
        if val is not None:
            return val

        val = value(callback)

        self.forever(key, val)

        return val

    def tagged_item_key(self, key):
        """
        Get a fully qualified key for a tagged item.

        :param key: The cache key
        :type key: str

        :rtype: str
        """
        return '%s:%s' % (hashlib.sha1(encode(self._tags.get_namespace())).hexdigest(), key)

    def get_prefix(self):
        """
        Get the cache key prefix.

        :rtype: str
        """
        return self._store.get_prefix()

    def _get_minutes(self, duration):
        """
        Calculate the number of minutes with the given duration.

        :param duration: The duration
        :type duration: int or datetime

        :rtype: int or None
        """
        if isinstance(duration, datetime.datetime):
            from_now = (duration - datetime.datetime.now()).total_seconds()
            from_now = math.ceil(from_now / 60)

            if from_now > 0:
                return from_now

            return

        return duration