1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 """
20 Caching and serialization facilities.
21 """
22
23 try:
24 from hashlib import md5
25 except ImportError:
26
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
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
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
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
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
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
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
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
137
138
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
152
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
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
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