comparison env/lib/python3.9/site-packages/boto/sdb/db/model.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4f3585e2f14b
1 # Copyright (c) 2006,2007,2008 Mitch Garnaat http://garnaat.org/
2 #
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-
9 # lowing conditions:
10 #
11 # The above copyright notice and this permission notice shall be included
12 # in all copies or substantial portions of the Software.
13 #
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
20 # IN THE SOFTWARE.
21
22 from boto.sdb.db.property import Property
23 from boto.sdb.db.key import Key
24 from boto.sdb.db.query import Query
25 import boto
26 from boto.compat import filter
27
28 class ModelMeta(type):
29 "Metaclass for all Models"
30
31 def __init__(cls, name, bases, dict):
32 super(ModelMeta, cls).__init__(name, bases, dict)
33 # Make sure this is a subclass of Model - mainly copied from django ModelBase (thanks!)
34 cls.__sub_classes__ = []
35
36 # Do a delayed import to prevent possible circular import errors.
37 from boto.sdb.db.manager import get_manager
38
39 try:
40 if filter(lambda b: issubclass(b, Model), bases):
41 for base in bases:
42 base.__sub_classes__.append(cls)
43 cls._manager = get_manager(cls)
44 # look for all of the Properties and set their names
45 for key in dict.keys():
46 if isinstance(dict[key], Property):
47 property = dict[key]
48 property.__property_config__(cls, key)
49 prop_names = []
50 props = cls.properties()
51 for prop in props:
52 if not prop.__class__.__name__.startswith('_'):
53 prop_names.append(prop.name)
54 setattr(cls, '_prop_names', prop_names)
55 except NameError:
56 # 'Model' isn't defined yet, meaning we're looking at our own
57 # Model class, defined below.
58 pass
59
60 class Model(object):
61 __metaclass__ = ModelMeta
62 __consistent__ = False # Consistent is set off by default
63 id = None
64
65 @classmethod
66 def get_lineage(cls):
67 l = [c.__name__ for c in cls.mro()]
68 l.reverse()
69 return '.'.join(l)
70
71 @classmethod
72 def kind(cls):
73 return cls.__name__
74
75 @classmethod
76 def _get_by_id(cls, id, manager=None):
77 if not manager:
78 manager = cls._manager
79 return manager.get_object(cls, id)
80
81 @classmethod
82 def get_by_id(cls, ids=None, parent=None):
83 if isinstance(ids, list):
84 objs = [cls._get_by_id(id) for id in ids]
85 return objs
86 else:
87 return cls._get_by_id(ids)
88
89 get_by_ids = get_by_id
90
91 @classmethod
92 def get_by_key_name(cls, key_names, parent=None):
93 raise NotImplementedError("Key Names are not currently supported")
94
95 @classmethod
96 def find(cls, limit=None, next_token=None, **params):
97 q = Query(cls, limit=limit, next_token=next_token)
98 for key, value in params.items():
99 q.filter('%s =' % key, value)
100 return q
101
102 @classmethod
103 def all(cls, limit=None, next_token=None):
104 return cls.find(limit=limit, next_token=next_token)
105
106 @classmethod
107 def get_or_insert(key_name, **kw):
108 raise NotImplementedError("get_or_insert not currently supported")
109
110 @classmethod
111 def properties(cls, hidden=True):
112 properties = []
113 while cls:
114 for key in cls.__dict__.keys():
115 prop = cls.__dict__[key]
116 if isinstance(prop, Property):
117 if hidden or not prop.__class__.__name__.startswith('_'):
118 properties.append(prop)
119 if len(cls.__bases__) > 0:
120 cls = cls.__bases__[0]
121 else:
122 cls = None
123 return properties
124
125 @classmethod
126 def find_property(cls, prop_name):
127 property = None
128 while cls:
129 for key in cls.__dict__.keys():
130 prop = cls.__dict__[key]
131 if isinstance(prop, Property):
132 if not prop.__class__.__name__.startswith('_') and prop_name == prop.name:
133 property = prop
134 if len(cls.__bases__) > 0:
135 cls = cls.__bases__[0]
136 else:
137 cls = None
138 return property
139
140 @classmethod
141 def get_xmlmanager(cls):
142 if not hasattr(cls, '_xmlmanager'):
143 from boto.sdb.db.manager.xmlmanager import XMLManager
144 cls._xmlmanager = XMLManager(cls, None, None, None,
145 None, None, None, None, False)
146 return cls._xmlmanager
147
148 @classmethod
149 def from_xml(cls, fp):
150 xmlmanager = cls.get_xmlmanager()
151 return xmlmanager.unmarshal_object(fp)
152
153 def __init__(self, id=None, **kw):
154 self._loaded = False
155 # first try to initialize all properties to their default values
156 for prop in self.properties(hidden=False):
157 try:
158 setattr(self, prop.name, prop.default_value())
159 except ValueError:
160 pass
161 if 'manager' in kw:
162 self._manager = kw['manager']
163 self.id = id
164 for key in kw:
165 if key != 'manager':
166 # We don't want any errors populating up when loading an object,
167 # so if it fails we just revert to it's default value
168 try:
169 setattr(self, key, kw[key])
170 except Exception as e:
171 boto.log.exception(e)
172
173 def __repr__(self):
174 return '%s<%s>' % (self.__class__.__name__, self.id)
175
176 def __str__(self):
177 return str(self.id)
178
179 def __eq__(self, other):
180 return other and isinstance(other, Model) and self.id == other.id
181
182 def _get_raw_item(self):
183 return self._manager.get_raw_item(self)
184
185 def load(self):
186 if self.id and not self._loaded:
187 self._manager.load_object(self)
188
189 def reload(self):
190 if self.id:
191 self._loaded = False
192 self._manager.load_object(self)
193
194 def put(self, expected_value=None):
195 """
196 Save this object as it is, with an optional expected value
197
198 :param expected_value: Optional tuple of Attribute, and Value that
199 must be the same in order to save this object. If this
200 condition is not met, an SDBResponseError will be raised with a
201 Confict status code.
202 :type expected_value: tuple or list
203 :return: This object
204 :rtype: :class:`boto.sdb.db.model.Model`
205 """
206 self._manager.save_object(self, expected_value)
207 return self
208
209 save = put
210
211 def put_attributes(self, attrs):
212 """
213 Save just these few attributes, not the whole object
214
215 :param attrs: Attributes to save, key->value dict
216 :type attrs: dict
217 :return: self
218 :rtype: :class:`boto.sdb.db.model.Model`
219 """
220 assert(isinstance(attrs, dict)), "Argument must be a dict of key->values to save"
221 for prop_name in attrs:
222 value = attrs[prop_name]
223 prop = self.find_property(prop_name)
224 assert(prop), "Property not found: %s" % prop_name
225 self._manager.set_property(prop, self, prop_name, value)
226 self.reload()
227 return self
228
229 def delete_attributes(self, attrs):
230 """
231 Delete just these attributes, not the whole object.
232
233 :param attrs: Attributes to save, as a list of string names
234 :type attrs: list
235 :return: self
236 :rtype: :class:`boto.sdb.db.model.Model`
237 """
238 assert(isinstance(attrs, list)), "Argument must be a list of names of keys to delete."
239 self._manager.domain.delete_attributes(self.id, attrs)
240 self.reload()
241 return self
242
243 save_attributes = put_attributes
244
245 def delete(self):
246 self._manager.delete_object(self)
247
248 def key(self):
249 return Key(obj=self)
250
251 def set_manager(self, manager):
252 self._manager = manager
253
254 def to_dict(self):
255 props = {}
256 for prop in self.properties(hidden=False):
257 props[prop.name] = getattr(self, prop.name)
258 obj = {'properties': props,
259 'id': self.id}
260 return {self.__class__.__name__: obj}
261
262 def to_xml(self, doc=None):
263 xmlmanager = self.get_xmlmanager()
264 doc = xmlmanager.marshal_object(self, doc)
265 return doc
266
267 @classmethod
268 def find_subclass(cls, name):
269 """Find a subclass with a given name"""
270 if name == cls.__name__:
271 return cls
272 for sc in cls.__sub_classes__:
273 r = sc.find_subclass(name)
274 if r is not None:
275 return r
276
277 class Expando(Model):
278
279 def __setattr__(self, name, value):
280 if name in self._prop_names:
281 object.__setattr__(self, name, value)
282 elif name.startswith('_'):
283 object.__setattr__(self, name, value)
284 elif name == 'id':
285 object.__setattr__(self, name, value)
286 else:
287 self._manager.set_key_value(self, name, value)
288 object.__setattr__(self, name, value)
289
290 def __getattr__(self, name):
291 if not name.startswith('_'):
292 value = self._manager.get_key_value(self, name)
293 if value:
294 object.__setattr__(self, name, value)
295 return value
296 raise AttributeError