==============================
 plone memoization decorators
==============================

Used to memoize the return values of functions and properties of classes
and Zope views.

volatile
========

The 'volatile' module defines a versatile caching decorator that gives
you total control of how the cache key is calculated and where it is
stored.  This decorator is explained in more in depth with example
usage in 'volatile.py'.

'volatile' caches can be stored in different places. A common use is
a zope RAMCache. There are convenience methods in the 'ram' module
to support that.

A quick example of a Five view that uses 'volatile' caching through the 'ram'
module:

  >>> from Products.Five import BrowserView
  >>> from plone.memoize import ram

  >>> def _render_details_cachekey(method, self, brain):
  ...    return hash((brain.getPath(), brain.modified))

  >>> class View(BrowserView):
  ...    @ram.cache(_render_details_cachekey)
  ...    def render_details(self, brain):
  ...        obj = brain.getObject()
  ...        view = obj.restrictedTraverse('@@obj-view')
  ...        return view.render()

The results of our hypothetical 'render_details' method are cached
*across requests* and independently of the (not) logged in user.  The
cache is only refreshed when the brain's path or modification date
change, as defined in '_render_details_cachekey'.

view and instance
=================

See view.txt and instance.txt for usage of cache decorators that have
a fixed cache key and cache storage.  The most common usage pattern of
these view and instance caching decorators is:

 from plone.memoize import instance

 class MyClass(object):
 
    @instance.memoize
    def some_expensive_function(self, arg1, arg2):
        ...

The first time some_expensive_function() is called, the return value will
be saved. On subsequent calls with the same arguments, the cached version
will be returned. Passing in different arguments will cause the function to
be called again.

Note that this only works if the arguments are hashable!

If you are writing a Zope 3 view, you can do:

 from plone.memoize import view

 class MyView(BrowserView):
 
    @view.memoize
    def some_expensive_function(self, arg1, arg2):
        ...

This has the same effect, but subsequent lookup of the same view in the
same context will be memoized as well.

You can also use @view.memoize_contextless to have the memoization not
take the context into account - the same view looked up during the same
request (but possibly on another context) with the same parameters will 
be memoized.

Note that this requires that the request is annotatable using zope.annotation!
