aboutsummaryrefslogtreecommitdiffstats
path: root/tools/python/xen/xend/Args.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/python/xen/xend/Args.py')
-rw-r--r--tools/python/xen/xend/Args.py126
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)