diff --git a/news/36.bugfix b/news/36.bugfix new file mode 100644 index 0000000..c8ab335 --- /dev/null +++ b/news/36.bugfix @@ -0,0 +1,3 @@ +Fix plone.memoize.view to support unhashable types in function arguments. + +Fixes: #36 diff --git a/plone/memoize/view.py b/plone/memoize/view.py index a21e385..af70a39 100644 --- a/plone/memoize/view.py +++ b/plone/memoize/view.py @@ -6,6 +6,8 @@ from zope.annotation.interfaces import IAnnotations from zope.globalrequest import getRequest +import json + class ViewMemo: key = "plone.memoize" @@ -44,7 +46,7 @@ def memogetter(*args, **kwargs): instance.__class__.__name__, func.__name__, args[1:], - frozenset(kwargs.items()), + frozenset(json.dumps(kwargs)), ) if key not in cache: cache[key] = func(*args, **kwargs) @@ -73,7 +75,7 @@ def memogetter(*args, **kwargs): instance.__class__.__name__, func.__name__, args[1:], - frozenset(kwargs.items()), + frozenset(json.dumps(kwargs)), ) if key not in cache: cache[key] = func(*args, **kwargs) diff --git a/plone/memoize/view.rst b/plone/memoize/view.rst index 45de49c..9397e00 100644 --- a/plone/memoize/view.rst +++ b/plone/memoize/view.rst @@ -81,7 +81,8 @@ Even though we've twiddled txt1, txt2 is not recalculated:: >>> msg.txt2 'hello world' -We support memoization of multiple signatures as long as all signature values are hashable:: +We support memoization of multiple signatures. +The signature values just need to be able to be converted into a JSON string:: >>> print(msg.getMsg('Ernest')) Ernest: goodbye cruel world! @@ -89,6 +90,15 @@ We support memoization of multiple signatures as long as all signature values ar >>> print(msg.getMsg('J.D.', **{'raise':'roofbeams'})) J.D.: goodbye cruel world! raise--roofbeams +We also support unhashable types like lists and dicts:: + + >>> print(msg.getMsg('J.D.', lower=['shields', 'engines'])) + J.D.: goodbye cruel world! lower--['shields', 'engines'] + + >>> print(msg.getMsg('J.D.', actions={'open': ['gates']})) + J.D.: goodbye cruel world! actions--{'open': ['gates']} + + We can alter data underneath, but nothing changes:: >>> msg.txt1 = 'sound and fury'