2013-01-03 09:18:49 +01:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
OOBHandler - Out Of Band Handler
|
2013-01-07 15:47:41 +01:00
|
|
|
|
2013-09-14 23:18:36 +02:00
|
|
|
The OOBHandler is called directly by out-of-band protocols. It supplies three
|
|
|
|
|
pieces of functionality:
|
2013-01-03 09:18:49 +01:00
|
|
|
|
2013-09-14 23:18:36 +02:00
|
|
|
function execution - the oob protocol can execute a function directly on
|
|
|
|
|
the server. Only functions specified in settings.OOB_PLUGIN_MODULE.OOB_FUNCS
|
|
|
|
|
are valid for this use.
|
|
|
|
|
repeat func execution - the oob protocol can request a given function be executed repeatedly
|
|
|
|
|
at a regular interval.
|
|
|
|
|
tracking - the oob protocol can request Evennia to track changes to fields/properties on
|
|
|
|
|
objects, as well as changes in Attributes. This is done by dynamically adding
|
|
|
|
|
tracker-objects on entities. The behaviour of those objects can be customized
|
|
|
|
|
via settings.OOB_PLUGIN_MODULE.OOB_TRACKERS.
|
2013-01-03 09:18:49 +01:00
|
|
|
|
2013-09-14 23:18:36 +02:00
|
|
|
oob functions have the following call signature:
|
|
|
|
|
function(caller, *args, **kwargs)
|
2013-09-07 15:01:41 +02:00
|
|
|
|
2013-09-14 23:18:36 +02:00
|
|
|
oob trackers should inherit from the OOBTracker class in this
|
|
|
|
|
module and implement a minimum of the same functionality.
|
2013-09-07 15:01:41 +02:00
|
|
|
|
2013-01-03 09:18:49 +01:00
|
|
|
"""
|
|
|
|
|
|
2013-10-15 20:00:18 +02:00
|
|
|
from inspect import isfunction
|
2013-09-07 15:01:41 +02:00
|
|
|
from django.conf import settings
|
2013-09-14 23:18:36 +02:00
|
|
|
from src.server.models import ServerConfig
|
|
|
|
|
from src.server.sessionhandler import SESSIONS
|
|
|
|
|
from src.scripts.scripts import Script
|
2013-10-07 19:57:01 +02:00
|
|
|
from src.utils.create import create_script
|
2013-09-14 23:18:36 +02:00
|
|
|
from src.utils.dbserialize import dbserialize, dbunserialize, pack_dbobj
|
|
|
|
|
from src.utils import logger
|
2013-10-15 20:00:18 +02:00
|
|
|
from src.utils.utils import all_from_module, to_str, is_iter, make_iter
|
2013-09-14 23:18:36 +02:00
|
|
|
|
|
|
|
|
_SA = object.__setattr__
|
|
|
|
|
_GA = object.__getattribute__
|
2013-10-15 20:00:18 +02:00
|
|
|
_DA = object.__delattr__
|
2013-09-14 23:18:36 +02:00
|
|
|
|
2013-10-15 20:00:18 +02:00
|
|
|
# load from plugin module
|
|
|
|
|
_OOB_FUNCS = dict((key, func) for key, func in all_from_module(settings.OOB_PLUGIN_MODULE).items() if isfunction(func))
|
|
|
|
|
_OOB_ERROR = _OOB_FUNCS.get("oob_error", None)
|
2013-09-14 23:18:36 +02:00
|
|
|
|
2013-09-19 20:41:42 +02:00
|
|
|
|
|
|
|
|
class TrackerHandler(object):
|
|
|
|
|
"""
|
|
|
|
|
This object is dynamically assigned to objects whenever one of its fields
|
|
|
|
|
are to be tracked. It holds an internal dictionary mapping to the fields
|
|
|
|
|
on that object. Each field can be tracked by any number of trackers (each
|
|
|
|
|
tied to a different callback).
|
|
|
|
|
"""
|
|
|
|
|
def __init__(self, obj):
|
|
|
|
|
"""
|
|
|
|
|
This is initiated and stored on the object as a property _trackerhandler.
|
|
|
|
|
"""
|
|
|
|
|
self.obj = obj.dbobj
|
|
|
|
|
self.ntrackers = 0
|
|
|
|
|
# initiate store only with valid on-object fieldnames
|
|
|
|
|
self.tracktargets = dict((key, {}) for key in _GA(_GA(self.obj, "_meta"), "get_all_field_names")())
|
|
|
|
|
|
|
|
|
|
def add(self, fieldname, trackerkey, trackerobj):
|
|
|
|
|
"""
|
|
|
|
|
Add tracker to the handler. Raises KeyError if fieldname
|
|
|
|
|
does not exist.
|
|
|
|
|
"""
|
|
|
|
|
self.tracktargets[fieldname][trackerkey] = trackerobj
|
|
|
|
|
self.ntrackers += 1
|
|
|
|
|
|
|
|
|
|
def remove(self, fieldname, trackerkey, *args, **kwargs):
|
|
|
|
|
"""
|
|
|
|
|
Remove tracker from handler. Raises KeyError if tracker
|
|
|
|
|
is not found.
|
|
|
|
|
"""
|
|
|
|
|
oobobj = self.tracktargets[fieldname][trackerkey]
|
|
|
|
|
try:
|
|
|
|
|
oobobj.at_delete(*args, **kwargs)
|
|
|
|
|
except Exception:
|
|
|
|
|
logger.log_trace()
|
|
|
|
|
del oobobj
|
|
|
|
|
self.ntrackers -= 1
|
|
|
|
|
if self.ntrackers <= 0:
|
|
|
|
|
# if there are no more trackers, clean this handler
|
|
|
|
|
del self
|
|
|
|
|
|
|
|
|
|
def update(self, fieldname, new_value):
|
|
|
|
|
"""
|
|
|
|
|
Called by the field when it updates to a new value
|
|
|
|
|
"""
|
|
|
|
|
for trackerobj in self.tracktargets[fieldname].values():
|
|
|
|
|
try:
|
|
|
|
|
trackerobj.update(fieldname, new_value)
|
|
|
|
|
except Exception:
|
|
|
|
|
logger.log_trace()
|
|
|
|
|
|
|
|
|
|
class TrackerBase(object):
|
2013-09-14 23:18:36 +02:00
|
|
|
"""
|
2013-09-19 20:41:42 +02:00
|
|
|
Base class for OOB Tracker objects.
|
2013-09-14 23:18:36 +02:00
|
|
|
"""
|
2013-09-19 20:41:42 +02:00
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
pass
|
2013-09-14 23:18:36 +02:00
|
|
|
def update(self, *args, **kwargs):
|
|
|
|
|
"Called by tracked objects"
|
|
|
|
|
pass
|
|
|
|
|
def at_remove(self, *args, **kwargs):
|
2013-09-19 20:41:42 +02:00
|
|
|
"Called when tracker is removed"
|
2013-09-14 23:18:36 +02:00
|
|
|
pass
|
2013-09-07 15:01:41 +02:00
|
|
|
|
2013-09-14 23:18:36 +02:00
|
|
|
# Default tracker OOB class
|
2013-09-07 15:01:41 +02:00
|
|
|
|
2013-09-19 20:41:42 +02:00
|
|
|
class OOBTracker(TrackerBase):
|
2013-09-07 15:01:41 +02:00
|
|
|
"""
|
2013-09-19 20:41:42 +02:00
|
|
|
A OOB object that passively sends data to a stored sessid whenever
|
|
|
|
|
a named database field changes.
|
2013-09-07 15:01:41 +02:00
|
|
|
"""
|
2013-09-19 20:41:42 +02:00
|
|
|
def __init__(self, fieldname, sessid, *args, **kwargs):
|
2013-09-07 15:01:41 +02:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
name - name of entity to track, such as "db_key"
|
|
|
|
|
track_type - one of "field", "prop" or "attr" for Database fields,
|
|
|
|
|
non-database Property or Attribute
|
|
|
|
|
sessid - sessid of session to report to
|
2013-09-07 15:01:41 +02:00
|
|
|
"""
|
2013-09-19 20:41:42 +02:00
|
|
|
self.fieldname = fieldname
|
2013-09-14 23:18:36 +02:00
|
|
|
self.sessid = sessid
|
|
|
|
|
|
|
|
|
|
def update(self, new_value, *args, **kwargs):
|
|
|
|
|
"Called by cache when updating the tracked entitiy"
|
2013-10-15 20:00:18 +02:00
|
|
|
SESSIONS.session_from_sessid(self.sessid).msg(oob=("trackreturn",
|
|
|
|
|
(self.fieldname, new_value)))
|
2013-01-03 09:18:49 +01:00
|
|
|
|
2013-09-14 23:18:36 +02:00
|
|
|
class _RepeaterPool(object):
|
2013-01-03 09:18:49 +01:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
This maintains a pool of _RepeaterScript scripts, ordered one per interval. It
|
|
|
|
|
will automatically cull itself once a given interval's script has no more
|
|
|
|
|
subscriptions.
|
2013-01-03 09:18:49 +01:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
|
|
|
|
|
class _RepeaterScript(Script):
|
2013-01-03 09:18:49 +01:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
Repeating script for triggering OOB functions. Maintained in the pool.
|
2013-01-03 09:18:49 +01:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
def at_script_creation(self):
|
|
|
|
|
"Called when script is initialized"
|
|
|
|
|
self.key = "oob_func"
|
|
|
|
|
self.desc = "OOB functionality script"
|
|
|
|
|
self.persistent = False #oob scripts should always be non-persistent
|
|
|
|
|
self.ndb.subscriptions = {}
|
|
|
|
|
|
|
|
|
|
def at_repeat(self):
|
|
|
|
|
"""
|
|
|
|
|
Calls subscriptions every self.interval seconds
|
|
|
|
|
"""
|
|
|
|
|
for (func_key, caller, interval, args, kwargs) in self.ndb.subscriptions.values():
|
|
|
|
|
try:
|
|
|
|
|
_OOB_FUNCS[func_key](caller, *args, **kwargs)
|
|
|
|
|
except Exception:
|
|
|
|
|
logger.log_trace()
|
|
|
|
|
|
|
|
|
|
def subscribe(self, store_key, caller, func_key, interval, *args, **kwargs):
|
|
|
|
|
"""
|
|
|
|
|
Sign up a subscriber to this oobfunction. Subscriber is
|
|
|
|
|
a database object with a dbref.
|
|
|
|
|
"""
|
|
|
|
|
self.ndb.subscriptions[store_key] = (func_key, caller, interval, args, kwargs)
|
|
|
|
|
|
|
|
|
|
def unsubscribe(self, store_key):
|
|
|
|
|
"""
|
|
|
|
|
Unsubscribe from oobfunction. Returns True if removal was
|
|
|
|
|
successful, False otherwise
|
|
|
|
|
"""
|
|
|
|
|
self.ndb.subscriptions.pop(store_key, None)
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self.scripts = {}
|
2013-01-03 09:18:49 +01:00
|
|
|
|
2013-09-14 23:18:36 +02:00
|
|
|
def add(self, store_key, caller, func_key, interval, *args, **kwargs):
|
2013-01-03 09:18:49 +01:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
Add a new tracking
|
2013-01-03 09:18:49 +01:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
if interval not in self.scripts:
|
|
|
|
|
# if no existing interval exists, create new script to fill the gap
|
|
|
|
|
new_tracker = create_script(self._RepeaterScript, key="oob_repeater_%is" % interval, interval=interval)
|
|
|
|
|
self.scripts[interval] = new_tracker
|
|
|
|
|
self.scripts[interval].subscribe(store_key, caller, func_key, interval, *args, **kwargs)
|
2013-01-03 09:18:49 +01:00
|
|
|
|
2013-09-14 23:18:36 +02:00
|
|
|
def remove(self, store_key, interval):
|
2013-01-03 09:18:49 +01:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
Remove tracking
|
2013-01-03 09:18:49 +01:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
if interval in self.scripts:
|
|
|
|
|
self.scripts[interval].unsubscribe(store_key)
|
|
|
|
|
if len(self.scripts[interval].ndb.subscriptions) == 0:
|
|
|
|
|
# no more subscriptions for this interval. Clean out the script.
|
|
|
|
|
self.scripts[interval].stop()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Main OOB Handler
|
2013-09-07 15:01:41 +02:00
|
|
|
|
|
|
|
|
class OOBHandler(object):
|
2013-01-03 09:18:49 +01:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
The OOBHandler maintains all dynamic on-object oob hooks. It will store the
|
|
|
|
|
creation instructions and and re-apply them at a server reload (but not after
|
|
|
|
|
a server shutdown)
|
2013-01-03 09:18:49 +01:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
def __init__(self):
|
2013-09-14 09:10:31 +02:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
Initialize handler
|
2013-09-14 09:10:31 +02:00
|
|
|
"""
|
2013-10-15 20:00:18 +02:00
|
|
|
self.sessionhandler = SESSIONS
|
2013-09-14 23:18:36 +02:00
|
|
|
self.oob_tracker_storage = {}
|
|
|
|
|
self.oob_repeat_storage = {}
|
|
|
|
|
self.oob_tracker_pool = _RepeaterPool()
|
2013-09-14 09:10:31 +02:00
|
|
|
|
2013-09-14 23:18:36 +02:00
|
|
|
def save(self):
|
2013-09-07 15:01:41 +02:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
Save the command_storage as a serialized string into a temporary
|
|
|
|
|
ServerConf field
|
2013-09-07 15:01:41 +02:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
if self.oob_tracker_storage:
|
|
|
|
|
ServerConfig.objects.conf(key="oob_tracker_storage", value=dbserialize(self.oob_tracker_storage))
|
|
|
|
|
if self.oob_repeat_storage:
|
|
|
|
|
ServerConfig.objects.conf(key="oob_repeat_storage", value=dbserialize(self.oob_repeat_storage))
|
2013-09-07 15:01:41 +02:00
|
|
|
|
2013-09-14 23:18:36 +02:00
|
|
|
def restore(self):
|
2013-09-07 15:01:41 +02:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
Restore the command_storage from database and re-initialize the handler from storage.. This is
|
|
|
|
|
only triggered after a server reload, not after a shutdown-restart
|
2013-09-07 15:01:41 +02:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
# load stored command instructions and use them to re-initialize handler
|
|
|
|
|
tracker_storage = ServerConfig.objects.conf(key="oob_tracker_storage")
|
|
|
|
|
if tracker_storage:
|
|
|
|
|
self.oob_tracker_storage = dbunserialize(tracker_storage)
|
2013-09-19 20:41:42 +02:00
|
|
|
for tracker_key, (obj, sessid, fieldname, args, kwargs) in self.oob_tracker_storage.items():
|
|
|
|
|
self.track(obj, sessid, fieldname, tracker_key, *args, **kwargs)
|
2013-09-14 23:18:36 +02:00
|
|
|
|
|
|
|
|
repeat_storage = ServerConfig.objects.conf(key="oob_repeat_storage")
|
|
|
|
|
if repeat_storage:
|
|
|
|
|
self.oob_repeat_storage = dbunserialize(repeat_storage)
|
|
|
|
|
for func_key, (caller, func_key, interval, args, kwargs) in self.oob_repeat_storage.items():
|
|
|
|
|
self.repeat(caller, func_key, interval, *args, **kwargs)
|
2013-09-07 15:01:41 +02:00
|
|
|
|
2013-09-14 23:18:36 +02:00
|
|
|
|
2013-10-15 20:00:18 +02:00
|
|
|
def track(self, obj, sessid, fieldname, oobclass, *args, **kwargs):
|
2013-09-07 15:01:41 +02:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
Create an OOB obj of class _oob_MAPPING[tracker_key] on obj. args,
|
|
|
|
|
kwargs will be used to initialize the OOB hook before adding
|
|
|
|
|
it to obj.
|
|
|
|
|
If property_key is not given, but the OOB has a class property property_name, this
|
|
|
|
|
will be used as the property name when assigning the OOB to
|
|
|
|
|
obj, otherwise tracker_key is ysed as the property name.
|
2013-09-07 15:01:41 +02:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
oobclass = _OOB_TRACKERS[tracker_key] # raise traceback if not found
|
2013-09-19 20:41:42 +02:00
|
|
|
if not "_trackerhandler" in _GA(obj, "__dict__"):
|
|
|
|
|
# assign trackerhandler to object
|
|
|
|
|
_SA(obj, "_trackerhandler", TrackerHandler(obj))
|
|
|
|
|
# initialize object
|
|
|
|
|
oob = oobclass(obj, sessid, fieldname, *args, **kwargs)
|
|
|
|
|
_GA(obj, "_trackerhandler").add(oob, fieldname)
|
|
|
|
|
|
2013-09-14 23:18:36 +02:00
|
|
|
# store calling arguments as a pickle for retrieval later
|
2013-09-19 20:41:42 +02:00
|
|
|
storekey = (pack_dbobj(obj), sessid, fieldname)
|
|
|
|
|
stored = (obj, sessid, fieldname, args, kwargs)
|
2013-09-14 23:18:36 +02:00
|
|
|
self.oob_tracker_storage[storekey] = stored
|
|
|
|
|
|
2013-09-19 20:41:42 +02:00
|
|
|
def untrack(self, obj, sessid, fieldname, tracker_key, *args, **kwargs):
|
2013-09-07 15:01:41 +02:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
Remove the OOB from obj. If oob implements an
|
|
|
|
|
at_delete hook, this will be called with args, kwargs
|
2013-09-07 15:01:41 +02:00
|
|
|
"""
|
|
|
|
|
try:
|
2013-09-14 23:18:36 +02:00
|
|
|
# call at_delete hook
|
2013-09-19 20:41:42 +02:00
|
|
|
_GA(obj, "_trackerhandler").remove(fieldname, tracker_key, *args, **kwargs)
|
2013-09-14 23:18:36 +02:00
|
|
|
except AttributeError:
|
|
|
|
|
pass
|
|
|
|
|
# remove the pickle from storage
|
2013-09-19 20:41:42 +02:00
|
|
|
store_key = (pack_dbobj(obj), sessid, fieldname)
|
2013-09-14 23:18:36 +02:00
|
|
|
self.oob_tracker_storage.pop(store_key, None)
|
2013-01-03 09:18:49 +01:00
|
|
|
|
2013-09-14 23:18:36 +02:00
|
|
|
def track_field(self, obj, sessid, field_name, tracker_key="oobtracker"):
|
2013-09-07 15:01:41 +02:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
Shortcut wrapper method for specifically tracking a database field.
|
|
|
|
|
Uses OOBTracker by default (change tracker_key to redirect)
|
|
|
|
|
Will create a tracker with a property name that the field cache
|
2013-09-19 20:41:42 +02:00
|
|
|
expects
|
2013-09-07 15:01:41 +02:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
# all database field names starts with db_*
|
|
|
|
|
field_name = field_name if field_name.startswith("db_") else "db_%s" % field_name
|
|
|
|
|
oob_tracker_name = "_track_%s_change" % field_name # field cache looks for name on this form
|
|
|
|
|
self.track(obj, tracker_key, field_name, sessid, property_name=oob_tracker_name)
|
2013-09-07 15:01:41 +02:00
|
|
|
|
2013-09-14 23:18:36 +02:00
|
|
|
def track_attribute(self, obj, sessid, attr_name, tracker_key="oobtracker"):
|
2013-01-03 09:18:49 +01:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
Shortcut wrapper method for specifically tracking the changes of an
|
|
|
|
|
Attribute on an object. Will create a tracker on the Attribute Object and
|
|
|
|
|
name in a way the Attribute expects.
|
2013-01-03 09:18:49 +01:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
# get the attribute object if we can
|
|
|
|
|
attrobj = _GA(obj, "attributes").get(attr_name, return_obj=True)
|
|
|
|
|
if attrobj:
|
|
|
|
|
oob_tracker_name = "_track_db_value_change"
|
|
|
|
|
self.track(attrobj, tracker_key, attr_name, sessid, property_name=oob_tracker_name)
|
2013-01-03 09:18:49 +01:00
|
|
|
|
2013-09-14 23:18:36 +02:00
|
|
|
def repeat(self, caller, func_key, interval=20, *args, **kwargs):
|
2013-01-03 09:18:49 +01:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
Start a repeating action. Every interval seconds,
|
|
|
|
|
the oobfunc corresponding to func_key is called with
|
|
|
|
|
args and kwargs.
|
2013-01-03 09:18:49 +01:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
if not func_key in _OOB_FUNCS:
|
|
|
|
|
raise KeyError("%s is not a valid OOB function name.")
|
|
|
|
|
store_key = (pack_dbobj(caller), func_key, interval)
|
|
|
|
|
# prepare to store
|
|
|
|
|
self.oob_repeat_storage[store_key] = (caller, func_key, interval, args, kwargs)
|
|
|
|
|
self.oob_tracker_pool.add(store_key, caller, func_key, interval, *args, **kwargs)
|
|
|
|
|
|
|
|
|
|
def unrepeat(self, caller, func_key, interval=20):
|
2013-01-03 09:18:49 +01:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
Stop a repeating action
|
2013-01-03 09:18:49 +01:00
|
|
|
"""
|
2013-09-14 23:18:36 +02:00
|
|
|
store_key = (pack_dbobj(caller), func_key, interval)
|
|
|
|
|
self.oob_tracker_pool.remove(store_key, interval)
|
|
|
|
|
self.oob_repeat_storage.pop(store_key, None)
|
|
|
|
|
|
2013-10-15 20:00:18 +02:00
|
|
|
def msg(self, sessid, funcname, *args, **kwargs):
|
|
|
|
|
"Shortcut to relay oob data back to portal"
|
|
|
|
|
session = self.sessionhandler.session_from_sessid(sessid)
|
|
|
|
|
if session:
|
|
|
|
|
session.msg(oob=(funcname, args, kwargs))
|
2013-09-14 23:18:36 +02:00
|
|
|
|
2013-10-15 20:00:18 +02:00
|
|
|
def execute_cmd(self, session, func_key, *args, **kwargs):
|
|
|
|
|
"""
|
|
|
|
|
Retrieve oobfunc from OOB_FUNCS and execute it immediately
|
|
|
|
|
using *args and **kwargs
|
|
|
|
|
"""
|
|
|
|
|
try:
|
|
|
|
|
oobfunc = _OOB_FUNCS[func_key] # raise traceback if not found
|
|
|
|
|
oobfunc(self, session, *args, **kwargs)
|
|
|
|
|
except KeyError:
|
|
|
|
|
errmsg = "OOB Error: function '%s' not recognized." % func_key
|
|
|
|
|
if _OOB_ERROR:
|
|
|
|
|
_OOB_ERROR(self, session, errmsg, *args, **kwargs)
|
|
|
|
|
else:
|
|
|
|
|
logger.log_trace(errmsg)
|
|
|
|
|
except Exception, err:
|
|
|
|
|
errmsg = "OOB Error: Exception in '%s'(%s, %s):\n%s" % (func_key, args, kwargs, err)
|
|
|
|
|
if _OOB_ERROR:
|
|
|
|
|
_OOB_ERROR(self, session, errmsg, *args, **kwargs)
|
|
|
|
|
else:
|
|
|
|
|
logger.log_trace(errmsg)
|
2013-09-14 23:18:36 +02:00
|
|
|
# access object
|
|
|
|
|
OOB_HANDLER = OOBHandler()
|