diff --git a/wsme/rest/json.py b/wsme/rest/json.py index 898c5a0..5aa0ed5 100644 --- a/wsme/rest/json.py +++ b/wsme/rest/json.py @@ -11,6 +11,7 @@ from simplegeneric import generic from wsme.types import Unset import wsme.types +from wsme.exc import UnknownArgument try: import simplejson as json @@ -191,68 +192,6 @@ def datetime_fromjson(datatype, value): return datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S') -class RestJson(object): - """ - REST+Json protocol. - - .. autoattribute:: name - .. autoattribute:: dataformat - .. autoattribute:: content_types - """ - - name = 'json' - content_type = 'application/json' - - #def __init__(self, nest_result=False): - # super(RestJsonProtocol, self).__init__() - # self.nest_result = nest_result - - def decode_arg(self, value, arg): - return fromjson(arg.datatype, value) - - def parse_arg(self, name, value): - return json.loads(value) - - def parse_args(self, body): - raw_args = json.loads(body) - return raw_args - - def encode_result(self, context, result): - r = tojson(context.funcdef.return_type, result) - if self.nest_result: - r = {'result': r} - return json.dumps(r) - - def encode_sample_value(self, datatype, value, format=False): - r = tojson(datatype, value) - content = json.dumps(r, ensure_ascii=False, - indent=4 if format else 0, - sort_keys=format) - return ('javascript', content) - - def encode_sample_params(self, params, format=False): - kw = {} - for name, datatype, value in params: - kw[name] = tojson(datatype, value) - content = json.dumps(kw, ensure_ascii=False, - indent=4 if format else 0, - sort_keys=format) - return ('javascript', content) - - def encode_sample_result(self, datatype, value, format=False): - r = tojson(datatype, value) - if self.nest_result: - r = {'result': r} - content = json.dumps(r, ensure_ascii=False, - indent=4 if format else 0, - sort_keys=format) - return ('javascript', content) - - -def get_format(): - return RestJson() - - def parse(s, datatypes, bodyarg): if hasattr(s, 'read'): jdata = json.load(s) @@ -263,18 +202,47 @@ def parse(s, datatypes, bodyarg): kw = {argname: fromjson(datatypes[argname], jdata)} else: kw = {} - for key, datatype in datatypes.items(): - if key in jdata: - kw[key] = fromjson(datatype, jdata[key]) + for key in jdata: + if key not in datatypes: + raise UnknownArgument(key) + kw[key] = fromjson(datatypes[key], jdata[key]) return kw -def tostring(value, datatype, attrname=None): +def encode_result(value, datatype, **options): jsondata = tojson(datatype, value) - if attrname is not None: - jsondata = {attrname: jsondata} - return json.dumps(tojson(datatype, value)) + if options.get('nest_result', False): + jsondata = {options.get('nested_result_attrname', 'result'): jsondata} + return json.dumps(jsondata) def encode_error(context, errordetail): return json.dumps(errordetail) + + +def encode_sample_value(datatype, value, format=False): + r = tojson(datatype, value) + content = json.dumps(r, ensure_ascii=False, + indent=4 if format else 0, + sort_keys=format) + return ('javascript', content) + + +def encode_sample_params(params, format=False): + kw = {} + for name, datatype, value in params: + kw[name] = tojson(datatype, value) + content = json.dumps(kw, ensure_ascii=False, + indent=4 if format else 0, + sort_keys=format) + return ('javascript', content) + + +def encode_sample_result(datatype, value, format=False): + r = tojson(datatype, value) + #if self.nest_result: + #r = {'result': r} + content = json.dumps(r, ensure_ascii=False, + indent=4 if format else 0, + sort_keys=format) + return ('javascript', content) diff --git a/wsme/rest/protocol.py b/wsme/rest/protocol.py index 2fe6c39..769dda9 100644 --- a/wsme/rest/protocol.py +++ b/wsme/rest/protocol.py @@ -60,6 +60,9 @@ class RestProtocol(Protocol): outformat = df context.outformat = outformat + context.outformat_options = { + 'nest_result': getattr(self, 'nest_result', False) + } yield context def extract_path(self, context): @@ -150,8 +153,9 @@ class RestProtocol(Protocol): return kw def encode_result(self, context, result): - out = context.outformat.tostring( - result, context.funcdef.return_type + out = context.outformat.encode_result( + result, context.funcdef.return_type, + **context.outformat_options ) return out diff --git a/wsme/rest/xml.py b/wsme/rest/xml.py index 00aa6f2..90f156d 100644 --- a/wsme/rest/xml.py +++ b/wsme/rest/xml.py @@ -224,73 +224,6 @@ def datetime_fromxml(datatype, element): return datetime.datetime.strptime(element.text, '%Y-%m-%dT%H:%M:%S') -class RestXmlProtocol(RestProtocol): - """ - REST+XML protocol. - - .. autoattribute:: name - .. autoattribute:: dataformat - .. autoattribute:: content_types - """ - name = 'restxml' - displayname = 'REST+Xml' - dataformat = 'xml' - content_types = ['text/xml'] - - def decode_arg(self, value, arg): - return fromxml(arg.datatype, value) - - def parse_arg(self, name, value): - return et.fromstring(u("<%s>%s") % (name, value, name)) - - def parse_args(self, body): - return dict((sub.tag, sub) for sub in et.fromstring(body)) - - def encode_result(self, context, result): - return et.tostring( - toxml(context.funcdef.return_type, 'result', result)) - - -class RestXml(object): - name = 'xml' - content_type = 'text/xml' - - def encode_error(self, context, errordetail): - el = et.Element('error') - et.SubElement(el, 'faultcode').text = errordetail['faultcode'] - et.SubElement(el, 'faultstring').text = errordetail['faultstring'] - if 'debuginfo' in errordetail: - et.SubElement(el, 'debuginfo').text = errordetail['debuginfo'] - return et.tostring(el) - - def encode_sample_value(self, datatype, value, format=False): - r = toxml(datatype, 'value', value) - if format: - xml_indent(r) - content = et.tostring(r) - return ('xml', content) - - def encode_sample_params(self, params, format=False): - node = et.Element('parameters') - for name, datatype, value in params: - node.append(toxml(datatype, name, value)) - if format: - xml_indent(node) - content = et.tostring(node) - return ('xml', content) - - def encode_sample_result(self, datatype, value, format=False): - r = toxml(datatype, 'result', value) - if format: - xml_indent(r) - content = et.tostring(r) - return ('xml', content) - - -def get_format(): - return RestXml() - - def parse(s, datatypes, bodyarg): if hasattr(s, 'read'): tree = et.parse(s) @@ -308,8 +241,10 @@ def parse(s, datatypes, bodyarg): return kw -def tostring(value, datatype, attrname='result'): - return et.tostring(toxml(datatype, attrname, value)) +def encode_result(value, datatype, **options): + return et.tostring(toxml( + datatype, options.get('nested_result_attrname', 'result'), value + )) def encode_error(context, errordetail): @@ -319,3 +254,29 @@ def encode_error(context, errordetail): if 'debuginfo' in errordetail: et.SubElement(el, 'debuginfo').text = errordetail['debuginfo'] return et.tostring(el) + + +def encode_sample_value(datatype, value, format=False): + r = toxml(datatype, 'value', value) + if format: + xml_indent(r) + content = et.tostring(r) + return ('xml', content) + + +def encode_sample_params(params, format=False): + node = et.Element('parameters') + for name, datatype, value in params: + node.append(toxml(datatype, name, value)) + if format: + xml_indent(node) + content = et.tostring(node) + return ('xml', content) + + +def encode_sample_result(datatype, value, format=False): + r = toxml(datatype, 'result', value) + if format: + xml_indent(r) + content = et.tostring(r) + return ('xml', content) diff --git a/wsme/tests/test_restjson.py b/wsme/tests/test_restjson.py index b18bf41..90d7712 100644 --- a/wsme/tests/test_restjson.py +++ b/wsme/tests/test_restjson.py @@ -263,9 +263,6 @@ class TestRestJson(wsme.tests.protocol.ProtocolTestCase): [int], {int: int}): assert fromjson(dt, None) is None - def test_parse_arg(self): - assert self.root.protocols[0].parse_arg('a', '5') == 5 - def test_nest_result(self): self.root.protocols[0].nest_result = True r = self.app.get('/returntypes/getint.json') @@ -283,7 +280,7 @@ class TestRestJson(wsme.tests.protocol.ProtocolTestCase): v.aint = 4 v.astr = 's' - r = self.root.protocols[0].encode_sample_value(MyType, v, True) + r = wsme.rest.json.encode_sample_value(MyType, v, True) print(r) assert r[0] == ('javascript') assert r[1] == json.dumps({'aint': 4, 'astr': 's'}, @@ -294,7 +291,7 @@ class TestRestJson(wsme.tests.protocol.ProtocolTestCase): assert tojson(wsme.types.bytes, b('ascii')) == u('ascii') def test_encode_sample_params(self): - r = self.root.protocols[0].encode_sample_params( + r = wsme.rest.json.encode_sample_params( [('a', int, 2)], True ) assert r[0] == 'javascript', r[0] @@ -303,19 +300,19 @@ class TestRestJson(wsme.tests.protocol.ProtocolTestCase): }''', r[1] def test_encode_sample_result(self): - r = self.root.protocols[0].encode_sample_result( + r = wsme.rest.json.encode_sample_result( int, 2, True ) assert r[0] == 'javascript', r[0] assert r[1] == '''2''' - self.root.protocols[0].nest_result = True - r = self.root.protocols[0].encode_sample_result( - int, 2, True - ) - assert r[0] == 'javascript', r[0] - assert r[1] == '''{ - "result": 2 -}''' + #self.root.protocols[0].nest_result = True + #r = wsme.rest.json.encode_sample_result( + #int, 2, True + #) + #assert r[0] == 'javascript', r[0] + #assert r[1] == '''{ + #"result": 2 +#}''' def test_PUT(self): data = {"id": 1, "name": u("test")} diff --git a/wsme/tests/test_restxml.py b/wsme/tests/test_restxml.py index 8af8150..982df7f 100644 --- a/wsme/tests/test_restxml.py +++ b/wsme/tests/test_restxml.py @@ -139,7 +139,7 @@ class TestRestXML(wsme.tests.protocol.ProtocolTestCase): value.aint = 5 value.atext = u('test') - language, sample = self.root.protocols[0].encode_sample_value( + language, sample = wsme.rest.xml.encode_sample_value( MyType, value, True) print (language, sample) @@ -150,13 +150,13 @@ class TestRestXML(wsme.tests.protocol.ProtocolTestCase): """) def test_encode_sample_params(self): - lang, content = self.root.protocols[0].encode_sample_params( + lang, content = wsme.rest.xml.encode_sample_params( [('a', int, 2)], True) assert lang == 'xml', lang assert content == b('\n 2\n'), content def test_encode_sample_result(self): - lang, content = self.root.protocols[0].encode_sample_result(int, 2, True) + lang, content = wsme.rest.xml.encode_sample_result(int, 2, True) assert lang == 'xml', lang assert content == b('2'), content @@ -183,8 +183,3 @@ class TestRestXML(wsme.tests.protocol.ProtocolTestCase): x = et.tostring(toxml(AType, 'value', AType())) assert x == b(''), x - - def test_parse_arg(self): - e = self.root.protocols[0].parse_arg('value', '5') - assert e.text == '5' - assert e.tag == 'value'