[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-API] Typing in XML-RPC

  • To: Xen-API <xen-api@xxxxxxxxxxxxxxxxxxx>
  • From: Anthony Liguori <aliguori@xxxxxxxxxx>
  • Date: Fri, 23 Jun 2006 17:03:03 -0500
  • Delivery-date: Fri, 23 Jun 2006 15:03:16 -0700
  • List-id: Discussion of API issues surrounding Xen <xen-api.lists.xensource.com>

Here's an example implementation to further illustrate my point.


Anthony Liguori

Anthony Liguori wrote:
One of the first things I noticed is that the spec defines some extended types. This is a bit challenging in XML-RPC. It's unclear to me how 64 bit integer is represented (since XML-RPC only defines 32 bit integers). Also, defining void to an empty string is understandable but requires some special casing that really shouldn't be necessary.

Here's what I propose:

As a convention, we never use <struct>'s on the wire to directly represent structures. By convention, structs always appear as:


Where typename is the string representation of the type and typevalue is the type-specific value.

Some common types would be:

struct - use this to represent actual structs. typevalue is the normal encoding of a struct long - 64 bit representation of struct. typevalue is the string representation
void - use to represent None.  typevalue is ignored.

What's nice about this sort of consistent approach is that we can write a marshalling/unmarshalling wrapper for Python that automagically does this conversion. Furthermore, if we did decide to support objects (as the current spec does), we could automagically marshal/unmarshal these over the wire.

The general idea here is that this is an extensible typing system for XML-RPC.

Another thing to consider is having a type of exception. I like exception based APIs (i'll say that for another email) however the format of the standard XML-RPC exception leaves a lot to be desired.



Anthony Liguori

xen-api mailing list

import xmlrpclib
import SimpleXMLRPCServer
from types import DictType, NoneType

class Marshaller(xmlrpclib.Marshaller):
    def dump_struct(self, value, write, escape=xmlrpclib.escape):
        self.__dump_struct(self, value, write, escape)
    def __init__(self, encoding=None, allow_none=0):
        xmlrpclib.Marshaller.__init__(self, encoding, allow_none)
        self.__dump_struct = self.dispatch[DictType]
        self.dispatch[DictType] = Marshaller.dump_struct

class Unmarshaller(xmlrpclib.Unmarshaller):
    dispatch_ext = {}

    def ext_struct(self, value):
        return value
    dispatch_ext['struct'] = ext_struct

    def end_struct(self, data):
        self.__end_struct(self, data)
        if self._on:
            a = self._stack[-1]
            if self.dispatch_ext.has_key(a['type']):
                a = self.dispatch_ext[a['type']](self, a['value'])
            self._stack[-1] = a
        self._on = not self._on
    def __init__(self, *args):
        self.__end_struct = self.dispatch["struct"]
        self.dispatch["struct"] = Unmarshaller.end_struct
        self._on = False

xmlrpclib.FastMarshaller = Marshaller
xmlrpclib.FastParser = xmlrpclib.ExpatParser
xmlrpclib.FastUnmarshaller = Unmarshaller

a = xmlrpclib.ServerProxy("http://localhost:8001/RPC2";)

print a.ident({'z': 'z', 'foo': {'poo': 'foo'}, 'doo': {'da': 'qe'}, 'a': 'b'})
xen-api mailing list



Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.