Metadata-Version: 1.0
Name: percache
Version: 0.1.1
Summary: Persistently cache results of callables
Home-page: http://bitbucket.org/obensonne/percache
Author: Oben Sonne
Author-email: obensonne@googlemail.com
License: MIT License
Description: 
        percache
        ========
        
        *percache* is a Python module to persistently cache results of
        functions (or callables in general) using decorators.
        
        It is somehow similar to the
        `Memoize Example <http://wiki.python.org/moin/PythonDecoratorLibrary#Memoize>`_
        from the Python Decorator Library but with the advantage that
        results are stored *persistently* in a cache file. *percache*
        provides memoization across multiple invocations of the Python
        interpreter.
        
        Example
        -------
        
        ::
        
        >>> import percache
        >>> cache = percache.Cache("/tmp/my-cache")
        >>>
        >>> @cache.check
        ... def longtask(a, b):
        ...     print("running a long task")
        ...     return a + b
        ...
        >>> longtask(1, 2)
        running a long task
        3
        >>>
        >>> longtask(1, 2)
        3
        >>> cache.close() # writes new cached results to disk
        
        As you can see at the missing output after the second invocation,
        ``longtask`` has been called once only. The second time the result
        is retrieved from the cache.
        *The key feature of this module is that this works across multiple invocations of the Python interpreter.*
        
        A requirement on the results to cache is that they are
        `pickable <http://docs.python.org/library/pickle.html#what-can-be-pickled-and-unpickled>`_.
        
        Each cache file can be used for any number of differently named
        callables.
        
        Caching details (you should know)
        ---------------------------------
        
        When caching the result of a callable, a SHA1 hash based on the callable's name
        and arguments is used as a key to store the result in the cache file.
        
        The hash calculation does not work directly with the arguments but with their
        *rerpresentations*, i.e. the string returned by applying ``repr()``. Argument
        representations are supposed to differentiate values
        sufficiently for the purpose of the function but identically across
        multiple invocations of the Python interpreter. By default the
        builtin function ``repr()`` is used to get argument
        representations. This is just perfect for basic types, lists,
        tuples and combinations of them but it may fail on other types:
        
        ::
        
        >>> repr(42)
        42                                  # good
        >>> repr(["a", "b", (1, 2L)])
        "['a', 'b', (1, 2L)]"               # good
        >>> o = object()
        >>> repr(o)
        '<object object at 0xb769a4f8>'     # bad (address is dynamic)
        >>> repr({"a":1,"b":2,"d":4,"c":3})
        "{'a': 1, 'c': 3, 'b': 2, 'd': 4}"  # bad (order may change)
        >>> class A(object):
        ...     def __init__(self, a):
        ...         self.a = a
        ...
        >>> repr(A(36))
        '<__main__.A object at 0xb725bb6c>' # bad (A.a not considered)
        >>> repr(A(35))
        '<__main__.A object at 0xb725bb6c>' # bad (A.a not considered)
        
        A *bad* representation is one that is not identically across
        Python invocations (all *bad* examples) or one that does not
        differentiate values sufficiently (last 2 *bad* examples).
        
        To use such types anyway you can either
        
        1. implement the type's ``__repr__()`` method accordingly or
        2. provide a custom representation function using the ``repr`` keyword of the
        ``Cache`` constructor.
        
        Implement the ``__repr__()`` method
        '''''''''''''''''''''''''''''''''''
        
        To pass dictionaries to *percache* decorated functions, you could
        wrap them in an own dictionary type with a suitable ``__repr__()``
        method:
        
        ::
        
        >>> class mydict(dict):
        ...     def __repr__(self):
        ...         items = ["%r: %r" % (k, self[k]) for k in sorted(self)]
        ...         return "{%s}" % ", ".join(items)
        ...
        >>> repr(mydict({"a":1,"b":2,"d":4,"c":3}))
        "{'a': 1, 'b': 2, 'c': 3, 'd': 4}"  # good (always same order)
        
        Provide a custom ``repr()`` function
        ''''''''''''''''''''''''''''''''''''
        
        The following example shows how to use a custom representation
        function to get a suitable argument representation of ``file``
        objects:
        
        ::
        
        >>> def myrepr(arg):
        ...     if isinstance(arg, file):
        ...         # return a string with file name and modification time
        ...         return "%s:%s" % (arg.name, os.fstat(arg.fileno())[8])
        ...     else:
        ...         return repr(arg)
        ...
        >>> cache = percache.Cache("/some/path", repr=myrepr)
        
        Housekeeping
        ------------
        
        - Don't forget to call the ``close()`` method of a ``Cache`` instance. No
        results are written to disk until this method is called
        
        - Make sure to delete the cache file whenever the behavior of a cached function
        has changed!
        
        - To prevent the cache from getting larger and larger you can call the
        ``clear()`` method of a ``Cache`` instance. By default it clears *all*
        results from the cache. The keyword ``maxage`` my be used to specify a
        maximum number of seconds passed since a cached result has been *used* the
        last time. Any result not used (written or accessed) for ``maxage`` seconds
        gets removed from the cache.
        
        Changes
        =======
        
        Version 0.1.1
        -------------
        
        - Fix wrong usage age output of command line interface.
        - Meet half way with pylint.
        
        Version 0.1
        -----------
        
        - Initial release
        
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Topic :: Software Development
Classifier: Intended Audience :: Developers
