1
2
3
4
5
6
7
8
9 """Helper for simple storage facility via cPickle and optionally zlib"""
10
11 __docformat__ = 'restructuredtext'
12
13 import os
14
15 from mvpa.base import externals
16
17 _d_geti_ = dict.__getitem__
18 _d_seti_ = dict.__setitem__
19
20 _o_geta_ = dict.__getattribute__
21 _o_seta_ = dict.__setattr__
22
23 if externals.exists('cPickle', raiseException=True) and \
24 externals.exists('gzip', raiseException=True):
25 import cPickle, gzip
26
27 if __debug__:
28 from mvpa.base import debug
31 """Simple container class with basic IO capabilities.
32
33 It is capable of storing itself in a file, or loading from a file using
34 cPickle (optionally via zlib from compressed files). Any serializable
35 object can be bound to a hamster to be stored.
36
37 To undig burried hamster use Hamster(filename). Here is an example:
38
39 >>> h = Hamster(bla='blai')
40 >>> h.boo = N.arange(5)
41 >>> h.dump(filename)
42 ...
43 >>> h = Hamster(filename)
44
45 Since Hamster introduces methods `dump`, `asdict` and property
46 'registered', those names cannot be used to assign an attribute,
47 nor provided in among constructor arguments.
48 """
49
50 __ro_attr = set(object.__dict__.keys() +
51 ['dump', 'registered', 'asdict'])
52 """Attributes which come with being an object"""
53
55 if len(args) > 0:
56 if len(kwargs) > 0:
57 raise ValueError, \
58 "Do not mix positional and keyword arguments. " \
59 "Use a single positional argument -- filename, " \
60 "or any number of keyword arguments, without having " \
61 "filename specified"
62 if len(args) == 1 and isinstance(args[0], basestring):
63 filename = args[0]
64 args = args[1:]
65 if __debug__:
66 debug('IOH', 'Undigging hamster from %s' % filename)
67
68 if filename.endswith('.gz'):
69 f = gzip.open(filename)
70 else:
71 f = open(filename)
72 result = cPickle.load(f)
73 if not isinstance(result, Hamster):
74 warning("Loaded other than Hamster class from %s" % filename)
75 return result
76 else:
77 raise ValueError, "Hamster accepts only a single positional " \
78 "argument and it must be a filename. Got %d " \
79 "arguments" % (len(args),)
80 else:
81 return object.__new__(cls)
82
83
85 """Initialize Hamster.
86
87 Providing a single parameter string would treat it as a
88 filename from which to undig the data. Otherwise all keyword
89 parameters are assigned into the attributes of the object.
90 """
91 if len(args) > 0:
92 if len(args) == 1 and isinstance(args[0], basestring):
93
94 args = args[1:]
95 else:
96 raise RuntimeError, "Should not get here"
97
98
99 for k,v in kwargs.iteritems():
100 setattr(self, k, v)
101
102 object.__init__(self)
103
104
105 - def dump(self, filename, compresslevel='auto'):
106 """Bury the hamster into the file
107
108 :Parameter:
109 filename: str
110 Name of the target file. When writing to a compressed file the
111 filename gets a '.gz' extension if not already specified. This
112 is necessary as the constructor uses the extension to decide
113 whether it loads from a compressed or uncompressed file.
114 compresslevel: 'auto' or int
115 Compression level setting passed to gzip. When set to
116 'auto', if filename ends with '.gz' `compresslevel` is set
117 to 5, 0 otherwise. However, when `compresslevel` is set to
118 0 gzip is bypassed completely and everything is written to
119 an uncompressed file.
120 """
121 if compresslevel == 'auto':
122 compresslevel = (0, 5)[int(filename.endswith('.gz'))]
123 if compresslevel > 0 and not filename.endswith('.gz'):
124 filename += '.gz'
125 if __debug__:
126 debug('IOH', 'Burying hamster into %s' % filename)
127 if compresslevel == 0:
128 f = open(filename, 'w')
129 else:
130 f = gzip.open(filename, 'w', compresslevel)
131 cPickle.dump(self, f)
132 f.close()
133
134
136 reg_attr = ["%s=%s" % (k, repr(getattr(self, k)))
137 for k in self.registered]
138 return "%s(%s)" % (self.__class__.__name__,
139 ", ".join(reg_attr))
140
141
142
143
144
145
146
147
148
149 @property
151 """List registered attributes.
152 """
153 reg_attr = [k for k in self.__dict__.iterkeys()
154 if not k in self.__ro_attr]
155 reg_attr.sort()
156 return reg_attr
157
158
160 """Just to prevent resetting read-only attributes, such as methods
161 """
162 if k in self.__ro_attr:
163 raise ValueError, "'%s' object attribute '%s' is read-only" \
164 % (self.__class__.__name__, k)
165 object.__setattr__(self, k, v)
166
167
169 """Return registered data as dictionary
170 """
171 return dict([(k, getattr(self, k))
172 for k in self.registered])
173