Leslie Orchard just wrote a WSGI middleware for interpreting XSLT. This is cool, because it's one of those things I've thought is perfect for WSGI, and I even mentioned it yesterday. This means any WSGI application can output XML and have it transformed by an XSLT stylesheet, without any awareness on the part of the application.
It's also great to see someone catch on to what WSGI is about. I'm afraid I haven't been that successful explaining it. But maybe I should use his endorsement of the architecture: "it's not another damn framework."
And that's exactly the kind of architectural principle that made me write Paste. I've been describing it as a "framework framework", which is awful -- 2x the badness! Really, it's a collection of exactly the sort of thing that Leslie wrote -- simple, decoupled bits of middleware. Oh, damn, there's that "middleware" word again, which is also bad. Simple, decoupled filters. Everything else in Paste is the crap I had to put in to get it to work together. Stuff like configuration. This isn't what makes me excited -- it's just the pain in the ass that someone needs to do, and at least in the context of WSGI no one else is doing it.
What makes me excited is bits of code like this. This is 55 (logical) lines of code that implement XSLT in front of any Python application that produces XML (and if someone writes a WSGI proxy app, in front of any application in any language). 55 lines -- that is what excites me.
So, like, if you have a web app that follows the WSGI spec, it can be swallowed up by filtering apps. The filtered apps can have any number of mammoth Python web frameworks powering them, and the filters can be as complex or simple as you want. Hell, build a web framework entirely out of composed filters! [emphasis his]
Which is exactly what I did with Paste's Webware interface, and later Wareweb -- I moved everything I could into middleware, and built the shell of a framework around it. And it works -- the core of paste.webkit is 776 lines of code, and the code it replaces is 6313 lines of code. That 700ish lines of code doesn't provide all the functionality of the original 6000ish lines of code; but it builds a Webwarish thing on top of generic libraries. For both of them I don't count the 600 lines in the standard library's cgi module either, or the 50,000+ lines in the standard library as a whole; so I think there is a fair comparison. If you refactored a framework like CherryPy to use WSGI middleware, I think you'd see the same kind of results.
The point of Paste is that you shouldn't have to compromise between simple and full-featured, or between abstract and convenient, or general and concrete. Paste is WSGI. Paste is filters built on filters. Paste is HTTP turned into Python dictionaries. WSGI is working from where CGI left off. It's the simplest thing that can work. It's not a framework.
I can't believe how far behind I've let myself get. I started futzing around with things like PHP and postnuke, and completely lost track of all the cool stuff going on in the python community. I hadn't even heard of WSGI until I ran across django by accident.
I have so much catching up to do!
Ian, I think finally get it. :-)
Paste is not a 'framework framework' and it's 'middleware'... it's 'filters'! <cue sound of mind going 'click!'> My brain only 'gets' things when I can see a practical use for it. :-)
I've been playing around with CherryPy's filters and that description makes sense. You can write a function or class method once, and use filters to repurpose the functions/methods for different contexts (HTTP/HTML vs XML-RPC) without touching your original function/method definitions.
Perhaps, you could also call them "wrappers" or "envelopes". And I'm sure Martin Fowler has a pattern with a really complicated name for it, too. :-) But filters fits my brain the best.
With filters (at least as I understand it in CherryPy), you can do the following:
Write a function called helloWorld() that simply returns the string "Hello, world!"
Now go write a filter that can accept XML-RPC commands and dispatch them to any function, and take any return values and return them as XML-RPC. (CherryPy already provides this for XML-RPC).
Do the same for SOAP, YAML, XML, JSON, GZIP compression, conversion to PDF, or whatever
- Setup up your config so various URLS can call your helloWorld using a filter of your choosing:
http://localhost/soap/helloWorld -> callable via SOAP client library, calls hellWorld, and returns "hello world" as a SOAP response. http://localhost/xmlrpc/helloWorld -> same thing as SOAP, but for for XML-RPC http://localhst/yaml/helloWorld -> etc, etc.
Voila! Paste now makes sense to me. I can see how this would be useful, too... I don't think Django does Webservices (XML-RPC, SOAP, REST), yet. (I could be wrong, but I haven't seen any mention of it, yet.) If there was a "standard" implementation of "filters" that other frameworks could use... then Django could benefit from this work for free without having to reimplement CherryPy's filters.
Now that I've written all of this... Do I understand WSGI and Paste correctly? Now, that I think about it... you also just reinvented unix pipes, but for the web. And I think Apache 2 even implements the same thing, too. (http://www.projectcomputing.com/resources/apacheFilterFAQ/) Correct?
I've been trying to understand WSGI and Paste for a while now, and have stayed subscribed to your blog despite not understanding what you were talking about. I kept wondering why you didn't just do something like Rails in Python.
The 0xDECAFBAD blog entry definitely made all the difference for me in understanding what you are doing, and why you are doing it. The 'framework' and 'middleware' words definitely have too much baggage to be used to describe something truly new and innovative. Another way of thinking about it is that we are only starting to see the first web frameworks worthy of the name, and perhaps the same can be said of WSGI as an example of 'real' middleware, at least in the brave new world of web 2.0.
I just wonder whether the Ruby/Rails people will be interested, and if so how they will adopt the ideas. I can't help but think about how cool it would be for the Python and Ruby people to use each others code.
Good work Ian, I hope you see some payback for your perseverance.