Wareweb
=======

.. contents::

Introduction
------------

Wareweb is a rethinking of the ideas behind `Webware
<http://webwareforpython.org>`_.  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.

Configuration
-------------

A simple `paste.deploy <http://pythonpaste.org/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
<http://pythonpaste.org/script/>`_ 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
<http://svn.pythonpaste.org/Paste/branches/old-pre-deploy-version/examples/todo_wareweb/>`_.

Interface
---------

See ``paste/wareweb/interfaces.py`` for a description of the
``IServlet`` interface; the `online documentation for IServlet
<http://pythonpaste.org/wareweb/class-wareweb.interfaces.IServlet.html>`_
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.
