From 1c2963997942db9028c90a688af42eff44238b30 Mon Sep 17 00:00:00 2001 From: ale-rt Date: Fri, 10 Apr 2020 18:07:41 +0200 Subject: [PATCH] Use the global request Use the zope global request if available as a fallback if the context does not have it Fixes #17 --- news/17.feature | 1 + plone/memoize/view.py | 29 +++++++++++++++--- plone/memoize/view.rst | 69 ++++++++++++++++++++++++++++++++++++++++++ setup.py | 4 ++- 4 files changed, 97 insertions(+), 6 deletions(-) create mode 100644 news/17.feature diff --git a/news/17.feature b/news/17.feature new file mode 100644 index 0000000..59ae812 --- /dev/null +++ b/news/17.feature @@ -0,0 +1 @@ +Use the zope global request if available as a fallback if the context does not have it [ale-rt] diff --git a/plone/memoize/view.py b/plone/memoize/view.py index 1c5200d..549df62 100644 --- a/plone/memoize/view.py +++ b/plone/memoize/view.py @@ -7,6 +7,14 @@ from zope.annotation.interfaces import IAnnotations +try: + from zope.globalrequest import getRequest +except ImportError: + + def getRequest(): + return None + + class ViewMemo(object): key = "plone.memoize" @@ -17,9 +25,12 @@ def memogetter(*args, **kwargs): instance = args[0] context = getattr(instance, "context", None) - request = getattr(instance, "request", None) + try: + request = instance.request + except AttributeError: + request = getRequest() - annotations = IAnnotations(request) + annotations = IAnnotations(request, {}) if self.key not in annotations: annotations[self.key] = dict() cache = annotations[self.key] @@ -52,10 +63,18 @@ def memogetter(*args, **kwargs): def memoize_contextless(self, func): def memogetter(*args, **kwargs): - instance = args[0] - request = getattr(instance, "request", None) - annotations = IAnnotations(request) + if args: + instance = args[0] + else: + instance = 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] diff --git a/plone/memoize/view.rst b/plone/memoize/view.rst index 75da470..e9ad76f 100644 --- a/plone/memoize/view.rst +++ b/plone/memoize/view.rst @@ -176,3 +176,72 @@ based on parameters, but not on context:: >>> print(msg2.getAnotherMsg('J.D.', **{'raise':'roofbeams'})) J.D.: so long, cruel world& raise--roofbeams +There is also support for using a global request +if zope.globalrequest is available. +With that you can cache also functions. + +If the global request is missing nothing changes: + + >>> a = "foo" + >>> @view.memoize_contextless + ... def memoized_function(): + ... return a + >>> memoized_function() + 'foo' + >>> a = "bar" + >>> memoized_function() + 'bar' + +Now we provide a global request which supports annotations: + + >>> from zope.globalrequest import setRequest + >>> from zope.interface import alsoProvides + >>> from zope.annotation import IAttributeAnnotatable + >>> global_request = TestRequest() + >>> alsoProvides(global_request, IAttributeAnnotatable) + >>> setRequest(global_request) + +With that in place the results are cached: + >>> a = "foo" + >>> memoized_function() + 'foo' + >>> a = "bar" + >>> memoized_function() + 'foo' + + +The same is true for an adapter: + + >>> class Adapter(object): + ... + ... msg = "foo" + ... + ... def __init__(self, context): + ... self.context = context + ... + ... @view.memoize + ... def context_aware_function(self): + ... return self.msg + ... + ... @view.memoize_contextless + ... def context_unaware_function(self): + ... return self.msg + +We now instatiate two objects: + >>> instance1 = Adapter(Dummy()) + >>> instance2 = Adapter(Dummy()) + >>> instance1.context_aware_function() + 'foo' + >>> instance1.context_unaware_function() + 'foo' + +Let's verify that the cache depends on the context: + >>> Adapter.msg = "bar" + >>> instance2.context_aware_function() + 'bar' + >>> instance1.context_unaware_function() + 'foo' + +Still instance1 is not aware of the change: + >>> instance1.context_aware_function() + 'foo' diff --git a/setup.py b/setup.py index be8e128..b4a624c 100644 --- a/setup.py +++ b/setup.py @@ -50,7 +50,9 @@ def read(*rnames): include_package_data=True, zip_safe=False, test_suite="plone.memoize.tests.test_suite", - extras_require=dict(test=["zope.configuration", "zope.publisher",]), + extras_require=dict( + test=["zope.configuration", "zope.globalrequest", "zope.publisher",] + ), install_requires=[ "setuptools", "six",