Source code for ploneintranet.layout.memoize.view
# -*- coding: utf-8 -*-
"""Memoize decorator for views.
Stores values in an annotation of the request.
Copied from plone.memoize but works also using zope.globalrequest
"""
from functools import wraps
from zope.annotation.interfaces import IAnnotations
from zope.globalrequest import getRequest
class ViewMemo(object):
key = "plone.memoize"
def memoize(self, func):
@wraps(func)
def memogetter(*args, **kwargs):
instance = args[0]
context = getattr(instance, "context", None)
try:
request = instance.request
except AttributeError:
request = getRequest()
annotations = IAnnotations(request, {})
if self.key not in annotations:
annotations[self.key] = dict()
cache = annotations[self.key]
# XXX: Not the most elegant thing in the world; in a Zope 2
# context, the physical path is a better key, since the id could
# change if the object is invalidated from the ZODB cache
try:
context_id = context.getPhysicalPath()
except AttributeError:
context_id = id(context)
# Note: we don't use args[0] in the cache key, since args[0] ==
# instance and the whole point is that we can cache different
# requests
key = (
context_id,
instance.__class__.__name__,
func.__name__,
args[1:],
frozenset(kwargs.items()),
)
if key not in cache:
cache[key] = func(*args, **kwargs)
return cache[key]
return memogetter
def memoize_contextless(self, func):
def memogetter(*args, **kwargs):
instance = args[0]
try:
request = instance.request
except AttributeError:
request = getRequest()
annotations = IAnnotations(request, {})
if self.key not in annotations:
annotations[self.key] = dict()
cache = annotations[self.key]
key = (
instance.__class__.__name__,
func.__name__,
args[1:],
frozenset(kwargs.items()),
)
if key not in cache:
cache[key] = func(*args, **kwargs)
return cache[key]
return memogetter
_m = ViewMemo()
memoize = _m.memoize
memoize_contextless = _m.memoize_contextless
__all__ = (memoize, memoize_contextless)