Caching wrapper for callables accepting a filename

import os


class FileCache(object):
    """Caching wrapper for callables accepting a filename.

    On every call, the modification time of the given file is examined.  If it
    is younger, the callable is executed again and the data is stored.  If
    not, the data already stored (cached) will be returned.

    Do not use this for very big files since the data is stored in memory.
    """

    def __init__(self, func):
        self.func = func
        self.last_mtime = 0
        self.data = None

    def __call__(self, filename):
        mtime = os.stat(filename).st_mtime
        if mtime > self.last_mtime:
            # File was modified.
            self.last_mtime = mtime
            self.data = self.func(filename)
        return self.data


def cache_file(func):
    """Decorator to wrap a callable in a `FileCache` instance."""
    return FileCache(func)


# example usage

from __future__ import with_statement

@cache_file
def load_data(filename):
    """Load some data from a file."""
    with open(filename, 'rb') as f:
        data = f.read()
    return data