Ticket #437: filecache.diff

File filecache.diff, 5.7 KB (added by nesh <nesh [at] studioquattro [dot] co [dot] yu>, 10 years ago)
  • django/utils/filecache.py

     
     1# -*- coding: utf-8 -*-
     2# vim:enc=utf8:fenc=utf8:sts=4:sw=4:sta:et:nofen:si:ai:nowrap
     3
     4# (C) Djordjevic Nebojsa <nesh@studioquattro.co.yu> 2005
     5# You're welcome to redistribute this software under the
     6# terms of the GNU Library General Public Licence version 2.0
     7# or, at your option, any higher version.
     8#
     9# You can read the complete GNU LGPL in the file COPYING
     10# which should come along with this software, or visit
     11# the Free Software Foundation's WEB site http://www.fsf.org
     12#
     13
     14
     15""" In memory file cache. It will automatically reload a file if it
     16    has changed. This includes its modification time being
     17    set backwards in time.
     18
     19    based on vampire TemplateCache
     20"""
     21
     22##################################################
     23## DEPENDENCIES ##
     24
     25import os
     26import time
     27
     28try:
     29  from threading import Lock
     30except:
     31    class Lock:
     32        def acquire(self): pass
     33        def release(self): pass
     34    # Lock
     35#
     36
     37##################################################
     38## GLOBALS AND CONSTANTS ##
     39
     40_cache = {}
     41
     42##################################################
     43## CLASSES ##
     44
     45class _FileInfo(object):
     46    __slots__ = ('path', 'mtime', 'atime', 'hits', 'content')
     47
     48    def __init__(self, path, mtime, content):
     49        super(_FileInfo, self).__init__()
     50        self.path = path
     51        self.mtime = mtime
     52        self.atime = time.time()
     53        self.hits = 0
     54        self.content = content
     55    # __init__
     56# _FileInfo
     57
     58class FileCache(object):
     59    """ dict based cache  """
     60
     61    __slots__ = ('_lock', '_frozen', '_cache')
     62
     63    def __init__(self):
     64        super(FileCache, self).__init__()
     65
     66        self._lock = Lock()
     67        self._frozen = False
     68        self._cache = {}
     69    # __init__
     70
     71    def files(self):
     72        self._lock.acquire()
     73        try:
     74            return self._cache.keys()
     75        finally:
     76            self._lock.release()
     77    # keys
     78
     79    def info(self, path):
     80        self._lock.acquire()
     81        try:
     82            path = os.path.normpath(path)
     83            return self._cache[path]
     84        finally:
     85            self._lock.release()
     86    # info
     87
     88    def unload(self, path):
     89        self._lock.acquire()
     90        try:
     91            path = os.path.normpath(path)
     92            if path in self._cache:
     93                del self._cache[path]
     94        finally:
     95            self._lock.release()
     96    # unload
     97
     98    def freeze(self):
     99        self._frozen = True
     100    # freeze
     101
     102    def load(self, path, mode='r'):
     103        self._lock.acquire()
     104        try:
     105            record = None
     106            # ensure the path is normalised
     107            path = os.path.normpath(path)
     108            # is page template already loaded
     109            if path in self._cache:
     110                record = self._cache[path]
     111                # check if reloads have been disabled
     112                if not self._frozen:
     113                    # has page template been changed
     114                    try:
     115                        mtime = os.path.getmtime(path)
     116                    except:
     117                        # page template must not exist
     118                        del self._cache[path]
     119                        raise
     120                    else:
     121                        if record.mtime != mtime:
     122                            # force reloading of page template
     123                            del self._cache[path]
     124                            record = None
     125                        # if
     126                    # try
     127                # if
     128            # if
     129            # need to load the page template
     130            if record is None:
     131                content = self.do_load(path, mode)
     132                mtime = os.path.getmtime(path)
     133                record = _FileInfo(path, mtime, content)
     134                self._cache[path] = record
     135                return self.make_content(content)
     136            else:
     137                content = record.content
     138                record.hits += 1
     139                record.atime = time.time()
     140                return self.make_content(content)
     141            # if
     142        finally:
     143            self._lock.release()
     144        # try
     145    # load
     146
     147    def make_content(self, content):
     148        """ return content
     149            derived classes can override this
     150            to do some proccesing before returning data
     151        """
     152        return content
     153    # make_content
     154
     155    def do_load(self, path, mode):
     156        """ load file
     157            derived classes can override this
     158            to do some proccesing before storing data
     159            i.e. parse template and store parsed version in
     160            the cache
     161        """
     162        fhandle = file(path, mode)
     163        content = fhandle.read()
     164        fhandle.close()
     165        return content
     166    # do_load
     167# FileCache
     168
     169##################################################
     170## FUNCTIONS ##
     171
     172def get_cache(cache_name, cache_object=FileCache):
     173    """ return cache named cache_name
     174        using FileCache object cache_object (default FileCache)
     175    """
     176
     177    global _cache
     178
     179    if cache_name not in _cache:
     180        _cache[cache_name] = cache_object()
     181    return _cache[cache_name]
     182# get_cache
     183
     184def delete_cache(cache_name):
     185    """ delete cache cache_name,
     186        if cache does not exists, do nothing
     187    """
     188
     189    global _cache
     190
     191    if cache_name in _cache:
     192        del _cache[cache_name]
     193# delete_cache
Back to Top