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.
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),
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.
"""
def testoob(character, *args, **kwargs):
@ -19,8 +24,6 @@ def testoob(character, *args, **kwargs):
return "testoob did stuff to the input string '%s'!" % val
# 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
# is up to these commands to return data on proper form.

View file

@ -1585,7 +1585,7 @@ class CmdExamine(ObjManipCommand):
else:
db_attr = [(attr.key, attr.value) for attr in ObjAttribute.objects.filter(db_obj=obj)]
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:
ndb_attr = None
string = ""

View file

@ -80,6 +80,7 @@ def register_oob_update_hook(obj,name, entity="field"):
if entity == "field":
global _OOB_FIELD_UPDATE_HOOKS
_OOB_FIELD_UPDATE_HOOKS[hid][name] = True
return
elif entity == "property":
global _OOB_PROP_UPDATE_HOOKS
_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
else:
return None
return hid
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]
else:
return None
return hid
# on-object database field cache
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
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.
@ -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
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
@ -104,7 +116,7 @@ class OOBhandler(object):
# set reference on caches module
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,
attribute or non-db-attribute. Uses cache hooks to
@ -112,12 +124,12 @@ class OOBhandler(object):
tracker - object who is tracking
tracked - object being tracked
name - field/property/attribute/ndb nam to watch
function - function object to call when entity update. When entitye <name>
key - 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, name, new_value, *args, **kwargs)
with function(obj, key, new_value, *args, **kwargs)
*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
changes to database fields and cached on-model properties)
**kwargs - additional, optionak keywords to send to function
@ -133,28 +145,32 @@ class OOBhandler(object):
try: tracked = tracked.dbobj
except AttributeError: pass
def default_callback(tracker, tracked, key, new_val, *args, **kwargs):
"Callback used if no function is supplied"
pass
thid = hashid(tracked)
if not thid:
return
oob_call = (function, tracked, name, args, kwargs)
oob_call = (function, tracked, key, args, kwargs)
if thid not in self.track_passive_subs:
if entity in ("db", "ndb", "custom"):
caches.register_oob_update_hook(tracked, name, entity=entity)
elif entity == "property":
if mode in ("db", "ndb", "custom"):
caches.register_oob_update_hook(tracked, key, mode=mode)
elif mode == "property":
# track property/field. We must first determine which cache to use.
if hasattr(tracked, 'db_%s' % name.lstrip("db_")):
hid = caches.register_oob_update_hook(tracked, name, entity="field")
if hasattr(tracked, 'db_%s' % key.lstrip("db_")):
hid = caches.register_oob_update_hook(tracked, key, mode="field")
else:
hid = caches.register_oob_update_hook(tracked, name, entity="property")
if not self.track_pass_subs[hid][name]:
self.track_pass_subs[hid][name] = {tracker:oob_call}
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}
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.
entity - one of "property", "db", "ndb" or "custom"
mode - one of "property", "db", "ndb" or "custom"
"""
try: tracked = tracked.dbobj
except AttributeError: pass
@ -162,27 +178,29 @@ class OOBhandler(object):
thid = hashid(tracked)
if not thid:
return
if len(self.track_passive_subs[thid][name]) == 1:
if entity in ("db", "ndb", "custom"):
caches.unregister_oob_update_hook(tracked, name, entity=entity)
elif entity == "property":
if hasattr(tracked, 'db_%s' % name.lstrip("db_")):
caches.unregister_oob_update_hook(tracked, name, entity="field")
if len(self.track_passive_subs[thid][key]) == 1:
if mode in ("db", "ndb", "custom"):
caches.unregister_oob_update_hook(tracked, key, mode=mode)
elif mode == "property":
if hasattr(, 'db_%s' % key.lstrip("db_")):
caches.unregister_oob_update_hook(tracked, key, mode="field")
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
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,
to inform the oob handler and all subscribing to this particular entity has been updated with new_val.
This is called by the caches when the object when its
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
for tracker, oob in self.track_passive_subs[hid][name].items():
for tracker, oob in self.track_passive_subs[hid][key].items():
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])
except Exception:
logger.log_trace()