1
2 """
3
4 @author: Fabio Erculiani <lxnay@sabayonlinux.org>
5 @contact: lxnay@sabayonlinux.org
6 @copyright: Fabio Erculiani
7 @license: GPL-2
8
9 B{Entropy Framework object disk serializer module}.
10
11 This module contains Entropy Python object serialization functions and
12 disk dumpers.
13
14 Serialized objects are stored to disk with proper permissions by default
15 into path given by entropy.const's etpConst['dumpstoragedir'].
16
17 Permissions are set using entropy.const's const_setup_perms and
18 const_setup_file functions.
19
20 Objects are serialized using Python's cPickle/pickle modules, thus
21 they must be "pickable". Please read Python Library reference for
22 more information.
23
24 """
25
26 import sys
27 import os
28 from entropy.const import etpConst, const_setup_perms, const_setup_file
29
30 COMPAT_PICKLE_PROTOCOL = 0
31
32 if sys.hexversion >= 0x3000000:
33 import pickle
34 else:
35 try:
36 import cPickle as pickle
37 except ImportError:
38 import pickle
39
40 pickle.HIGHEST_PROTOCOL = COMPAT_PICKLE_PROTOCOL
41 pickle.DEFAULT_PROTOCOL = COMPAT_PICKLE_PROTOCOL
42
43 D_EXT = etpConst['cachedumpext']
44 D_DIR = etpConst['dumpstoragedir']
45 E_GID = etpConst['entropygid']
46 if E_GID == None:
47 E_GID = 0
48
49
50 -def dumpobj(name, my_object, complete_path = False, ignore_exceptions = True):
51 """
52 Dump pickable object to file
53
54 @param name: name of the object
55 @type name: string
56 @param my_object: object to dump
57 @type my_object: any Python "pickable" object
58 @keyword complete_path: consider "name" argument as
59 a complete path (this overrides the default dump
60 path given by etpConst['dumpstoragedir'])
61 @type complete_path: bool
62 @keyword ignore_exceptions: ignore any possible exception
63 (EOFError, IOError, OSError,)
64 @type ignore_exceptions: bool
65 @return: None
66 @rtype: None
67 @raise EOFError: could be caused by pickle.dump, ignored if
68 ignore_exceptions is True
69 @raise IOError: could be caused by pickle.dump, ignored if
70 ignore_exceptions is True
71 @raise OSError: could be caused by pickle.dump, ignored if
72 ignore_exceptions is True
73 """
74 while True:
75 try:
76 if complete_path:
77 dmpfile = name
78 else:
79 dump_path = os.path.join(D_DIR, name)
80 dump_dir = os.path.dirname(dump_path)
81
82 my_dump_dir = dump_dir
83 d_paths = []
84 while not os.path.isdir(my_dump_dir):
85 d_paths.append(my_dump_dir)
86 my_dump_dir = os.path.dirname(my_dump_dir)
87 if d_paths:
88 d_paths = sorted(d_paths)
89 for d_path in d_paths:
90 os.mkdir(d_path)
91 const_setup_file(d_path, E_GID, 0o775)
92
93 dmpfile = dump_path+D_EXT
94 with open(dmpfile, "wb") as dmp_f:
95 if sys.hexversion >= 0x3000000:
96 pickle.dump(my_object, dmp_f,
97 protocol = COMPAT_PICKLE_PROTOCOL, fix_imports = True)
98 else:
99 pickle.dump(my_object, dmp_f)
100 dmp_f.flush()
101 const_setup_file(dmpfile, E_GID, 0o664)
102 except RuntimeError:
103 try:
104 os.remove(dmpfile)
105 except OSError:
106 pass
107 except (EOFError, IOError, OSError):
108 if not ignore_exceptions:
109 raise
110 break
111
113 """
114 Serialize object to ser_f (file)
115
116 @param myobj: Python object to serialize
117 @type myobj: any Python picklable object
118 @param ser_f: file object to write to
119 @type ser_f: file object
120 @keyword do_seek: move file cursor back to the beginning
121 of ser_f
122 @type do_seek: bool
123 @return: file object where data has been written
124 @rtype: file object
125 @raise RuntimeError: caused by pickle.dump in case of
126 system errors
127 @raise EOFError: caused by pickle.dump in case of
128 race conditions on multi-processing or multi-threading
129 @raise IOError: caused by pickle.dump in case of
130 race conditions on multi-processing or multi-threading
131 @raise pickle.PicklingError: when object cannot be recreated
132 """
133 if sys.hexversion >= 0x3000000:
134 pickle.dump(myobj, ser_f, protocol = COMPAT_PICKLE_PROTOCOL,
135 fix_imports = True)
136 else:
137 pickle.dump(myobj, ser_f)
138 ser_f.flush()
139 if do_seek:
140 ser_f.seek(0)
141 return ser_f
142
144 """
145 Unserialize file to object (file)
146
147 @param serial_f: file object which data will be read from
148 @type serial_f: file object
149 @return: rebuilt object
150 @rtype: any Python pickable object
151 @raise pickle.UnpicklingError: when object cannot be recreated
152 """
153 if sys.hexversion >= 0x3000000:
154 return pickle.load(serial_f, fix_imports = True,
155 encoding = 'raw_unicode_escape')
156 else:
157 return pickle.load(serial_f)
158
160 """
161 Unserialize pickle string to object
162
163 @param mystring: data stream in string form to reconstruct
164 @type mystring: string
165 @return: reconstructed object
166 @rtype: any Python pickable object
167 @raise pickle.UnpicklingError: when object cannot be recreated
168 """
169 if sys.hexversion >= 0x3000000:
170 return pickle.loads(mystring, fix_imports = True,
171 encoding = 'raw_unicode_escape')
172 else:
173 return pickle.loads(mystring)
174
176 """
177 Serialize object to string
178
179 @param myobj: object to serialize
180 @type myobj: any Python picklable object
181 @return: serialized string
182 @rtype: string
183 @raise pickle.PicklingError: when object cannot be recreated
184 """
185 if sys.hexversion >= 0x3000000:
186 return pickle.dumps(myobj, protocol = COMPAT_PICKLE_PROTOCOL,
187 fix_imports = True, encoding = 'raw_unicode_escape')
188 else:
189 return pickle.dumps(myobj)
190
191 -def loadobj(name, complete_path = False):
192 """
193 Load object from a file
194 @param name: name of the object to load
195 @type name: string
196 @keyword complete_path: determine whether name argument
197 is a complete disk path to serialized object
198 @type complete_path: bool
199 @return: object or None
200 @rtype: any Python pickable object or None
201 """
202 while True:
203 if complete_path:
204 dmpfile = name
205 else:
206 dump_path = os.path.join(D_DIR, name)
207
208
209 dmpfile = dump_path+D_EXT
210 if os.path.isfile(dmpfile) and os.access(dmpfile, os.R_OK):
211 try:
212 with open(dmpfile, "rb") as dmp_f:
213 obj = None
214 try:
215 if sys.hexversion >= 0x3000000:
216 obj = pickle.load(dmp_f, fix_imports = True,
217 encoding = 'raw_unicode_escape')
218 else:
219 obj = pickle.load(dmp_f)
220 except (ValueError, EOFError, IOError,
221 OSError, pickle.UnpicklingError, TypeError,
222 AttributeError,):
223 pass
224 return obj
225 except (IOError, OSError,):
226 pass
227 break
228
230 """
231 Get dumped object mtime
232
233 @param name: object name
234 @type name: string
235 @return: mtime of the file containing the serialized object or 0
236 if not found
237 @rtype: int
238 """
239 mtime = 0
240 dump_path = os.path.join(D_DIR, name+D_EXT)
241 if os.path.isfile(dump_path) and os.access(dump_path, os.R_OK):
242 mtime = os.path.getmtime(dump_path)
243 return int(mtime)
244
246 """
247 Remove cached object referenced by its object name
248
249 @param name: object name
250 @type name: string
251 @return: bool representing whether object has been
252 removed or not
253 @rtype: bool
254 @raise OSError: in case of troubles with os.remove()
255 """
256 filepath = D_DIR+"/"+name+D_EXT
257 if os.path.isfile(filepath) and os.access(filepath, os.W_OK):
258 os.remove(filepath)
259 return True
260 return False
261