[Soap-Python] rpclib -> spyne: multiple MethodDescriptor to a single proxy function

C Anthony Risinger anthony.risinger at corvisa.com
Mon Jun 25 19:29:08 CEST 2012


hello,

while briefly trying to update to the spyne codebase, i am encountering 
an AssertionError due to spyne enforcing a 1-to-1 mapping between 
MethodDescriptor and the function it wraps:

   File "/path/to/spyne/interface/_base.py", line 224, in populate_interface
     assert not s.get_method_id(method) in self.method_id_map
AssertionError

... the problem is that i am currently building the MethodDescriptors 
dynamically, and mapping to a single _proxy function; this SOAP service 
is really proxying/exposing another JSON service (no JSON support in 
rpclib/spyne during development).

service definition (disregard custom json functions, unrelated):

-----------------------------------------------
from rpclib import MethodDescriptor
from rpclib.interface.wsdl import Wsdl11
from rpclib.service import ServiceBase
from requests import request
import json

from awesome import models


API_VERISION_JSON = 1
API_VERISION_SOAP = 1


METHODS = [('method_one', 'put', 'some method two'),
            ('method_two', 'post', 'some method two')]


def _bind(udp):
     m, verb, doc = udp
     def f(*args, **kwds):
         name = kwds['_default_function_name']
         in_message = getattr(models, m)
         out_message = getattr(models, m+'Response', None)
         if out_message is None:
             out_message = getattr(models, m+'_response')
         desc = MethodDescriptor(function=_proxy,
                                 in_message=in_message,
                                 out_message=out_message,
                                 doc=doc,
                                 is_callback=False,
                                 is_async=False,
                                 mtom=False,
                                 in_header=None,
                                 out_header=None,
                                 faults=None,
                                 port_type=None,
                                 no_ctx=False,
                                 udp=udp,
                                 class_key=name)
         return desc
     f.__doc__ = doc
     f._is_rpc = True
     return f


def _proxy(ctx, req):
     res = None
     ret = None
     method, verb, doc = ctx.descriptor.udp
     host = 'http://%(SERVER_NAME)s:%(SERVER_PORT)s' % \
         ctx.transport.req_env
     endpoint = '%s/api/v%s/%s/' % (host, API_VERISION_JSON, method)
     headers = {'content-type': 'application/json'}
     try:
         res = request(verb, endpoint, headers=headers,
                       data=json.dumps(req.json(req)))
         res_json = json.loads(res.text)
     except Exception, e:
         import traceback
         if res:
             print res.text
         traceback.print_exc()
         raise e
     out_message = ctx.descriptor.out_message
     if len(out_message._type_info) == 1:
         out_message = out_message._type_info[0]
     return out_message.json(res_json)


MyService = type('MyService', (ServiceBase,),
     dict([(udp[0], _bind(udp)) for udp in METHODS]))
-----------------------------------------------

... thats's the complete -- working -- service definition, with only the 
method list truncated and some names changed to protect the innocent. in 
short: i store the method name, HTTP verb, and __doc__ in udp, then use 
that and the transport context to rebuild the real request.

i haven't spent much time investigating, but why is this restriction 
necessary?  the solution ATM means needlessly wrapping _proxy for each 
method with a module level function, since lambdas probably wouldn't 
work either (albeit, i didn't try :-)

how can i solve this cleanly, or better, patch spyne to not care what 
callable actually implements the method (since the pattern was working 
rather nicely)?

thanks!

-- 

C Anthony


-----------------------------------------
CONFIDENTIALITY: The information contained in this communication may be confidential and is intended only for the use of the intended recipient(s). If the reader of this message is not the intended recipient(s), you are hereby notified that
any dissemination, distribution, or copying of this communication, or any of its contents, is strictly prohibited. If you have received this communication in error, please return it to the sender immediately and delete any copy of it from your computer system.


More information about the Soap mailing list