Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/services/console/lib/purk/events.py
diff options
context:
space:
mode:
Diffstat (limited to 'services/console/lib/purk/events.py')
-rw-r--r--services/console/lib/purk/events.py298
1 files changed, 298 insertions, 0 deletions
diff --git a/services/console/lib/purk/events.py b/services/console/lib/purk/events.py
new file mode 100644
index 0000000..2a0d45e
--- /dev/null
+++ b/services/console/lib/purk/events.py
@@ -0,0 +1,298 @@
+import sys
+import os
+import traceback
+
+pyending = os.extsep + 'py'
+
+class error(Exception):
+ pass
+
+class EventStopError(error):
+ pass
+
+class CommandError(error):
+ pass
+
+class data(object):
+ done = False
+ quiet = False
+
+ def __init__(self, **kwargs):
+ for attr in kwargs.items():
+ setattr(self, *attr)
+
+trigger_sequence = ("pre", "setup", "on", "setdown", "post")
+
+all_events = {}
+loaded = {}
+
+# An event has occurred, the e_name event!
+def trigger(e_name, e_data=None, **kwargs):
+ if e_data is None:
+ e_data = data(**kwargs)
+
+ #print 'Event:', e_name, e_data
+
+ failure = True
+ error = None
+
+ if e_name in all_events:
+ for e_stage in trigger_sequence:
+ if e_stage in all_events[e_name]:
+ for f_ref, s_name in all_events[e_name][e_stage]:
+ try:
+ f_ref(e_data)
+ except EventStopError:
+ return
+ except CommandError, e:
+ error = e.args
+ continue
+ except:
+ traceback.print_exc()
+ failure = False
+ if failure:
+ print "Error handling: " + e_name
+
+ return error
+
+# Stop all processing of the current event now!
+def halt():
+ raise EventStopError
+
+# Registers a specific function with an event at the given sequence stage.
+def register(e_name, e_stage, f_ref, s_name=""):
+ global all_events
+
+ if e_name not in all_events:
+ all_events[e_name] = {}
+
+ if e_stage not in all_events[e_name]:
+ all_events[e_name][e_stage] = []
+
+ all_events[e_name][e_stage] += [(f_ref, s_name)]
+
+# turn a filename (or module name) and trim it to the name of the module
+def get_scriptname(name):
+ s_name = os.path.basename(name)
+ if s_name.endswith(pyending):
+ s_name = s_name[:-len(pyending)]
+ return s_name
+
+#take a given script name and turn it into a filename
+def get_filename(name):
+ # split the directory and filename
+ dirname = os.path.dirname(name)
+ s_name = get_scriptname(name)
+
+ for path in dirname and (dirname,) or sys.path:
+ filename = os.path.join(path, s_name + pyending)
+ if os.access(filename, os.R_OK):
+ return filename
+
+ raise ImportError("No urk script %s found" % name)
+
+# register the events defined by obj
+def register_all(name, obj):
+ # we look through everything defined in the file
+ for f in dir(obj):
+ # for each bit of the event sequence
+ for e_stage in trigger_sequence:
+
+ # if the function is for this bit
+ if f.startswith(e_stage):
+ # get a reference to a function
+ f_ref = getattr(obj, f)
+ #print f
+ # normalise to the event name
+ e_name = f.replace(e_stage, "", 1)
+
+ # add our function to the right event section
+ register(e_name, e_stage, f_ref, name)
+
+ break
+
+#load a .py file into a new module object without affecting sys.modules
+def load_pyfile(filename):
+ s_name = get_scriptname(filename)
+ return __import__(s_name)
+
+# Load a python script and register
+# the functions defined in it for events.
+# Return True if we loaded the script, False if it was already loaded
+def load(name):
+ s_name = get_scriptname(name)
+ filename = get_filename(name)
+
+ if s_name in loaded:
+ return False
+
+ loaded[s_name] = None
+
+ try:
+ module = load_pyfile(filename)
+ loaded[s_name] = module
+ except:
+ del loaded[s_name]
+ raise
+
+ register_all(s_name, loaded[s_name])
+
+ return module
+
+# Is the script with the given name loaded?
+def is_loaded(name):
+ return get_scriptname(name) in loaded
+
+# Remove any function which was defined in the given script
+def unload(name):
+ s_name = get_scriptname(name)
+
+ del loaded[s_name]
+
+ for e_name in list(all_events):
+ for e_stage in list(all_events[e_name]):
+ to_check = all_events[e_name][e_stage]
+
+ all_events[e_name][e_stage] = [(f, m) for f, m in to_check if m != s_name]
+
+ if not all_events[e_name][e_stage]:
+ del all_events[e_name][e_stage]
+
+ if not all_events[e_name]:
+ del all_events[e_name]
+
+def reload(name):
+ s_name = get_scriptname(name)
+
+ if s_name not in loaded:
+ return False
+
+ temp = loaded[s_name]
+
+ unload(s_name)
+
+ try:
+ load(name)
+ return True
+ except:
+ loaded[s_name] = temp
+ register_all(s_name, temp)
+ raise
+
+def run(text, window, network):
+ split = text.split(' ')
+
+ c_data = data(name=split.pop(0), text=text, window=window, network=network)
+
+ if split and split[0].startswith('-'):
+ c_data.switches = set(split.pop(0)[1:])
+ else:
+ c_data.switches = set()
+
+ c_data.args = split
+
+ event_name = "Command" + c_data.name.capitalize()
+ #print "searching: " + event_name
+ #for s in all_events:
+ # print "match: " + s
+ # if s == event_name:
+ # print "we got it!"
+
+ if event_name in all_events:
+ result = trigger(event_name, c_data)
+
+ if result:
+ print "* /%s: %s" % (c_data.name, result[0])
+ c_data.window.write("* /%s: %s" % (c_data.name, result[0]))
+ else:
+ trigger("Command", c_data)
+
+ if not c_data.done:
+ c_data.window.write("* /%s: No such command exists" % (c_data.name))
+
+def onCommandPyeval(e):
+ loc = sys.modules.copy()
+ loc.update(e.__dict__)
+ import pydoc #fix nonresponsive help() command
+ old_pager, pydoc.pager = pydoc.pager, pydoc.plainpager
+ try:
+ result = repr(eval(' '.join(e.args), loc))
+ if 's' in e.switches:
+ run(
+ 'say - %s => %s' % (' '.join(e.args),result),
+ e.window,
+ e.network
+ )
+ else:
+ e.window.write(result)
+ except:
+ for line in traceback.format_exc().split('\n'):
+ e.window.write(line)
+ pydoc.pager = old_pager
+
+def onCommandPyexec(e):
+ loc = sys.modules.copy()
+ loc.update(e.__dict__)
+ import pydoc #fix nonresponsive help() command
+ old_pager, pydoc.pager = pydoc.pager, pydoc.plainpager
+ try:
+ exec ' '.join(e.args) in loc
+ except:
+ for line in traceback.format_exc().split('\n'):
+ e.window.write(line)
+ pydoc.pager = old_pager
+
+def onCommandLoad(e):
+ if e.args:
+ name = e.args[0]
+ else:
+ e.window.write('Usage: /load scriptname')
+
+ try:
+ if load(name):
+ e.window.write("* The script '%s' has been loaded." % name)
+ else:
+ raise CommandError("The script is already loaded; use /reload instead")
+ except:
+ e.window.write(traceback.format_exc(), line_ending='')
+ raise CommandError("Error loading the script")
+
+def onCommandUnload(e):
+ if e.args:
+ name = e.args[0]
+ else:
+ e.window.write('Usage: /unload scriptname')
+
+ if is_loaded(name):
+ unload(name)
+ e.window.write("* The script '%s' has been unloaded." % name)
+ else:
+ raise CommandError("No such script is loaded")
+
+def onCommandReload(e):
+ if e.args:
+ name = e.args[0]
+ else:
+ e.window.write('Usage: /reload scriptname')
+
+ try:
+ if reload(name):
+ e.window.write("* The script '%s' has been reloaded." % name)
+ else:
+ raise CommandError("The script isn't loaded yet; use /load instead")
+ except:
+ e.window.write(traceback.format_exc(), line_ending='')
+
+def onCommandScripts(e):
+ e.window.write("Loaded scripts:")
+ for name in loaded:
+ e.window.write("* %s" % name)
+
+def onCommandEcho(e):
+ e.window.write(' '.join(e.args))
+
+name = ''
+for name in globals():
+ if name.startswith('onCommand'):
+ register(name[2:], "on", globals()[name], '_all_events')
+del name