Share more code between restjson and restxml
This commit is contained in:
19
wsme/exc.py
19
wsme/exc.py
@@ -5,7 +5,8 @@ if '_' not in __builtin__.__dict__:
|
|||||||
|
|
||||||
|
|
||||||
class ClientSideError(RuntimeError):
|
class ClientSideError(RuntimeError):
|
||||||
pass
|
def __str__(self):
|
||||||
|
return unicode(self).encode('utf8', 'ignore')
|
||||||
|
|
||||||
|
|
||||||
class InvalidInput(ClientSideError):
|
class InvalidInput(ClientSideError):
|
||||||
@@ -18,9 +19,6 @@ class InvalidInput(ClientSideError):
|
|||||||
return _(u"Invalid input for field/attribute %s. Value: '%s'. %s") % (
|
return _(u"Invalid input for field/attribute %s. Value: '%s'. %s") % (
|
||||||
self.fieldname, self.value, self.msg)
|
self.fieldname, self.value, self.msg)
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return unicode(self).encode('utf8', 'ignore')
|
|
||||||
|
|
||||||
|
|
||||||
class MissingArgument(ClientSideError):
|
class MissingArgument(ClientSideError):
|
||||||
def __init__(self, argname, msg=''):
|
def __init__(self, argname, msg=''):
|
||||||
@@ -31,8 +29,15 @@ class MissingArgument(ClientSideError):
|
|||||||
return _(u'Missing argument: "%s"%s') % (
|
return _(u'Missing argument: "%s"%s') % (
|
||||||
self.argname, self.msg and ": " + self.msg or "")
|
self.argname, self.msg and ": " + self.msg or "")
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return unicode(self).encode('utf8', 'ignore')
|
class UnknownArgument(ClientSideError):
|
||||||
|
def __init__(self, argname, msg=''):
|
||||||
|
self.argname = argname
|
||||||
|
self.msg = msg
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return _(u'Unknown argument: "%s"%s') % (
|
||||||
|
self.argname, self.msg and ": " + self.msg or "")
|
||||||
|
|
||||||
|
|
||||||
class UnknownFunction(ClientSideError):
|
class UnknownFunction(ClientSideError):
|
||||||
@@ -42,5 +47,3 @@ class UnknownFunction(ClientSideError):
|
|||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return _(u"Unknown function name: %s") % (self.name)
|
return _(u"Unknown function name: %s") % (self.name)
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return unicode(self).encode('utf8', 'ignore')
|
|
||||||
|
|||||||
37
wsme/rest.py
37
wsme/rest.py
@@ -1,7 +1,7 @@
|
|||||||
import webob
|
import webob
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from wsme.exc import UnknownFunction
|
from wsme.exc import UnknownFunction, MissingArgument, UnknownArgument
|
||||||
|
|
||||||
html_body = """
|
html_body = """
|
||||||
<html>
|
<html>
|
||||||
@@ -24,6 +24,39 @@ class RestProtocol(object):
|
|||||||
return True
|
return True
|
||||||
return request.headers.get('Content-Type') in self.content_types
|
return request.headers.get('Content-Type') in self.content_types
|
||||||
|
|
||||||
|
def read_arguments(self, request, arguments):
|
||||||
|
if len(request.params) and request.body:
|
||||||
|
raise ClientSideError(
|
||||||
|
"Cannot read parameters from both a body and GET/POST params")
|
||||||
|
|
||||||
|
body = None
|
||||||
|
if 'body' in request.params:
|
||||||
|
body = request.params['body']
|
||||||
|
|
||||||
|
if body is None and len(request.params):
|
||||||
|
parsed_args = {}
|
||||||
|
for key, value in request.params.items():
|
||||||
|
parsed_args[key] = self.parse_arg(value)
|
||||||
|
else:
|
||||||
|
if body is None:
|
||||||
|
body = request.body
|
||||||
|
parsed_args = self.parse_args(body)
|
||||||
|
|
||||||
|
kw = {}
|
||||||
|
|
||||||
|
for arg in arguments:
|
||||||
|
if arg.name not in parsed_args:
|
||||||
|
if arg.mandatory:
|
||||||
|
raise MissingArgument(arg.name)
|
||||||
|
continue
|
||||||
|
|
||||||
|
value = parsed_args.pop(arg.name)
|
||||||
|
kw[arg.name] = self.decode_arg(value, arg)
|
||||||
|
|
||||||
|
if parsed_args:
|
||||||
|
raise UnknownArgument(parsed_args.keys()[0])
|
||||||
|
return kw
|
||||||
|
|
||||||
def handle(self, root, request):
|
def handle(self, root, request):
|
||||||
path = request.path.strip('/').split('/')
|
path = request.path.strip('/').split('/')
|
||||||
|
|
||||||
@@ -34,7 +67,7 @@ class RestProtocol(object):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
func, funcdef = root._lookup_function(path)
|
func, funcdef = root._lookup_function(path)
|
||||||
kw = self.decode_args(request, funcdef.arguments)
|
kw = self.read_arguments(request, funcdef.arguments)
|
||||||
result = func(**kw)
|
result = func(**kw)
|
||||||
# TODO make sure result type == a._wsme_definition.return_type
|
# TODO make sure result type == a._wsme_definition.return_type
|
||||||
res.body = self.encode_result(result, funcdef.return_type)
|
res.body = self.encode_result(result, funcdef.return_type)
|
||||||
|
|||||||
@@ -92,17 +92,15 @@ class RestJsonProtocol(RestProtocol):
|
|||||||
dataformat = 'json'
|
dataformat = 'json'
|
||||||
content_types = ['application/json', 'text/json', '', None]
|
content_types = ['application/json', 'text/json', '', None]
|
||||||
|
|
||||||
def decode_args(self, req, arguments):
|
def decode_arg(self, value, arg):
|
||||||
if not req.body:
|
return fromjson(arg.datatype, value)
|
||||||
return {}
|
|
||||||
raw_args = json.loads(req.body)
|
def parse_arg(self, value):
|
||||||
kw = {}
|
return json.loads(value)
|
||||||
for farg in arguments:
|
|
||||||
if farg.mandatory and farg.name not in raw_args:
|
def parse_args(self, body):
|
||||||
raise MissingArgument(farg.name)
|
raw_args = json.loads(body)
|
||||||
value = raw_args[farg.name]
|
return raw_args
|
||||||
kw[farg.name] = fromjson(farg.datatype, value)
|
|
||||||
return kw
|
|
||||||
|
|
||||||
def encode_result(self, result, return_type):
|
def encode_result(self, result, return_type):
|
||||||
r = tojson(return_type, result)
|
r = tojson(return_type, result)
|
||||||
|
|||||||
@@ -116,26 +116,14 @@ class RestXmlProtocol(RestProtocol):
|
|||||||
dataformat = 'xml'
|
dataformat = 'xml'
|
||||||
content_types = ['text/xml']
|
content_types = ['text/xml']
|
||||||
|
|
||||||
def decode_args(self, req, arguments):
|
def decode_arg(self, value, arg):
|
||||||
if req.body:
|
return fromxml(arg.datatype, value)
|
||||||
try:
|
|
||||||
el = et.fromstring(req.body)
|
|
||||||
except Exception, e:
|
|
||||||
raise ClientSideError(str(e))
|
|
||||||
else:
|
|
||||||
el = et.Element('parameters')
|
|
||||||
|
|
||||||
if el.tag != 'parameters':
|
def parse_arg(self, value):
|
||||||
raise ClientSideError("Input should be a 'parameters' xml tag")
|
return et.fromstring(value)
|
||||||
|
|
||||||
kw = {}
|
def parse_args(self, body):
|
||||||
for farg in arguments:
|
return dict((sub.tag, sub) for sub in et.fromstring(body))
|
||||||
sub = el.find(farg.name)
|
|
||||||
if farg.mandatory and sub is None:
|
|
||||||
raise MissingArgument(farg.name)
|
|
||||||
if sub is not None:
|
|
||||||
kw[farg.name] = fromxml(farg.datatype, sub)
|
|
||||||
return kw
|
|
||||||
|
|
||||||
def encode_result(self, result, return_type):
|
def encode_result(self, result, return_type):
|
||||||
return et.tostring(toxml(return_type, 'result', result))
|
return et.tostring(toxml(return_type, 'result', result))
|
||||||
|
|||||||
Reference in New Issue
Block a user