29 June 2008

Adding a page to Confluence with Python

Perl has been my scripting language of choice for quite a while. This blog is completely written in object-oriented Perl, for instance. However, recently I keep running into difficulty installing the Perl packages from CPAN that I need to get stuff done. Without modules like XMLRPC::Lite, it’s hard to write scripts that interact with our applications at work.

With some reluctance, I decided to have a look at Python for scripting XML-RPC. As it turns out, Python is a great language for writing scripts which use XML-RPC to interact with Confluence. It’s simple to write, and the Python XML-RPC library, xmlrpclib, is shipped with every Python installation.

Here’s a script that I use to add a row to a table in a Confluence page. You can use it to add rows to a table inside a {chart} macro to create a statistics page on Confluence.

#!/usr/bin/python

import sys, string, xmlrpclib, re

if len(sys.argv) < 3:
   exit("Usage: " + sys.argv[0] + " spacekey pagetitle");

input = "".join(sys.stdin.readlines()).rstrip();
spacekey = sys.argv[1];
pagetitle = sys.argv[2];

server = xmlrpclib.ServerProxy('http://www.example.com/confluence/rpc/xmlrpc');
token = server.confluence1.login('username', 'password');
page = server.confluence1.getPage(token, spacekey, pagetitle);
if page is None:
   exit("Could not find page " + spacekey + ":" + pagetitle);

content = page['content'];
pattern = re.compile('^\|\|.*\n(?!\|)', re.MULTILINE);
content = pattern.sub('\g<0>' + input + '\n', content);

page['content'] = content;
server.confluence1.storePage(token, page);

This script is amazingly succinct, and the objects returned by the XML-RPC API behave like normal Python dictionaries. It even handles the typing of strings and numbers correctly — page IDs are strings in our remote API, and Perl turns them into number types which can’t be sent back to the server without manual intervention.

The above script could easily be (and has been) adapted to edit pages in other ways, create new pages, and so on. There is an enormous amount of possibility with the Confluence remote API.

I think I’ll be writing my future XML-RPC scripts for Confluence in Python now.