Webware certainly isn't the best and hottest and most wonderful of all application servers out there. There's Paste, for one thing, which has a Webware emulation layer in case you ever want to move your Webware application to the latest and greatest. I'm going to use Webware because it works and because, as Bruce Eckels once said about Python in general, It Fits Your Brain.

(Bruce once also coined of Python the phrase, "Life is better without braces." He was talking about Python's use of whitespace, but I'm building toward a use of Python as a Web generation language and in a future entry I'll show you how to use Python's metaprogramming capabilities to build HTML, XML, and JSON without worrying too much about hand-coding HTML, XML, or JSON.)

What do you need to know about Webware? Let's start with a concrete example: What happens in Webware when you browse to http://localhost:8080/DemoPage (assuming it exists, of course, which it will, soon, if it doesn't already)?

Webware, the AppServer, looks at the path and determines if the first part of it refers to one of several Applications. An "Application", in the definition of a web application is a collection of web pages and their underlying machinery intended to get something done. A Webware process can host multiple applications, but for our simple case, we'll use just one, the default application, which is '/'.

Webware creates a Transaction object, which contains one each of Request, Response, and Session objects, and sends this transaction to Webware's internal router. We'll use the default router for now. The default route that came when we set up our application last time created a directory, MyContext, and it's in there that Webware looks for a Page to handle the transaction.

(There are two technical sticking points here. First, if this is your second or later visit to that URL, it's entirely likely that Webware fetched the Page object out of its cache. The Page object will retain values that were set on the object in previous transactions, which can mess up your logic. Also, these values cannot be relied upon; the Appserver is just as likely to build a new page object.

Second, a pedantic writer would have started with the whole Servlet idea, of which Page is just a kind of servlet, but I think that's just confusing. For now, you care about Pages. We'll worry about Page parent classes much later.)

The article Anatomy of a Webware Transaction discusses this from the point of view of the application server. But in my experience, the correct point of view for understanding is yours. So here's what happens:

Webware looks inside MyContext for a file called DemoPage.py, inside of which there must be a class named DemoPage that must inherit from Webkit.Page. Webkit.Page exists within the context of the application, so it can be imported easily.

So, short form: http://localhost:8080/DemoPage translates to /MyContext/DemoPage.py, which must contain:

from Webkit.Page import Page

class DemoPage(Page):

Webware then calls three methods on the DemoPage object it found or created: awake(), action(), and sleep(). You'll rarely write any of these methods yourself; you'll usually rely on Page's behavior. Instead, you'll write actions and writers.

Let's do the most basic: just write stuff. To do that, you create a method called writeContent. If you go find Webware's Page.py, you'll see that it does a lot of stuff for you. It writes out your DTD, your HTML header, and the tags. Everything else can be put into a single method: writeContent. This method is what you use to send the most common response back to the browser: a chunk of HTML.

So go ahead and open up a file called DemoPage.py, and put in the following:

from Webkit.Page import Page

class DemoPage(Page):
    def writeContent(self):
        self.write('<h3>Hello World!</h3>')

Congratulations, you've just written a web-based application. You can now browse to http://localhost:8080/DemoPage and see the results. Even better, if you open it up in Firebug (you do have Firebug installed, right?) you can see what the HTML looks like, which is pretty good.