Skip to content Skip to sidebar Skip to footer

How Do You @rpc _returns Polymorphic Types In Spyne?

Edit Example, class A(ComplexModel): Id = Unicode class B(ComplexModel): __extends__ = A Name = Unicode @rpc(String, _returns=A) def hello(self, name): ret = B()

Solution 1:

Deleting my previous answer as you apparently need polymorphism, not multiple return types.

So, There are two ways of doing polymorphism in Spyne: The Python way and the Spyne way.

Let:

classA(ComplexModel):
    i =Integer

classB(A):
    s =Unicode

classC(A):
    d = DateTime

The Python way uses duck typing to return values.

Let's define a generic class:

classGenericA(ComplexModel):
    i = Integer
    s = Unicode
    d = DateTime

and use it as return value of our sample service:

classSomeService(ServiceBase):
    @rpc(Unicode(values=['A', 'B', 'C']), _returns=GenericA)defget_some_a(self, type_name):
        # (...)

This way, you get your data, but it's tagged as a GenericA object. If you don't care about this, you can create a class that has all types from all objects (assuming attributes with same names have the same type) and just be done with it. This is easy, stable and works today.

If that's not enough for your needs, you have to do the polymorphism the Spyne way. To do that, first set your return type to the base class:

classSomeService(ServiceBase):
    @rpc(Unicode(values=['A', 'B', 'C']), _returns=A)defget_some_a(self, type_name):
        # (...)

and tag your output protocol to be polymorphic:

application = Application([SomeService], 'tns',
    in_protocol=Soap11(validator='lxml'),
    out_protocol=Soap11(polymorphic=True)
)

This requires at least Spyne-2.12.

Working example: https://github.com/arskom/spyne/blob/a1b3593f3754a9c8a6787c29ff50f591db89fd49/examples/xml/polymorphism.py

Solution 2:

Also, you don't need to do this:

class Account(DeclarativeBase):
    __tablename__ = 'account'

    id = Column(Integer, primary_key=True)
    user_name = Column(String(256))
    first_name = Column(String(256))
    last_name = Column(String(256))

class XAccount(TableModel):
    __table__ = Account.__table__

This works just as well:

from spyne import TTableModel

TableModel = TTableModel() # Think of this as Spyne's declarative_baseclass Account(TableModel):
    __tablename__ = 'account'

    id = Integer(primary_key=True)
    user_name = Unicode(256)
    first_name = Unicode(256)
    last_name = Unicode(256)

where your table metadata is in TableModel.Attributes.sqla_metadata

Objects created this way are usable in both in SQLAlchemy queries and as Spyne types.

Post a Comment for "How Do You @rpc _returns Polymorphic Types In Spyne?"