~ntt-pf-lab/nova/monkey_patch_notification

« back to all changes in this revision

Viewing changes to vendor/boto/boto/sdb/db/model.py

  • Committer: Jesse Andrews
  • Date: 2010-05-28 06:05:26 UTC
  • Revision ID: git-v1:bf6e6e718cdc7488e2da87b21e258ccc065fe499
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.manager import get_manager
 
23
from boto.sdb.db.property import Property
 
24
from boto.sdb.db.key import Key
 
25
from boto.sdb.db.query import Query
 
26
import boto
 
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
        try:
 
36
            if filter(lambda b: issubclass(b, Model), bases):
 
37
                for base in bases:
 
38
                    base.__sub_classes__.append(cls)
 
39
                cls._manager = get_manager(cls)
 
40
                # look for all of the Properties and set their names
 
41
                for key in dict.keys():
 
42
                    if isinstance(dict[key], Property):
 
43
                        property = dict[key]
 
44
                        property.__property_config__(cls, key)
 
45
                prop_names = []
 
46
                props = cls.properties()
 
47
                for prop in props:
 
48
                    if not prop.__class__.__name__.startswith('_'):
 
49
                        prop_names.append(prop.name)
 
50
                setattr(cls, '_prop_names', prop_names)
 
51
        except NameError:
 
52
            # 'Model' isn't defined yet, meaning we're looking at our own
 
53
            # Model class, defined below.
 
54
            pass
 
55
        
 
56
class Model(object):
 
57
    __metaclass__ = ModelMeta
 
58
    __consistent__ = False # Consistent is set off by default
 
59
    id = None
 
60
 
 
61
    @classmethod
 
62
    def get_lineage(cls):
 
63
        l = [c.__name__ for c in cls.mro()]
 
64
        l.reverse()
 
65
        return '.'.join(l)
 
66
 
 
67
    @classmethod
 
68
    def kind(cls):
 
69
        return cls.__name__
 
70
    
 
71
    @classmethod
 
72
    def _get_by_id(cls, id, manager=None):
 
73
        if not manager:
 
74
            manager = cls._manager
 
75
        return manager.get_object(cls, id)
 
76
            
 
77
    @classmethod
 
78
    def get_by_id(cls, ids=None, parent=None):
 
79
        if isinstance(ids, list):
 
80
            objs = [cls._get_by_id(id) for id in ids]
 
81
            return objs
 
82
        else:
 
83
            return cls._get_by_id(ids)
 
84
 
 
85
    get_by_ids = get_by_id
 
86
 
 
87
    @classmethod
 
88
    def get_by_key_name(cls, key_names, parent=None):
 
89
        raise NotImplementedError, "Key Names are not currently supported"
 
90
 
 
91
    @classmethod
 
92
    def find(cls, limit=None, next_token=None, **params):
 
93
        q = Query(cls, limit=limit, next_token=next_token)
 
94
        for key, value in params.items():
 
95
            q.filter('%s =' % key, value)
 
96
        return q
 
97
 
 
98
    @classmethod
 
99
    def lookup(cls, name, value):
 
100
        return cls._manager.lookup(cls, name, value)
 
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 initialize all properties to their default values
 
156
        for prop in self.properties(hidden=False):
 
157
            setattr(self, prop.name, prop.default_value())
 
158
        if kw.has_key('manager'):
 
159
            self._manager = kw['manager']
 
160
        self.id = id
 
161
        for key in kw:
 
162
            if key != 'manager':
 
163
                # We don't want any errors populating up when loading an object,
 
164
                # so if it fails we just revert to it's default value
 
165
                try:
 
166
                    setattr(self, key, kw[key])
 
167
                except Exception, e:
 
168
                    boto.log.exception(e)
 
169
 
 
170
    def __repr__(self):
 
171
        return '%s<%s>' % (self.__class__.__name__, self.id)
 
172
 
 
173
    def __str__(self):
 
174
        return str(self.id)
 
175
    
 
176
    def __eq__(self, other):
 
177
        return other and isinstance(other, Model) and self.id == other.id
 
178
 
 
179
    def _get_raw_item(self):
 
180
        return self._manager.get_raw_item(self)
 
181
 
 
182
    def load(self):
 
183
        if self.id and not self._loaded:
 
184
            self._manager.load_object(self)
 
185
 
 
186
    def put(self):
 
187
        self._manager.save_object(self)
 
188
 
 
189
    save = put
 
190
        
 
191
    def delete(self):
 
192
        self._manager.delete_object(self)
 
193
 
 
194
    def key(self):
 
195
        return Key(obj=self)
 
196
 
 
197
    def set_manager(self, manager):
 
198
        self._manager = manager
 
199
 
 
200
    def to_dict(self):
 
201
        props = {}
 
202
        for prop in self.properties(hidden=False):
 
203
            props[prop.name] = getattr(self, prop.name)
 
204
        obj = {'properties' : props,
 
205
               'id' : self.id}
 
206
        return {self.__class__.__name__ : obj}
 
207
 
 
208
    def to_xml(self, doc=None):
 
209
        xmlmanager = self.get_xmlmanager()
 
210
        doc = xmlmanager.marshal_object(self, doc)
 
211
        return doc
 
212
 
 
213
class Expando(Model):
 
214
 
 
215
    def __setattr__(self, name, value):
 
216
        if name in self._prop_names:
 
217
            object.__setattr__(self, name, value)
 
218
        elif name.startswith('_'):
 
219
            object.__setattr__(self, name, value)
 
220
        elif name == 'id':
 
221
            object.__setattr__(self, name, value)
 
222
        else:
 
223
            self._manager.set_key_value(self, name, value)
 
224
            object.__setattr__(self, name, value)
 
225
 
 
226
    def __getattr__(self, name):
 
227
        if not name.startswith('_'):
 
228
            value = self._manager.get_key_value(self, name)
 
229
            if value:
 
230
                object.__setattr__(self, name, value)
 
231
                return value
 
232
        raise AttributeError
 
233
 
 
234