Python Paste


Wareweb

Introduction

Wareweb is a rethinking of the ideas behind Webware. Webware is a fairly old framework, written back in the days of Python 1.5.2, and some of the API decisions behind it now show their age. Also, many of the abstractions in Webware didn't turn out to be useful, while some other abstractions are missing.

Wareweb tries to keep the basic model of Webware, while simplifying many portions and adding some new techniques. It's not backward compatible, but it doesn't require major revamping to apply to a Webware application.

Wareweb also requires Python 2.4; as long as we're updating the API, I want to make it as modern as possible. Decorators in particular are widely used in the framework.

Status

Wareweb was an experiment in framework design. It's a fairly stable piece of software, and some code is build upon it, but further development is not planned. The author recommends looking at other WSGI-based frameworks, like Pylons.

Configuration

A simple paste.deploy configuration for a Wareweb application named MyPackage looks like:

[app:main]
use = egg:Wareweb
app_name = mypackage
package_name = mypackage
debug = true

You can create a basic package with paster like:

paster create --template=basic_package MyPackage

You'll have to create a mypackage.web package after. An example that hasn't been updated recently, but may be helpful, is available in the repository.

Interface

See paste/wareweb/interfaces.py for a description of the IServlet interface; the online documentation for IServlet is a good description.

Components and Events

There are a couple fairly simple metaprogramming techniques added to Servlet to make it easier to add functionality.

Active Attributes

When you create a class, attributes can be "active". That is, simply assigning the attribute can cause changes to the class.

This is implemented by looking for a special method __addtoclass__ in all new attributes. The dispatchers, for instance, add themselves as "event listeners," so that simply by putting a dispatcher in your class definition somewhere you'll have changed the functionality of the class.

Events

Many methods throw events (with paste.wareweb.event.raise_event). An event is sent to each listener on the object, and the handler can do nothing (returning event.Continue) or can override or respond to the event in some way.

Dispatching objects listen for the end_awake event (called at the end of awake()), and may call an extra method on the servlet based on some criteria (like _awake_ or path_info).

Templating systems can use an event to write a template. ZPTKit overrides start_respond to write the template.

Unpacking Methods

On a per-method basis you can use the algorithms in paste.wareweb.unpack to unpack your request. E.g., something like:

dispatch = MethodDispatch()

@public
@unpack
def edit_item(self, item_id_int_path, name):
    Item.get(id=item_id_int_path).name = name

This unpacks a request like servlet_name/edit_item/1?name=new_name into the function call. Note that MethodDispatch makes /edit_item call the edit_item() method. @public declares that the method is actually available to the public. @unpack uses the method signature to identify the parts -- item_id_int_path ends with _path, and so will be taken from path_info; and has _int and so will be coerced into an integer.

Automatic Properties

Methods that end with __get, __set and __del will automatically be turned into properties. Subclasses can selectively replace just one of these implementations, while leaving the others in place.

Differences from Webware

This is a rough summary of the differences from Webware. There's lots of little things that are just plain gone; this doesn't enumerate all of them.

No Request And Response

There are no longer request and response objects. There is only the servlet. The servlet contains all the useful methods from these objects.

From the response, several methods:

  • set_cookie
  • set_header
  • add_header
  • write
  • redirect

From the request, several attributes (note: no methods):

  • environ
  • config
  • request_method
  • app_url
  • path_info
  • path_parts
  • fields

For more exact details, see paste.wareweb.interfaces.IServlet

Only One Servlet Class

There's one Servlet for everyone -- no Servlet, HTTPServlet, and Page. All servlets instances are not threadsafe, because they contain information about the request and response in their instance variables. In practice no Webware servlets were threadsafe, nor was there anything to be gained by that.

Also, reusable functionality is not meant to be added with subclasses of Servlet. Subclassing is for the end-developer to add application-specific functionality; there's other techniques for adding reusable functionality.

No _action_ by default

URL dispatching is handled more generically; several dispatchers are available, one which implements the _action_ parsing of Webware. Dispatchers for XML-RPC and JSON-RPC are also possible, and they have their own built-in methods of indicating methods. Other forms of URL parsing are also implemented.