Suds makes the soapy world less slippery

Development April 5th, 2008

In the last post, I was whining about the bumps in the road when trying to consume a SOAP web service using python. Thanks to Olosta’s suggestion, Suds.

Suds logo The cute yellow rubber duck makes the soapy world less slippery. There is no need to generate execution code using an external tool like wsdl.exe for C#, just load the WSDL in the runtime, the ServiceProxy object would dynamically generate the function calls for you. It still in actively developed, salute to joetel.

Something needs to tailor to adapt to the Microsoft Office SharePoint Server: the connection persistence. As you may know, the default authentication used in SharePoint web service is NTLM, undocumented, but well known to the public. NTLM authenticates the connection, so in current suds implementation, each method invocation incurs redundant NTLM negotiation-challenge-and-response. I would dig more for this issue; stay tuned.

Who would be old school python developer?

Development April 3rd, 2008

Two posts (here and here) in programming.reddit.com discussed the state-of-the-art python IDEs. Two of them really arouse my interest: Komodo Edit and IronPython Studio which is honorably mentioned in the comment.

Komodo Edit is the shrunk-and-free version ActiveState’s flagship Komodo IDE. It is rooted in the same technology as Firefox, using XUL framework to render the UI, same Add-on mechanism to support 3rd-party package, and the UI is quite clean, eye-candy lacking in another term:

Komodo Edit in action

Furthermore, thanks to ActiveState’s generosity, there is an open source initiative openkomodo’s Snapdragon project to build a full-fledged IDE based upon the Komodo Edit’s code base. Though I suffer the huge memory footprint of Firefox from time to time, I still believe this is a much lightweight IDE compared to the versatile Eclipse.

Another option is IronPython Studio based upon award-winning Microsoft Visual Studio technology. Whether you like it or not, we have to admit that lots of programmers would feel at home when using familiar interface. However, strictly speaking it is not a python IDE, you are locked to IronPython, and most likely you could not resist the temptation to use .Net and WPF. And at the end of day, the ultimate question may emerge: “Why not use C#? The syntax is quite similar, and we are no longer treated as second-class developers.” I doubt that Silverlight may make a difference if you are not a Web developer.

The last but not the least question when I read through all the comments. I was quite amazed to find so few comments from the die-hard old school guys. Here is one comment about using Emacs and python mode, how about Vim users? Did they just disregard this kind of flame-prone discussion or already lost the faith to convince the other world?

So if you happened to be a heavy-weight Vim user and program with python, I would appreciate if you could drop a message here to share your experience.

Learning Django by Example(7) Attach a tag

Web January 20th, 2008

Tag is probably the most distinguish feature of Web 2.0 applications that differentiate them from the traditional hierarchy categories. I want to attach a Web 2.0 tag to Gelman, so the user could simply click the tag, and find the related books that may arouse his/her interest.

django-taggingis a generic tag application to simplify the backend development, all you need to do is just add the TagField to the Book model:
class Book(models.Model):
……
tags = TagField()

And in the book_detail.html template, refer it as object.tags as this:

{{ object.tags|popuptags|safe }}

popuptags is a custom tag that decorates the tags as a list of HTML links, and join them:

@register.filter
def popuptags(value):
    tags = value.split(” “)
    return ” “.join([‘<a href="/bookshelf/tags/%s">%s</a>’ % (x, x) for x in tags])

So tag foo is linked with /bookshelf/tags/foo, so just redirect the request to the view:

(r‘^tags/(?P<tag_name>[\w-]+)/$’, views.by_tag)

And handle it in views.py:

@login_required
def by_tag(request, tag_name):
    tag = Tag.objects.get(name=tag_name)
    return list_detail.object_list(
        request,
        queryset=TaggedItem.objects.get_by_model(Book, tag),
        template_name=“bookshelf/book_list.html”,
        extra_context={‘title’: ‘Tagged by %s’ % tag_name},
    )

All the tedious work has been handled by django-tagging: we first get a tag object by name, and then build a QuerySet using get_by_model method; the rest is handled by the generic view, done. Salute to django-tagging developers!

We would discuss how to add a tag in the next post, that is the magic of Dojo.

Python/SOAP: second encounter

Web January 15th, 2008

It looks like my experience in Python/SOAP programming no better than the first encounter. Here is the full story:

I am working on a client application to consume Microsoft SharePoint server web service recently. Since the client does not support scripting, I decided to develop a Python console application to ease my routine job.

The first two candidate are SOAPpy and ZSI. SOAPpy is the official library used in the DiveIntoPython, and ZSI is the succeeder of SOAPpy.

The first problem I have met in Python 2.5 environment is ZSI-2.0 depends on PyXML, which is not compatible to Python 2.5 though, so I migrated to ZSI-2.1_a1, and eventually get ZSI successfully imported. ZSI supports two approaches to use WSDL, I must admit I won’t consider any web service without WSDL.

  • ServiceProxy: dynamically build the method proxy in the run time
  • wsdl2py: generate the python code in compile time for later use

Neither of them works even for a simple web service from xmethods.com. Some type error or attribute exception is thrown when calling service method.

So I went back to the traditional SOAPpy. Though it is a little annoying to build fpconst, (thanks to easy_install to make it less painful), I really love the SOAPpy’s API, simple and stupid:

from SOAPpy import WSDL         
wsdlFile = ‘http://www.xmethods.net/sd/2001/TemperatureService.wsdl’)
server = WSDL.Proxy(wsdlFile)
server.foo(‘bar’)

However, the SOAPpy generate wrong SOAP message. Once the type is declared as sequence, the SOAPpy would insert tag as the container, that failed the service provider.

Don’t forget we have not touched the authentication, NTLM, the default certification policy used in most of the SharePoint server in the Intranet. This is really a long way to go.

UPDATE: Moved to Web category, so it won’t pollute the Gentoo Planet.

UPDATE: Thanks to Lawrence’s advice, I did try soaplib tonight last night. It is really a promising library for SOAP, the parser is based upon cElementTree, so it is supposed fast and memory-friendly. Once you build the service provider, Bang, you already get the consumer application. The only problem is there is no official support for WSDL. wsdl2py in ext package seems promising, it is under active development and should not be used in a production scenario, and checked-in 1 year ago. No wonder there are tons of errors in WSDL parsing. I just wonder optio developers may have a private code repository for daily check-in, and they may sync their work to the public from time to time.

Once I finish WSDL specification, I may refactor the wsdl2py module.

One up to Python expert (1) - Decorators

Development November 15th, 2007

I have been using Python for almost 4 years. I still remembered how amazed I was by the elegance of code indention, simplicity at the first sight, started from the official tutorial, then dive into it, daily scripts, then couple of side projects, but until today, I still hesitate to claim a Python expert. I would rather share this series of the journey to broaden my vision and deepen my insight on this beautiful language.

Introduction

Dr. David Mertz has a stunning demonstration in Charming Python column show this language feature, decorater. Here is the sample code to add spam, the favorite food for python, to arbitrary function:

#!/usr/bin/env python

def addspam(fn):
        def new(*args):
                “new method”
                print “spam spam spam”
                return fn(*args)
        return new

@addspam
def add(a,b):
        “add method”
        print a**2 + b**2

if __name__ == “__main__”:
        add(3, 4)

The output of is:

spam spam spam
25

According to the Python language reference, the @ operation is defined as:

Decorator expressions are evaluated when the function is defined, in the scope that contains the function definition. The result must be a callable, which is invoked with the function object as the only argument. The returned value is bound to the function name instead of the function object. Multiple decorators are applied in nested fashion.

Therefore, our add is defined as:

add = addspam(add)

new is an anonymous function, the name is arbitrary since we would never call it directly. When add is invoked, addspam is evaluated and returns a callable object, new, which accepts the arguments, then is executed. As a well-behaviored decorator, new eventually calls the decoratee after spreads the word, “spam”.

Before we rush to more sophisticated application, let’s take a look at the flaws of the crystal ball. Yes, it is not crystal transparent, new blocks the signature of add:

>>> print add.__doc__
new method

We can copy the meta data by all means, but is there a smart way to avoid the boilerplate code? Yes, we can use Michele Simionato’s decorator library like this:

#!/usr/bin/env python
from decorator import decorator
@decorator
def addspam(fn, *args, **kw):
    “new method”
    print “spam spam spam”, args
    return fn(*args)

@addspam
def add(a,b):
    “add method”
    print a**2 + b**2

if __name__ == “__main__”:
    print add.__doc__
    add(3, 4)

That is quite dizzying, What is the on the earth under the hood?

Under the hood

First, let us inspect the vanilla version, each decorator would block the signature of the decoratee, illustrated by different colors.

Signatures blocked by decorators

Here is the code snippet of decorator.py

def decorator(caller):
    def _decorator(func): # the real meat is here
        infodict = getinfo(func)
        argnames = infodict[‘argnames’]
        assert not (‘_call_’ in argnames or ‘_func_’ in argnames), (
            ‘You cannot use _call_ or _func_ as argument names!’)
        src = “lambda %(signature)s: _call_(_func_, %(signature)s)” % infodict
        # import sys; print >> sys.stderr, src # for debugging purposes
        dec_func = eval(src, dict(_func_=func, _call_=caller))
        return update_wrapper(dec_func, func, infodict)
    return update_wrapper(_decorator, caller)

The first difference that caught my eye was the _decorator’s argument, func, instead of new’s *args. Does this matter?

Yes, that is the trick of the magic. decorator decorates the addspam which decorates add, are you still awake? So add is the argument for decorator’s anonymous function, i.e _decorator.

There are two assistants for the magic: getinfo copy the signature of the function; update_wrapper seals the _decorator with caller’s signature. When add is invoked, decorator(addspam) is evaluated, which returns _decortor with addspam’s signature, in another word, decorator is transparent to addspam. _decorator is also the decorator of add, so _decorator(add) is executed:

  1. Sanity check: make sure keyword is not used in the argument names
  2. Cook the real meat: build addspam(add) in dec_func. Please check 3.6.2 String Formatting Operations for the syntax of mapping dictionary.
  3. Seal the can with fun(i.e add)’s signature

Here is the dynamic illustration:

Signatures relayed by decorators

Patterns

I would discuss this topic in detail later, you could take a look at official wiki.

Memorize

This pattern is well-documented in Wikipedia, and here is an effective but obtrusive implementation in DDJ[1], the corresponding python implementation is much more intuitive:

@memoize
def fib(n):
    print “%d is caculated” % n
    if  n < 2 :
        return 1;
    else:
        return fib(n-1) + fib(n-2)

Programming by Contract

Programming by Contract is an approach for software engineering. Microsoft Visual C++ introduced SAL annotations for precondition and postcondition. Decorators helps to separate the contract and logic[2]:

@precondition(“tom > 0″)
@precondition(“jerry > 1″)
@postcondition(lambda x: x > 1)
def foo(tom=1, jerry=2, rose=3, jack=4):
        print tom
        return jack

Precondition determines the requirement of the arguments, it is more convenient to use names of arguments for evaluation; postcondition specifies the return value, function object is more appropriate to refer the returned value. Here is the full implementation.

Aspect oriented programming

AOP is quite popular in Java community, there is corresponding Python project, PEAK for enterprise environment. For lightweight AOP developer, the decorator could do some help, such as the canonical fund transfer example:

@precondition(“amount > 0″)
@precondition(“fromAccount.amount > amount”)   
def transfer(fromAccount, toAccount, amount):
        # TODO: add transaction here.
        fromAccount.withdraw(amount)
        toAccount.deposit(amount)

Conclusion

Decorator opens a door to override the default behavior of function. The add-on lets the magic shine and hide the mechanism behind the curtain.

[1] It would be a juicy topic to implement decorator via metaprogramming
[2] Serious DBC users may consider PyDBC