Skip to content

Instantly share code, notes, and snippets.

@thet
Created November 30, 2020 10:36
Show Gist options
  • Save thet/6315f5dde2165053e914e800535d59f1 to your computer and use it in GitHub Desktop.
Save thet/6315f5dde2165053e914e800535d59f1 to your computer and use it in GitHub Desktop.
plone.memoize helpers with support for plone.subrequest
# -*- coding: utf-8 -*-
# memoize support for plone.subrequest subrequests.
# usage:
# >>> import ./memoize
# >>> from ./memoize import instance_memoize
# >>> @memoize.parent_request_memoize
# >>> def _results(self):
# >>> return "expensive calculation"
# >>>
# >>> @memoize.instance_memoize
# >>> def results(self):
# >>> return "another expensive calculation"
from Products.CMFPlone.utils import get_top_request
from zope.annotation.interfaces import IAnnotations
parent_request_memo_key = "_parentrequest_memoizer"
instance_memo_pre = "__memoize__"
_marker = object()
def parent_request_memoize(func):
def memogetter(*args, **kwargs):
instance = args[0]
context = getattr(instance, "context", None)
request = getattr(instance, "request", None)
request = get_top_request(request)
annotations = IAnnotations(request)
cache = annotations.get(parent_request_memo_key, _marker)
if cache is _marker:
cache = annotations[parent_request_memo_key] = dict()
key = (
context.getPhysicalPath(),
instance.__class__.__name__,
func.__name__,
args[1:],
frozenset(kwargs.items()),
)
value = cache.get(key, _marker)
if value is _marker:
value = cache[key] = func(*args, **kwargs)
return value
return memogetter
def parent_request_memoize_contextless(func):
def memogetter(*args, **kwargs):
instance = args[0]
request = getattr(instance, "request", None)
request = get_top_request(request)
annotations = IAnnotations(request)
cache = annotations.get(parent_request_memo_key, _marker)
if cache is _marker:
cache = annotations[parent_request_memo_key] = dict()
key = (
instance.__class__.__name__,
func.__name__,
args[1:],
frozenset(kwargs.items()),
)
value = cache.get(key, _marker)
if value is _marker:
value = cache[key] = func(*args, **kwargs)
return value
return memogetter
def instance_memoize(func):
# TODO: make sure, this isn't causing a transaction.commit() and DB write.
def memogetter(*args, **kwargs):
instance = args[0]
key = instance_memo_pre + func.__name__
if getattr(instance, key, _marker) == _marker:
setattr(instance, key, func(*args, **kwargs))
return getattr(instance, key)
return memogetter
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment