Package elisa :: Package core :: Package utils :: Module caching

Source Code for Module elisa.core.utils.caching

  1  # -*- coding: utf-8 -*- 
  2  # Moovida - Home multimedia server 
  3  # Copyright (C) 2009 Fluendo Embedded S.L. (www.fluendo.com). 
  4  # All rights reserved. 
  5  # 
  6  # This file is available under one of two license agreements. 
  7  # 
  8  # This file is licensed under the GPL version 3. 
  9  # See "LICENSE.GPL" in the root of this distribution including a special 
 10  # exception to use Moovida with Fluendo's plugins. 
 11  # 
 12  # The GPL part of Moovida is also available under a commercial licensing 
 13  # agreement from Fluendo. 
 14  # See "LICENSE.Moovida" in the root directory of this distribution package 
 15  # for details on that license. 
 16  # 
 17  # Author: Olivier Tilloy <olivier@fluendo.com> 
 18   
 19  """ 
 20  Caching and serialization facilities. 
 21  """ 
 22   
 23  try: 
 24      from hashlib import md5 
 25  except ImportError: 
 26      # hashlib is new in Python 2.5 
 27      from md5 import md5 
 28   
 29  import os 
 30  import cPickle 
 31   
 32  from elisa.core import default_config 
 33  from elisa.core.utils import defer 
 34  from elisa.core.utils.internet import get_page 
 35   
 36   
37 -def get_cache_path(cache_dir):
38 """ 39 Return the absolute path to a specific cache directory. 40 41 The cache directory is located in the local moovida directory and will be 42 created if it doesn't exist yet. 43 44 @param cache_dir: the name of the cache directory 45 @type cache_dir: C{unicode} 46 47 @return: the absolute path to the cache directory 48 @rtype: C{unicode} 49 """ 50 cache = os.path.join(default_config.CONFIG_DIR, cache_dir) 51 if not os.path.exists(cache): 52 os.makedirs(cache, 0755) 53 return cache
54 55
56 -def get_pictures_cache_path():
57 """ 58 @return: the absolute path to the pictures cache directory 59 @rtype: C{unicode} 60 """ 61 return get_cache_path(u'pictures_cache')
62 63
64 -def get_cached_file_path(uri, cache_path, extension=None):
65 """ 66 Return the full path to a file cached on disk corresponding to the URI. 67 This does not check whether the cached file actually exists. 68 69 This implementation is very loosely based on the freedesktop thumbnail 70 specification (http://jens.triq.net/thumbnail-spec/). 71 72 @param uri: the URI to a resource to cache 73 @type uri: L{elisa.core.media_uri.MediaUri} 74 @param cache_path: the full path to the cache directory 75 @type cache_path: C{unicode} 76 @param extension: the file extension the cached file should have 77 (default C{None}, use the URI's path extension) 78 @type extension: C{unicode} 79 80 @return: the full path to the file cached on disk 81 @rtype: C{unicode} 82 """ 83 if uri.scheme == 'file': 84 # The file is local, it does not make sense to cache it 85 return os.path.normpath(uri.path) 86 87 digest = md5(unicode(uri)).hexdigest() 88 if extension is None: 89 extension = uri.extension 90 if extension: 91 cached_file = u'%s.%s' % (digest, extension) 92 else: 93 cached_file = unicode(digest) 94 95 return os.path.join(cache_path, cached_file)
96 97
98 -def get_cached_image_path(image_uri):
99 """ 100 Specialized implementation of get_cached_file_path for images. 101 102 @param image_uri: the URI to an image resource to cache 103 @type image_uri: L{elisa.core.media_uri.MediaUri} 104 105 @return: the full path to the image cached on disk 106 @rtype: C{unicode} 107 """ 108 return get_cached_file_path(image_uri, get_pictures_cache_path())
109 110
111 -def cache_to_file(data, cache_file_path):
112 """ 113 Write some data to a cache file on disk for faster subsequent access. 114 115 If the cache file already exists, it is overwritten. 116 117 @param data: the binary data to cache 118 @type data: C{str} 119 @param cache_file_path: the full path to the cache file 120 @type cache_file_path: C{unicode} 121 122 @return: the full path to the cache file (C{cache_file_path}) 123 @rtype: C{unicode} 124 """ 125 # TODO: make this asynchronous 126 fd = open(cache_file_path, 'wb') 127 try: 128 fd.write(data) 129 finally: 130 fd.close() 131 return cache_file_path
132 133
134 -def _get(uri):
135 # This function is meant to be monkey-patched in unit tests. 136 return get_page(uri)
137 138
139 -def get_and_cache_to_file(uri, cache_path):
140 """ 141 Get a distant resource over HTTP if needed and cache it. 142 143 @param uri: the URI of the resource to retrieve and cache 144 @type uri: L{elisa.core.media_uri.MediaUri} 145 @param cache_path: the full path to the cache directory 146 @type cache_path: C{unicode} 147 148 @return: a deferred fired with the full path to the cached file when done 149 @rtype: L{elisa.core.utils.defer.Deferred} 150 """ 151 # FIXME: when the distant resource needs to be retrieved, the deferred 152 # returned is not cancellable. 153 cached_file_path = get_cached_file_path(uri, cache_path) 154 if os.path.exists(cached_file_path): 155 return defer.succeed(cached_file_path) 156 157 dfr = _get(str(uri)) 158 dfr.addCallback(cache_to_file, cached_file_path) 159 return dfr
160 161
162 -def serialize(obj, dump_file_path):
163 """ 164 Serialize an object to a file on disk. 165 166 @param obj: the object to serialize 167 @type obj: C{object} 168 @param dump_file_path: the full path to the file to dump the object to 169 @type dump_file_path: C{unicode} 170 """ 171 fd = open(dump_file_path, 'wb') 172 try: 173 cPickle.dump(obj, fd) 174 finally: 175 fd.close()
176 177
178 -def deserialize(dump_file_path):
179 """ 180 De-serialize a object from a file on disk. 181 182 @param dump_file_path: the full path to the file the object was dumped to 183 @type dump_file_path: C{unicode} 184 185 @return: the de-serialized object 186 @rtype: C{object} 187 188 @raise C{IOError}: if the file cannot be read 189 """ 190 fd = open(dump_file_path, 'rb') 191 try: 192 obj = cPickle.load(fd) 193 finally: 194 fd.close() 195 return obj
196