Permalink
Browse files

Implement MessagePackRpc.

  • Loading branch information...
1 parent 468a705 commit eeb5d9328ab4d92e672bbd2cfe11a6ce3c449e09 @plq committed Aug 6, 2012
Showing with 99 additions and 23 deletions.
  1. +26 −21 spyne/protocol/msgpack/__init__.py
  2. +73 −2 spyne/test/protocol/test_msgpack.py
View
47 spyne/protocol/msgpack/__init__.py
@@ -60,14 +60,14 @@ def create_out_string(self, ctx, out_string_encoding='utf8'):
ctx.out_string = (msgpack.packb(o) for o in ctx.out_document)
-class MessagePackRpc(ProtocolBase):
+class MessagePackRpc(MessagePackObject):
"""An integration class for the msgpack-rpc protocol."""
mime_type = 'application/x-msgpack'
- REQUEST = 0
- RESPONSE = 1
- NOTIFY = 2
+ MSGPACK_REQUEST = 0
+ MSGPACK_RESPONSE = 1
+ MSGPACK_NOTIFY = 2
def create_in_document(self, ctx, in_string_encoding=None):
"""Sets ``ctx.in_document``, using ``ctx.in_string``.
@@ -76,37 +76,37 @@ def create_in_document(self, ctx, in_string_encoding=None):
argument is ignored.
"""
+ # TODO: Use feed api
ctx.in_document = msgpack.unpackb(''.join(ctx.in_string))
try:
- len(self.in_document)
+ len(ctx.in_document)
except TypeError:
raise MessagePackDecodeError("Input must be an itearble.")
- # FIXME: Msgid is ignored. Is this a problem?
- if not len(ctx.in_document in (3,4)):
+ if not (3 <= len(ctx.in_document) <= 4):
raise MessagePackDecodeError("Length of input iterable must be "
"either 3 or 4")
def decompose_incoming_envelope(self, ctx, message):
# FIXME: For example: {0: 0, 1: 0, 2: "some_call", 3: [1,2,3]} will also
# work. Is this a problem?
+
+ # FIXME: Msgid is ignored. Is this a problem?
msgparams = []
- if len(self.in_document) == 3:
- msgtype, msgid, msgname = self.message
+ if len(ctx.in_document) == 3:
+ msgtype, msgid, msgname = ctx.in_document
- elif len(self.in_document) == 4:
- msgtype, msgid, msgname, msgparams = self.message
+ elif len(ctx.in_document) == 4:
+ msgtype, msgid, msgname, msgparams = ctx.in_document
- if msgtype == MessagePackRpc.REQUEST:
+ if msgtype == MessagePackRpc.MSGPACK_REQUEST:
assert message == DictObject.REQUEST
- self.on_request(message[1], message[2], message[3])
- elif msgtype == MessagePackRpc.RESPONSE:
+ elif msgtype == MessagePackRpc.MSGPACK_RESPONSE:
assert message == DictObject.RESPONSE
- self.on_response(message[1], message[2], message[3])
- elif msgtype == MessagePackRpc.NOTIFY:
+ elif msgtype == MessagePackRpc.MSGPACK_NOTIFY:
raise NotImplementedError()
else:
@@ -115,7 +115,7 @@ def decompose_incoming_envelope(self, ctx, message):
ctx.method_request_string = '{%s}%s' % (self.app.interface.get_tns(),
msgname)
- ctx.in_header_doc = None # MsgPackRpc does not seem to have Header support
+ ctx.in_header_doc = None # MessagePackRpc does not seem to have Header support
ctx.in_body_doc = msgparams
logger.debug('\theader : %r' % (ctx.in_header_doc))
@@ -137,7 +137,7 @@ def deserialize(self, ctx, message):
body_class = ctx.descriptor.out_message
if body_class:
- ctx.in_object = body_class.get_serialization_instance(self.in_body_doc)
+ ctx.in_object = body_class.get_serialization_instance(ctx.in_body_doc)
else:
ctx.in_object = []
@@ -150,7 +150,8 @@ def serialize(self, ctx, message):
self.event_manager.fire_event('before_serialize', ctx)
if ctx.out_error is not None:
- ctx.out_document = [ctx.out_error._to_dict(ctx.out_error)]
+ ctx.out_document = [MessagePackObject.RESPONSE, 0,
+ ctx.out_error.to_dict(ctx.out_error)]
else:
# get the result message
@@ -178,9 +179,13 @@ def serialize(self, ctx, message):
# transform the results into a dict:
if out_type.Attributes.max_occurs > 1:
- ctx.out_document = (self._to_value(out_type, inst, wrapper_name)
+ ctx.out_document = [[MessagePackRpc.MSGPACK_RESPONSE, 0, None,
+ (self._to_value(out_type, inst, wrapper_name)
for inst in out_instance)
+ ]]
else:
- ctx.out_document = [self._to_value(out_type, out_instance, wrapper_name)]
+ ctx.out_document = [[MessagePackRpc.MSGPACK_RESPONSE, 0, None,
+ self._to_value(out_type, out_instance, wrapper_name)
+ ]]
self.event_manager.fire_event('after_serialize', ctx)
View
75 spyne/test/protocol/test_msgpack.py
@@ -20,10 +20,81 @@
import msgpack
import unittest
-from spyne.test.protocol._test_dictobj import TDictObjectTest
+from StringIO import StringIO
+
+from spyne.application import Application
+from spyne.decorator import rpc
+from spyne.service import ServiceBase
+from spyne.model.complex import Array
+from spyne.model.primitive import String
+from spyne.model.complex import ComplexModel
+from spyne.model.primitive import Unicode
from spyne.protocol.msgpack import MessagePackObject
+from spyne.protocol.msgpack import MessagePackRpc
+from spyne.server.wsgi import WsgiApplication
+from spyne.server.wsgi import WsgiMethodContext
+from spyne.test.protocol._test_dictobj import TDictObjectTest
+
+TestMessagePackObject = TDictObjectTest(msgpack, MessagePackObject,
+ "Client.MessagePackDecodeError")
+from spyne.test.test_service import start_response
+
+class TestMessagePackRpc(unittest.TestCase):
+ def test_rpc(self):
+ data = {"a":"b", "c": "d"}
+
+
+ class KeyValuePair(ComplexModel):
+ key = Unicode
+ value = Unicode
+
+ class Service(ServiceBase):
+ @rpc(String(max_occurs='unbounded'),
+ _returns=Array(KeyValuePair),
+ _in_variable_names={
+ 'keys': 'key'
+ }
+ )
+ def get_values(ctx, keys):
+ for k in keys:
+ yield KeyValuePair(key=k, value=data[k])
+
+ application = Application([Service],
+ in_protocol=MessagePackRpc(),
+ out_protocol=MessagePackRpc(),
+ name='Service', tns='tns'
+ )
+ server = WsgiApplication(application)
+
+ input_string = msgpack.packb([0,0,"get_values", [["a","c"]] ])
+ input_stream = StringIO(input_string)
+
+ ret = server({
+ 'CONTENT_LENGTH': str(len(input_string)),
+ 'CONTENT_TYPE': 'application/x-msgpack',
+ 'HTTP_CONNECTION': 'close',
+ 'HTTP_CONTENT_LENGTH': str(len(input_string)),
+ 'HTTP_CONTENT_TYPE': 'application/x-msgpack',
+ 'PATH_INFO': '/',
+ 'QUERY_STRING': '',
+ 'SERVER_NAME': 'localhost',
+ 'SERVER_PORT': '7000',
+ 'REQUEST_METHOD': 'POST',
+ 'wsgi.url_scheme': 'http',
+ 'wsgi.input': input_stream,
+ }, start_response)
-TestMessagePackObject = TDictObjectTest(msgpack, MessagePackObject, "Client.MessagePackDecodeError" )
+ ret = ''.join(ret)
+ print repr(ret)
+ print msgpack.unpackb(ret)
+ assert ret == msgpack.packb([1, 0, None, {'get_valuesResponse': {
+ 'get_valuesResult': {
+ 'KeyValuePair': [
+ {'value': 'b', 'key': 'a'},
+ {'value': 'd', 'key': 'c'}
+ ]
+ }}}
+ ])
if __name__ == '__main__':
unittest.main()

0 comments on commit eeb5d93

Please sign in to comment.