root/galaxy-central/eggs/Beaker-1.4-py2.6.egg/beaker/cache.py @ 3

リビジョン 3, 9.3 KB (コミッタ: kohda, 14 年 前)

Install Unix tools  http://hannonlab.cshl.edu/galaxy_unix_tools/galaxy.html

行番号 
1"""Cache object
2
3The Cache object is used to manage a set of cache files and their
4associated backend. The backends can be rotated on the fly by
5specifying an alternate type when used.
6
7Advanced users can add new backends in beaker.backends
8
9"""
10import pkg_resources
11import warnings
12
13import beaker.container as container
14import beaker.util as util
15from beaker.exceptions import BeakerException, InvalidCacheBackendError
16
17# Initialize the basic available backends
18clsmap = {
19          'memory':container.MemoryNamespaceManager,
20          'dbm':container.DBMNamespaceManager,
21          'file':container.FileNamespaceManager,
22          }
23
24
25# Load up the additional entry point defined backends
26for entry_point in pkg_resources.iter_entry_points('beaker.backends'):
27    try:
28        NamespaceManager = entry_point.load()
29        name = entry_point.name
30        if name in clsmap:
31            raise BeakerException("NamespaceManager name conflict,'%s' "
32                                  "already loaded" % name)
33        clsmap[name] = NamespaceManager
34    except (InvalidCacheBackendError, SyntaxError):
35        # Ignore invalid backends
36        pass
37    except:
38        import sys
39        from pkg_resources import DistributionNotFound
40        # Warn when there's a problem loading a NamespaceManager
41        if not isinstance(sys.exc_info()[1], DistributionNotFound):
42            import traceback
43            from StringIO import StringIO
44            tb = StringIO()
45            traceback.print_exc(file=tb)
46            warnings.warn("Unable to load NamespaceManager entry point: '%s': "
47                          "%s" % (entry_point, tb.getvalue()), RuntimeWarning,
48                          2)
49
50
51# Load legacy-style backends
52try:
53    import beaker.ext.memcached as memcached
54    clsmap['ext:memcached'] = memcached.MemcachedNamespaceManager
55except InvalidCacheBackendError, e:
56    clsmap['ext:memcached'] = e
57
58try:
59    import beaker.ext.database as database
60    clsmap['ext:database'] = database.DatabaseNamespaceManager
61except InvalidCacheBackendError, e:
62    clsmap['ext:database'] = e
63
64try:
65    import beaker.ext.sqla as sqla
66    clsmap['ext:sqla'] = sqla.SqlaNamespaceManager
67except InvalidCacheBackendError, e:
68    clsmap['ext:sqla'] = e
69
70try:
71    import beaker.ext.google as google
72    clsmap['ext:google'] = google.GoogleNamespaceManager
73except (InvalidCacheBackendError, SyntaxError), e:
74    clsmap['ext:google'] = e
75
76
77class Cache(object):
78    """Front-end to the containment API implementing a data cache.
79
80    ``namespace``
81        the namespace of this Cache
82
83    ``type``
84        type of cache to use
85
86    ``expire``
87        seconds to keep cached data
88
89    ``expiretime``
90        seconds to keep cached data (legacy support)
91
92    ``starttime``
93        time when cache was cache was
94    """
95    def __init__(self, namespace, type='memory', expiretime=None,
96                 starttime=None, expire=None, **nsargs):
97        try:
98            cls = clsmap[type]
99            if isinstance(cls, InvalidCacheBackendError):
100                raise cls
101        except KeyError:
102            raise TypeError("Unknown cache implementation %r" % type)
103           
104        self.namespace = cls(namespace, **nsargs)
105        self.expiretime = expiretime or expire
106        self.starttime = starttime
107        self.nsargs = nsargs
108       
109    def put(self, key, value, **kw):
110        self._get_value(key, **kw).set_value(value)
111    set_value = put
112   
113    def get(self, key, **kw):
114        """Retrieve a cached value from the container"""
115        return self._get_value(key, **kw).get_value()
116    get_value = get
117   
118    def remove_value(self, key, **kw):
119        mycontainer = self._get_value(key, **kw)
120        if mycontainer.has_current_value():
121            mycontainer.clear_value()
122    remove = remove_value
123
124    def _get_value(self, key, **kw):
125        if isinstance(key, unicode):
126            key = key.encode('ascii', 'backslashreplace')
127
128        if 'type' in kw:
129            return self._legacy_get_value(key, **kw)
130
131        kw.setdefault('expiretime', self.expiretime)
132        kw.setdefault('starttime', self.starttime)
133       
134        return container.Value(key, self.namespace, **kw)
135   
136    def _legacy_get_value(self, key, type, **kw):
137        expiretime = kw.pop('expiretime', self.expiretime)
138        starttime = kw.pop('starttime', None)
139        createfunc = kw.pop('createfunc', None)
140        kwargs = self.nsargs.copy()
141        kwargs.update(kw)
142        c = Cache(self.namespace.namespace, type=type, **kwargs)
143        return c._get_value(key, expiretime=expiretime, createfunc=createfunc,
144                            starttime=starttime)
145    _legacy_get_value = util.deprecated(_legacy_get_value, "Specifying a "
146        "'type' and other namespace configuration with cache.get()/put()/etc. "
147        "is deprecated. Specify 'type' and other namespace configuration to "
148        "cache_manager.get_cache() and/or the Cache constructor instead.")
149   
150    def clear(self):
151        """Clear all the values from the namespace"""
152        self.namespace.remove()
153   
154    # dict interface
155    def __getitem__(self, key):
156        return self.get(key)
157   
158    def __contains__(self, key):
159        return self._get_value(key).has_current_value()
160   
161    def has_key(self, key):
162        return key in self
163   
164    def __delitem__(self, key):
165        self.remove_value(key)
166   
167    def __setitem__(self, key, value):
168        self.put(key, value)
169
170
171class CacheManager(object):
172    def __init__(self, **kwargs):
173        """Initialize a CacheManager object with a set of options
174       
175        Options should be parsed with the
176        :func:`~beaker.util.parse_cache_config_options` function to
177        ensure only valid options are used.
178       
179        """
180        self.kwargs = kwargs
181        self.caches = {}
182        self.regions = kwargs.pop('cache_regions', {})
183   
184    def get_cache(self, name, **kwargs):
185        kw = self.kwargs.copy()
186        kw.update(kwargs)
187        return self.caches.setdefault(name + str(kw), Cache(name, **kw))
188   
189    def get_cache_region(self, name, region):
190        if region not in self.regions:
191            raise BeakerException('Cache region not configured: %s' % region)
192        kw = self.regions[region]
193        return self.caches.setdefault(name + str(kw), Cache(name, **kw))
194   
195    def region(self, region, *args):
196        """Decorate a function to cache itself using a cache region
197       
198        The region decorator requires arguments if there are more than
199        2 of the same named function, in the same module. This is
200        because the namespace used for the functions cache is based on
201        the functions name and the module.
202       
203       
204        Example::
205           
206            # Assuming a cache object is available like:
207            cache = CacheManager(dict_of_config_options)
208           
209           
210            def populate_things():
211               
212                @cache.region('short_term', 'some_data')
213                def load(search_term, limit, offset):
214                    return load_the_data(search_term, limit, offset)
215               
216                return load('rabbits', 20, 0)
217       
218        .. note::
219           
220            The function being decorated must only be called with
221            positional arguments.
222       
223        """
224        cache = [None]
225        key = " ".join(str(x) for x in args)
226       
227        def decorate(func):
228            def cached(*args):
229                reg = self.regions[region]
230                if not reg.get('enabled', True):
231                    return func(*args)
232               
233                if not cache[0]:
234                    namespace = util.func_namespace(func)
235                    cache[0] = self.get_cache_region(namespace, region)
236               
237                cache_key = key + " " + " ".join(str(x) for x in args)
238                def go():
239                    return func(*args)
240               
241                return cache[0].get_value(cache_key, createfunc=go)
242            return cached
243        return decorate
244
245    def cache(self, *args, **kwargs):
246        """Decorate a function to cache itself with supplied parameters
247
248        ``args``
249            used to make the key unique for this function, as in region()
250            above.
251
252        ``kwargs``
253            parameters to be passed to get_cache(), will override defaults
254
255        Example::
256
257            # Assuming a cache object is available like:
258            cache = CacheManager(dict_of_config_options)
259           
260           
261            def populate_things():
262               
263                @cache.cache('mycache', expire=15)
264                def load(search_term, limit, offset):
265                    return load_the_data(search_term, limit, offset)
266               
267                return load('rabbits', 20, 0)
268       
269        .. note::
270           
271            The function being decorated must only be called with
272            positional arguments.
273
274        """
275        cache = [None]
276        key = " ".join(str(x) for x in args)
277       
278        def decorate(func):
279            def cached(*args):
280                if not cache[0]:
281                    namespace = util.func_namespace(func)
282                    cache[0] = self.get_cache(namespace, **kwargs)
283                cache_key = key + " " + " ".join(str(x) for x in args)
284                def go():
285                    return func(*args)
286
287                return cache[0].get_value(cache_key, createfunc=go)
288            return cached
289        return decorate
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。