add utility for caching values in the request

git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@3791 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2010-03-30 13:33:28 +00:00
parent 44fb2e3142
commit 64064d60b3
3 changed files with 131 additions and 1 deletions

60
zutil/rcache.py Normal file
View file

@ -0,0 +1,60 @@
#
# Copyright (c) 2010 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
A simple mechanism for caching values in the request.
$Id$
"""
INVALID = object()
def caching(self, method, id):
annot = self.request.annotations
item = annot.setdefault('cybertools.util.rcache', {})
value = item.get(id, INVALID)
if value is INVALID:
value = method()
item[id] = value
return value
def requestCache(method):
def _cache(self):
return caching(self, method, method.__name__)
return _cache
rcache = requestCache
class requestCacheProperty(object):
def __init__(self, func):
self.func = func
def __get__(self, inst, class_):
if inst is None:
return self
id = self.func.__name__
value = caching(inst, self.func, id)
inst.__dict__[id] = value
return value
rcacheproperty = requestCacheProperty

69
zutil/rcache.txt Normal file
View file

@ -0,0 +1,69 @@
============
Data Caching
============
$Id$
>>> from cybertools.zutil.rcache import rcache, rcacheproperty
>>> class View(object):
... def __init__(self, context, request):
... self.context = context
... self.request = request
...
... @rcache
... def calculate():
... print 'calculating'
... return 42
...
... @rcacheproperty
... def value():
... print 'calculating'
... return 43
>>> from zope.publisher.browser import TestRequest
>>> request = TestRequest()
When we first call the calculation method it gets executed.
>>> v1 = View(None, request)
>>> v1.calculate()
calculating
42
Subsequent calls just fetch the value from the cache.
>>> v1.calculate()
42
Even if we create a new view object (with the same request as before) the
value is just taken from the cache.
>>> v2 = View(None, request)
>>> v2.calculate()
42
Let's now have a look at the case where the result of the calculation is
stored immediately in the view.
>>> v1.value
calculating
43
>>> v1.value
43
>>> v2.value
43
If we associate a new request with the view the calculation is done again
when using the method.
>>> v1.request = TestRequest()
>>> v1.calculate()
calculating
42
If we use the property the value is taken direktly from the instance.
>>> v1.value
43

View file

@ -19,7 +19,8 @@ def test_suite():
#unittest.makeSuite(Test), # we don't need this
#doctest.DocTestSuite(cybertools.zutil.property, optionflags=flags),
DocFileSuite('jeep.txt', optionflags=flags),
))
doctest.DocFileSuite('rcache.txt', optionflags=flags),
))
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')