Skip to content
This repository
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 137 lines (107 sloc) 4.421 kb
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
# $Id: CacheRegion.py,v 1.3 2006/01/28 04:19:30 tavis_rudd Exp $
'''
Cache holder classes for Cheetah:

Cache regions are defined using the #cache Cheetah directive. Each
cache region can be viewed as a dictionary (keyed by cacheRegionID)
handling at least one cache item (the default one). It's possible to add
cacheItems in a region by using the `varyBy` #cache directive parameter as
in the following example::
#def getArticle
this is the article content.
#end def

#cache varyBy=$getArticleID()
$getArticle($getArticleID())
#end cache

The code above will generate a CacheRegion and add new cacheItem for each value
of $getArticleID().
'''

try:
    from hashlib import md5
except ImportError:
    from md5 import md5

import time
import Cheetah.CacheStore

class CacheItem(object):
    '''
A CacheItem is a container storing:

- cacheID (string)
- refreshTime (timestamp or None) : last time the cache was refreshed
- data (string) : the content of the cache
'''
    
    def __init__(self, cacheItemID, cacheStore):
        self._cacheItemID = cacheItemID
        self._cacheStore = cacheStore
        self._refreshTime = None
        self._expiryTime = 0

    def hasExpired(self):
        return (self._expiryTime and time.time() > self._expiryTime)
    
    def setExpiryTime(self, time):
        self._expiryTime = time

    def getExpiryTime(self):
        return self._expiryTime

    def setData(self, data):
        self._refreshTime = time.time()
        self._cacheStore.set(self._cacheItemID, data, self._expiryTime)

    def getRefreshTime(self):
        return self._refreshTime

    def getData(self):
        assert self._refreshTime
        return self._cacheStore.get(self._cacheItemID)

    def renderOutput(self):
        """Can be overridden to implement edge-caching"""
        return self.getData() or ""

    def clear(self):
        self._cacheStore.delete(self._cacheItemID)
        self._refreshTime = None

class _CacheDataStoreWrapper(object):
    def __init__(self, dataStore, keyPrefix):
        self._dataStore = dataStore
        self._keyPrefix = keyPrefix
        
    def get(self, key):
        return self._dataStore.get(self._keyPrefix+key)

    def delete(self, key):
        self._dataStore.delete(self._keyPrefix+key)

    def set(self, key, val, time=0):
        self._dataStore.set(self._keyPrefix+key, val, time=time)

class CacheRegion(object):
    '''
A `CacheRegion` stores some `CacheItem` instances.

This implementation stores the data in the memory of the current process.
If you need a more advanced data store, create a cacheStore class that works
with Cheetah's CacheStore protocol and provide it as the cacheStore argument
to __init__. For example you could use
Cheetah.CacheStore.MemcachedCacheStore, a wrapper around the Python
memcached API (http://www.danga.com/memcached).
'''
    _cacheItemClass = CacheItem
    
    def __init__(self, regionID, templateCacheIdPrefix='', cacheStore=None):
        self._isNew = True
        self._regionID = regionID
        self._templateCacheIdPrefix = templateCacheIdPrefix
        if not cacheStore:
            cacheStore = Cheetah.CacheStore.MemoryCacheStore()
        self._cacheStore = cacheStore
        self._wrappedCacheDataStore = _CacheDataStoreWrapper(
            cacheStore, keyPrefix=templateCacheIdPrefix+':'+regionID+':')
        self._cacheItems = {}

    def isNew(self):
        return self._isNew
        
    def clear(self):
        " drop all the caches stored in this cache region "
        for cacheItemId in self._cacheItems.keys():
            cacheItem = self._cacheItems[cacheItemId]
            cacheItem.clear()
            del self._cacheItems[cacheItemId]
        
    def getCacheItem(self, cacheItemID):
        """ Lazy access to a cacheItem

Try to find a cache in the stored caches. If it doesn't
exist, it's created.
Returns a `CacheItem` instance.
"""
        cacheItemID = md5(str(cacheItemID)).hexdigest()
        
        if cacheItemID not in self._cacheItems:
            cacheItem = self._cacheItemClass(
                cacheItemID=cacheItemID, cacheStore=self._wrappedCacheDataStore)
            self._cacheItems[cacheItemID] = cacheItem
            self._isNew = False
        return self._cacheItems[cacheItemID]
Something went wrong with that request. Please try again.