Some further work on the OOBhandler mechanism.

This commit is contained in:
Griatch 2013-01-04 10:35:29 +01:00
parent b0b0fa7983
commit 58c010ef46
4 changed files with 57 additions and 37 deletions

View file

@ -7,10 +7,15 @@
is selected by settings.OOB_FUNC_MODULE. is selected by settings.OOB_FUNC_MODULE.
All functions defined global in this module will be available All functions defined global in this module will be available
for the oob system to call. They will be called with a session/character for the oob system to call. They will be called in the following
way:
a session/character
as first argument (depending on if the session is logged in or not), as first argument (depending on if the session is logged in or not),
following by any number of extra arguments. The return value will following by any number of extra arguments. The return value will
be packed and returned to the oob protocol and can be on any form. be packed and returned to the oob protocol and can be on any form.
""" """
def testoob(character, *args, **kwargs): def testoob(character, *args, **kwargs):
@ -19,8 +24,6 @@ def testoob(character, *args, **kwargs):
return "testoob did stuff to the input string '%s'!" % val return "testoob did stuff to the input string '%s'!" % val
# MSDP_MAP is a standard suggestions for making it easy to create generic guis. # MSDP_MAP is a standard suggestions for making it easy to create generic guis.
# this maps MSDP command names to Evennia commands found in OOB_FUNC_MODULE. It # this maps MSDP command names to Evennia commands found in OOB_FUNC_MODULE. It
# is up to these commands to return data on proper form. # is up to these commands to return data on proper form.

View file

@ -1585,7 +1585,7 @@ class CmdExamine(ObjManipCommand):
else: else:
db_attr = [(attr.key, attr.value) for attr in ObjAttribute.objects.filter(db_obj=obj)] db_attr = [(attr.key, attr.value) for attr in ObjAttribute.objects.filter(db_obj=obj)]
try: try:
ndb_attr = [(aname, avalue) for aname, avalue in obj.ndb.__dict__.items()] ndb_attr = [(aname, avalue) for aname, avalue in obj.ndb.__dict__.items() if not aname.startswith("_")]
except Exception: except Exception:
ndb_attr = None ndb_attr = None
string = "" string = ""

View file

@ -80,6 +80,7 @@ def register_oob_update_hook(obj,name, entity="field"):
if entity == "field": if entity == "field":
global _OOB_FIELD_UPDATE_HOOKS global _OOB_FIELD_UPDATE_HOOKS
_OOB_FIELD_UPDATE_HOOKS[hid][name] = True _OOB_FIELD_UPDATE_HOOKS[hid][name] = True
return
elif entity == "property": elif entity == "property":
global _OOB_PROP_UPDATE_HOOKS global _OOB_PROP_UPDATE_HOOKS
_OOB_PROP_UPDATE_HOOKS[hid][name] = True _OOB_PROP_UPDATE_HOOKS[hid][name] = True
@ -94,7 +95,6 @@ def register_oob_update_hook(obj,name, entity="field"):
_OOB_CUSTOM_UPDATE_HOOKS[hid][name] = True _OOB_CUSTOM_UPDATE_HOOKS[hid][name] = True
else: else:
return None return None
return hid
def unregister_oob_update_hook(obj, name, entity="property"): def unregister_oob_update_hook(obj, name, entity="property"):
""" """
@ -116,7 +116,6 @@ def unregister_oob_update_hook(obj, name, entity="property"):
del _OOB_CUSTOM_UPDATE_HOOKS[hid][name] del _OOB_CUSTOM_UPDATE_HOOKS[hid][name]
else: else:
return None return None
return hid
# on-object database field cache # on-object database field cache
def get_field_cache(obj, name): def get_field_cache(obj, name):

View file

@ -3,7 +3,7 @@ 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
Evennia via OOB negotiation. It is meant specifically to be imported Evennia via OOB negotiation. It is meant specifically to be imported
and used by the module defined in settings.OOB_MODULE. and used by the module defined in settings.OOB_FUNC_MODULE.
Import src.server.oobhandler and use the methods in OOBHANDLER. Import src.server.oobhandler and use the methods in OOBHANDLER.
@ -26,6 +26,18 @@ track_active - this is an active reporting mechanism making use of a Script. Thi
Trivial operations such as get/setting individual properties one time is best done directly from Trivial operations such as get/setting individual properties one time is best done directly from
the OOB_MODULE functions. the OOB_MODULE functions.
Examples of call from OOB_FUNC_MODULE:
from src.server.oobhandler import OOBHANDLER
def track_desc(session, *args, **kwargs):
"Sets up a passive watch for the desc attribute on session object"
if session.player and session.player.character:
char = session.player.character
OOBHANDLER.track_passive(session, char, "desc", entity="db")
# to start off we return the value once
return char.db.desc
""" """
from collections import defaultdict from collections import defaultdict
@ -104,7 +116,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, name, function, entity="db", *args, **kwargs): def track_passive(self, tracker, tracked, key, 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
@ -112,12 +124,12 @@ class OOBhandler(object):
tracker - object who is tracking tracker - object who is tracking
tracked - object being tracked tracked - object being tracked
name - field/property/attribute/ndb nam to watch key - field/property/attribute/ndb nam to watch
function - function object to call when entity update. When entitye <name> 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, name, new_value, *args, **kwargs) with function(obj, key, new_value, *args, **kwargs)
*args - additional, optional arguments to send to function *args - additional, optional arguments to send to function
entity (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
changes to database fields and cached on-model properties) changes to database fields and cached on-model properties)
**kwargs - additional, optionak keywords to send to function **kwargs - additional, optionak keywords to send to function
@ -133,28 +145,32 @@ 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):
"Callback used if no function is supplied"
pass
thid = hashid(tracked) thid = hashid(tracked)
if not thid: if not thid:
return return
oob_call = (function, tracked, name, args, kwargs) oob_call = (function, tracked, key, args, kwargs)
if thid not in self.track_passive_subs: if thid not in self.track_passive_subs:
if entity in ("db", "ndb", "custom"): if mode in ("db", "ndb", "custom"):
caches.register_oob_update_hook(tracked, name, entity=entity) caches.register_oob_update_hook(tracked, key, mode=mode)
elif entity == "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' % name.lstrip("db_")): if hasattr(tracked, 'db_%s' % key.lstrip("db_")):
hid = caches.register_oob_update_hook(tracked, name, entity="field") hid = caches.register_oob_update_hook(tracked, key, mode="field")
else: else:
hid = caches.register_oob_update_hook(tracked, name, entity="property") hid = caches.register_oob_update_hook(tracked, key, mode="property")
if not self.track_pass_subs[hid][name]: if not self.track_pass_subs[hid][key]:
self.track_pass_subs[hid][name] = {tracker:oob_call} self.track_pass_subs[hid][key] = {tracker:oob_call}
else: else:
self.track_passive_subs[hid][name][tracker] = oob_call self.track_passive_subs[hid][key][tracker] = oob_call
def untrack_passive(self, tracker, tracked, name, entity="db"): def untrack_passive(self, tracker, tracked, key, mode="db"):
""" """
Remove passive tracking from an object's entity. Remove passive tracking from an object's entity.
entity - one of "property", "db", "ndb" or "custom" mode - one of "property", "db", "ndb" or "custom"
""" """
try: tracked = tracked.dbobj try: tracked = tracked.dbobj
except AttributeError: pass except AttributeError: pass
@ -162,27 +178,29 @@ class OOBhandler(object):
thid = hashid(tracked) thid = hashid(tracked)
if not thid: if not thid:
return return
if len(self.track_passive_subs[thid][name]) == 1: if len(self.track_passive_subs[thid][key]) == 1:
if entity in ("db", "ndb", "custom"): if mode in ("db", "ndb", "custom"):
caches.unregister_oob_update_hook(tracked, name, entity=entity) caches.unregister_oob_update_hook(tracked, key, mode=mode)
elif entity == "property": elif mode == "property":
if hasattr(tracked, 'db_%s' % name.lstrip("db_")): if hasattr(, 'db_%s' % key.lstrip("db_")):
caches.unregister_oob_update_hook(tracked, name, entity="field") caches.unregister_oob_update_hook(tracked, key, mode="field")
else: else:
caches.unregister_oob_update_hook(tracked, name, entity="property") caches.unregister_oob_update_hook(tracked, key, mode="property")
try: del self.track_passive_subs[thid][name][tracker] try: del self.track_passive_subs[thid][key][tracker]
except (KeyError, TypeError): pass except (KeyError, TypeError): pass
def update(self, hid, name, new_val): def update(self, hid, key, new_val):
""" """
This is called by the caches when the tracked object when its property/field/etc is updated, This is called by the caches when the object when its
to inform the oob handler and all subscribing to this particular entity has been updated with new_val. property/field/etc is updated, to inform the oob handler and
all subscribing to this particular entity has been updated
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][name].items(): for tracker, oob in self.track_passive_subs[hid][key].items():
try: try:
# function(tracker, tracked, key, new_value, *args, **kwargs) # function(tracker, , key, 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()