1
# Copyright (c) 2006,2007,2008 Mitch Garnaat http://garnaat.org/
3
# Permission is hereby granted, free of charge, to any person obtaining a
4
# copy of this software and associated documentation files (the
5
# "Software"), to deal in the Software without restriction, including
6
# without limitation the rights to use, copy, modify, merge, publish, dis-
7
# tribute, sublicense, and/or sell copies of the Software, and to permit
8
# persons to whom the Software is furnished to do so, subject to the fol-
11
# The above copyright notice and this permission notice shall be included
12
# in all copies or substantial portions of the Software.
14
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
16
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22
from boto.exception import SDBPersistenceError
23
from boto.sdb.persist.checker import StringChecker, PasswordChecker, IntegerChecker, BooleanChecker
24
from boto.sdb.persist.checker import DateTimeChecker, ObjectChecker, S3KeyChecker, S3BucketChecker
25
from boto.utils import Password
27
class Property(object):
29
def __init__(self, checker_class, **params):
31
self.checker = checker_class(**params)
34
def set_name(self, name):
36
self.slot_name = '__' + self.name
38
class ScalarProperty(Property):
41
domain = obj._manager.domain
42
domain.put_attributes(obj.id, {self.name : self.to_string(obj)}, replace=True)
44
def to_string(self, obj):
45
return self.checker.to_string(getattr(obj, self.name))
48
domain = obj._manager.domain
49
a = domain.get_attributes(obj.id, self.name)
50
# try to get the attribute value from SDB
52
value = self.checker.from_string(a[self.name], obj)
53
setattr(obj, self.slot_name, value)
54
# if it's not there, set the value to the default value
56
self.__set__(obj, self.checker.default)
58
def __get__(self, obj, objtype):
61
value = getattr(obj, self.slot_name)
62
except AttributeError:
65
value = getattr(obj, self.slot_name)
67
value = self.checker.default
68
setattr(obj, self.slot_name, self.checker.default)
71
def __set__(self, obj, value):
72
self.checker.check(value)
74
old_value = getattr(obj, self.slot_name)
76
old_value = self.checker.default
77
setattr(obj, self.slot_name, value)
82
setattr(obj, self.slot_name, old_value)
85
class StringProperty(ScalarProperty):
87
def __init__(self, **params):
88
ScalarProperty.__init__(self, StringChecker, **params)
90
class PasswordProperty(ScalarProperty):
95
def __init__(self, **params):
96
ScalarProperty.__init__(self, PasswordChecker, **params)
98
def __set__(self, obj, value):
101
ScalarProperty.__set__(self, obj, p)
103
def __get__(self, obj, objtype):
104
return Password(ScalarProperty.__get__(self, obj, objtype))
106
class SmallPositiveIntegerProperty(ScalarProperty):
108
def __init__(self, **params):
109
params['size'] = 'small'
110
params['signed'] = False
111
ScalarProperty.__init__(self, IntegerChecker, **params)
113
class SmallIntegerProperty(ScalarProperty):
115
def __init__(self, **params):
116
params['size'] = 'small'
117
params['signed'] = True
118
ScalarProperty.__init__(self, IntegerChecker, **params)
120
class PositiveIntegerProperty(ScalarProperty):
122
def __init__(self, **params):
123
params['size'] = 'medium'
124
params['signed'] = False
125
ScalarProperty.__init__(self, IntegerChecker, **params)
127
class IntegerProperty(ScalarProperty):
129
def __init__(self, **params):
130
params['size'] = 'medium'
131
params['signed'] = True
132
ScalarProperty.__init__(self, IntegerChecker, **params)
134
class LargePositiveIntegerProperty(ScalarProperty):
136
def __init__(self, **params):
137
params['size'] = 'large'
138
params['signed'] = False
139
ScalarProperty.__init__(self, IntegerChecker, **params)
141
class LargeIntegerProperty(ScalarProperty):
143
def __init__(self, **params):
144
params['size'] = 'large'
145
params['signed'] = True
146
ScalarProperty.__init__(self, IntegerChecker, **params)
148
class BooleanProperty(ScalarProperty):
150
def __init__(self, **params):
151
ScalarProperty.__init__(self, BooleanChecker, **params)
153
class DateTimeProperty(ScalarProperty):
155
def __init__(self, **params):
156
ScalarProperty.__init__(self, DateTimeChecker, **params)
158
class ObjectProperty(ScalarProperty):
160
def __init__(self, **params):
161
ScalarProperty.__init__(self, ObjectChecker, **params)
163
class S3KeyProperty(ScalarProperty):
165
def __init__(self, **params):
166
ScalarProperty.__init__(self, S3KeyChecker, **params)
168
def __set__(self, obj, value):
169
self.checker.check(value)
171
old_value = getattr(obj, self.slot_name)
173
old_value = self.checker.default
174
if isinstance(value, str):
175
value = self.checker.from_string(value, obj)
176
setattr(obj, self.slot_name, value)
181
setattr(obj, self.slot_name, old_value)
184
class S3BucketProperty(ScalarProperty):
186
def __init__(self, **params):
187
ScalarProperty.__init__(self, S3BucketChecker, **params)
189
def __set__(self, obj, value):
190
self.checker.check(value)
192
old_value = getattr(obj, self.slot_name)
194
old_value = self.checker.default
195
if isinstance(value, str):
196
value = self.checker.from_string(value, obj)
197
setattr(obj, self.slot_name, value)
202
setattr(obj, self.slot_name, old_value)
205
class MultiValueProperty(Property):
207
def __init__(self, checker_class, **params):
208
Property.__init__(self, checker_class, **params)
210
def __get__(self, obj, objtype):
213
value = getattr(obj, self.slot_name)
214
except AttributeError:
217
value = getattr(obj, self.slot_name)
219
value = MultiValue(self, obj, [])
220
setattr(obj, self.slot_name, value)
226
domain = obj._manager.domain
227
a = domain.get_attributes(obj.id, self.name)
230
if not isinstance(lst, list):
233
value = self.checker.from_string(value, obj)
235
setattr(obj, self.slot_name, MultiValue(self, obj, _list))
237
def __set__(self, obj, value):
238
if not isinstance(value, list):
239
raise SDBPersistenceError('Value must be a list')
240
setattr(obj, self.slot_name, MultiValue(self, obj, value))
241
str_list = self.to_string(obj)
242
domain = obj._manager.domain
244
if len(str_list) == 1:
245
domain.put_attributes(obj.id, {self.name : str_list[0]}, replace=True)
251
domain.put_attributes(obj.id, {self.name : str_list}, replace=True)
252
setattr(obj, self.slot_name, MultiValue(self, obj, value))
254
def __delete__(self, obj):
256
domain = obj._manager.domain
257
domain.delete_attributes(obj.id, [self.name])
258
setattr(obj, self.slot_name, MultiValue(self, obj, []))
260
def to_string(self, obj):
262
for value in self.__get__(obj, type(obj)):
263
str_list.append(self.checker.to_string(value))
266
class StringListProperty(MultiValueProperty):
268
def __init__(self, **params):
269
MultiValueProperty.__init__(self, StringChecker, **params)
271
class SmallIntegerListProperty(MultiValueProperty):
273
def __init__(self, **params):
274
params['size'] = 'small'
275
params['signed'] = True
276
MultiValueProperty.__init__(self, IntegerChecker, **params)
278
class SmallPositiveIntegerListProperty(MultiValueProperty):
280
def __init__(self, **params):
281
params['size'] = 'small'
282
params['signed'] = False
283
MultiValueProperty.__init__(self, IntegerChecker, **params)
285
class IntegerListProperty(MultiValueProperty):
287
def __init__(self, **params):
288
params['size'] = 'medium'
289
params['signed'] = True
290
MultiValueProperty.__init__(self, IntegerChecker, **params)
292
class PositiveIntegerListProperty(MultiValueProperty):
294
def __init__(self, **params):
295
params['size'] = 'medium'
296
params['signed'] = False
297
MultiValueProperty.__init__(self, IntegerChecker, **params)
299
class LargeIntegerListProperty(MultiValueProperty):
301
def __init__(self, **params):
302
params['size'] = 'large'
303
params['signed'] = True
304
MultiValueProperty.__init__(self, IntegerChecker, **params)
306
class LargePositiveIntegerListProperty(MultiValueProperty):
308
def __init__(self, **params):
309
params['size'] = 'large'
310
params['signed'] = False
311
MultiValueProperty.__init__(self, IntegerChecker, **params)
313
class BooleanListProperty(MultiValueProperty):
315
def __init__(self, **params):
316
MultiValueProperty.__init__(self, BooleanChecker, **params)
318
class ObjectListProperty(MultiValueProperty):
320
def __init__(self, **params):
321
MultiValueProperty.__init__(self, ObjectChecker, **params)
323
class HasManyProperty(Property):
325
def set_name(self, name):
327
self.slot_name = '__' + self.name
329
def __get__(self, obj, objtype):
335
Special Multi Value for boto persistence layer to allow us to do
338
def __init__(self, property, obj, _list):
339
self.checker = property.checker
340
self.name = property.name
345
return repr(self._list)
347
def __getitem__(self, key):
348
return self._list.__getitem__(key)
350
def __delitem__(self, key):
352
self._list.__delitem__(key)
353
domain = self.object._manager.domain
354
domain.delete_attributes(self.object.id, {self.name: [self.checker.to_string(item)]})
357
return len(self._list)
359
def append(self, value):
360
self.checker.check(value)
361
self._list.append(value)
362
domain = self.object._manager.domain
363
domain.put_attributes(self.object.id, {self.name: self.checker.to_string(value)}, replace=False)
365
def index(self, value):
368
return self._list.index(x)
370
def remove(self, value):
371
del(self[self.index(value)])