Saturday, September 25, 2010

Using Sharepoint Lists with Python

Continuing my tradition of shoving Python into new and unusual places, I recently worked out how to use Python to post items to a Sharepoint List.

We use Sharepoint for some of our intranet needs, and I was experimenting with error-reporting workflows. While I ultimately didn't stick with Sharepoint for this purpose, the Python code worked fine and I wanted to share.

First, a few things to note. Sharepoint uses several SOAP-based webservices as a means of exposing functionality to other tools/languages. One of these is for manipulating Lists, which are Sharepoint's basic storehouse for items that hold arbitrary columns/fields of data.

I was unfamiliar with SOAP prior to this, and ended up using the "suds" extension for Python to help with the formatting. Suds is necessary to run the examples below, and can be downloaded on the Suds SourceForge page.

The "sharepoint" module I'm posting below has basic usage like this:

import sharepoint

item_data = {
   'item_id'   : 32,
   'Log Time'  : datetime.datetime.now( ),
   'Message'   : 'Sharepoint is rather obtuse',
   'User Name' : 'adam.pletcher',
}

sp_list = sharepoint.Sharepoint_List( 'http://sp_server/some_site/', 'Sharepoint List Name', 'domain_name', 'user_name', 'rot13_encoded_password' )
result = sp_list.add_item( item_data )
Walking through the above, first we create a simple dictionary of key/value pairs. The keys are the Sharepoint names for the columns in your list, and the values are the values you wish to submit for your new list item. Then, we construct a Sharepoint_List instance, passing it the site URL, List Name, domain, user and password. Finally, call our add_item method on that object, passing it the data dictionary we made.

The add_item method accepts most data types, including Python datetime objects, as shown. You can easily extend add_item to do something more elaborate.

One thing to watch out for is the list's column/field names used in your dictionary. These must be strings matching the true Sharepoint names of your fields. Even if you rename a column later, it's true name will not change once the list has been created. The only flexibility I currently provide in add_item is the ability to leave spaces in the field names.

I experimented with NTLM as a means of using the current user's Windows Authentication instead of requiring the username/pass each time. I was not successful in that, however... if anyone has success there I'd love to hear about it. As it stands, the Sharepoint_List class requires the username and a ROT-13 encoded password. If you've never encoded anything, here's how to do that from a Python prompt:
>>> 'my_password'.encode( 'rot-13' )
'zl_cnffjbeq'
The complete "sharepoint" module described here can be downloaded below. Adding an item isn't the only thing the Sharepoint lists webservice offers. You can use the framework in this module to do more including edits, deletes and other actions.

Python_Sharepoint.zip (3 KB)

6 comments:

Strzelewicz Alexandre said...
This comment has been removed by a blog administrator.
Daniel said...

Thanks. Your code was a useful starting point. I like working with the suds client object directly.

To make this example work with suds 0.4, you will have to wrap any XML arguments with Raw():

client.service.GetListItems(listName, '', Raw(Element('Query').append('Where')), ...)

instead of

GetListItems(listName, '', Element('ns1:query').append(Element('Query').append('Where'))

which works in suds 0.3.9 but fails in suds 0.4.

suds will create the tag for the parameter name, so there's no need to create Element('ns1:parameterName') when using Raw(). You may also pass plain text to Raw().

ajung said...

You may also check into haufe.sharepoint: http://pypi.python.org/pypi/haufe.sharepoint

Stefan Høj-Edwards said...

In your source code, you are using a rather extensive __doc__ string formatting, e.g.:

######################
*Arguments:*
* ``item_data`` ...

*Returns:*
* Service_Command_Result object containing result of add command

*Examples:* ::
(code)
######################


Can you refer to what sort of format it is and if it can be used with some sort of documentation pipeline?

Adam Pletcher said...

@Stefan:
At work we use Sphinx for building HTML documentation:
http://sphinx.pocoo.org/

It uses "reStructuredText" markup, which is what you see in those docstrings.

We've been very happy using Sphinx for documentation building. It's also used to build the official Python documentation, seen in action here:
http://docs.python.org/

Mangesh said...

Is it possible to read the item from sharepoint list?
Can you provide short example?