diff options
Diffstat (limited to 'tools/python/xen/xend/Args.py')
-rw-r--r-- | tools/python/xen/xend/Args.py | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/tools/python/xen/xend/Args.py b/tools/python/xen/xend/Args.py new file mode 100644 index 0000000000..527e841d3d --- /dev/null +++ b/tools/python/xen/xend/Args.py @@ -0,0 +1,126 @@ +import sxp + +class ArgError(StandardError): + pass + +class Args: + """Argument encoding support for HTTP. + """ + + def __init__(self, paramspec, keyspec): + self.arg_ord = [] + self.arg_dict = {} + self.key_ord = [] + self.key_dict = {} + for (name, type) in paramspec: + self.arg_ord.append(name) + self.arg_dict[name] = type + for (name, type) in keyspec: + self.key_ord.append(name) + self.key_dict[name] = type + + def get_args(self, d, xargs=None): + args = {} + keys = {} + params = [] + if xargs: + self.split_args(xargs, args, keys) + self.split_args(d, args, keys) + for a in self.arg_ord: + if a in args: + params.append(args[a]) + else: + raise ArgError('Missing parameter: %s' % a) + return (params, keys) + + def split_args(self, d, args, keys): + for (k, v) in d.items(): + if k in self.arg_dict: + type = self.arg_dict[k] + val = self.coerce(type, v) + args[k] = val + elif k in self.key_dict: + type = self.key_dict[k] + val = self.coerce(type, v) + keys[k] = val + else: + raise ArgError('Invalid parameter: %s' % k) + + def get_form_args(self, f, xargs=None): + d = {} + for (k, v) in f.items(): + n = len(v) + if ((k not in self.arg_dict) and + (k not in self.key_dict)): + continue + if n == 0: + continue + elif n == 1: + d[k] = v[0] + else: + raise ArgError('Too many values for %s' % k) + return self.get_args(d, xargs=xargs) + + def coerce(self, type, v): + try: + if type == 'int': + return int(v) + if type == 'str': + return str(v) + if type == 'sxpr': + return self.sxpr(v) + except ArgError: + raise + except StandardError, ex: + raise ArgError(str(ex)) + + def sxpr(self, v): + if instanceof(v, types.ListType): + return v + if instanceof(v, types.File) or hasattr(v, 'readline'): + return sxpr_file(v) + if instanceof(v, types.StringType): + return sxpr_file(StringIO(v)) + return str(v) + + def sxpr_file(self, fin): + try: + vals = sxp.parse(fin) + except: + raise ArgError('Coercion to sxpr failed') + if len(vals) == 1: + return vals[0] + else: + raise ArgError('Too many sxprs') + + def call_with_args(self, fn, args, xargs=None): + (params, keys) = self.get_args(args, xargs=xargs) + fn(*params, **keys) + + def call_with_form_args(self, fn, fargs, xargs=None): + (params, keys) = self.get_form_args(fargs, xargs=xargs) + fn(*params, **keys) + +class ArgFn(Args): + """Represent a remote HTTP operation as a function. + Used on the client. + """ + + def __init__(self, fn, paramspec, keyspec={}): + Args.__init__(self, paramspec, keyspec) + self.fn = fn + + def __call__(self, fargs, xargs=None): + return self.call_with_args(self.fn, fargs, xargs=xargs) + +class FormFn(Args): + """Represent an operation as a function over a form. + Used in the HTTP server. + """ + + def __init__(self, fn, paramspec, keyspec={}): + Args.__init__(self, paramspec, keyspec) + self.fn = fn + + def __call__(self, fargs, xargs=None): + return self.call_with_form_args(self.fn, fargs, xargs=xargs) |