diskcache-community 5.7.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,480 @@
1
+ """Django-compatible disk and file backed cache."""
2
+
3
+ from functools import wraps
4
+
5
+ from django.core.cache.backends.base import BaseCache
6
+ from django.utils.module_loading import import_string
7
+
8
+ try:
9
+ from django.core.cache.backends.base import DEFAULT_TIMEOUT
10
+ except ImportError: # pragma: no cover
11
+ # For older versions of Django simply use 300 seconds.
12
+ DEFAULT_TIMEOUT = 300
13
+
14
+ from .core import ENOVAL, Disk, args_to_key, full_name, resolve_ignore
15
+ from .fanout import FanoutCache
16
+
17
+
18
+ class DjangoCache(BaseCache):
19
+ """Django-compatible disk and file backed cache."""
20
+
21
+ def __init__(self, directory, params):
22
+ """Initialize DjangoCache instance.
23
+
24
+ The `params` mapping holds the keys of the Django ``CACHES`` setting.
25
+ ``SHARDS`` and ``DATABASE_TIMEOUT`` configure the underlying
26
+ :class:`FanoutCache <diskcache.FanoutCache>`, ``DISK`` selects the
27
+ :class:`Disk <diskcache.Disk>` type or subclass used for serialization
28
+ as a class or a dotted import path such as ``'diskcache.SafeDisk'``,
29
+ and ``OPTIONS`` passes further settings through.
30
+
31
+ :param str directory: cache directory
32
+ :param dict params: cache parameters
33
+
34
+ """
35
+ super().__init__(params)
36
+ shards = params.get('SHARDS', 8)
37
+ timeout = params.get('DATABASE_TIMEOUT', 0.010)
38
+ options = dict(params.get('OPTIONS', {}))
39
+ disk = params.get('DISK', options.pop('disk', Disk))
40
+ if isinstance(disk, str):
41
+ disk = import_string(disk)
42
+ self._cache = FanoutCache(
43
+ directory, shards, timeout, disk=disk, **options
44
+ )
45
+
46
+ @property
47
+ def directory(self):
48
+ """Cache directory."""
49
+ return self._cache.directory
50
+
51
+ def cache(self, name):
52
+ """Return Cache with given `name` in subdirectory.
53
+
54
+ :param str name: subdirectory name for Cache
55
+ :return: Cache with given name
56
+
57
+ """
58
+ return self._cache.cache(name)
59
+
60
+ def deque(self, name, maxlen=None):
61
+ """Return Deque with given `name` in subdirectory.
62
+
63
+ :param str name: subdirectory name for Deque
64
+ :param maxlen: max length (default None, no max)
65
+ :return: Deque with given name
66
+
67
+ """
68
+ return self._cache.deque(name, maxlen=maxlen)
69
+
70
+ def index(self, name):
71
+ """Return Index with given `name` in subdirectory.
72
+
73
+ :param str name: subdirectory name for Index
74
+ :return: Index with given name
75
+
76
+ """
77
+ return self._cache.index(name)
78
+
79
+ def add(
80
+ self,
81
+ key,
82
+ value,
83
+ timeout=DEFAULT_TIMEOUT,
84
+ version=None,
85
+ read=False,
86
+ tag=None,
87
+ retry=True,
88
+ ):
89
+ """Set a value in the cache if the key does not already exist. If
90
+ timeout is given, that timeout will be used for the key; otherwise the
91
+ default cache timeout will be used.
92
+
93
+ Return True if the value was stored, False otherwise.
94
+
95
+ :param key: key for item
96
+ :param value: value for item
97
+ :param float timeout: seconds until the item expires
98
+ (default 300 seconds)
99
+ :param int version: key version number (default None, cache parameter)
100
+ :param bool read: read value as bytes from file (default False)
101
+ :param str tag: text to associate with key (default None)
102
+ :param bool retry: retry if database timeout occurs (default True)
103
+ :return: True if item was added
104
+
105
+ """
106
+ # pylint: disable=arguments-differ
107
+ key = self.make_key(key, version=version)
108
+ timeout = self.get_backend_timeout(timeout=timeout)
109
+ return self._cache.add(key, value, timeout, read, tag, retry)
110
+
111
+ def get(
112
+ self,
113
+ key,
114
+ default=None,
115
+ version=None,
116
+ read=False,
117
+ expire_time=False,
118
+ tag=False,
119
+ retry=False,
120
+ store_time=False,
121
+ ):
122
+ """Fetch a given key from the cache. If the key does not exist, return
123
+ default, which itself defaults to None.
124
+
125
+ When `expire_time`, `tag` or `store_time` is true, the result is a
126
+ tuple of the value followed by the requested metadata in that order.
127
+
128
+ :param key: key for item
129
+ :param default: return value if key is missing (default None)
130
+ :param int version: key version number (default None, cache parameter)
131
+ :param bool read: if True, return file handle to value
132
+ (default False)
133
+ :param float expire_time: if True, return expire_time in tuple
134
+ (default False)
135
+ :param tag: if True, return tag in tuple (default False)
136
+ :param bool retry: retry if database timeout occurs (default False)
137
+ :param bool store_time: if True, return store_time in tuple
138
+ (default False)
139
+ :return: value for item if key is found else default
140
+
141
+ """
142
+ # pylint: disable=arguments-differ,too-many-arguments
143
+ key = self.make_key(key, version=version)
144
+ return self._cache.get(
145
+ key, default, read, expire_time, tag, retry, store_time
146
+ )
147
+
148
+ def read(self, key, version=None):
149
+ """Return file handle corresponding to `key` from Cache.
150
+
151
+ :param key: Python key to retrieve
152
+ :param int version: key version number (default None, cache parameter)
153
+ :return: file open for reading in binary mode
154
+ :raises KeyError: if key is not found
155
+
156
+ """
157
+ key = self.make_key(key, version=version)
158
+ return self._cache.read(key)
159
+
160
+ def set(
161
+ self,
162
+ key,
163
+ value,
164
+ timeout=DEFAULT_TIMEOUT,
165
+ version=None,
166
+ read=False,
167
+ tag=None,
168
+ retry=True,
169
+ ):
170
+ """Set a value in the cache. If timeout is given, that timeout will be
171
+ used for the key; otherwise the default cache timeout will be used.
172
+
173
+ :param key: key for item
174
+ :param value: value for item
175
+ :param float timeout: seconds until the item expires
176
+ (default 300 seconds)
177
+ :param int version: key version number (default None, cache parameter)
178
+ :param bool read: read value as bytes from file (default False)
179
+ :param str tag: text to associate with key (default None)
180
+ :param bool retry: retry if database timeout occurs (default True)
181
+ :return: True if item was set
182
+
183
+ """
184
+ # pylint: disable=arguments-differ
185
+ key = self.make_key(key, version=version)
186
+ timeout = self.get_backend_timeout(timeout=timeout)
187
+ return self._cache.set(key, value, timeout, read, tag, retry)
188
+
189
+ def touch(self, key, timeout=DEFAULT_TIMEOUT, version=None, retry=True):
190
+ """Touch a key in the cache. If timeout is given, that timeout will be
191
+ used for the key; otherwise the default cache timeout will be used.
192
+
193
+ :param key: key for item
194
+ :param float timeout: seconds until the item expires
195
+ (default 300 seconds)
196
+ :param int version: key version number (default None, cache parameter)
197
+ :param bool retry: retry if database timeout occurs (default True)
198
+ :return: True if key was touched
199
+
200
+ """
201
+ # pylint: disable=arguments-differ
202
+ key = self.make_key(key, version=version)
203
+ timeout = self.get_backend_timeout(timeout=timeout)
204
+ return self._cache.touch(key, timeout, retry)
205
+
206
+ def pop(
207
+ self,
208
+ key,
209
+ default=None,
210
+ version=None,
211
+ expire_time=False,
212
+ tag=False,
213
+ retry=True,
214
+ ):
215
+ """Remove corresponding item for `key` from cache and return value.
216
+
217
+ If `key` is missing, return `default`.
218
+
219
+ Operation is atomic. Concurrent operations will be serialized.
220
+
221
+ :param key: key for item
222
+ :param default: return value if key is missing (default None)
223
+ :param int version: key version number (default None, cache parameter)
224
+ :param float expire_time: if True, return expire_time in tuple
225
+ (default False)
226
+ :param tag: if True, return tag in tuple (default False)
227
+ :param bool retry: retry if database timeout occurs (default True)
228
+ :return: value for item if key is found else default
229
+
230
+ """
231
+ key = self.make_key(key, version=version)
232
+ return self._cache.pop(key, default, expire_time, tag, retry)
233
+
234
+ def delete(self, key, version=None, retry=True):
235
+ """Delete a key from the cache, failing silently.
236
+
237
+ :param key: key for item
238
+ :param int version: key version number (default None, cache parameter)
239
+ :param bool retry: retry if database timeout occurs (default True)
240
+ :return: True if item was deleted
241
+
242
+ """
243
+ # pylint: disable=arguments-differ
244
+ key = self.make_key(key, version=version)
245
+ return self._cache.delete(key, retry)
246
+
247
+ def incr(self, key, delta=1, version=None, default=None, retry=True):
248
+ """Increment value by delta for item with key.
249
+
250
+ If key is missing and default is None then raise KeyError. Else if key
251
+ is missing and default is not None then use default for value.
252
+
253
+ Operation is atomic. All concurrent increment operations will be
254
+ counted individually.
255
+
256
+ Assumes value may be stored in a SQLite column. Most builds that target
257
+ machines with 64-bit pointer widths will support 64-bit signed
258
+ integers.
259
+
260
+ :param key: key for item
261
+ :param int delta: amount to increment (default 1)
262
+ :param int version: key version number (default None, cache parameter)
263
+ :param int default: value if key is missing (default None)
264
+ :param bool retry: retry if database timeout occurs (default True)
265
+ :return: new value for item on success else None
266
+ :raises ValueError: if key is not found and default is None
267
+
268
+ """
269
+ # pylint: disable=arguments-differ
270
+ key = self.make_key(key, version=version)
271
+ try:
272
+ return self._cache.incr(key, delta, default, retry)
273
+ except KeyError:
274
+ raise ValueError("Key '%s' not found" % key) from None
275
+
276
+ def decr(self, key, delta=1, version=None, default=None, retry=True):
277
+ """Decrement value by delta for item with key.
278
+
279
+ If key is missing and default is None then raise KeyError. Else if key
280
+ is missing and default is not None then use default for value.
281
+
282
+ Operation is atomic. All concurrent decrement operations will be
283
+ counted individually.
284
+
285
+ Unlike Memcached, negative values are supported. Value may be
286
+ decremented below zero.
287
+
288
+ Assumes value may be stored in a SQLite column. Most builds that target
289
+ machines with 64-bit pointer widths will support 64-bit signed
290
+ integers.
291
+
292
+ :param key: key for item
293
+ :param int delta: amount to decrement (default 1)
294
+ :param int version: key version number (default None, cache parameter)
295
+ :param int default: value if key is missing (default None)
296
+ :param bool retry: retry if database timeout occurs (default True)
297
+ :return: new value for item on success else None
298
+ :raises ValueError: if key is not found and default is None
299
+
300
+ """
301
+ # pylint: disable=arguments-differ
302
+ return self.incr(key, -delta, version, default, retry)
303
+
304
+ def has_key(self, key, version=None):
305
+ """Returns True if the key is in the cache and has not expired.
306
+
307
+ :param key: key for item
308
+ :param int version: key version number (default None, cache parameter)
309
+ :return: True if key is found
310
+
311
+ """
312
+ key = self.make_key(key, version=version)
313
+ return key in self._cache
314
+
315
+ def expire(self):
316
+ """Remove expired items from cache.
317
+
318
+ :return: count of items removed
319
+
320
+ """
321
+ return self._cache.expire()
322
+
323
+ def stats(self, enable=True, reset=False):
324
+ """Return cache statistics hits and misses.
325
+
326
+ :param bool enable: enable collecting statistics (default True)
327
+ :param bool reset: reset hits and misses to 0 (default False)
328
+ :return: (hits, misses)
329
+
330
+ """
331
+ return self._cache.stats(enable=enable, reset=reset)
332
+
333
+ def create_tag_index(self):
334
+ """Create tag index on cache database.
335
+
336
+ Better to initialize cache with `tag_index=True` than use this.
337
+
338
+ :raises Timeout: if database timeout occurs
339
+
340
+ """
341
+ self._cache.create_tag_index()
342
+
343
+ def drop_tag_index(self):
344
+ """Drop tag index on cache database.
345
+
346
+ :raises Timeout: if database timeout occurs
347
+
348
+ """
349
+ self._cache.drop_tag_index()
350
+
351
+ def evict(self, tag):
352
+ """Remove items with matching `tag` from cache.
353
+
354
+ :param str tag: tag identifying items
355
+ :return: count of items removed
356
+
357
+ """
358
+ return self._cache.evict(tag)
359
+
360
+ def cull(self):
361
+ """Cull items from cache until volume is less than size limit.
362
+
363
+ :return: count of items removed
364
+
365
+ """
366
+ return self._cache.cull()
367
+
368
+ def clear(self):
369
+ """Remove *all* values from the cache at once."""
370
+ return self._cache.clear()
371
+
372
+ def close(self, **kwargs):
373
+ """Close the cache connection."""
374
+ # pylint: disable=unused-argument
375
+ self._cache.close()
376
+
377
+ def get_backend_timeout(self, timeout=DEFAULT_TIMEOUT):
378
+ """Return seconds to expiration.
379
+
380
+ :param float timeout: seconds until the item expires
381
+ (default 300 seconds)
382
+
383
+ """
384
+ if timeout == DEFAULT_TIMEOUT:
385
+ timeout = self.default_timeout
386
+ elif timeout == 0:
387
+ # ticket 21147 - avoid time.time() related precision issues
388
+ timeout = -1
389
+ return None if timeout is None else timeout
390
+
391
+ def memoize(
392
+ self,
393
+ name=None,
394
+ timeout=DEFAULT_TIMEOUT,
395
+ version=None,
396
+ typed=False,
397
+ tag=None,
398
+ ignore=(),
399
+ ):
400
+ """Memoizing cache decorator.
401
+
402
+ Decorator to wrap callable with memoizing function using cache.
403
+ Repeated calls with the same arguments will lookup result in cache and
404
+ avoid function evaluation.
405
+
406
+ If name is set to None (default), the callable name will be determined
407
+ automatically.
408
+
409
+ When timeout is set to zero, function results will not be set in the
410
+ cache. Cache lookups still occur, however. Read
411
+ :doc:`case-study-landing-page-caching` for example usage.
412
+
413
+ If typed is set to True, function arguments of different types will be
414
+ cached separately. For example, f(3) and f(3.0) will be treated as
415
+ distinct calls with distinct results.
416
+
417
+ The original underlying function is accessible through the __wrapped__
418
+ attribute. This is useful for introspection, for bypassing the cache,
419
+ or for rewrapping the function with a different cache.
420
+
421
+ An additional `__cache_key__` attribute can be used to generate the
422
+ cache key used for the given arguments.
423
+
424
+ Remember to call memoize when decorating a callable. If you forget,
425
+ then a TypeError will occur.
426
+
427
+ :param str name: name given for callable (default None, automatic)
428
+ :param float timeout: seconds until the item expires
429
+ (default 300 seconds)
430
+ :param int version: key version number (default None, cache parameter)
431
+ :param bool typed: cache different types separately (default False)
432
+ :param str tag: text to associate with arguments (default None)
433
+ :param set ignore: positional or keyword args to ignore (default ());
434
+ an int ignores the argument at that position, a str ignores
435
+ the parameter with that name however it is passed
436
+ :return: callable decorator
437
+
438
+ """
439
+ # Caution: Nearly identical code exists in Cache.memoize
440
+ if callable(name):
441
+ raise TypeError('name cannot be callable')
442
+
443
+ def decorator(func):
444
+ """Decorator created by memoize() for callable `func`."""
445
+ base = (full_name(func),) if name is None else (name,)
446
+ ignored = resolve_ignore(func, ignore)
447
+
448
+ @wraps(func)
449
+ def wrapper(*args, **kwargs):
450
+ """Wrapper for callable to cache arguments and return values."""
451
+ key = wrapper.__cache_key__(*args, **kwargs)
452
+ result = self.get(key, ENOVAL, version, retry=True)
453
+
454
+ if result is ENOVAL:
455
+ result = func(*args, **kwargs)
456
+ valid_timeout = (
457
+ timeout is None
458
+ or timeout == DEFAULT_TIMEOUT
459
+ or timeout > 0
460
+ )
461
+ if valid_timeout:
462
+ self.set(
463
+ key,
464
+ result,
465
+ timeout,
466
+ version,
467
+ tag=tag,
468
+ retry=True,
469
+ )
470
+
471
+ return result
472
+
473
+ def __cache_key__(*args, **kwargs):
474
+ """Make key for cache given function arguments."""
475
+ return args_to_key(base, args, kwargs, typed, ignored)
476
+
477
+ wrapper.__cache_key__ = __cache_key__
478
+ return wrapper
479
+
480
+ return decorator