Source code for mg.utils.exif.cache

# MG_GPL_HEADER_BEGIN
# 
# This file is part of Media Gallery, GNU GPLv2.
# 
# Media Gallery is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
# 
# Media Gallery is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with Media Gallery; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# 
# MG_GPL_HEADER_END

__author__ = "Media Gallery contributors <mg@lists.ssji.net>"
__copyright__ = "(c) 2011"
__credits__ = ["Dimitri Refauvelet", "Nicolas Pouillon"]

_default = object()

class LruDict:
    def __init__(self, size = 10):
        self.__size = size
        self.__entries = {}
        self.__lru = []

    def __touch(self, key):
        if key in self.__entries:
            self.__lru.remove(key)
        self.__lru.insert(0, key)

    def __check_size(self):
        if len(self.__entries) > self.__size:
            try:
                del self.__entries[self.__lru[-1]]
            except:
                pass
            try:
                del self.__lru[-1]
            except:
                pass

    def __setitem__(self, key, val):
        self.__touch(key)
        self.__entries[key] = val
        self.__check_size()

    def __getitem__(self, key):
        self.__touch(key)
        return self.__entries[key]

    def __delitem__(self, key):
        del self.__entries[key]
        del self.__lru[key]

    def __contains__(self, key):
        return key in self.__entries

    def get(self, key, default = _default):
        try:
            return self[key]
        except KeyError:
            if default is __default:
                raise
            return default

class PhotoExifCache(LruDict):

    def __key(self, obj):
        app = obj.__class__._meta.app_label
        name = obj.__class__._meta.object_name.lower()
        pk = str(obj.pk)
        return "_".join((app, name, pk))

    def __generate_data(self, fd):
        from mg.utils.exif.contrib.exif import process_file
        return process_file(fd)

    def get(self, obj, fd):
        key = self.__key(obj)

        if key in self:
            return self[key]

        data = self.__generate_data(fd)

        self[key] = data
        return data

exif_cache = PhotoExifCache()