Reputation: 1376
I've seen in many Spyne examples that all the methods don't have the typical self
parameter; there aren't examples of Spyne using the self
parameter, nor cls
. They use a ctx
parameter, but ctx
doesn't refer to the instance nor to the class (and I need to maintain some state).
Is it possible to use it? Or are the classes not instantiated, and used as static classes?
I was trying to do something similar to:
# -*- coding: utf-8 -*-
from __future__ import (
absolute_import,
unicode_literals,
print_function,
division
)
from spyne.decorator import rpc
from spyne.service import ServiceBase
from spyne.model.primitive import String
class RadianteRPC(ServiceBase):
def __init__(self, name):
self._name = name
@rpc(_returns=String)
def whoami(self):
"""
Dummy test method.
"""
return "Hello I am " + self._name + "!"
The problem with this piece of code is that RadianteRPC
never seems to be instantiated as an object by Spyne, but used as a static class.
Solution 1: As it stands, Spyne doesn't instantiate any object. Then, if we need to store some state, we can do it through class properties.
Since we can't access to the cls
parameter in our methods, we need to refer the class by its name, so we can do something like:
class RadianteRPC(ServiceBase):
_name = "Example"
@rpc(_returns=String)
def whoami(ctx): # ctx is the 'context' parameter used by Spyne
"""
Dummy test method.
"""
return "Hello I am " + RadianteRPC._name + "!"
Solution 2 (found in Spyne mailing lists) :
In many cases, it's possible that we can't directly refer to the class name, so we have another alternative: find the class through the ctx parameter.
class RadianteRPC(ServiceBase):
_name = "Example"
@rpc(_returns=String)
def whoami(ctx): # ctx is the 'context' parameter used by Spyne
"""
Dummy test method.
"""
return "Hello I am " + ctx.descriptor.service_class._name + "!"
Upvotes: 3
Views: 1313
Reputation: 11
What I did is to subclass the Application class, and then access the application object through ctx.app.
from spyne.protocol.soap.soap11 import Soap11
from spyne.server.wsgi import WsgiApplication
from spyne import Application, rpc, ServiceBase, Unicode, Boolean
class MyApplication(Application):
def __init__(self, *args, **kargs):
Application.__init__(self, *args, **kargs)
assert not hasattr(self, 'session')
self.session = 1
def increment_session(self):
self.session += 1
def get_session(self):
return self.session
class Service(ServiceBase):
@rpc(_returns=Integer)
def increment_session(ctx):
s = ctx.app.get_session()
self.increment_session()
return s
application = MyApplication([MatlabAdapterService],
'spyne.soap',
in_protocol=Soap11(validator='lxml'),
out_protocol=Soap11())
wsgi_application = WsgiApplication(application)
...
I guess there should be a "cleaner" way - not requiring subclassing of the Application class - by subclassing the Context, but this should allow you to work dynamically.
To come back to your question, you also have the opportunity to access your service, since this is defined in the Application.services attribute.
Upvotes: 1