ppolv’s blog

December 1, 2007

a pythonic walk on jabber’s pubsub

Filed under: jabber, python, x60br, xmpp — Tags: , , , , , — ppolv @ 9:10 am

In the previous post, i wrote about the tool i’m using to work with XMPP PubSub.
Now instead of the GUI, we will use the base APIs to create a node hierarchy directly from a python script. The hierarchy will have collection and leaf nodes, mirroring an initial “model” a -recursive- list structure. An example model can looks like the following:

hierarchy = [
             (COLLECTION,"collection1",[
                      (COLLECTION,"collection1.1",[]),
                      (LEAF,"node1.1"),
                      (LEAF,"node1.2")
                   ]),
             (LEAF,"node1"),
             (LEAF,"node2"),
             (COLLECTION,"collection2",[
                      (LEAF,"node2.1")
                 ]),
             (COLLECTION,"collection3",[
                      (LEAF,"node3.1"),
                      (LEAF,"node3.2"),
                      (LEAF,"node3.3")
                  ]),
             ]

The pubsub api of x60br is coded following the twisted asynchronous way: most of the methods perform a IQ call to the server and then return a Deferred, whitout blocking the caller. Then the calling code should register their own callbacks on that deferred to be executed when the response/error becomes available.
The API is still far for complete or stable… but enough to play with it. You can check the epydoc’s generated API Documentation.

In this example, to create the node hierarchy, the main function iterate over the list of tuples, creating the appropriated nodes, and returns a Deferred that will be fired when all responses where received from the server.

def add_nodes(ps,nodes,parent_collection = None):
    #ps is the pubsub service
    if nodes == []: #nothing to do
        return defer.succeed(None)

    #array of pending responses from the server
    #used to fire a callback when all request have been fulfilled
    pending = [] 

    for node in nodes:
        print "Creating node ", node[1]
        if node[0] is LEAF:
            d = ps.create_leaf_node(node[1], parent_collection)
            d.addErrback(log_err,node[1])
            pending.append(d)
        else:
            d = defer.Deferred()
            d_collection = ps.create_collection_node(node[1], parent_collection)
            def create_childs(parent_node,parent_cb,childs):
                d_childs = add_nodes(ps,childs,parent_node)
                #when all childs have been created, fire the completion
                #of the parent's defer
                d_childs.chainDeferred(parent_cb)

            #after the collection node is created, create all children
            d_collection.addCallback(create_childs,d,node[2])
            d_collection.addErrback(d.errback)
            d.addErrback(log_err,node[1])
            pending.append(d)
    return defer.DeferredList(pending,fireOnOneErrback=1, consumeErrors=1)

The full source code for the example is in http://svn.berlios.de/svnroot/repos/x60br/trunk/samples/hierarchy_creation.py

The code is simple, although if you aren’t used to Twisted, it may seems more complex than what really is.
The deferred d_collection is used for collection nodes, after receiving the confirmation that a collection node was created, we make a recursive call to create all the children of that collection.

This simple example creates nodes using the default configuration assigned by the server , but you can also specify configuration fields at creation time, or change the configuration after the creation of the node.

Advertisements

2 Comments »

  1. Would you mind to elaborate about the server which you use ?

    I test x60br against ejabberd 2.0.0 and cannot create any node. But I am new to jabber too, so that does not say much.

    Best wishes

    Norbert

    Comment by Norbert Klamann — April 15, 2008 @ 12:10 pm

  2. Hi Norbert,
    You are right, this code doesn’t work against the ejabberd’s pubsub implementation.
    It should work against OpenFire, at least it worked the last time I tested it.
    You could check the code at http://svn.berlios.de/svnroot/repos/x60br/trunk/samples/hierarchy_creation_ejabberd.py ,
    for a “hacked” version of this code that works with ejabberd 2.0 . The trick is to use the appropriate prefix for naming “child” nodes (please refer to the notes in the code). Keep in mind that ejabberd’s pubsub implementation is a really powerfull beast, a plugin-based beast ( see http://www.process-one.net/en/blogs/article/introducing_the_xmpp_application_server ).

    (disclamer: I’m currently doing an internship at process-one 🙂 )

    I’m not sure when (if) I will update the x60br library, it worked for me at the time I wrote it, but now that project is over and I’m not using it anymore.
    In http://wokkel.ik.nu/ seems to be another python pubsub library, I never use it though.
    Or you can wait for exmpp to be published ( http://blog.ciarang.com/posts/adventures-in-jabberlang/#comment-87 )

    Comment by ppolv — April 15, 2008 @ 10:30 pm


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: