Some cleanups, properly marking the OOB stuff as WIP still. OOB is progressing but not yet functional or in its final form.

This commit is contained in:
Griatch 2013-01-07 15:47:41 +01:00
parent 0ac2a58428
commit 5ef92b6bf8
4 changed files with 54 additions and 49 deletions

View file

@ -15,7 +15,7 @@ _ATTR_CACHE = defaultdict(dict)
_FIELD_CACHE = defaultdict(dict) _FIELD_CACHE = defaultdict(dict)
_PROP_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_FIELD_UPDATE_HOOKS = defaultdict(dict)
_OOB_PROP_UPDATE_HOOKS = defaultdict(dict) _OOB_PROP_UPDATE_HOOKS = defaultdict(dict)
_OOB_ATTR_UPDATE_HOOKS = defaultdict(dict) _OOB_ATTR_UPDATE_HOOKS = defaultdict(dict)

View file

@ -1,4 +1,6 @@
""" """
-- OBS - OOB is not yet functional in Evennia. Don't use this module --
OOB - Out-of-band central handler OOB - Out-of-band central handler
This module presents a central API for requesting data from objects in This module presents a central API for requesting data from objects in
@ -116,7 +118,7 @@ class OOBhandler(object):
# set reference on caches module # set reference on caches module
caches._OOB_HANDLER = self 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, Passively track changes to an object property,
attribute or non-db-attribute. Uses cache hooks to attribute or non-db-attribute. Uses cache hooks to
@ -124,10 +126,10 @@ class OOBhandler(object):
tracker - object who is tracking tracker - object who is tracking
tracked - object being tracked 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 <key> function - function object to call when entity update. When entitye <key>
is updated, this function will be called with called 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 *args - additional, optional arguments to send to function
mode (keyword) - the type of entity to track. One of mode (keyword) - the type of entity to track. One of
"property", "db", "ndb" or "custom" ("property" includes both "property", "db", "ndb" or "custom" ("property" includes both
@ -145,29 +147,29 @@ class OOBhandler(object):
try: tracked = tracked.dbobj try: tracked = tracked.dbobj
except AttributeError: pass 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" "Callback used if no function is supplied"
pass pass
thid = hashid(tracked) thid = hashid(tracked)
if not thid: if not thid:
return 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 thid not in self.track_passive_subs:
if mode in ("db", "ndb", "custom"): 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": elif mode == "property":
# track property/field. We must first determine which cache to use. # track property/field. We must first determine which cache to use.
if hasattr(tracked, 'db_%s' % key.lstrip("db_")): if hasattr(tracked, 'db_%s' % entityname.lstrip("db_")):
hid = caches.register_oob_update_hook(tracked, key, mode="field") hid = caches.register_oob_update_hook(tracked, entityname, mode="field")
else: else:
hid = caches.register_oob_update_hook(tracked, key, mode="property") hid = caches.register_oob_update_hook(tracked, entityname, mode="property")
if not self.track_pass_subs[hid][key]: if not self.track_pass_subs[hid][entityname]:
self.track_pass_subs[hid][key] = {tracker:oob_call} self.track_pass_subs[hid][entityname] = {tracker:oob_call}
else: 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. Remove passive tracking from an object's entity.
mode - one of "property", "db", "ndb" or "custom" mode - one of "property", "db", "ndb" or "custom"
@ -178,19 +180,19 @@ class OOBhandler(object):
thid = hashid(tracked) thid = hashid(tracked)
if not thid: if not thid:
return 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"): 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": elif mode == "property":
if hasattr(, 'db_%s' % key.lstrip("db_")): if hasattr(, 'db_%s' % entityname.lstrip("db_")):
caches.unregister_oob_update_hook(tracked, key, mode="field") caches.unregister_oob_update_hook(tracked, entityname, mode="field")
else: 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 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 This is called by the caches when the object when its
property/field/etc is updated, to inform the oob handler and property/field/etc is updated, to inform the oob handler and
@ -198,9 +200,9 @@ class OOBhandler(object):
with new_val. with new_val.
""" """
# tell all tracking objects of the update # 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: 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]) oob[0](tracker, oob[1], oob[2], new_val, *oob[3], **oob[4])
except Exception: except Exception:
logger.log_trace() logger.log_trace()
@ -208,13 +210,13 @@ class OOBhandler(object):
# Track (active/proactive tracking) # Track (active/proactive tracking)
# creating and storing tracker scripts # 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, Create a tracking, re-use script with same interval if available,
otherwise create a new one. otherwise create a new one.
args: 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 func - function to call at interval seconds
(all other args become argjs into func) (all other args become argjs into func)
keywords: keywords:
@ -223,20 +225,20 @@ class OOBhandler(object):
""" """
if interval in self.track_active_subs: if interval in self.track_active_subs:
# tracker with given interval found. Add to its 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: else:
# create new tracker with given interval # create new tracker with given interval
new_tracker = create.create_script(_OOBTracker, key="oob_tracking_%i" % interval, interval=interval) new_tracker = create.create_script(_OOBTracker, oobkey="oob_tracking_%i" % interval, interval=interval)
new_tracker.track(key, func, *args, **kwargs) new_tracker.track(oobkey, func, *args, **kwargs)
self.track_active_subs[interval] = new_tracker 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) tracker = self.track_active_subs.get(interval)
if tracker: if tracker:
tracker.untrack(key) tracker.untrack(oobkey)
# handler object # handler object
OOBHANDLER = OOBhandler() OOBHANDLER = OOBhandler()

View file

@ -218,46 +218,50 @@ class ServerSession(Session):
""" """
This receives out-of-band data from the Portal. 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 This method parses the data input (a dict) and uses
it to launch correct methods from those plugged into it to launch correct methods from those plugged into
the system. the system.
data = {funcname: ( [args], {kwargs]), data = {oobkey: (funcname, (args), {kwargs}),
funcname: ( [args], {kwargs}), ...} oobkey: (funcname, (args), {kwargs}), ...}
example: example:
data = {"get_hp": ([], {}), data = {"get_hp": ("oob_get_hp, [], {}),
"update_counter", (["counter1"], {"now":True}) } "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 = {} outdata = {}
entity = self.get_character() for oobkey, functuple in data.items():
if not entity:
entity = self.get_player()
if not entity:
entity = self
for funcname, argtuple in data.items():
# loop through the data, calling available functions. # 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: if func:
try: try:
outdata[funcname] = func(self, entity, *argtuple[0], **argtuple[1]) outdata[funcname] = func(oobkey, self, *functuple[1], **functuple[2])
except Exception: except Exception:
logger.log_trace() logger.log_trace()
else: else:
logger.log_errmsg("oob_data_in error: funcname '%s' not found in OOB_FUNC_MODULE." % funcname) logger.log_errmsg("oob_data_in error: funcname '%s' not found in OOB_FUNC_MODULE." % funcname)
if outdata: if outdata:
# we have a result, send it back # we have a direct result - send it back right away
self.oob_data_out(outdata) self.oob_data_out(outdata)
def oob_data_out(self, data): def oob_data_out(self, data):
""" """
This sends data from Server to the Portal across the AMP connection. 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) self.sessionhandler.oob_data_out(self, data)

View file

@ -120,9 +120,7 @@ class TypeClass(object):
""" """
Transparently save data to the dbobj object in Transparently save data to the dbobj object in
all situations. Note that this does not all situations. Note that this does not
necessarily mean storing it to the database necessarily mean storing it to the database.
unless data is stored into a propname
corresponding to a field on ObjectDB model.
""" """
#print "set %s -> %s" % (propname, value) #print "set %s -> %s" % (propname, value)
if propname in PROTECTED: if propname in PROTECTED:
@ -138,6 +136,7 @@ class TypeClass(object):
if dbobj: if dbobj:
_SA(dbobj, propname, value) _SA(dbobj, propname, value)
else: else:
# only as a last resort do we save on the typeclass object
_SA(self, propname, value) _SA(self, propname, value)
def __eq__(self, other): def __eq__(self, other):