From 5ef92b6bf8a80f071b9c4131fdf586ff8d84f6e4 Mon Sep 17 00:00:00 2001 From: Griatch Date: Mon, 7 Jan 2013 15:47:41 +0100 Subject: [PATCH] Some cleanups, properly marking the OOB stuff as WIP still. OOB is progressing but not yet functional or in its final form. --- src/server/caches.py | 2 +- src/server/oobhandler.py | 62 +++++++++++++++++++----------------- src/server/serversession.py | 34 +++++++++++--------- src/typeclasses/typeclass.py | 5 ++- 4 files changed, 54 insertions(+), 49 deletions(-) diff --git a/src/server/caches.py b/src/server/caches.py index eb269c5012..e388f602ff 100644 --- a/src/server/caches.py +++ b/src/server/caches.py @@ -15,7 +15,7 @@ _ATTR_CACHE = defaultdict(dict) _FIELD_CACHE = defaultdict(dict) _PROP_CACHE = defaultdict(dict) -# OOB hooks +# OOB hooks (OOB not yet functional, don't use yet) _OOB_FIELD_UPDATE_HOOKS = defaultdict(dict) _OOB_PROP_UPDATE_HOOKS = defaultdict(dict) _OOB_ATTR_UPDATE_HOOKS = defaultdict(dict) diff --git a/src/server/oobhandler.py b/src/server/oobhandler.py index f921a792ee..429f49c52c 100644 --- a/src/server/oobhandler.py +++ b/src/server/oobhandler.py @@ -1,4 +1,6 @@ """ +-- OBS - OOB is not yet functional in Evennia. Don't use this module -- + OOB - Out-of-band central handler This module presents a central API for requesting data from objects in @@ -116,7 +118,7 @@ class OOBhandler(object): # set reference on caches module caches._OOB_HANDLER = self - def track_passive(self, tracker, tracked, key, callback=None, mode="db", *args, **kwargs): + 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 @@ -124,10 +126,10 @@ class OOBhandler(object): tracker - object who is tracking tracked - object being tracked - key - field/property/attribute/ndb nam to watch + entityname - field/property/attribute/ndb nam to watch function - function object to call when entity update. When entitye is updated, this function will be called with called - with function(obj, key, new_value, *args, **kwargs) + 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 @@ -145,29 +147,29 @@ class OOBhandler(object): try: tracked = tracked.dbobj except AttributeError: pass - def default_callback(tracker, tracked, key, new_val, *args, **kwargs): + 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, tracked, key, args, kwargs) + 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, key, mode=mode) + 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' % key.lstrip("db_")): - hid = caches.register_oob_update_hook(tracked, key, mode="field") + 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, key, mode="property") - if not self.track_pass_subs[hid][key]: - self.track_pass_subs[hid][key] = {tracker:oob_call} + 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][key][tracker] = oob_call + self.track_passive_subs[hid][entityname][tracker] = oob_call - def untrack_passive(self, tracker, tracked, key, mode="db"): + 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" @@ -178,19 +180,19 @@ class OOBhandler(object): thid = hashid(tracked) if not thid: return - if len(self.track_passive_subs[thid][key]) == 1: + if len(self.track_passive_subs[thid][entityname]) == 1: if mode in ("db", "ndb", "custom"): - caches.unregister_oob_update_hook(tracked, key, mode=mode) + caches.unregister_oob_update_hook(tracked, entityname, mode=mode) elif mode == "property": - if hasattr(, 'db_%s' % key.lstrip("db_")): - caches.unregister_oob_update_hook(tracked, key, mode="field") + if hasattr(, 'db_%s' % entityname.lstrip("db_")): + caches.unregister_oob_update_hook(tracked, entityname, mode="field") else: - caches.unregister_oob_update_hook(tracked, key, mode="property") + caches.unregister_oob_update_hook(tracked, entityname, mode="property") - try: del self.track_passive_subs[thid][key][tracker] + try: del self.track_passive_subs[thid][entityname][tracker] except (KeyError, TypeError): pass - def update(self, hid, key, new_val): + def update(self, hid, entityname, new_val): """ This is called by the caches when the object when its property/field/etc is updated, to inform the oob handler and @@ -198,9 +200,9 @@ class OOBhandler(object): with new_val. """ # tell all tracking objects of the update - for tracker, oob in self.track_passive_subs[hid][key].items(): + for tracker, oob in self.track_passive_subs[hid][entityname].items(): try: - # function(tracker, , key, new_value, *args, **kwargs) + # function(oobkey, tracker, tracked, entityname, new_value, *args, **kwargs) oob[0](tracker, oob[1], oob[2], new_val, *oob[3], **oob[4]) except Exception: logger.log_trace() @@ -208,13 +210,13 @@ class OOBhandler(object): # Track (active/proactive tracking) # creating and storing tracker scripts - def track_active(self, key, func, interval=30, *args, **kwargs): + def track_active(self, oobkey, func, interval=30, *args, **kwargs): """ Create a tracking, re-use script with same interval if available, otherwise create a new one. args: - key - interval-unique identifier needed for removing tracking later + oobkey - interval-unique identifier needed for removing tracking later func - function to call at interval seconds (all other args become argjs into func) keywords: @@ -223,20 +225,20 @@ class OOBhandler(object): """ if interval in self.track_active_subs: # tracker with given interval found. Add to its subs - self.track_active_subs[interval].track(key, func, *args, **kwargs) + self.track_active_subs[interval].track(oobkey, func, *args, **kwargs) else: # create new tracker with given interval - new_tracker = create.create_script(_OOBTracker, key="oob_tracking_%i" % interval, interval=interval) - new_tracker.track(key, func, *args, **kwargs) + new_tracker = create.create_script(_OOBTracker, oobkey="oob_tracking_%i" % interval, interval=interval) + new_tracker.track(oobkey, func, *args, **kwargs) self.track_active_subs[interval] = new_tracker - def untrack_active(self, key, interval): + def untrack_active(self, oobkey, interval): """ - Remove tracking for a given interval and key + Remove tracking for a given interval and oobkey """ tracker = self.track_active_subs.get(interval) if tracker: - tracker.untrack(key) + tracker.untrack(oobkey) # handler object OOBHANDLER = OOBhandler() diff --git a/src/server/serversession.py b/src/server/serversession.py index 501ef42571..f1303e8d8f 100644 --- a/src/server/serversession.py +++ b/src/server/serversession.py @@ -218,46 +218,50 @@ class ServerSession(Session): """ This receives out-of-band data from the Portal. + OBS - preliminary. OOB not yet functional in Evennia. Don't use. + This method parses the data input (a dict) and uses it to launch correct methods from those plugged into the system. - data = {funcname: ( [args], {kwargs]), - funcname: ( [args], {kwargs}), ...} + data = {oobkey: (funcname, (args), {kwargs}), + oobkey: (funcname, (args), {kwargs}), ...} example: - data = {"get_hp": ([], {}), - "update_counter", (["counter1"], {"now":True}) } + data = {"get_hp": ("oob_get_hp, [], {}), + "update_counter", ("counter", ["counter1"], {"now":True}) } - All functions will be called with a back-reference to this session as first argument. + All function names must be defined in settings.OOB_FUNC_MODULE. Each + function will be called with the oobkey and a back-reference to this session + as their first two arguments. """ outdata = {} - entity = self.get_character() - if not entity: - entity = self.get_player() - if not entity: - entity = self - - for funcname, argtuple in data.items(): + for oobkey, functuple in data.items(): # loop through the data, calling available functions. - func = OOB_FUNC_MODULE.__dict__.get(funcname, None) + func = OOB_FUNC_MODULE.__dict__.get(functuple[0]) if func: try: - outdata[funcname] = func(self, entity, *argtuple[0], **argtuple[1]) + outdata[funcname] = func(oobkey, self, *functuple[1], **functuple[2]) except Exception: logger.log_trace() else: logger.log_errmsg("oob_data_in error: funcname '%s' not found in OOB_FUNC_MODULE." % funcname) if outdata: - # we have a result, send it back + # we have a direct result - send it back right away self.oob_data_out(outdata) def oob_data_out(self, data): """ This sends data from Server to the Portal across the AMP connection. + + OBS - preliminary. OOB not yet functional in Evennia. Don't use. + + data = {oobkey: (funcname, (args), {kwargs}), + oobkey: (funcname, (args), {kwargs}), ...} + """ self.sessionhandler.oob_data_out(self, data) diff --git a/src/typeclasses/typeclass.py b/src/typeclasses/typeclass.py index 4c0b1d5696..f708ede3a1 100644 --- a/src/typeclasses/typeclass.py +++ b/src/typeclasses/typeclass.py @@ -120,9 +120,7 @@ class TypeClass(object): """ Transparently save data to the dbobj object in all situations. Note that this does not - necessarily mean storing it to the database - unless data is stored into a propname - corresponding to a field on ObjectDB model. + necessarily mean storing it to the database. """ #print "set %s -> %s" % (propname, value) if propname in PROTECTED: @@ -138,6 +136,7 @@ class TypeClass(object): if dbobj: _SA(dbobj, propname, value) else: + # only as a last resort do we save on the typeclass object _SA(self, propname, value) def __eq__(self, other):