|
a/Ming/ming/base.py |
|
b/Ming/ming/base.py |
|
... |
|
... |
15 |
return self[name]
|
15 |
return self[name]
|
16 |
except KeyError:
|
16 |
except KeyError:
|
17 |
raise AttributeError, name
|
17 |
raise AttributeError, name
|
18 |
|
18 |
|
19 |
def __setattr__(self, name, value):
|
19 |
def __setattr__(self, name, value):
|
|
|
20 |
if name in self.__class__.__dict__:
|
|
|
21 |
dict.__setattr__(self, name, value)
|
|
|
22 |
else:
|
20 |
self.__setitem__(name, value)
|
23 |
self.__setitem__(name, value)
|
21 |
|
24 |
|
22 |
@classmethod
|
25 |
@classmethod
|
23 |
def from_bson(cls, bson):
|
26 |
def from_bson(cls, bson):
|
24 |
if isinstance(bson, dict):
|
27 |
if isinstance(bson, dict):
|
25 |
return Object(
|
28 |
return Object(
|
|
... |
|
... |
76 |
self.instance = instance
|
79 |
self.instance = instance
|
77 |
self.cls = cls
|
80 |
self.cls = cls
|
78 |
|
81 |
|
79 |
def __call__(self, session):
|
82 |
def __call__(self, session):
|
80 |
'''In order to use an alternate session, just use Class.mgr(other_session)'''
|
83 |
'''In order to use an alternate session, just use Class.mgr(other_session)'''
|
81 |
return Manager(session, self.instance, self.cls)
|
84 |
result = Manager(self.instance, self.cls)
|
|
|
85 |
result.session = session
|
|
|
86 |
return result
|
82 |
|
87 |
|
83 |
def get(self, **kwargs):
|
88 |
def get(self, **kwargs):
|
84 |
"""
|
89 |
"""
|
85 |
Returns one matching record, or None
|
90 |
Returns one matching record, or None
|
86 |
e.g.
|
91 |
e.g.
|
|
... |
|
... |
214 |
mm = cls.__mongometa__ = type('__mongometa__', tuple(mm_bases), mm_dict)
|
219 |
mm = cls.__mongometa__ = type('__mongometa__', tuple(mm_bases), mm_dict)
|
215 |
if not hasattr(mm, 'polymorphic_on'):
|
220 |
if not hasattr(mm, 'polymorphic_on'):
|
216 |
mm.polymorphic_on = None
|
221 |
mm.polymorphic_on = None
|
217 |
mm.polymorphic_registry = None
|
222 |
mm.polymorphic_registry = None
|
218 |
# Make sure mongometa's schema incorporates base schemas
|
223 |
# Make sure mongometa's schema incorporates base schemas
|
219 |
my_schema = schema.Object()
|
224 |
fields = dict()
|
220 |
for base in mm_bases:
|
225 |
for base in mm_bases:
|
221 |
if hasattr(base, 'schema'):
|
226 |
if hasattr(base, 'schema'):
|
222 |
if base.schema:
|
227 |
if base.schema:
|
223 |
my_schema.extend(schema.SchemaItem.make(base.schema))
|
228 |
fields.update(base.schema.fields)
|
224 |
if mm.schema:
|
229 |
if mm.schema:
|
|
|
230 |
my_schema = schema.SchemaItem.make(mm.schema, inherited_fields=fields)
|
|
|
231 |
else:
|
225 |
my_schema.extend(schema.SchemaItem.make(mm.schema))
|
232 |
my_schema = schema.SchemaItem.make(fields)
|
226 |
# Collect fields
|
233 |
# Collect fields
|
227 |
for k,v in dct.iteritems():
|
234 |
for k,v in dct.iteritems():
|
228 |
if isinstance(v, Field):
|
235 |
if isinstance(v, Field):
|
229 |
v.name = k
|
236 |
v.name = k
|
230 |
si = schema.SchemaItem.make(v.type, *v.args, **v.kwargs)
|
237 |
si = schema.SchemaItem.make(v.type, *v.args, **v.kwargs)
|
|
... |
|
... |
278 |
return cls.__mongometa__.schema.validate(
|
285 |
return cls.__mongometa__.schema.validate(
|
279 |
data, allow_extra=allow_extra, strip_extra=strip_extra)
|
286 |
data, allow_extra=allow_extra, strip_extra=strip_extra)
|
280 |
else:
|
287 |
else:
|
281 |
return cls(data)
|
288 |
return cls(data)
|
282 |
|
289 |
|
283 |
class VersionedDocument(Document):
|
|
|
284 |
'''Special Document allowing snapshot and rollback.'''
|
|
|
285 |
|
|
|
286 |
class __mongometa__:
|
|
|
287 |
'''Extension of the Document class providing
|
|
|
288 |
|
|
|
289 |
snapshot - class to be used as snapshots of the current class
|
|
|
290 |
snapshot_untracked - field names to be skipped when snapshotting
|
|
|
291 |
'''
|
|
|
292 |
name=None
|
|
|
293 |
session=None
|
|
|
294 |
indexes=[]
|
|
|
295 |
snapshot=None
|
|
|
296 |
snapshot_untracked=set()
|
|
|
297 |
schema=dict(
|
|
|
298 |
_last_snapshot_id=str)
|
|
|
299 |
|
|
|
300 |
def snapshot(self, author):
|
|
|
301 |
'''Create a snapshot object of the current object with the specified
|
|
|
302 |
author field.
|
|
|
303 |
'''
|
|
|
304 |
mm = self.__mongometa__
|
|
|
305 |
# Get last snapshot
|
|
|
306 |
snapshot = mm.snapshot(dict(
|
|
|
307 |
(k,v) for k,v in self.iteritems()
|
|
|
308 |
if k not in mm.snapshot_untracked))
|
|
|
309 |
snapshot._original_id = self._id
|
|
|
310 |
snapshot._author = author
|
|
|
311 |
del snapshot['_id']
|
|
|
312 |
snapshot._id = hashlib.sha1(str(snapshot)).hexdigest()
|
|
|
313 |
if snapshot._id == self.get('_last_snapshot_id', None):
|
|
|
314 |
return
|
|
|
315 |
snapshot.m.save()
|
|
|
316 |
self._last_snapshot_id = snapshot._id
|
|
|
317 |
|
|
|
318 |
def rollback(self):
|
|
|
319 |
'''Revert one snapshot operation, restoring the values from the most
|
|
|
320 |
recent snapshot and destroying the most recent snapshot in the process.
|
|
|
321 |
'''
|
|
|
322 |
mm = self.__mongometa__
|
|
|
323 |
snapshot = mm.snapshot.m.find(
|
|
|
324 |
dict(_id=self._last_snapshot_id)).one()
|
|
|
325 |
fields = dict(snapshot)
|
|
|
326 |
del fields['_author']
|
|
|
327 |
self.update(fields)
|
|
|
328 |
if '_last_snapshot_id' not in snapshot:
|
|
|
329 |
del self['_last_snapshot_id']
|
|
|
330 |
snapshot.m.delete()
|
|
|
331 |
|
|
|
332 |
class Cursor(object):
|
290 |
class Cursor(object):
|
333 |
'''Python class proxying a MongoDB cursor, constructing and validating
|
291 |
'''Python class proxying a MongoDB cursor, constructing and validating
|
334 |
objects that it tracks
|
292 |
objects that it tracks
|
335 |
'''
|
293 |
'''
|
336 |
|
294 |
|
|
... |
|
... |
344 |
def __len__(self):
|
302 |
def __len__(self):
|
345 |
return self.count()
|
303 |
return self.count()
|
346 |
|
304 |
|
347 |
def next(self):
|
305 |
def next(self):
|
348 |
bson = self.cursor.next()
|
306 |
bson = self.cursor.next()
|
349 |
if bson:
|
307 |
if bson is None: return None
|
350 |
return self.cls.make(bson, allow_extra=False, strip_extra=True)
|
308 |
return self.cls.make(bson, allow_extra=False, strip_extra=True)
|
351 |
else:
|
|
|
352 |
return None
|
|
|
353 |
|
309 |
|
354 |
def count(self):
|
310 |
def count(self):
|
355 |
return self.cursor.count()
|
311 |
return self.cursor.count()
|
356 |
|
312 |
|
357 |
def limit(self, limit):
|
313 |
def limit(self, limit):
|