+##
+# Call dispatcher
+##
+
+def has_annotation(method, name):
+ """ Check if the method contains the given annoation.
+ """
+ return method.__doc__ and method.__doc__.find("@%s" % name) > -1
+
+def list_call_dispatcher(method, userdesc, perms, vhost, *arg):
+ """Dispatch the call to the right handler.
+ This function checks the options of the called method the set the environment of the call.
+ The dispatcher uses method annotation (special tokens in the documentation of the method) to
+ guess the requested environment:
+ @mlist: the handler requires a mlist object instead of the vhost/listname couple
+ @lock: the handler requires the mlist to be locked (@mlist MUST be specified)
+ @edit: the handler edit the mlist (@mlist MUST be specified)
+ @admin: the handler requires admin rights on the list (@mlist MUST be specified)
+ @root: the handler requires site admin rights
+ """
+ try:
+ print "calling method: %s" % method
+ if has_annotation(method, "root") and perms != "admin":
+ return 0
+ if has_annotation(method, "mlist"):
+ listname = str(arg[0])
+ arg = arg[1:]
+ mlist = MailList.MailList(vhost + VHOST_SEP + listname.lower(), lock=0)
+ if has_annotation(method, "admin") and not is_admin_on(userdesc, perms, mlist):
+ return 0
+ if has_annotation(method, "edit") or has_annotation(method, "lock"):
+ return list_call_locked(method, userdesc, perms, mlist, has_annotation(method, "edit"), *arg)
+ else:
+ return method(userdesc, perms, mlist, *arg)
+ else:
+ return method(userdesc, perms, vhost, *arg)
+ except Exception, e:
+ sys.stderr.write('Exception in dispatcher %s\n' % str(e))
+ raise e
+ return 0
+
+def list_call_locked(method, userdesc, perms, mlist, edit, *arg):
+ """Call the given method after locking the mlist.
+ """
+ try:
+ mlist.Lock()
+ ret = method(userdesc, perms, mlist, *arg)
+ if edit:
+ mlist.Save()
+ mlist.Unlock()
+ return ret
+ except Exception, e:
+ sys.stderr.write('Exception in locked call %s: %s\n' % (method.__name__, str(e)))
+ mlist.Unlock()
+ return 0
+ # TODO: use finally when switching to python 2.5
+