|
Package Dropbox ::
Package web2py ::
Package gluon ::
Module storage
|
|
1
2
3
4 """
5 This file is part of the web2py Web Framework
6 Copyrighted by Massimo Di Pierro <mdipierro@cs.depaul.edu>
7 License: LGPLv3 (http://www.gnu.org/licenses/lgpl.html)
8
9 Provides:
10
11 - List; like list but returns None instead of IndexOutOfBounds
12 - Storage; like dictionary allowing also for `obj.foo` for `obj['foo']`
13 """
14
15 import cPickle
16 import portalocker
17
18 __all__ = ['List', 'Storage', 'Settings', 'Messages',
19 'StorageList', 'load_storage', 'save_storage']
20
21
23 """
24 A Storage object is like a dictionary except `obj.foo` can be used
25 in addition to `obj['foo']`, and setting obj.foo = None deletes item foo.
26
27 >>> o = Storage(a=1)
28 >>> print o.a
29 1
30
31 >>> o['a']
32 1
33
34 >>> o.a = 2
35 >>> print o['a']
36 2
37
38 >>> del o.a
39 >>> print o.a
40 None
41 """
42 __slots__ = ()
43 __setattr__ = dict.__setitem__
44 __delattr__ = dict.__delitem__
45 __getitem__ = dict.get
46 __getattr__ = dict.get
47 __repr__ = lambda self: '<Storage %s>' % dict.__repr__(self)
48
49 __getstate__ = lambda self: None
50 __copy__ = lambda self: Storage(self)
51
53 """
54 Return a Storage value as a list.
55
56 If the value is a list it will be returned as-is.
57 If object is None, an empty list will be returned.
58 Otherwise, [value] will be returned.
59
60 Example output for a query string of ?x=abc&y=abc&y=def
61 >>> request = Storage()
62 >>> request.vars = Storage()
63 >>> request.vars.x = 'abc'
64 >>> request.vars.y = ['abc', 'def']
65 >>> request.vars.getlist('x')
66 ['abc']
67 >>> request.vars.getlist('y')
68 ['abc', 'def']
69 >>> request.vars.getlist('z')
70 []
71 """
72 value = self.get(key, [])
73 if value is None or isinstance(value, (list, tuple)):
74 return value
75 else:
76 return [value]
77
79 """
80 Return the first or only value when given a request.vars-style key.
81
82 If the value is a list, its first item will be returned;
83 otherwise, the value will be returned as-is.
84
85 Example output for a query string of ?x=abc&y=abc&y=def
86 >>> request = Storage()
87 >>> request.vars = Storage()
88 >>> request.vars.x = 'abc'
89 >>> request.vars.y = ['abc', 'def']
90 >>> request.vars.getfirst('x')
91 'abc'
92 >>> request.vars.getfirst('y')
93 'abc'
94 >>> request.vars.getfirst('z')
95 """
96 values = self.getlist(key)
97 return values[0] if values else default
98
99 - def getlast(self, key, default=None):
100 """
101 Returns the last or only single value when
102 given a request.vars-style key.
103
104 If the value is a list, the last item will be returned;
105 otherwise, the value will be returned as-is.
106
107 Simulated output with a query string of ?x=abc&y=abc&y=def
108 >>> request = Storage()
109 >>> request.vars = Storage()
110 >>> request.vars.x = 'abc'
111 >>> request.vars.y = ['abc', 'def']
112 >>> request.vars.getlast('x')
113 'abc'
114 >>> request.vars.getlast('y')
115 'def'
116 >>> request.vars.getlast('z')
117 """
118 values = self.getlist(key)
119 return values[-1] if values else default
120
121 PICKABLE = (str, int, long, float, bool, list, dict, tuple, set)
122
123
125 """
126 like Storage but missing elements default to [] instead of None
127 """
130
132 if key in self:
133 return getattr(self, key)
134 else:
135 r = []
136 setattr(self, key, r)
137 return r
138
139
149
150
159
160
163 if key != 'lock_keys' and self['lock_keys'] and key not in self:
164 raise SyntaxError('setting key \'%s\' does not exist' % key)
165 if key != 'lock_values' and self['lock_values']:
166 raise SyntaxError('setting value cannot be changed: %s' % key)
167 self[key] = value
168
169
173
175 value = self[key]
176 if isinstance(value, str):
177 return str(self.T(value))
178 return value
179
180
182 """
183 Eventually this should replace class Storage but causes memory leak
184 because of http://bugs.python.org/issue1469629
185
186 >>> s = FastStorage()
187 >>> s.a = 1
188 >>> s.a
189 1
190 >>> s['a']
191 1
192 >>> s.b
193 >>> s['b']
194 >>> s['b']=2
195 >>> s['b']
196 2
197 >>> s.b
198 2
199 >>> isinstance(s,dict)
200 True
201 >>> dict(s)
202 {'a': 1, 'b': 2}
203 >>> dict(FastStorage(s))
204 {'a': 1, 'b': 2}
205 >>> import pickle
206 >>> s = pickle.loads(pickle.dumps(s))
207 >>> dict(s)
208 {'a': 1, 'b': 2}
209 >>> del s.b
210 >>> del s.a
211 >>> s.a
212 >>> s.b
213 >>> s['a']
214 >>> s['b']
215 """
217 dict.__init__(self, *args, **kwargs)
218 self.__dict__ = self
219
221 return getattr(self, key) if key in self else None
222
224 return dict.get(self, key, None)
225
227 self.__dict__ = {}
228 s = FastStorage(self)
229 self.__dict__ = self
230 return s
231
233 return '<Storage %s>' % dict.__repr__(self)
234
237
239 dict.__init__(self, sdict)
240 self.__dict__ = self
241
242 - def update(self, *args, **kwargs):
243 dict.__init__(self, *args, **kwargs)
244 self.__dict__ = self
245
246
248 """
249 Like a regular python list but a[i] if i is out of bounds return None
250 instead of IndexOutOfBounds
251 """
252
253 - def __call__(self, i, default=None, cast=None, otherwise=None):
254 """
255 request.args(0,default=0,cast=int,otherwise='http://error_url')
256 request.args(0,default=0,cast=int,otherwise=lambda:...)
257 """
258 n = len(self)
259 if 0 <= i < n or -n <= i < 0:
260 value = self[i]
261 else:
262 value = default
263 if cast:
264 try:
265 value = cast(value)
266 except (ValueError, TypeError):
267 from http import HTTP, redirect
268 if otherwise is None:
269 raise HTTP(404)
270 elif isinstance(otherwise, str):
271 redirect(otherwise)
272 elif callable(otherwise):
273 return otherwise()
274 else:
275 raise RuntimeError("invalid otherwise")
276 return value
277
278
279 if __name__ == '__main__':
280 import doctest
281 doctest.testmod()
282