Back to index

plone3  3.1.7
view.py
Go to the documentation of this file.
00001 """
00002 Memoize decorator for views.
00003 
00004 Stores values in an annotation of the request. See view.txt.
00005 """
00006 
00007 try:
00008     from zope.annotation.interfaces import IAnnotations
00009     from zope.annotation.interfaces import IAttributeAnnotatable
00010 except ImportError:
00011     from zope.app.annotation.interfaces import IAnnotations
00012     from zope.app.annotation.interfaces import IAttributeAnnotatable
00013 
00014 from zope.interface import alsoProvides
00015 
00016 _marker = object()
00017 class ViewMemo(object):
00018     
00019     key = 'plone.memoize'
00020     
00021     def memoize(self, func):
00022         def memogetter(*args, **kwargs):
00023             instance = args[0]
00024             
00025             context = getattr(instance, 'context', None)            
00026             request = getattr(instance, 'request', None)
00027             
00028             # XXX: A Zope 2 workaround/optimisation (will degrade gracefully)
00029             if request is None:
00030                 request = getattr(context, 'REQUEST', None)
00031             
00032             annotations = IAnnotations(request)
00033             cache = annotations.get(self.key, _marker)
00034             
00035             if cache is _marker:
00036                 cache = annotations[self.key] = dict()
00037                 
00038             # XXX: Not the most elegant thing in the world; in a Zope 2
00039             # context, the physical path is a better key, since the id could
00040             # change if the object is invalidated from the ZODB cache
00041             
00042             try:
00043                 context_id = context.getPhysicalPath()
00044             except AttributeError:
00045                 context_id = id(context)
00046             
00047             # Note: we don't use args[0] in the cache key, since args[0] == 
00048             # instance and the whole point is that we can cache different
00049             # requests
00050             
00051             key = (context_id, instance.__class__.__name__, func.__name__, 
00052                    args[1:], frozenset(kwargs.items()))
00053             value = cache.get(key, _marker)
00054             if value is _marker:
00055                 value = cache[key] = func(*args, **kwargs)
00056             return value
00057         return memogetter
00058 
00059     def memoize_contextless(self, func):
00060         def memogetter(*args, **kwargs):
00061             instance = args[0]
00062             request = getattr(instance, 'request', None)
00063             
00064             annotations = IAnnotations(request)
00065             cache = annotations.get(self.key, _marker)
00066             
00067             if cache is _marker:
00068                 cache = annotations[self.key] = dict()
00069             
00070             key = (instance.__class__.__name__, func.__name__, 
00071                    args[1:], frozenset(kwargs.items()))
00072             value = cache.get(key, _marker)
00073             if value is _marker:
00074                 value = cache[key] = func(*args, **kwargs)
00075             return value
00076         return memogetter
00077 
00078 _m = ViewMemo()
00079 memoize = _m.memoize
00080 memoize_contextless = _m.memoize_contextless
00081 
00082 __all__ = (memoize, memoize_contextless)