Esempio n. 1
0
    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
Esempio n. 2
0
    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