PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/Lib/site-packages/django/core/cache/backends/filebased.py

https://gitlab.com/areema/myproject
Python | 154 lines | 128 code | 14 blank | 12 comment | 27 complexity | 510547d05cbde0165e3904262dd608d1 MD5 | raw file
  1. "File-based cache backend"
  2. import errno
  3. import glob
  4. import hashlib
  5. import io
  6. import os
  7. import random
  8. import tempfile
  9. import time
  10. import zlib
  11. from django.core.cache.backends.base import DEFAULT_TIMEOUT, BaseCache
  12. from django.core.files.move import file_move_safe
  13. from django.utils.encoding import force_bytes
  14. try:
  15. from django.utils.six.moves import cPickle as pickle
  16. except ImportError:
  17. import pickle
  18. class FileBasedCache(BaseCache):
  19. cache_suffix = '.djcache'
  20. def __init__(self, dir, params):
  21. super(FileBasedCache, self).__init__(params)
  22. self._dir = os.path.abspath(dir)
  23. self._createdir()
  24. def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
  25. if self.has_key(key, version):
  26. return False
  27. self.set(key, value, timeout, version)
  28. return True
  29. def get(self, key, default=None, version=None):
  30. fname = self._key_to_file(key, version)
  31. if os.path.exists(fname):
  32. try:
  33. with io.open(fname, 'rb') as f:
  34. if not self._is_expired(f):
  35. return pickle.loads(zlib.decompress(f.read()))
  36. except IOError as e:
  37. if e.errno == errno.ENOENT:
  38. pass # Cache file was removed after the exists check
  39. return default
  40. def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
  41. self._createdir() # Cache dir can be deleted at any time.
  42. fname = self._key_to_file(key, version)
  43. self._cull() # make some room if necessary
  44. fd, tmp_path = tempfile.mkstemp(dir=self._dir)
  45. renamed = False
  46. try:
  47. with io.open(fd, 'wb') as f:
  48. expiry = self.get_backend_timeout(timeout)
  49. f.write(pickle.dumps(expiry, -1))
  50. f.write(zlib.compress(pickle.dumps(value), -1))
  51. file_move_safe(tmp_path, fname, allow_overwrite=True)
  52. renamed = True
  53. finally:
  54. if not renamed:
  55. os.remove(tmp_path)
  56. def delete(self, key, version=None):
  57. self._delete(self._key_to_file(key, version))
  58. def _delete(self, fname):
  59. if not fname.startswith(self._dir) or not os.path.exists(fname):
  60. return
  61. try:
  62. os.remove(fname)
  63. except OSError as e:
  64. # ENOENT can happen if the cache file is removed (by another
  65. # process) after the os.path.exists check.
  66. if e.errno != errno.ENOENT:
  67. raise
  68. def has_key(self, key, version=None):
  69. fname = self._key_to_file(key, version)
  70. if os.path.exists(fname):
  71. with io.open(fname, 'rb') as f:
  72. return not self._is_expired(f)
  73. return False
  74. def _cull(self):
  75. """
  76. Removes random cache entries if max_entries is reached at a ratio
  77. of num_entries / cull_frequency. A value of 0 for CULL_FREQUENCY means
  78. that the entire cache will be purged.
  79. """
  80. filelist = self._list_cache_files()
  81. num_entries = len(filelist)
  82. if num_entries < self._max_entries:
  83. return # return early if no culling is required
  84. if self._cull_frequency == 0:
  85. return self.clear() # Clear the cache when CULL_FREQUENCY = 0
  86. # Delete a random selection of entries
  87. filelist = random.sample(filelist,
  88. int(num_entries / self._cull_frequency))
  89. for fname in filelist:
  90. self._delete(fname)
  91. def _createdir(self):
  92. if not os.path.exists(self._dir):
  93. try:
  94. os.makedirs(self._dir, 0o700)
  95. except OSError as e:
  96. if e.errno != errno.EEXIST:
  97. raise EnvironmentError(
  98. "Cache directory '%s' does not exist "
  99. "and could not be created'" % self._dir)
  100. def _key_to_file(self, key, version=None):
  101. """
  102. Convert a key into a cache file path. Basically this is the
  103. root cache path joined with the md5sum of the key and a suffix.
  104. """
  105. key = self.make_key(key, version=version)
  106. self.validate_key(key)
  107. return os.path.join(self._dir, ''.join(
  108. [hashlib.md5(force_bytes(key)).hexdigest(), self.cache_suffix]))
  109. def clear(self):
  110. """
  111. Remove all the cache files.
  112. """
  113. if not os.path.exists(self._dir):
  114. return
  115. for fname in self._list_cache_files():
  116. self._delete(fname)
  117. def _is_expired(self, f):
  118. """
  119. Takes an open cache file and determines if it has expired,
  120. deletes the file if it is has passed its expiry time.
  121. """
  122. exp = pickle.load(f)
  123. if exp is not None and exp < time.time():
  124. f.close() # On Windows a file has to be closed before deleting
  125. self._delete(f.name)
  126. return True
  127. return False
  128. def _list_cache_files(self):
  129. """
  130. Get a list of paths to all the cache files. These are all the files
  131. in the root cache dir that end on the cache_suffix.
  132. """
  133. if not os.path.exists(self._dir):
  134. return []
  135. filelist = [os.path.join(self._dir, fname) for fname
  136. in glob.glob1(self._dir, '*%s' % self.cache_suffix)]
  137. return filelist