def track_passive(self, oobkey, tracker, tracked, entityname, callback=None, mode="db", *args, **kwargs): """ Passively track changes to an object property, attribute or non-db-attribute. Uses cache hooks to do this on demand, without active tracking. tracker - object who is tracking tracked - object being tracked entityname - field/property/attribute/ndb nam to watch function - function object to call when entity update. When entitye <key> is updated, this function will be called with called with function(obj, entityname, new_value, *args, **kwargs) *args - additional, optional arguments to send to function mode (keyword) - the type of entity to track. One of "property", "db", "ndb" or "custom" ("property" includes both changes to database fields and cached on-model properties) **kwargs - additional, optionak keywords to send to function Only entities that are being -cached- can be tracked. For custom on-typeclass properties, a custom hook needs to be created, calling the update() function in this module whenever the tracked entity changes. """ # always store database object (in case typeclass changes along the way) try: tracker = tracker.dbobj except AttributeError: pass try: tracked = tracked.dbobj except AttributeError: pass def default_callback(tracker, tracked, entityname, new_val, *args, **kwargs): "Callback used if no function is supplied" pass thid = hashid(tracked) if not thid: return oob_call = (function, oobkey, tracker, tracked, entityname, args, kwargs) if thid not in self.track_passive_subs: if mode in ("db", "ndb", "custom"): caches.register_oob_update_hook(tracked, entityname, mode=mode) elif mode == "property": # track property/field. We must first determine which cache to use. if hasattr(tracked, 'db_%s' % entityname.lstrip("db_")): hid = caches.register_oob_update_hook(tracked, entityname, mode="field") else: hid = caches.register_oob_update_hook(tracked, entityname, mode="property") if not self.track_pass_subs[hid][entityname]: self.track_pass_subs[hid][entityname] = {tracker:oob_call} else: self.track_passive_subs[hid][entityname][tracker] = oob_call
def untrack_passive(self, tracker, tracked, entityname, mode="db"): """ Remove passive tracking from an object's entity. mode - one of "property", "db", "ndb" or "custom" """ try: tracked = tracked.dbobj except AttributeError: pass thid = hashid(tracked) if not thid: return if len(self.track_passive_subs[thid][entityname]) == 1: if mode in ("db", "ndb", "custom"): caches.unregister_oob_update_hook(tracked, entityname, mode=mode) elif mode == "property": if hasattr(, 'db_%s' % entityname.lstrip("db_")): caches.unregister_oob_update_hook(tracked, entityname, mode="field") else: caches.unregister_oob_update_hook(tracked, entityname, mode="property") try: del self.track_passive_subs[thid][entityname][tracker] except (KeyError, TypeError): pass