About

Archive for August, 2011

Introspecting Python Decorators

Over the last couple of years I’ve found myself using python decorators to annotate handlers for web requests more and more, both when using Django and with micro-frameworks like mnml and newf.

Where the same functionality is required for all handlers, or the required functionality can be determined from standard request or response headers, using WSGI or Django middleware is fine, but where the required functionality is varies based on the handler its much cleaner to use a parameterised decorator than poluting the environment or response objects just to control the middleware. Functionality can be added to a framework as a suite of decorators and plugged together in an aspect oriented way like lego to easily build up sophisticated behaviours.

Unlike other mechanisms for implementing macros, templating or aspect orientation that introduce a new language, python decorators are pure syntactic sugar that under the hood are simply rewritten as python expressions:

@requires_oauth_scope("email")
def notify_friends(request):
    pass

Is simply shorthand for:

def notify_friends(request):
    pass

notify_friends = requires_oauth_scope("email")(notify_friends)

This simplicity is powerful as it allows decorators to also be used as normal functions, for example to build up higher level decorators that bundle common decorator configurations, but it also means that decorators potentially interact badly with another powerful Python feature: introspection.

In the above example the undecorated notify_friends function has the __name__ “notify_friends”, but the decorated function has the __name__ “requires_oauth_scope”. When decorators are used extensively, this can seriously impact the usefulness of introspection for debugging or generating documentation.

Decorating your decorators with the functools @wraps decorator, which copies the __name__ of the wrapped function over to the wrapping function solves this introspection problem, but introduces another: the decorators now become invisible to introspection. In the example above the __name__ of the decorated function would now be “notify_friends” as in the undecorated case, but we wouldn’t know that the function had been decorated or not.

A potential solution to this new problem is to store the details about the decoration in another attribute that can be inspected at runtime. In addition to copying over the __name__ attribute, functools.wraps also copies over the target __dict__ by default, allowing it to be used to store information about the decoration and be correctly copied over when decorators are chained:

from functools import wraps

def requires_oauth_scope(scope):

    def decorator(target):

        target.__dict__["my_project_requires_oauth_scope"] = scope

        @wraps(target)
        def wrapper(*args, **kwargs):
            # return target(*args, **kwargs) or FORBIDDEN if token does not have required scope

        return wrapper
    return decorator

By constructing decorators in this way we get the benefits of python decorators and more declarative C# style attributes that are visible to introspection.

You’re The Boss Lives!

You're The Boss Screenshot

Back in 2005, while I was working on Second Life in Nottingham, before Linden Lab Brighton existed, I ran a workshop as part of the Screenplay “Boss Frenzy!” day at the Radiator Festival which allowed children to collaboratively create a computer game by drawing or making bosses with collage.

Dozens of people came to the Broadway in Nottingham and got busy with pens, pencils, paper, scissors, glue and magazines to design bosses for our “You’re The Boss!” shmup. We had an amazing time and created a charming and delightful game which I talked about on the original Second Life blog.

I immediately thought of it when we started planning the Brighton Maker Faire a couple of months ago and was delighted when the project was accepted. Unfortunately 6 years of bit rot had taken it’s toll and disaster loomed after discovering that I’d hosted the Game Maker files on the web space provided by an old ISP account and didn’t have them on my patchy backups. Luckily the ever amazing Torley had a copy of the executable and with the help of a decompiler I was able to recover the Game Maker files I needed to run the project again.

So, if you’re near Brighton on the 3rd of September and like the idea of collaboratively making an arcade game with scissors, glue and pens then please come along. If you have a Windows machine then check out the game we made in Nottingham in 2005. I think it’s still charming and delightful 6 years on. You can download it here.

This time round I’d like to make the game completely out of Creative Commons licensed works, so please suggest CC licensed books, comics and pictures that might make good source material in the comments, or bring them along on the day.