[Spread-users] Python binding for Spread

Bradley McLean brad at bradm.net
Thu Sep 27 11:39:08 EDT 2001


Attached is a python binding for spread.  It does not
support the authentication work (because I didn't see
any documentation on it).

I'm willing to make extensions and donate this to the
project if folks are interested.

I started from a SWIG generated interface, and then
replaced almost all of it with hand coding for various
reasons.

-Brad
-------------- next part --------------
#include <stdlib.h>
#include "Python.h"
#include "sp.h"
#include "sp_func.h"

#ifdef __cplusplus
extern "C" {
#endif


static PyObject *_wrap_SP_version(PyObject *self, PyObject *args) {
    int major;
    int minor;
    int rev;
    int result;
    
    result = (int) SP_version(&major,&minor,&rev);
    // believe that result cannot come back as a useful value, so don't
    // bother to return it up to the scripting layer.
    return Py_BuildValue("iii",major,minor,rev);
}

/*  FUTURE, when these are documented and I can figure out how to map
them to python:

static PyObject *_wrap_SP_set_auth_method(PyObject *self, PyObject *args) {
    PyObject *resultobj;
    char *arg0 ;
    int (*arg1)(int ,void *) ;
    void *arg2 ;
    PyObject * argo1 =0 ;
    PyObject * argo2 =0 ;
    int result ;
    
// deal with the objects in here
    if(!PyArg_ParseTuple(args,(char *)"sOO:SP_set_auth_method",&arg0,
                         &argo1,&argo2)) return NULL;
    result = (int )SP_set_auth_method((char const *)arg0,arg1,arg2);
    return = PyInt_FromLong((long)result);
}


static PyObject *_wrap_SP_set_auth_methods(PyObject *self, PyObject *args) {
    PyObject *resultobj;
    int arg0 ;
    char **arg1 ;
    int (**arg2)(int ,void *) ;
    void **arg3 ;
    PyObject * argo1 =0 ;
    PyObject * argo2 =0 ;
    PyObject * argo3 =0 ;
    int result ;
    
    if(!PyArg_ParseTuple(args,(char *)"iOOO:SP_set_auth_methods",&arg0,
                         &argo1,&argo2,&argo3)) return NULL;

// deal with the objects in here.
    result = (int )SP_set_auth_methods(arg0,(char const *(*))arg1,arg2,arg3);
    resultobj = PyInt_FromLong((long)result);
    return resultobj;
}

*/

static PyObject *_wrap_SP_connect(PyObject *self, PyObject *args) {
    char *spread_name;
    char *private_name;
    int priority;
    int groupmsgs;
    int handle ;
    char private_group[MAX_PRIVATE_NAME] ;
    int result ;
    
    if(!PyArg_ParseTuple(args,(char *)"ssii:SP_connect",
              &spread_name,&private_name,&priority,&groupmsgs)) return NULL;
    result = (int )SP_connect((char const *)spread_name,
                              (char const *)private_name,
                              priority,groupmsgs,&handle,private_group);
    return Py_BuildValue("iis",result,handle,private_group);
}


static PyObject *_wrap_SP_connect_timeout(PyObject *self, PyObject *args) {
    char *spread_name ;
    char *private_name ;
    int priority ;
    int groupmsgs ;
    int handle ;
    char private_group[MAX_PRIVATE_NAME];
    sp_time timeout ;
    int result ;
    
    if(!PyArg_ParseTuple(args,(char *)"ssiill:SP_connect_timeout",
                         &spread_name,&private_name,&priority,&groupmsgs,
                         &timeout.sec,&timeout.usec)) return NULL;
    result = (int )SP_connect_timeout((char const *)spread_name,
                                      (char const *)private_name,priority,
                                      groupmsgs,&handle,private_group,timeout);
    return Py_BuildValue("iis",result,handle,private_group);
}


static PyObject *_wrap_SP_disconnect(PyObject *self, PyObject *args) {
    int handle;
    
    if(!PyArg_ParseTuple(args,(char *)"i:SP_disconnect",&handle)) return NULL;
    return PyInt_FromLong((long)SP_disconnect(handle));
}


static PyObject *_wrap_SP_join(PyObject *self, PyObject *args) {
    int handle;
    char *groupname;
    int result;
    
    if(!PyArg_ParseTuple(args,(char *)"is:SP_join",&handle,&groupname))
        return NULL;
    result = (int )SP_join(handle,(char const *)groupname);
    return PyInt_FromLong((long)result);
}


static PyObject *_wrap_SP_leave(PyObject *self, PyObject *args) {
    int handle;
    char *groupname;
    int result;
    
    if(!PyArg_ParseTuple(args,(char *)"is:SP_leave",&handle,&groupname))
        return NULL;
    result = (int )SP_leave(handle,(char const *)groupname);
    return PyInt_FromLong((long)result);
}

static PyObject *_wrap_SP_multicast(PyObject *self, PyObject *args) {
    int handle;
    int svc;
    int groupcnt;
    char *groupname;
    char (*grouplist)[MAX_GROUP_NAME] ;
    short msgtype ;
    int msglen ;
    char *msg ;
    PyObject * groups =0 ;
    PyObject * str =0 ;
    int i, result ;
    
    if(!PyArg_ParseTuple(args,(char *)"iishis:SP_multicast",&handle,
                         &svc,&groupname,&msgtype,&msglen,&msg)) {
        if(!PyArg_ParseTuple(args,(char *)"iiOhis:SP_multigroup_multicast",
                             &handle,&svc,&groups,&msgtype,
                             &msglen,&msg)) return NULL;
        if ( !PySequence_Check(groups) ) return NULL;
        grouplist = (char (*)[MAX_GROUP_NAME])calloc(PySequence_Length(groups),
                                                     MAX_GROUP_NAME);
        if ( grouplist == NULL ) return NULL;
        groupcnt=PySequence_Length(groups);
        for ( i=0; i < groupcnt; i++ ) {
            str = PySequence_GetItem(groups,i);
            if ( !PyString_Check(str) ) return NULL;
            strncpy(grouplist[i],PyString_AsString(str),MAX_GROUP_NAME);
        }
        result = (int )SP_multigroup_multicast(handle,svc,groupcnt,
                                               (char const (*)[32])grouplist,
                                               msgtype,msglen,
                                               (char const *)msg);
        free(grouplist);
    } else { /* Single group form */
        result = (int )SP_multicast(handle,svc,(char const *)groupname,
                                    msgtype,msglen,(char const *)msg);
    }
    return PyInt_FromLong((long)result);
}

static PyObject *_wrap_SP_receive(PyObject *self, PyObject *args) {
    PyObject *resultobj;
    int hand;
    int maxgrp;
    int msglen;
    service service_type;
    char sender[MAX_GROUP_NAME];
    int numgrp;
    char (*grps)[MAX_GROUP_NAME];
    int16 type;
    int endian;
    char *msg;
    PyObject *grouplist;
    int i, result ;
    
    if(!PyArg_ParseTuple(args,(char *)"iii:SP_receive",&hand,&maxgrp,&msglen))
        return NULL;
    grps = (char (*)[MAX_GROUP_NAME])calloc(maxgrp,MAX_GROUP_NAME);
    if ( grps == NULL ) return NULL;
    msg = calloc(msglen,1);
    if ( msg == NULL ) return NULL;
    sender[0] = 0;
    result = (int )SP_receive(hand,&service_type,sender,maxgrp,&numgrp,
                              grps,&type,&endian,msglen,msg);
    if ( result <= 0 ) {
        grouplist = PyInt_FromLong((long) numgrp);
    } else {
        grouplist = PyList_New(numgrp);
        for ( i=0; i < numgrp; i++ ) {
            PyList_SetItem(grouplist,i,PyString_FromString(grps[i]));
        }
    }
    resultobj = Py_BuildValue("iisOhis",result,service_type,sender,
                              grouplist,type,endian,msg);
    free(msg);
    free(grps);
    return resultobj;
}

static PyObject *_wrap_SP_poll(PyObject *self, PyObject *args) {
    PyObject *resultobj;
    int handle ;
    int result ;
    
    if(!PyArg_ParseTuple(args,(char *)"i:SP_poll",&handle)) return NULL;
    result = (int )SP_poll(handle);
    resultobj = PyInt_FromLong((long)result);
    return resultobj;
}

/* Future?  We don't actually ever decode these objects; we just export
   the visible names.
static PyObject *_wrap_SP_equal_group_ids(PyObject *self, PyObject *args) {
    PyObject *resultobj;
    group_id *handle ;
    group_id *arg1 ;
    PyObject * argo0 =0 ;
    PyObject * argo1 =0 ;
    int result ;
    
    if(!PyArg_ParseTuple(args,(char *)"OO:SP_equal_group_ids",&argo0,&argo1))
        return NULL;
    if ((SWIG_ConvertPtr(argo0,(void **) &handle,SWIGTYPE_p_group_id,1)) == -1)
        return NULL;
    if ((SWIG_ConvertPtr(argo1,(void **) &arg1,SWIGTYPE_p_group_id,1)) == -1)
        return NULL;
    result = (int )SP_equal_group_ids(*handle,*arg1);
    resultobj = PyInt_FromLong((long)result);
    return resultobj;
}

*/


static PyMethodDef spredMethods[] = {
	 { (char *)"SP_version", _wrap_SP_version, METH_VARARGS },
//	 { (char *)"SP_set_auth_method", _wrap_SP_set_auth_method, METH_VARARGS },
//	 { (char *)"SP_set_auth_methods", _wrap_SP_set_auth_methods, METH_VARARGS },
	 { (char *)"SP_connect", _wrap_SP_connect, METH_VARARGS },
	 { (char *)"SP_connect_timeout", _wrap_SP_connect_timeout, METH_VARARGS },
	 { (char *)"SP_disconnect", _wrap_SP_disconnect, METH_VARARGS },
	 { (char *)"SP_join", _wrap_SP_join, METH_VARARGS },
	 { (char *)"SP_leave", _wrap_SP_leave, METH_VARARGS },
	 { (char *)"SP_multicast", _wrap_SP_multicast, METH_VARARGS },
	 { (char *)"SP_receive", _wrap_SP_receive, METH_VARARGS },
	 { (char *)"SP_poll", _wrap_SP_poll, METH_VARARGS },
//	 { (char *)"SP_equal_group_ids", _wrap_SP_equal_group_ids, METH_VARARGS },
	 { NULL, NULL }
};

#ifdef __cplusplus
}
#endif

static struct { char *name; long lvalue; } const_table[] = {
    { (char*)"LOW_PRIORITY", (long) LOW_PRIORITY},
    { (char*)"MEDIUM_PRIORITY", (long) MEDIUM_PRIORITY},
    { (char*)"HIGH_PRIORITY", (long) HIGH_PRIORITY},
    { (char*)"DEFAULT_SPREAD_PORT", (long) DEFAULT_SPREAD_PORT},
    { (char*)"SPREAD_VERSION", (long) SPREAD_VERSION},
    { (char*)"MAX_GROUP_NAME", (long) MAX_GROUP_NAME},
    { (char*)"MAX_PRIVATE_NAME", (long) MAX_PRIVATE_NAME},
    { (char*)"MAX_PROC_NAME", (long) MAX_PROC_NAME},
    { (char*)"UNRELIABLE_MESS", (long) UNRELIABLE_MESS},
    { (char*)"RELIABLE_MESS", (long) RELIABLE_MESS},
    { (char*)"FIFO_MESS", (long) FIFO_MESS},
    { (char*)"CAUSAL_MESS", (long) CAUSAL_MESS},
    { (char*)"AGREED_MESS", (long) AGREED_MESS},
    { (char*)"SAFE_MESS", (long) SAFE_MESS},
    { (char*)"REGULAR_MESS", (long) REGULAR_MESS},
    { (char*)"SELF_DISCARD", (long) SELF_DISCARD},
    { (char*)"DROP_RECV", (long) DROP_RECV},
    { (char*)"REG_MEMB_MESS", (long) REG_MEMB_MESS},
    { (char*)"TRANSITION_MESS", (long) TRANSITION_MESS},
    { (char*)"CAUSED_BY_JOIN", (long) CAUSED_BY_JOIN},
    { (char*)"CAUSED_BY_LEAVE", (long) CAUSED_BY_LEAVE},
    { (char*)"CAUSED_BY_DISCONNECT", (long) CAUSED_BY_DISCONNECT},
    { (char*)"CAUSED_BY_NETWORK", (long) CAUSED_BY_NETWORK},
    { (char*)"MEMBERSHIP_MESS", (long) MEMBERSHIP_MESS},
    { (char*)"ENDIAN_RESERVED", (long) ENDIAN_RESERVED},
    { (char*)"RESERVED", (long) RESERVED},
    { (char*)"REJECT_MESS", (long) REJECT_MESS},
    { (char*)"ACCEPT_SESSION", (long) ACCEPT_SESSION},
    { (char*)"ILLEGAL_SPREAD", (long) ILLEGAL_SPREAD},
    { (char*)"COULD_NOT_CONNECT", (long) COULD_NOT_CONNECT},
    { (char*)"REJECT_QUOTA", (long) REJECT_QUOTA},
    { (char*)"REJECT_NO_NAME", (long) REJECT_NO_NAME},
    { (char*)"REJECT_ILLEGAL_NAME", (long) REJECT_ILLEGAL_NAME},
    { (char*)"REJECT_NOT_UNIQUE", (long) REJECT_NOT_UNIQUE},
    { (char*)"REJECT_VERSION", (long) REJECT_VERSION},
    { (char*)"CONNECTION_CLOSED", (long) CONNECTION_CLOSED},
    { (char*)"REJECT_AUTH", (long) REJECT_AUTH},
    { (char*)"ILLEGAL_SESSION", (long) ILLEGAL_SESSION},
    { (char*)"ILLEGAL_SERVICE", (long) ILLEGAL_SERVICE},
    { (char*)"ILLEGAL_MESSAGE", (long) ILLEGAL_MESSAGE},
    { (char*)"ILLEGAL_GROUP", (long) ILLEGAL_GROUP},
    { (char*)"BUFFER_TOO_SHORT", (long) BUFFER_TOO_SHORT},
    { (char*)"GROUPS_TOO_SHORT", (long) GROUPS_TOO_SHORT},
    { (char*)"MESSAGE_TOO_LONG", (long) MESSAGE_TOO_LONG},
    { (char*)"MAX_SCATTER_ELEMENTS", (long) MAX_SCATTER_ELEMENTS},
{0}};

#ifdef __cplusplus
extern "C" 
#endif
void initspred(void) {
    PyObject *m, *d, *val;
    int i;
    m = Py_InitModule((char*)"spred", spredMethods);
    for ( i=0; const_table[i].name; i++ ) {
    d = PyModule_GetDict(m);
        val = PyInt_FromLong(const_table[i].lvalue);
        PyDict_SetItemString(d,const_table[i].name,val);
        Py_DECREF(val);
    }
}
-------------- next part --------------
import spred
import string, types

version = spred.SP_version

class spread:

    LOW_PRIORITY = spred.LOW_PRIORITY
    MEDIUM_PRIORITY = spred.MEDIUM_PRIORITY
    HIGH_PRIORITY = spred.HIGH_PRIORITY
    DEFAULT_SPREAD_PORT = spred.DEFAULT_SPREAD_PORT
    SPREAD_VERSION = spred.SPREAD_VERSION
    MAX_GROUP_NAME = spred.MAX_GROUP_NAME
    MAX_PRIVATE_NAME = spred.MAX_PRIVATE_NAME
    MAX_PROC_NAME = spred.MAX_PROC_NAME
    UNRELIABLE_MESS = spred.UNRELIABLE_MESS
    RELIABLE_MESS = spred.RELIABLE_MESS
    FIFO_MESS = spred.FIFO_MESS
    CAUSAL_MESS = spred.CAUSAL_MESS
    AGREED_MESS = spred.AGREED_MESS
    SAFE_MESS = spred.SAFE_MESS
    REGULAR_MESS = spred.REGULAR_MESS
    SELF_DISCARD = spred.SELF_DISCARD
    DROP_RECV = spred.DROP_RECV
    REG_MEMB_MESS = spred.REG_MEMB_MESS
    TRANSITION_MESS = spred.TRANSITION_MESS
    CAUSED_BY_JOIN = spred.CAUSED_BY_JOIN
    CAUSED_BY_LEAVE = spred.CAUSED_BY_LEAVE
    CAUSED_BY_DISCONNECT = spred.CAUSED_BY_DISCONNECT
    CAUSED_BY_NETWORK = spred.CAUSED_BY_NETWORK
    MEMBERSHIP_MESS = spred.MEMBERSHIP_MESS
    ENDIAN_RESERVED = spred.ENDIAN_RESERVED
    RESERVED = spred.RESERVED
    REJECT_MESS = spred.REJECT_MESS

    error = {   spred.LOW_PRIORITY : 'LOW_PRIORITY',
                spred.MEDIUM_PRIORITY : 'MEDIUM_PRIORITY',
                spred.HIGH_PRIORITY : 'HIGH_PRIORITY',
                spred.DEFAULT_SPREAD_PORT : 'DEFAULT_SPREAD_PORT',
                spred.SPREAD_VERSION : 'SPREAD_VERSION',
                spred.DROP_RECV : 'DROP_RECV',
                spred.REG_MEMB_MESS : 'REG_MEMB_MESS',
                spred.TRANSITION_MESS : 'TRANSITION_MESS',
                spred.CAUSED_BY_JOIN : 'CAUSED_BY_JOIN',
                spred.CAUSED_BY_LEAVE : 'CAUSED_BY_LEAVE',
                spred.CAUSED_BY_DISCONNECT : 'CAUSED_BY_DISCONNECT',
                spred.CAUSED_BY_NETWORK : 'CAUSED_BY_NETWORK',
                spred.MEMBERSHIP_MESS : 'MEMBERSHIP_MESS',
                spred.ENDIAN_RESERVED : 'ENDIAN_RESERVED',
                spred.RESERVED : 'RESERVED',
                spred.REJECT_MESS : 'REJECT_MESS',
                spred.ACCEPT_SESSION : 'ACCEPT_SESSION',
                spred.ILLEGAL_SPREAD : 'ILLEGAL_SPREAD',
                spred.COULD_NOT_CONNECT : 'COULD_NOT_CONNECT',
                spred.REJECT_QUOTA : 'REJECT_QUOTA',
                spred.REJECT_NO_NAME : 'REJECT_NO_NAME',
                spred.REJECT_ILLEGAL_NAME : 'REJECT_ILLEGAL_NAME',
                spred.REJECT_NOT_UNIQUE : 'REJECT_NOT_UNIQUE',
                spred.REJECT_VERSION : 'REJECT_VERSION',
                spred.CONNECTION_CLOSED : 'CONNECTION_CLOSED',
                spred.REJECT_AUTH : 'REJECT_AUTH',
                spred.ILLEGAL_SESSION : 'ILLEGAL_SESSION',
                spred.ILLEGAL_SERVICE : 'ILLEGAL_SERVICE',
                spred.ILLEGAL_MESSAGE : 'ILLEGAL_MESSAGE',
                spred.ILLEGAL_GROUP : 'ILLEGAL_GROUP',
                spred.BUFFER_TOO_SHORT : 'BUFFER_TOO_SHORT',
                spred.GROUPS_TOO_SHORT : 'GROUPS_TOO_SHORT',
                spred.MESSAGE_TOO_LONG : 'MESSAGE_TOO_LONG',
                spred.MAX_SCATTER_ELEMENTS : 'MAX_SCATTER_ELEMENTS' }

    def __init__(self,spreadname,privatename,priority = 0,group = 1):
        (res,self.handle,self.privategroup) = spred.SP_connect(spreadname,privatename,priority,group)
        if res != spred.ACCEPT_SESSION:
            raise self.error[res]
        self.groups = {}

    def __del__(self):
        res = spred.SP_disconnect(self.handle)
        if res != 0:
            raise self.error[res]

    def join(self,group):
        res = spred.SP_join(self.handle,group)
        if res != 0:
            raise self.error[res]
        # Not needed, the membership message does it:
        #self.groups[group] = (self.privategroup)

    def leave(self,group):
        res = spred.SP_leave(self.handle,group)
        if res != 0:
            raise self.error[res]
        del self.groups[group]

    def _membership(self,res,service,sender,groups,type,endian,msg):
        self.groups[sender]=groups

    def multicast(self,service,groups,msgtype,message):
        res = spred.SP_multicast(self.handle,service,groups,msgtype,
                                   len(message),message)
        if res < 0:
            raise self.error[res]


    def receive(self,maxgroups=4,messagelen=1024):
        while 1:
            result = spred.SP_receive(self.handle,maxgroups,messagelen)
            (res,service,sender,groups,type,endian,msg) = result
            if res < 0:
                if res == spred.GROUPS_TOO_SHORT:
                    maxgroups = -groups
                elif res == spred.BUFFER_TOO_SHORT:
                    messagelen = -endian
                else:
                    raise self.error[res]
            if service & spred.MEMBERSHIP_MESS:
                self._membership(res,service,sender,groups,type,endian,msg)
            else:
                return result

    def poll(self):
        return spred.SP_poll(self.handle)

-------------- next part --------------
A non-text attachment was scrubbed...
Name: buildspred.sh
Type: application/x-sh
Size: 164 bytes
Desc: not available
Url : http://lists.spread.org/pipermail/spread-users/attachments/20010927/2b6cd98b/attachment.sh 
-------------- next part --------------
from spread import spread

chan1 = spread('4803 at localhost','one')

chan1.join("g1")

chan1.multicast(spread.RELIABLE_MESS,"g1",0,'Welcome to Spread Test')

while 1:
    res = chan1.receive()
    print "Got> ",res



More information about the Spread-users mailing list