[spyne] Factory with deepcopy?

Roberto Maurizzi roberto.maurizzi at gmail.com
Wed Oct 1 10:51:17 UTC 2014


Hello people,

I'm exposing some services as both SOAP and json.
I've read the docs on this and I know I can't 'reuse' the same MyService
class in 2 applications. The recommended way is to create a generator
function that then returns a copy of the class contained in it.

For a very stupid reason :-) (I don't get Sphinx autodocs for the method of
the Service defined inside the generator function, and yes, it should be
fixable in Sphinx config) I wondered if it was possible to use a different
approach to do this, to get a generic 'spyne service factory'.
I first tried to subclass the ServiceBase-derived class and it didn't work
(Metaclass is lost, I'd guess, but for these think I need to improve my
Python knowledge ^^; )

I ended up trying to deepcopy the class with something like this (that also
adds an optional header used for authentication - in a poor adn non-generic
way, right now - and allows you to specify a different service name for the
"clones".


def SpyneServiceFactory(serviceClass, with_headers=False,
service_name=None):
    """
    Factory for spyne's ServiceBase classes, required by Spyne to be able
to use the same service definition from
    two or more different web services Applications at the same time.

    :param dec[6] serviceClass:   a ServiceBase subclass implementing web
service calls
    :param str[2] with_headers:   if True, the class will expect a
RequestHeader with
                                  username and password in the header of
every call (makes sense for SOAP only)
    :returns:                     a deepcopy of the input serviceClass

    """

    import copy

    ClonedServiceProvider = copy.deepcopy(serviceClass)
    if with_headers:
        ClonedServiceProvider.__in_header__ = RequestHeader

    if service_name:
        ClonedServiceProvider.__service_name__ = service_name

    def _on_method_call(ctx):
        if ctx.in_header is None:
            log.info("{0} - unauthenticated
call".format(serviceClass.__name__))
            return
        log.info("{0} - auth requested for
{1}/{2}".format(serviceClass.__name__, ctx.in_header.username,
ctx.in_header.password))
        # authenticate the user and raise an authorization exception if
this fails. Using a username/authtoken
        # like in spyne's own example is recommened but not what the
current service consumer wants to do...

    if with_headers:
        ClonedServiceProvider.event_manager.add_listener('method_call',
_on_method_call)
    return ClonedServiceProvider



Is this something acceptable or did I miss some subtle (...or obvious!)
side effect that will result in errors or worse once I start to use it "for
real"?
A test implementation looks to be working correctly right now, but
concurrent use isn't enough to expose possible "reentrancy" problems.


Thanks,
Roberto
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.spyne.io/archives/people/attachments/20141001/014fbaab/attachment.html>


More information about the people mailing list