3

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 + "!"
castarco
  • 1,368
  • 2
  • 17
  • 33
  • 2
    Could you provide an example? Are the methods decorated with `@staticmethod` or `@classmethod`? – jonrsharpe Aug 14 '14 at 10:48
  • No, the methods aren't decorated with staticmethod nor classmethod. The problem is related with Spyne architecture, it's not a "Python" problem. – castarco Aug 14 '14 at 13:20
  • @jonrsharpe I've added a better explanation of my problem. I need to reopen the question to add the solution as an answer. – castarco Aug 19 '14 at 09:09
  • As it stands, it's still not a good question - for example, what exactly was happening with your previous attempts? Errors (provide full traceback)? Consider reading [this checklist](http://meta.stackoverflow.com/questions/260648/stack-overflow-question-checklist). – jonrsharpe Aug 19 '14 at 09:15
  • It has no sense to provide traceback (the traceback doesn't provide any clue about the solution). Yes, I've done research, I've dived in the Spyne source code, and I've read the documentation. – castarco Aug 19 '14 at 09:28
  • It would be helpful to mention your research, and the conclusions (if any) you drew from it, if only to prevent others pointlessly doing the same thing and telling you what you already know. – jonrsharpe Aug 19 '14 at 09:32
  • I've added two solutions to the problem. – castarco Aug 19 '14 at 09:54
  • I do not understand the downvote. I'm facing the same issue actually. What I need is not a solution to fix a bug, it's to know the best practice: how is it supposed to be done? I can't imagine that people working with Spyne never had this common problem: having some attributes maintained... – Julien Greard Aug 29 '14 at 15:01
  • @castarco: thanks for solution1 and solution2, but it looks more like a workaround than a perfect solution imo. Spyne doesn't have any "whoAmI" method? If it doesn't, maybe it's not supposed to be done that way... in Python you can allways do stuff, but often it's not the way it's supposed to work :) – Julien Greard Aug 29 '14 at 15:04

1 Answers1

1

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.

chiesax
  • 11
  • 2