Spa: My Imperfect Python Web Framework

Thu 28 May 2015 | -- (permalink)

A few posts ago I lamented the absence of a Python web framework that worked just the way I wanted, and started messing with some proof-of-concept code for a framework that would.

Things have snowballed since then. I started implementing my ideas in a smallish project at work. Some of my colleagues started pulling parts out into a separate library. I presented my thoughts at a conference the other day.

My friend Tabo teased on IRC "you're going to end up writing a framework. deep inside you know it." I've resisted this, because frameworks inevitably have to pick a preferred application structure, favor integrating some tools over others, and sometimes build more walls than bridges. For all that I learned from Django and all the time it has saved me in building websites, I've also spent a lot of time fighting and swearing at it. I really don't want to build something that people have to fight and swear at.

In speaking with people after my talk though, I realized just how much domain knowledge was hidden in the glue code that makes my sample app work, and I felt apprehensive about them stumbling over all the gotchas that I didn't have time to cover. That, and the desire to start using these patterns in more projects, have proven Tabo right.

I'm making a web framework. It's called Spa. The name is good for a few reasons:

  1. It's short.
  2. It sounds relaxing.
  3. It was available on PyPi.
  4. The letters can stand for Single Page Application, the kind of app that I want to make it easier to write.

I'm still working out exactly what should go into it. I'm at version 0.0.1, and have used it to re-implement my Python- and Postgres-backed version of the TodoMVC app.

The features so far:

  1. A dispatcher for class-based, REST-style routing.
  2. Support for the RESTSockets pattern (treating websocket connections as another REST method that means "stream any changes to this resource").
  3. A built-in, configurable handler for serving a folder full of static files at a designated path in your app. (Werkzeug has a built-in middleware for this, but I wanted it to be in my routes, not my middlewares.)
  4. A streaming gzip middleware.

And the things I want to add next:

  1. Merge in the streaming backend abstractions that my colleagues put into the Banter library at our recent hackathon. (I don't know where that code is though. :( ).
  2. Some brain-dead-simple helpers for serving a home page (the one piece of content we have to render server side, to bootstrap everything in the browser). Mostly this means generating tags for JS and CSS files, and doing content-based cache busting. I have this in the Todo app, but haven't pulled it into Spa yet.
  3. A really good tutorial that teaches the reader how to build a real time web app with the framework.

I'll try to blog my progress here.