This is the complete documentation from SVN.
To get it:
$ svn co http://divmod.org/svn/Divmod/trunk/Nevow/ Nevow-svn
$ cp -a Nevow-svn Nevow-svn-withoutdoc
$ rm Nevow-svn-withoutdoc/**/*.{xhtml,tpl}
$ diff -Naur Nevow-svn-withoutdoc Nevow-svn
diff -Naur Nevow-0.10.0/doc/howto/chattutorial/concepts.xhtml Nevow-0.10.0-new/doc/howto/chattutorial/concepts.xhtml
--- Nevow-0.10.0/doc/howto/chattutorial/concepts.xhtml 1970-01-01 01:00:00.000000000 +0100
+++ Nevow-0.10.0-new/doc/howto/chattutorial/concepts.xhtml 2010-03-02 20:42:55.000000000 +0100
@@ -0,0 +1,136 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Concepts</title>
+ </head>
+<body>
+
+<h1>Concepts</h1>
+
+<h2>Servers and Clients</h2>
+
+<p>COMET applications can seem an almost impenetrable mess when one is first
+learning about them, much like when writing event-based desktop
+applications. However, there are some basic concepts that we can emphasize now
+to circumvent or alleviate most of the confusion.</p>
+
+<p>In principle, the problem is very simple:</p>
+<ul>
+<li>We want out users to interact with a <q>web page</q> with out having to refresh
+the page, and we want new data and/or views to be rendered in response to our
+users' actions;</li>
+<li>We want the ability to push updates to user pages from the server to the
+browser, when the server has new data or views that are ready.</li>
+</ul>
+
+<p>As usual, the implementation of the solution is much more complicated than
+the statement of the problem, but hopefully the way that we have designed
+Athena will hide those implementation details while providing powerful tools to
+build the applications you envision. So, let's take a look at what you need to
+know about servers and clients when building Athena web applications.</p>
+
+<p>It is crucial that one understands that when we write Athena applications,
+we are doing a few different things:</p>
+<ul>
+<li>Writing server code in Python that performs server actions</li>
+<li>Writing server code in Python that makes remote calls to the browser</li>
+<li>Writing browser code in JavaScript that performs browser actions</li>
+<li>Writing browser code in JavaScript that makes remote calls to the server</li>
+</ul>
+
+<p>Since server-on-server and client-on-client are rather common place and
+generally well understood, we will ignore those for now. As the other two
+are the focus of AJAX/COMET and thus also the primary domain of Athena, that is
+what we will discuss below.</p>
+
+<p>Browser-to-server calls are made by Athena via the now-famous
+ XMLHttpRequest. Server-to-browser calls are opened by the browser ahead of
+time, and when the server is ready, the data is sent to the browser via that
+connection.</p>
+
+<h2>JavaScript: Making Calls to the Server</h2>
+
+<p>When creating the JavaScript portion of our applications, we subclass
+an Athena JavaScript widget, which has a method named
+<code>callRemote()</code>. By utilizing this method, we can send messages from
+our JavaScript client to the server (as long as the method we call exists in
+the server code).</p>
+
+<p>For example, in the chat application we will be building in this series
+of tutorials, we will have a JavaScript class called <code>ChatterBox</code> with a
+<code>say()</code> method, like the following:</p>
+<pre>
+function say(self, msg) {
+ self.callRemote("say", msg);
+ // Now show the text to the user somehow...
+}
+</pre>
+<p>This will make a remote call to the Python server code, executing the
+<code>say()</code> method and passing the <code>msg</code> variable as a
+parameter.</p>
+
+<p>In Athena, the relationship between the browser code and the server code is
+established by declaring the JavaScript module in the Python server code, in
+the following manner:</p>
+<pre class="python">
+class ChatterBox(LiveElement):
+ jsClass = u'ChatThing.ChatterBox'
+</pre>
+<p>Additionally, in order for the JS to be able to make a call to remote Python
+code, the Python method has to be exposed. This is a security feature,
+implemented to ensure the JavaScript code can only call Python methods that
+have been specifically marked as safe. Appropriately enough, this is done in
+your Python class with the <code>expose</code> decorator:</p>
+
+<pre class="python">
+def say(self, text):
+ for chatter in chatRoom:
+ chatter.youHeardSomething(text)
+say = expose(say)
+</pre>
+
+<h2>Python: Making Calls to the Browser</h2>
+
+<p>Now what about the COMET side of the equation? If we want our server to
+update data in the browser, we need to be able to call JavaScript code from our
+Python server. We use a similar Python method as the JavaScript one (when
+making calls from the browser to the server), acquired when our Python class
+inherited from <code>nevow.athena.LiveElement</code>:</p>
+
+<pre class="python">
+def hear(self, sayer, text):
+ self.callRemote("hear", sayer, text)
+</pre>
+
+<p>In order for this call to work, we need to have the <code>hear()</code>
+method defined in our <code>ChatterBox</code> JavaScript class, and that will
+look like this:</p>
+<pre>
+function hear(self, avatarName, text) {
+ // Here, you'd show the user some text.
+}
+</pre>
+
+<p>Unlike on our Python classes, no special annotations need to be made on the
+JavaScript side: all JavaScript methods on browser-side Widget objects are
+allowed to be called by the server. If you've sent code to the browser, you've
+already forfeited the ability to control when it's called. There wouldn't be a
+point to limiting the server's rights to run its code when the user can freely
+run it herself.</p>
+
+<h2>Summary</h2>
+
+<p>With the samples above, you should have a growing sense of how Python and
+JavaScript interact as servers and clients in the world of Athena. In
+particular, you should be getting a sense of how JavaScript and Python will be
+interacting in your Athena applications.</p>
+
+<p>This has just been a taste of Athena with a few peeks into the code we
+will be writing. We will cover these topics in greater detail in the following
+pages, within the context of creating a functional Athena application,
+complete with step-by-step instructions and rationale.</p>
+
+</body>
+</html>
diff -Naur Nevow-0.10.0/doc/howto/chattutorial/env.xhtml Nevow-0.10.0-new/doc/howto/chattutorial/env.xhtml
--- Nevow-0.10.0/doc/howto/chattutorial/env.xhtml 1970-01-01 01:00:00.000000000 +0100
+++ Nevow-0.10.0-new/doc/howto/chattutorial/env.xhtml 2010-03-02 20:42:55.000000000 +0100
@@ -0,0 +1,122 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Setting up an Environment</title>
+ </head>
+<body>
+
+<h1>Setting up an Environment</h1>
+
+<h2>Install</h2>
+
+To run this tutorial, you need to have nevow available to python and
+you'll need the files in the doc/howto tree. You don't even have to
+install nevow; the examples will run within the source tree.
+
+
+<h3>Combinator: The Divmod Way</h3>
+
+<p>Using SVN
+with <a href="http://divmod.org/trac/wiki/DivmodCombinator">Combinator</a>
+is the best way to try out the example code in-place (and hop between
+other SVN branches in the future). This is how we develop and test our
+applications at Divmod. If you have a system installation of Twisted
+that you don't want to update or interfere with, you can use this
+method without installing anything.
+</p>
+
+<ol>
+
+<li>Create a projects directory or change to some other test directory
+of your choice:
+<pre class="shell">
+$ mkdir ~/Projects
+$ cd ~/Projects
+</pre>
+</li>
+
+
+<li>If you don't have the
+<a href="http://twistedmatrix.com/trac/">twisted library</a>, check it out now:
+<pre class="shell">
+$ svn co svn://svn.twistedmatrix.com/svn/Twisted/trunk Twisted/trunk
+</pre>
+</li>
+
+<li>Then get Combinator and Nevow (and the rest of Divmod). See the
+<a href="http://divmod.org/trac/wiki/CombinatorTutorial">Combinator
+Tutorial</a> for more about these special checkout paths.
+<pre class="shell">
+$ svn co http://divmod.org/svn/Divmod/trunk Divmod/trunk
+</pre>
+</li>
+
+<li>Set up the Combinator environment in this shell. You'll need this
+step in any future test shells since it adjusts PATH and PYTHONPATH:
+<pre class="shell">
+$ eval `python Divmod/trunk/Combinator/environment.py`
+(some "link:" lines are normal)
+</pre>
+</li>
+
+<li>Register both the Twisted and Divmod (and thus Nevow+Athena) codebases with
+Combinator:
+<pre class="shell">
+$ chbranch Twisted trunk
+$ chbranch Divmod trunk
+</pre>
+</li>
+
+<li>You can check to see if your environment is ready to go by running the
+tutorial tests (from any directory, after executing the previous command):
+<pre class="shell">
+$ trial nevow.test.test_howtolistings
+</pre>
+If they all pass, you're ready to begin the tutorial.
+</li>
+</ol>
+
+
+
+<h3>Standard distutils Installation</h3>
+
+<p>If you don't want to manage branches and environments with
+Combinator, you can install our code in the
+standard <code>site-packages</code> directory. You'll still need the
+source tree so you can use the files in doc/howto.</p>
+
+<p>For those that would prefer the <q>old way,</q> here's how you do it:</p>
+
+<ol>
+
+<li>Create a projects directory:
+<pre class="shell">
+$ mkdir ~/Projects
+$ cd ~/Projects
+</pre>
+</li>
+
+<li>Checkout and install the latest Twisted:
+<pre class="shell">
+$ svn co svn://svn.twistedmatrix.com/svn/Twisted/trunk Twisted
+$ cd Twisted
+$ sudo python setup.py install
+$ cd ../
+</pre>
+</li>
+
+<li>Checkout and install Nevow:
+<pre class="shell">
+$ svn co http://divmod.org/svn/Divmod/trunk/Nevow Nevow
+$ cd Nevow
+$ sudo python setup.py install
+$ cd ../
+</pre>
+</li>
+
+</ol>
+
+</body>
+</html>
diff -Naur Nevow-0.10.0/doc/howto/chattutorial/index.xhtml Nevow-0.10.0-new/doc/howto/chattutorial/index.xhtml
--- Nevow-0.10.0/doc/howto/chattutorial/index.xhtml 1970-01-01 01:00:00.000000000 +0100
+++ Nevow-0.10.0-new/doc/howto/chattutorial/index.xhtml 2010-03-02 20:42:55.000000000 +0100
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Nevow Athena from Scratch, or The Evolution of a Chat Application</title>
+ </head>
+<body>
+
+ <h1>Nevow Athena from Scratch, or The Evolution of a Chat Application</h1>
+
+<h2>The <q>Chat Tutorial</q> Series</h2>
+
+<p>
+Athena is the JavaScript engine behind Nevow, providing a great deal of
+resources and power to the developer of asynchronous web applications. To
+demonstrate this, we are using a web chat application as our primary example
+in this tutorial. The tutorial is split into several parts: a few introductory
+pages and then independent (but related) tutorials of increasing complexity.
+</p>
+
+<ol>
+ <li>Basics
+ <ul>
+ <li><a href="intro.xhtml">Introduction</a></li>
+ <li><a href="concepts.xhtml">Concepts of Athena: AJAX, COMET, and Python</a></li>
+ <li><a href="env.xhtml">Setting Up the Tutorial Environment and Running Tutorial Source Code</a></li>
+ </ul>
+ </li>
+ <li><a href="part00/index.xhtml">Toy <q>Echo</q> Application </a></li>
+ <li><a href="part01/index.xhtml">Simple Chat and Two-Way Communications</a></li>
+</ol>
+
+<h2>History</h2>
+<p>
+Nevow's predecessor was Woven (and prior to that, WebMVC). Woven had something
+called <code>LivePage</code> that was doing DOM manipulation as far back as
+2002. In early 2003, Woven event handlers supported sending JavaScript back to
+the user's browser, allowing pages to be updated in response to user-generated
+events. The earliest publicly visible revisions of Nevow made use of XHR
+(XMLHttpRequest) in early 2004. These facts are notable because Nevow was using
+AJAX a year before the term was coined in 2005 and had working code in 2002 and
+2003 that predated Netscape publishing articles on what they called <q>Inner
+Browsing</q> where all navigation takes place withing a single page.
+</p>
+
+<p>
+Again taking the lead, Athena offers features which developers cannot find
+elsewhere. In this series, we attempt to expose these excellent qualities
+to the world of application
+developers.
+</p>
+
+</body>
+</html>
+
diff -Naur Nevow-0.10.0/doc/howto/chattutorial/intro.xhtml Nevow-0.10.0-new/doc/howto/chattutorial/intro.xhtml
--- Nevow-0.10.0/doc/howto/chattutorial/intro.xhtml 1970-01-01 01:00:00.000000000 +0100
+++ Nevow-0.10.0-new/doc/howto/chattutorial/intro.xhtml 2010-03-02 20:42:55.000000000 +0100
@@ -0,0 +1,106 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Introduction</title>
+ </head>
+<body>
+
+<h1>Introduction</h1>
+
+<h2>Who is this tutorial for?</h2>
+
+<p>This tutorial is for people who want to build interactive client-server
+functionality where a web-browser is the client. It will show you how to build
+a live, interactive chat application that requires nothing more than a web
+browser that supports JavaScript.</p>
+
+<p>The interesting thing about a chat application, which shows why Nevow Athena
+is special, is that it involves two-way communication. In other words, it
+involves not only the recently-popular AJAX (the web browser sending commands
+to the server without loading a new page) but also the trickier and, in our
+opinion, somewhat cooler technique known as COMET (the web server
+sending commands to the <em>browser</em>).</p>
+
+<h2>Who is this tutorial <em>not</em> for?</h2>
+
+<p>Nevow Athena is <em>not</em> for people who want a normal web application
+framework. If you want one of those, you should use
+non-Athena-<a href="http://divmod.org/trac/wiki/DivmodNevow">Nevow</a>,
+<a href="http://www.djangoproject.com/">Django</a>,
+<a href="http://turbogears.org/">TurboGears</a>, or maybe even
+<a href="http://rubyonrails.org/">Ruby On Rails</a>. Athena doesn't work in terms
+of pages, links, or HTTP requests and responses; it is a client-server
+framework that works in terms of widgets, JavaScript objects, and symmetric
+asynchronous message queues.</p>
+
+<p>However, as alluded to above, Athena is part of a larger framework, Nevow,
+which can be used to build more general-purpose and <q>traditional</q>
+web applications.</p>
+
+<h2>AJAX</h2>
+
+<p>AJAX isn't a technology in and of itself, bur rather an amalgam of
+technologies used together in order to accomplish the goal of making web
+applications more responsive than traditional delivery and interactive
+mechanisms, such as HTML forms submitted to a server.</p>
+
+<p>In particular, AJAX consists of the following:</p>
+<ul>
+<li>Asynchronous communications from a user's browser to a server</li>
+<li>JavaScript</li>
+<li>Exchanged data (usually XML or JSON)</li>
+</ul>
+
+<h2>COMET</h2>
+
+<p>Historically, the focus of AJAX technologies was user-event driven. However,
+with the need to update the user's browser with events generated at the server,
+a solution more sophisticated than AJAX was needed; this has been dubbed COMET.
+Athena is implemented using both AJAX and COMET techniques, and therefore
+allows two-way browser <-> server communications.</p>
+
+<h2>Athena Basics</h2>
+
+<p>We've provided brief background information on AJAX/COMET, but what is the
+purpose of Athena? What makes Athena different than other solutions? Here are a
+few key points that should help with these questions::</p>
+<ul>
+<li>Athena exists to make writing COMET web applications easy.</li>
+<li>Athena is written in Python and JavaScript</li>
+<li>It is written to be used with Nevow, a <a
+href="http://twistedmatrix.com/">Twisted</a>-based web framework.</li>
+<li>Similar to Twisted's <a
+href="http://twistedmatrix.com/projects/core/documentation/howto/pb-intro.html">Perspective
+Broker</a>, Athena employs remote calls.</li>
+</ul>
+
+<p>Athena was written by Twisted and Divmod developers (in addition to
+contributing members of the community) in order to bring the outdated and
+Nevow-incompatible Woven LivePage technology to Nevow. In addition, it was an
+opportunity to improve upon the original design and incorporate new features to
+address the growing needs of developers.</p>
+
+<h2>Target Applications</h2>
+
+<p>Good candidates for Athena web applications would include those where the
+application needs to respond to user input and/or updates from servers, such
+as the following:</p>
+<ul>
+<li>conference software (e.g. whiteboard, shared text, chat, etc.)</li>
+<li>mail clients</li>
+<li>interactive, multi-player games</li>
+<li>social networking tools</li>
+<li>office applications (e.g., spreadsheets, word processors, etc.)</li>
+</ul>
+
+<h2>Target Developers</h2>
+
+<p>Anyone who wants to create interactive, web-based applications is a
+potential Nevow/Athena user. It's best to have some background in writing web
+applications, and in addition, to know how to use Nevow. However, we hope that
+this tutorial will be just as useful for beginners as experienced
+developers.</p>
+
+</body>
+</html>
diff -Naur Nevow-0.10.0/doc/howto/chattutorial/part00/index.xhtml Nevow-0.10.0-new/doc/howto/chattutorial/part00/index.xhtml
--- Nevow-0.10.0/doc/howto/chattutorial/part00/index.xhtml 1970-01-01 01:00:00.000000000 +0100
+++ Nevow-0.10.0-new/doc/howto/chattutorial/part00/index.xhtml 2010-03-02 20:42:55.000000000 +0100
@@ -0,0 +1,230 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Nevow Athena from Scratch: Echo Application</title>
+ </head>
+<body>
+
+<h2>What is an "Echo Application?"</h2>
+
+<p>
+Our first foray into building an Athena application will be an easy venture:
+we want to type something in an input box and have it echoed back to us on
+the same page, without having to reload anything. Why? Well, our eventual
+goal is to have a working chat server, with all sorts of technical bells
+and whistles (persistent storage, authentication,
+etc.), but that's a bit heady for right now. Many of the same principles
+which we will eventually employ in our chat application exist for a simple
+case of sending textual messages between a web browser and a server. This
+is the essence of our "Echo" application.
+</p>
+
+<h2>Mental Preparation</h2>
+
+<p>In the
+<a href="../intro.html">Introduction</a> and the
+<a href="../concepts.html">Concepts</a> pages, we had a refresher on AJAX and
+COMET and we learned a little bit about what that looks like for Athena. But
+as we sit down to actually write an Athena application, what do we need to
+wrap our heads around?
+</p>
+
+<p>Given the introductory knowledge we have, we know that we will need to
+write some JavaScript, some Python, and if our past experience in developing
+web applications is any guide, some form of template. This indeed is the
+case, but here's something big: we're not working with pages and page
+templates; we're working with "elements", or parts of the DOM tree. We will
+not be creating page resources; we will be creating just the parts of a
+"traditional" page that will be dynamic and interactive.
+</p>
+
+<h2>Architecture</h2>
+
+<p>Now that we've pumped ourselves up and before we start clacking away at the
+keyboard, we need to get pointed in the right direction. We need a
+plan. Here's what we know:</p>
+
+<ol>
+<li>We will have a server that:
+ <ul>
+ <li>serves dynamic elements in a resource accessible via a URL;</li>
+ <li>communicates with a client.</li>
+ </ul>
+</li>
+<li>We will have a client that:
+ <ul>
+ <li>communicates with the server;</li>
+ <li>updates its DOM tree.</li>
+ </ul>
+</li>
+</ol>
+
+<p>The user experience of this application will be the following:</p>
+<ol>
+<li>they will type text in an input on a form; and</li>
+<li>the typed text will be rendered to a different part of the page upon
+hitting a submit button.</li>
+</ol>
+
+<p>We will not simply write user input to a <code>div</code> with JavaScript
+DOM manipulation, but will instead pass data like we expect will be necessary
+when we write our chat application. After all, it's probably best to build
+towards our goal. In order to accomplish this, the application will do
+something like the following:</p>
+
+<ol>
+<li>JavaScript client code will extract user input and send
+it to our server;</li>
+<li>Python code will receive messages from the client;</li>
+<li>Python code will send messages to the client; and</li>
+<li>a template file (or <code>stan</code> code) will be used for
+presentation.</li>
+</ol>
+
+<p></p>
+
+<h2>Let the Coding Begin</h2>
+
+<p>In a future installment, we will outline the development process from
+the perspective of test-driven development, in order to not only show how
+to write unit tests for Athena (Python and JavaScript), but to encourage
+good programming practices while working with Athena. For now, though, we will
+just dive right in.</p>
+
+<h3>Presentation</h3>
+
+<p>Let's start with the easy bit: what our app will look like. Here is the
+template for our echo application:</p>
+
+<a href="listings/echothing/template.html" class="html-listing" />
+
+<p>Things to note:</p>
+<ul>
+<li>This is not a complete HTML document, but is an XHTML template for an
+"element".</li>
+<li>The name space declarations in the top <code>div</code> tag are necessary
+for the operation of Athena.</li>
+<li>When we hit the "Send" button, our JavaScript class will call the
+<code>doSay()</code> method.</li>
+</ul>
+
+<h3>Writing the Client</h3>
+
+<p>Next up is the JavaScript. We need to send our data to the server. In a
+full chat application, it would be necessary to send the data to the server
+so that we could propagate the message to all connected clients. In this
+case, with the simple echo, we're not going to do anything with the data
+that gets sent to the server, except send it back, of course.</p>
+
+<p>Our JavaScript will need to do several things:</p>
+<ol>
+<li>import required modules;</li>
+<li>inherit <code>callRemote</code> functionality from the base
+<code>Widget</code> class;</li>
+<li>setup convenience attributes;</li>
+<li>implement the <code>doSay()</code> method we put in our template above;
+and</li>
+<li>implement a method for updating the DOM with data it receives from
+the server</li>
+</ol>
+
+<a href="listings/echothing/js/EchoThing.js" class="py-listing" />
+
+<p>Points to note:</p>
+<ul>
+<li>Those import statements aren't just pretty: they are necessary! In Athena,
+you need to treat those like you treat the import statements in Python.
+</li>
+<li>The attributes set in the <code>__init__()</code> method are for
+convenience when we reference them in other methods.</li>
+<li>Note the <code>callRemote()</code> method in <code>doSay()</code>,
+As mentioned in the <a href="../concepts.html">Concepts</a> section, this
+is how JavaScript is communicating with our Python server.</li>
+<li>Another thing about <code>doSay</code>: this is the submit handler. As
+such, it needs to return false so that the browser is prevented from doing a
+normal form submission.</li>
+<li><code>addText()</code> is the method that will be updating the browser
+DOM once the server sends the data back.</li>
+</ul>
+
+<p>There's not much to say about the next one. This is what sets up the
+relationship between our module name and the actual file itself (so that
+the JavaScript can be loaded):</p>
+
+<a href="listings/nevow/plugins/echothing_package.py" class="py-listing" />
+
+<h3>Writing the Server</h3>
+
+<p>Despite what one might think, writing the server may be the easiest
+part! If you've created Nevow applications before, then this will look
+very familiar. The only method we need is one that will send data back to
+the client. Besides importing the necessary modules and creating a class
+with some boilerplate, that's about it.
+</p>
+
+<p>Let's take a look at the code:</p>
+
+<a href="listings/echothing/echobox.py" class="py-listing" />
+
+<p>As promised, simple as can be. We do make use of a Twisted utility that
+simplifies typing the path to our template. Some very important points:</p>
+<ul>
+<li>The <code>jsClass</code> assignment is what connects this code to your
+JavaScript code.</li>
+<li>As discussed in the <a href="../concepts.html">Concepts</a> section,
+the <code>expose</code> decorator is required if our JavaScript is going
+to be able to call the <code>say()</code> method.</li>
+</ul>
+
+<h3>Putting it All Together</h3>
+
+<p>Now that we've got all the code in front of us, we can trace out exactly
+what happens:</p>
+<ol>
+<li>the user loads the resource in their browser, and the template is
+rendered;</li>
+<li>after typing a message in the input box, the user hits submit;</li>
+<li>upon hitting submit, the client code <code>doSay()</code> method is
+called;</li>
+<li><code>doSay()</code> makes a remote call to the Python server method
+<code>say()</code>;</li>
+<li>the Python server receives the data when <code>say()</code> is called, and
+then it passes that data to the client code's <code>addText()</code> method;</li>
+<li>with control back in the client code and data fresh from the server,
+JavaScript can now update the page's DOM with the new data, and this is
+what the <code>addText()</code> method does;</li>
+<li>when <code>addText()</code> finishes, the cycle has completed and the
+browser now displays the latest data input by the user.</li>
+</ol>
+
+<h3>The Fruits of Our Labor</h3>
+
+<p>Now we get to run it! This is a little different than what you may be
+used to, if you have written Twisted applications in the past. We are using
+the plugin architecture of Twisted and Nevow such that <code>twistd</code>
+will publish our element in an HTTP service. To do this, we will use
+<code>twistd</code>'s <code>athena-widget</code> command:</p>
+
+<pre class="shell">
+cd Nevow/doc/howto/chattutorial/part00/listings
+twistd -n athena-widget --element=echothing.echobox.EchoElement
+</pre>
+
+<p>If you executed this against the tutorial code on your local machine,
+you can now visit <a href="http://localhost:8080">localhost:8080</a> and start
+echoing to your heart's content.</p>
+
+<h2>Summary</h2>
+
+<p>As you can see, our echo application is a toy app that doesn't do
+anything very useful. However, it has provided us with a basis for learning how
+to write working Athena code that lets a browser and server communicate
+with each other, both sending and receiving data. As such, we now have a
+solid foundation upon which we can build a functional, useful <i>and</i>
+instructional chat application.</p>
+
+</body>
+</html>
+
diff -Naur Nevow-0.10.0/doc/howto/chattutorial/part01/index.xhtml Nevow-0.10.0-new/doc/howto/chattutorial/part01/index.xhtml
--- Nevow-0.10.0/doc/howto/chattutorial/part01/index.xhtml 1970-01-01 01:00:00.000000000 +0100
+++ Nevow-0.10.0-new/doc/howto/chattutorial/part01/index.xhtml 2010-03-02 20:42:55.000000000 +0100
@@ -0,0 +1,236 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Nevow Athena from Scratch: Chat Application</title>
+ </head>
+<body>
+
+<h2>Architecture</h2>
+
+<p>We'll assume that you've read all the preceding sections of this tutorial
+and have just finished the "Echo" application example. As such, we don't need
+to do any more "mental preparation" and can skip straight to a description of
+the architecture.</p>
+
+<p>Fundamentally, this is no different than our echo application: there is
+a little more chatter that takes place between the client and server;
+there's another object involved (a <code>ChatRoom</code>); and we'll have
+to run the server a little differently.
+</p>
+
+<p>Here are the new features we want to support:</p>
+<ul>
+<li>login form;</li>
+<li>in-memory user storage;</li>
+<li>the ability to send global alerts to all users; and</li>
+<li>the ability for all users to "hear" when another user speaks in the
+chat room;</li>
+</ul>
+
+<p>A general rule we can establish about our architecture is that if something
+has to happen for everyone, that code needs to appear on the server side,
+since it's the server that is keeping track of all users. If something is
+going to happen irrespective of other users or if browser DOM manipulation
+is required, then we know the client will be the recipient of the code.</p>
+
+<p>As such, in the features above, the login form will be client code. The
+user storage, global alerts, and "hearing" will be implemented in server
+code for the data; updating the DOM with that data will be implemented in
+client code.</p>
+
+<p>The user experience of this application will be the following:</p>
+<ol>
+<li>they will be presented with a login box (no password, only username);</li>
+<li>upon logging in, a message will be sent to all logged in users that
+this person has joined, they will see a message at the bottom of the
+chat that states their login name, and the login form will be replaced with
+a chat area and a text input field;</li>
+<li>they will type text in the input field; and</li>
+<li>the typed text will appear in the browser of every person who is
+logged in.</li>
+</ol>
+
+<p>Building upon our previous example, our application will do the
+following:</p>
+
+<ol>
+<li>JavaScript client code will extract user input and send
+it to our server;</li>
+<li>Python code will receive messages from the client;</li>
+<li>Python code will process these messages;</li>
+<li>Python code will send messages to the all clients; and</li>
+<li>a template file (or <code>stan</code> code) will be used for
+presentation.</li>
+</ol>
+
+<h2>More Coding</h2>
+
+<h3>Presentation</h3>
+
+<p>The template is very similar as it was in the previous example, with
+the differences being a new login box, a "logged in as"
+area, and some name changes:</p>
+
+<a href="listings/chatthing/template.html" class="html-listing" />
+
+<p>We've now got two JavaScript methods that need to be defined:
+<code>doSetUsername()</code> and <code>doSay()</code>. We can also infer
+from this template that elements will be hidden and shown after login
+(note the presence of <code>style="display:none"</code> in two places). With
+these observations in hand, let's proceed to the JavaScript code.</p>
+
+<h3>Writing the Client</h3>
+
+<p>Referring back to our thoughts in the "Architecture" section above, we
+can establish that the JavaScript code needs the following:</p>
+
+<ul>
+<li>have the same basic boilerplate as in the "echo" example (imports,
+inheritance, attribute-setting in the constructor);</li>
+<li>implement the <code>doSetUsername()</code> and <code>doSay()</code>
+methods;</li>
+<li>create a method that will send a message to all users; and</li>
+<li>create a method that will let everyone know when someone says
+something. Let's see how this is done.</li>
+</ul>
+
+<a href="listings/chatthing/js/ChatThing.js" class="py-listing" />
+
+<p>There is a little abstraction here:</p>
+<ul>
+<li>we need a general message-sending method (<code>displayMessage()</code>) for any
+message that gets sent to all users;</li>
+<li>for user chat messages, we need something that will prepend the username so
+that everyone knows who said what (<code>displayUserMessage()</code>), and once this method
+does its thing, it passes the adjusted message on to <code>displayMessage()</code>.</li>
+</ul>
+
+<p>Other than that, this is very straight-forward code; it's pretty much
+the same as the "Echo" tutorial. The <code>display*()</code> methods
+are only responsible for updating the UI, just as we would expect.</p>
+
+We also need the same glue that we demonstrated in the "Echo" example:
+
+<a href="listings/nevow/plugins/chatthing_package.py" class="py-listing" />
+
+<h3>Writing the Server</h3>
+
+<p>The server code is a bit more complicated. We
+anticipated this above in the "Architecture" section where we noted that
+the Python code needs to receive, process and send messages.</p>
+
+<a href="listings/chatthing/chatterbox.py" class="py-listing" />
+
+<p>There is something in our "Chat" code that is not at all present in the
+"Echo" application: the <code>ChatRoom</code> object. We need this object for the
+following functionality:</p>
+<ul>
+<li>a means of instantiating new <code>ChatterElement</code> clients;</li>
+<li>a "singleton" instance for keeping track of all <code>ChatterElement</code> clients;</li>
+<li>a means sending messages to all clients;</li>
+</ul>
+
+<p>Let's look at the second two reasons first. In our "Chat" application,
+a new <code>ChatterElement</code> is created whenever a user connects,
+so we will have potentially many of these instances. In order
+for our chat server to function as designed, it will need a way to
+communicate with each of these. If we create an object that can keep the
+<code>ChatterElement</code>es in a list, then it will be able to iterate that
+list and call methods that, in turn, make remote calls to the JavaScript.
+</p>
+
+<p>Because we need the chat room to be a singleton object, it
+can only be instantiated once. But we need many instantiations of
+<code>ChatterElement</code> -- one for each connection, in fact. So what do
+we do? Well, in this case, we make one of the methods
+of <code>ChatRoom</code> a factory for instantiating a
+<code>ChatterElement</code>. Before we return the instance, though, we
+append it to the list of instances that the <code>ChatRoom</code>
+is keeping track of.
+</p>
+
+<h3>Putting it All Together</h3>
+
+
+<p>Now that we've got all the code in front of us, we can trace out exactly what happens:</p>
+
+<ol>
+<li>the user loads the resource in their browser, and the template is rendered;</li>
+<li>after typing a message in the input box, the user hits submit;</li>
+<li>JavaScript client code calls to the server with the text the user submitted;</li>
+<li>the server gets the message and shares it with all the connected
+<code>ChatterElement</code>s;</li>
+<li>each <code>ChatterElement</code> hears this message and passes it back to the JavaScript client;</li>
+<li>the client prepends the username to the message and then updates the display with the complete message.</li>
+</ol>
+
+<p>
+Keep in mind that <code>ChatterElement</code> entails several duties: it
+establishes a relationship with a room object, it "registers" a user (there's a
+one-to-one mapping between users and <code>ChatterElement</code>), it sends
+messages to the browser, and it receives messages from the chat room. Being a
+<code>LiveElement</code> subclass, <code>ChatterElement</code> is also
+responsible for the view (via the document factory).
+</p>
+
+
+<h3>Running with <code>twistd</code></h3>
+
+<p>One last bit of code that may seem odd is the <code>chat</code>
+variable we define right after the <code>ChatRoom</code> class. What
+is this? This is how we make all this cleverness work as a twisted
+plugin. </p>
+
+<p>If you recall, in our "Echo" application, we ran the code with
+the following command:
+</p>
+
+<pre class="shell">
+twistd -n athena-widget --element=echothing.echobox.EchoElement
+</pre>
+
+<p>The value we pass as the <code>--element</code> argument is the dotted
+name of the <code>LiveElement</code> object of which our "web page"
+is primarily comprised: the <code>EchoElement</code> object. In
+our "Chat" application, we have more moving parts: not only
+do we have the <code>ChatterElement</code> object, but we have the
+<code>ChatRoom</code> object which is responsible for keeping track of
+many <code>ChatterElement</code>es. By defining the <code>chat</code>
+variable, we are accomplishing the following all at once:
+</p>
+
+<ul>
+<li>providing a variable that can be accessed as a dotted name and thus
+used when starting the server (<code>chatthing.chatterbox.chat</code>);</li>
+<li>creating a singleton of <code>ChatRoom</code> (via the "magic"
+of Python module-level instantiations);</li>
+<li>making use of a factory, that when called, will both return a
+new <code>ChatterElement</code> instance <i>and</i> add itself to the
+<code>ChatRoom</code>.</li>
+</ul>
+
+<p>Running this version of our code is a little bit different than the
+"Echo" version. This is because of the <code>ChatRoom</code> code we
+discussed above. As such, we pass a factory as our element, like so:</p>
+
+<pre class="shell">
+cd Nevow/doc/howto/chattutorial/part01/listings
+twistd -n athena-widget --element=chatthing.chatterbox.chat
+</pre>
+
+<p>If you executed this against the tutorial code on your local machine,
+you can now visit <a href="http://localhost:8080/">http://localhost:8080/</a>
+and start chatting to your heart's content.</p>
+
+<h2>Summary</h2>
+<p>
+Unlike our echo application, the chat application has some real functionality
+and does some useful stuff: supporting user chats via browser/server two-way
+communications. It should be evident now how the echo application provided a
+basic conceptual and (partially) functional foundation upon which our chat work
+could be based.
+</p>
+</body>
+</html>
diff -Naur Nevow-0.10.0/doc/howto/deployment.xhtml Nevow-0.10.0-new/doc/howto/deployment.xhtml
--- Nevow-0.10.0/doc/howto/deployment.xhtml 1970-01-01 01:00:00.000000000 +0100
+++ Nevow-0.10.0-new/doc/howto/deployment.xhtml 2010-03-02 20:42:55.000000000 +0100
@@ -0,0 +1,300 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>
+ Deployment
+ </title>
+ </head>
+ <body>
+ <h1>Deployment</h1>
+
+ <p>
+ Nevow includes two major phases for deciding what HTML to render. <a
+ href="traversal.xhtml">Object Traversal</a> is the procedure by which a
+ URL is mapped to a Python object which will perform the HTML
+ generation. <a href="glossary.xhtml">Page Rendering</a> is the process by
+ which data objects are combined with an HTML template to produce the
+ final output.
+ </p>
+
+ <p>
+ Before any of this can take place, however, we must have an environment
+ in which our Python code can run in response to an HTTP request, and HTML
+ can be returned to the browser for rendering. This is called the
+ <a href="glossary.xhtml">Deployment Environment</a>.
+ </p>
+
+ <p>
+ There are various deployment options for Nevow page code:
+ </p>
+
+ <ul>
+ <li>
+ CGI: Simple deployment in almost any HTTP server
+ </li>
+ <li>
+ WSGI: A more complete and flexible way for deploying on many HTTP
+ servers
+ </li>
+ <li>
+ Twisted.Web: A standalone application server process which includes a
+ built-in HTTP server
+ </li>
+ <li>
+ Zomne: A small CGI which hands off HTTP requests to a long-running
+ application server process, similar to FastCGI or SCGI
+ </li>
+ </ul>
+
+ <h2>CGI</h2>
+
+ <p>
+ You can deploy Nevow on any webserver which uses the Common Gateway
+ Interface. Using this method, your code is responsible for properly
+ formatting and outputting the HTTP response headers, and Nevow is used
+ only to generate the HTML body of your page. Here is the simplest
+ possible CGI:
+ </p>
+
+ <pre class="python">
+#!/usr/bin/env python
+
+print "Content-type: text/plain\r\n\r\n",
+
+from nevow import rend, loaders
+
+class HelloWorld(rend.Page):
+ docFactory = loaders.stan("Hello, world!")
+
+print HelloWorld().renderSynchronously()
+ </pre>
+
+ <p>
+ With this simple CGI you can use the Nevow template loaders and standard
+ nevow template interpolation techniques in your CGIs. However, you do not
+ get any <a href="traversal.xhtml">Object Traversal</a> features, and you
+ have to generate HTTP headers yourself. WSGI is a slightly higher-level
+ deployment option which does not suffer these problems.
+ </p>
+
+ <h2>WSGI</h2>
+
+ <p>
+ WSGI is a python interface for plugging web applications into various
+ HTTP server architectures. It is described in <a
+ href="http://www.python.org/peps/pep-0333.html">PEP 333</a>, the Python
+ Web Services Gateway Interface Python Enhancement Proposal. Nevow
+ includes the <code class="API">nevow.wsgi</code> module, which includes a
+ <code>createWSGIApplication</code> function which takes a Page and
+ returns a standard WSGI application callable. With the help of the
+ <code>run_with_cgi</code> example gateway from the PEP (which I will omit
+ here), our CGI example becomes shorter:
+ </p>
+
+ <pre class="python">
+#!/usr/bin/env python
+
+from nevow import rend, loaders, wsgi
+
+class HelloWorld(rend.Page):
+ docFactory = loaders.stan("Hello, world!")
+
+run_with_cgi(wsgi.createWSGIApplication(HelloWorld()))
+ </pre>
+
+ <p>
+ Of course, you can use any available WSGI gateway to publish your
+ application object, such as one of the gateways which comes with the <a
+ href="http://peak.telecommunity.com/">PEAK</a> toolkit. For example, here
+ is a simple python module which creates a WSGI application which we will
+ then deploy with PEAK's SimpleHTTPServer gateway::
+ </p>
+
+ <pre class="python">
+## helloworld.py
+
+from nevow import rend, loaders, wsgi
+
+class HelloWorld(rend.Page):
+ docFactory = loaders.stan("Hello, world!")
+
+application = wsgi.createWSGIApplication(HelloWorld())
+ </pre>
+
+ <p>
+ Save this file as "helloworld.py" somewhere on your PYTHONPATH and then
+ run the following command:
+ </p>
+
+ <pre>peak launch WSGI import:helloworld.application</pre>
+
+ <p>
+ This will bring up a SimpleHTTPServer running your Nevow code and launch
+ a web browser to view the output. (TODO: I couldn't get this working
+ immediately but I will seek assistance with PEAK and update the
+ instructions once I do.)
+ </p>
+
+ <h2>Twisted.Web</h2>
+
+ <p>
+ A convenient and powerful way to deploy Nevow applications is inside a
+ process running the twisted.web HTTP server. With Python, Twisted, and
+ Nevow installed, you have all you need to run a Web Application, with no
+ other dependencies or external HTTP servers such as Apache
+ required. Running your Nevow applications under twisted.web also gives
+ you access to some of the more advanced "Live" features of Nevow, such as
+ <code>nevow.livepage</code> and <code>nevow.canvas</code>. Currently,
+ these modules require more control over the HTTP socket than CGI or WSGI
+ can provide. (This may change in the future.)
+ </p>
+
+ <p>
+ Deploying a Nevow application under twisted.web requires a little more
+ boilerplate, but can be considerably easier to set up than other
+ deployment options because there are no external dependencies. Note that
+ normally you should declare your Page classes in modules external to the
+ twisted configuration file, but everything is included in one file here
+ for brevity. Here is the minimal configuration file required to use
+ Nevow with twisted.web:
+ </p>
+
+ <pre class="python">
+from nevow import rend, loaders, appserver
+
+class HelloWorld(rend.Page):
+ docFactory = loaders.stan("Hello, world!")
+
+from twisted.application import service, internet
+application = service.Application("hello-world")
+internet.TCPServer(8080, appserver.NevowSite(HelloWorld())).setServiceParent(application)
+ </pre>
+
+ <p>
+ Save this file as "helloworld.tac" and start the server using the
+ command:
+ </p>
+
+ <pre>twistd -noy helloworld.tac</pre>
+
+ <p>
+ Then visit your twisted.web server by viewing the url
+ "http://localhost:8080/" in your browser. See the twistd man page for
+ more information about what twistd is capable of, including daemonizing
+ the HTTP server.
+ </p>
+
+ <h2>Zomne</h2>
+
+ <p>
+ <em>Warning</em> Zomne is experimental. It may blow up your computer and
+ require your first born son as a sacrifice. Zomne also only works in
+ UNIX-like environments where unix domain sockets are available, and may
+ not work on windows.
+ </p>
+
+ <p>
+ Zomne, or "Zombie Nevow", is a CGI written in C which can start up a
+ long-running Application Server process if one is not already running. It
+ then uses a simple custom protocol to transmit information about the HTTP
+ request from the CGI process to the application server process.
+ </p>
+
+ <p>
+ Zomne combines the ease of deployment of the CGI environment with the
+ speed and flexibility of the twisted.web long-running application server
+ process model.
+ </p>
+
+ <p>
+ To use Zomne, you must first compile the CGI. cd into the directory
+ created when unpacking the Nevow tarball, and compile the CGI:
+ </p>
+
+ <pre>% gcc zomne.c</pre>
+
+ <p>
+ Move it into your cgi-bin:
+ </p>
+
+ <pre>% mv a.out /Library/WebServer/CGI-Executables/nevow.cgi</pre>
+
+ <p>
+ Create a file which tells the cgi where to look for the application:
+ </p>
+
+ <pre>
+% cat > /Library/WebServer/CGI-Executables/.nevow.cgi.dir
+/Users/dp/zomne-test
+^D</pre>
+
+ <p>
+ The CGI name can be anything, as long as there is a file with a prepended
+ "." and a postfixed ".dir" in the same directory which contains the full
+ path of a zomne application directory. Next, create the application
+ directory:
+ </p>
+
+ <pre>mkdir /Users/dp/zomne-test</pre>
+
+ <p>
+ Finally, create the zomne.tac file which the zomne.cgi will execute to
+ start the long-running application server process:
+ </p>
+
+ <pre class="python">
+from nevow import rend, loaders, zomnesrv
+
+class HelloWorld(rend.Page):
+ docFactory = loaders.stan("Hello, world!")
+
+from twisted.application import service, internet
+application = service.Application('nevow-zomne-test')
+internet.UNIXServer('zomne.socket', zomnesrv.ZomneFactory(HelloWorld())).setServiceParent(application)
+ </pre>
+
+ <p>
+ Now, visiting the nevow.cgi URL through the web should render the Hello
+ World page, after a pause while the server is starting up. Subsequent
+ requests should be very fast, because the application server is already
+ running, and the CGI merely has to forward the request to it.
+ </p>
+
+ <p>
+ Another useful capability of the zomne CGI process is the ability to
+ control environment variables the CGI will use. Create a directory named
+ "zomne_environ" in the application directory, and fill it with text files
+ whose name will be the environment key and whose contents will be the
+ environment value:
+ </p>
+
+ <pre>
+% cd zomne-test
+% mkdir zomne-environ
+% cd zomne-environ
+% cat > PYTHONPATH
+/Users/dp/Projects/Nevow:/Users/dp/Projects/helloworld
+^D</pre>
+
+ <h2>Conclusion</h2>
+
+ <p>
+ Nevow may be deployed in a number of environments, from the most
+ restrictive to the most permissive. Writing a CGI can be an easy way to
+ try out the Nevow templating mechanism, but can be slow. A long-running
+ application server process can be a good way to get good performance as
+ well as additional features such as in-memory server-side sessions,
+ advanced automatic form handling with formless, and live page updating
+ features such as nevow.livepage and nevow.canvas.
+ </p>
+
+ <p>
+ Which deployment option you choose will depend on the amount of control
+ you have over your deployment environment, and what advanced features
+ your application will require.
+ </p>
+ </body>
+</html>
diff -Naur Nevow-0.10.0/doc/howto/gettingstarted.xhtml Nevow-0.10.0-new/doc/howto/gettingstarted.xhtml
--- Nevow-0.10.0/doc/howto/gettingstarted.xhtml 1970-01-01 01:00:00.000000000 +0100
+++ Nevow-0.10.0-new/doc/howto/gettingstarted.xhtml 2010-03-02 20:42:55.000000000 +0100
@@ -0,0 +1,110 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>
+ Getting Started
+ </title>
+ </head>
+ <body>
+ <h1>Getting Started</h1>
+
+ <p>
+ Warning: This document has only just been started. It's not going to get
+ you very far right now.
+ </p>
+
+ <p>
+ Nevow is a reasonably large library and can be quite daunting at
+ first. This document's aim is to guide the first time user in building a
+ Nevow application.
+ </p>
+
+ <h2>Our First Application</h2>
+
+ <p>
+ Let's dive straight in, here's the code for our first (very, very simple)
+ application. Create the following module, helloworld.py:
+ </p>
+
+ <a href="listings/gettingstarted/helloworld.py" class="py-listing">
+ helloworld.py
+ </a>
+
+ <p>
+ It looks quite simple but let's walk through it anyway.
+ </p>
+
+ <p>
+ First, we import two Nevow modules. <code
+ class="API">nevow.loaders</code> contains template loaders of which the
+ two most useful are <code class="API" base="nevow.loaders">xmlfile</code>
+ and <code class="API" base="nevow.loaders">stan</code>.
+ <code>xmlfile</code> can load any well-formed XML (i.e. XHTML) file;
+ <code>stan</code> loads a stan tree (more on these later). The other
+ module, <code class="API">nevow.rend</code>, contains all Nevow's
+ standard renders, many of which we'll meet in this document.
+ </p>
+
+ <p>
+ We then define the <code>HelloWorld</code> class that subclasses <code
+ class="API" base="nevow">rend.Page</code>, Nevow's main resource
+ class. <code>HelloWorld</code> has two class
+ attributes. <code>addSlash</code> tells <code>rend.Page</code> to
+ redirect to a version of the request URL that ends in a <code>/</code> if
+ necessary. You generally want to set this to <code>True</code> for the
+ root resource. <code>docFactory</code> tells the page instance where to
+ get the template from. In this case we're providing a loader that parses
+ an HTML file (not shown) from disk.
+ </p>
+
+ <p>
+ Hmm, ok I hear you say but how do I see it. Well, Twisted provides a good
+ web server which we can use. Twisted also includes a clever little
+ application for starting Twisted applications. Here's the helloworld.tac
+ file, a Twisted Application Configuration:
+ </p>
+
+ <a href="listings/gettingstarted/helloworld.tac" class="py-listing">
+ helloworld.tac
+ </a>
+
+ <p>
+ Give it a go, run the following and connect to <a
+ href="http://localhost:8080/">http://localhost:8080/</a> to see your
+ application:
+ </p>
+
+ <pre>twistd -ny helloworld.tac</pre>
+
+ <p>
+ You'll probably notice that you get log output on the console. This is
+ just one of the good things that twistd does. It can also daemonize the
+ application, shed privileges if run as root, etc.
+ </p>
+
+ <p>
+ TAC files are covered in more detail in the Twisted documentation but
+ let's quickly explain what all this does anyway.
+ </p>
+
+ <p>
+ When <code class="shell">twistd</code> starts up it loads the
+ <code>.tac</code> file (it's just Python) and looks for the attribute
+ called <code>application</code>. When <code class="shell">twistd</code>
+ is all ready to go it starts the <code>application</code>.
+ </p>
+
+ <p>
+ The application is not much use unless it actually does something so the
+ next thing we do is create a <code class="API"
+ base="nevow.appserver">NevowSite</code> instance, <code>site</code>, and
+ pass it a root resource, a <code>HelloWorld</code> instance. Finally, we
+ create a TCP server that makes the site available on port 8080 and bind
+ the server to the application to ensure the server is started when the
+ application is started.
+ </p>
+ </body>
+</html>
diff -Naur Nevow-0.10.0/doc/howto/glossary.xhtml Nevow-0.10.0-new/doc/howto/glossary.xhtml
--- Nevow-0.10.0/doc/howto/glossary.xhtml 1970-01-01 01:00:00.000000000 +0100
+++ Nevow-0.10.0-new/doc/howto/glossary.xhtml 2010-03-02 20:42:55.000000000 +0100
@@ -0,0 +1,82 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>
+ Glossary
+ </title>
+ </head>
+ <body>
+ <h1>Glossary</h1>
+
+ <h2>Object Traversal</h2>
+
+ <p>
+ The process by which a Python object is located to render HTML for a
+ given HTTP URL. For example, given the URL http://example.com/foo/bar,
+ Object Traversal will begin at the "Root Resource" object by asking it
+ for an object which is capable of rendering the page at ('foo',
+ 'bar'). The "Root Resource" returns an object and a list of unhandled
+ path segments, and the traversal continues across this new Resource
+ object until all path segments have been consumed.
+ </p>
+
+ <h2>Page Rendering</h2>
+
+ <p>
+ The process by which a Python object, usually a rend.Page subclass, turns
+ itself into HTML. Page Rendering involves locating some page data,
+ loading a template document, and applying the template to the data, in
+ the process generating HTML.
+ </p>
+
+ <h2>Deployment Environment</h2>
+
+ <p>
+ The environment in which a Nevow application is deployed. Generally
+ involves an HTTP server which is configured to route certain (or all)
+ HTTP requests through the Nevow Object Traversal and Page Rendering
+ process. Deployment environments include CGI, WSGI, and twisted.web.
+ </p>
+
+ <h2>DOM</h2>
+
+ <p>
+ Document Object Model. A tree of objects which represent the structure of
+ an XHTML document in memory. Nevow uses a nonstandard DOM named "stan",
+ which is made up of simple Python lists, dicts, strings, and
+ nevow.stan.Tag instances.
+ </p>
+
+ <h2>Flattener</h2>
+
+ <p>
+ A Python function which knows how to translate from a rich type to a
+ string containing HTML. For example, the integer flattener calls str() on
+ the integer. The string flattener escapes characters which are unsafe in
+ HTML, such as <, >, and &.
+ </p>
+
+ <h2>Tag</h2>
+
+ <p>
+ A class, defined at nevow.stan.Tag, which holds information about a
+ single HTML tag in a DOM. Tag instances have three attributes: tagName,
+ attributes, and children. tagName is a string indicating the tag
+ name. attributes is a dict indicating the HTML attributes of that
+ node. children is a list indicating the child nodes of that node.
+ </p>
+
+ <h2>Tag Specials</h2>
+
+ <p>
+ A Tag attribute which is "special" to nevow. Tag specials include data,
+ render, pattern, slot, and macro. Tag Specials will never be output as
+ HTML attributes of tags, but will be used by the internal Nevow rendering
+ process to influence how the Tag is rendered.
+ </p>
+
+ </body>
+</html>
diff -Naur Nevow-0.10.0/doc/howto/index.xhtml Nevow-0.10.0-new/doc/howto/index.xhtml
--- Nevow-0.10.0/doc/howto/index.xhtml 1970-01-01 01:00:00.000000000 +0100
+++ Nevow-0.10.0-new/doc/howto/index.xhtml 2010-03-02 20:42:55.000000000 +0100
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>
+ Manual
+ </title>
+ </head>
+ <body>
+ <h1>
+ Manual
+ </h1>
+ <ul class="toc">
+ <li>
+ <a href="intro.xhtml">Introduction</a>
+ </li>
+ <li>
+ <a href="gettingstarted.xhtml">Getting Started</a>
+ <p>A basic introduction to rendering a web page in Nevow.</p>
+ </li>
+ <li>
+ <a href="traversal.xhtml">Object Traversal</a>
+ <p>Getting from an URL to a Python page object you want to render.</p>
+ </li>
+ <li>
+ <a href="publishing.xhtml">Object Publishing</a>
+ <p>Exposing Python objects as parts of a web page in Nevow.</p>
+ </li>
+ <li>
+ <a href="xmltemplates.xhtml">XML Templates</a>
+ <p>Using standard XHTML as a template for Nevow.</p>
+ </li>
+ <li>
+ <a href="deployment.xhtml">Deployment</a>
+ <p>How to get your Nevow application running on different types of
+ servers.</p>
+ </li>
+ <li>
+ <a href="chattutorial/index.xhtml">Nevow Athena</a>
+ <p>Two-way communication with JavaScript in a web browser.</p>
+ </li>
+ <li>
+ <a href="glossary.xhtml">Glossary</a>
+ </li>
+ </ul>
+ </body>
+</html>
diff -Naur Nevow-0.10.0/doc/howto/intro.xhtml Nevow-0.10.0-new/doc/howto/intro.xhtml
--- Nevow-0.10.0/doc/howto/intro.xhtml 1970-01-01 01:00:00.000000000 +0100
+++ Nevow-0.10.0-new/doc/howto/intro.xhtml 2010-03-02 20:42:55.000000000 +0100
@@ -0,0 +1,294 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>
+ A Web Application Construction Kit
+ </title>
+ </head>
+ <body>
+ <h1>A Web Application Construction Kit</h1>
+
+ <h2>Summary</h2>
+
+ <p>
+ Nevow is a next-generation web application templating system, based on
+ the ideas developed in the Twisted Woven package. Its main focus is on
+ separating the HTML template from both the business logic and the display
+ logic, while allowing the programmer to write pure Python code as much as
+ possible. It separates your code into 'data' and 'render' functions, a
+ simplified implementation of traditional MVC. It has various parts which
+ can be used individually or as a whole, integrated web solution:
+ </p>
+
+ <ul>
+ <li>
+ XHTML templates: contain no programming logic, only nodes tagged with
+ nevow attributes
+ </li>
+ <li>
+ data/render methods: simplified MVC
+ </li>
+ <li>
+ stan: An s-expression-like syntax for expressing xml in pure python
+ </li>
+ <li>
+ formless: For describing the types of objects which may be passed to
+ methods of your classes, validating and coercing string input from
+ either web or command-line sources, and calling your methods
+ automatically once validation passes
+ </li>
+ <li>
+ formless.webform: For rendering web forms based on formless type
+ descriptions, accepting form posts and passing them to formless
+ validators, and rendering error forms in the event validation fails
+ </li>
+ <li>
+ livepage: Cross-browser JavaScript glue for sending client side events
+ to the server and server side events to the client after the page has
+ loaded, without causing the entire page to refresh
+ </li>
+ </ul>
+
+ <h2>Disk based templates</h2>
+
+ <p>
+ Nevow includes the ability to load templates off disk. These templates
+ may have processing directives which cause the execution of python
+ methods at render time. The attribute technique was inspired by the
+ attributes used by ZPT. However, no actual code may be embedded in the
+ HTML template:
+ </p>
+
+ <pre>
+<html xmlns:nevow="http://nevow.com/ns/nevow/0.1">
+ <head>
+ <title>Greetings!</title>
+ </head>
+ <body>
+ <h1 style="font-size: large">Now I will greet you:</h1>
+ <span nevow:render="greet" />
+ </body>
+</html></pre>
+
+ <p>
+ This template can then be loaded and rendered like so:
+ </p>
+
+ <pre class="python">
+class Greeter(rend.Page):
+ docFactory = loaders.xmlfile("Greeting.html")
+
+ def render_greet(self, context, data):
+ return random.choice(["Hello", "Greetings", "Hi"]), " ", data
+
+Greeter("My name is").renderString()
+ </pre>
+
+ <h2>data/render methods</h2>
+
+ <p>
+ To allow clean isolation between code which fetches data from a data
+ source and code which renders the data into HTML, nevow allows you to
+ write both 'data' methods and 'render' methods. These concepts are
+ inspired by MVC, but simpler, since the framework can handle most of the
+ controller aspect. An example:
+ </p>
+
+ <pre>
+<html xmlns:nevow="http://nevow.com/ns/nevow/0.1">
+ <body>
+ <span nevow:data="name" nevow:render="colorful" />
+ <span nevow:data="fun" nevow:render="colorful" />
+ </body>
+</html></pre>
+
+ <p>
+ This template can be loaded and rendered using a class such as this:
+ </p>
+
+ <pre class="python">
+class Colorful(rend.Page):
+ docFactory = loaders.xmlfile("Colorful.html")
+
+ def render_colorful(self, context, data):
+ color = random.choice(['red', 'green', 'blue'])
+ return context.tag(style="color: %s" % color)
+
+ def data_name(self, context, data):
+ return "Your name here"
+
+ def data_fun(self, context, data):
+ return "Are we having fun yet?"
+ </pre>
+
+ <h2>Stan</h2>
+
+ <p>
+ One of the most powerful things about nevow is stan, an s-expression-like
+ syntax for producing XML fragments in pure Python syntax. Stan is not
+ required for using nevow, but it is both a simple and powerful way to
+ both lay out one's XHTML templates and express one's display logic. A
+ brief example will illustrate its utility:
+ </p>
+
+ <pre class="python">
+import random
+from nevow import rend, tags
+
+class Greeter(rend.Page):
+ def greet(self, context, data):
+ return random.choice(["Hello", "Greetings", "Hi"]), " ", data
+
+ docFactory = loaders.stan(
+ tags.html[
+ tags.head[ tags.title[ "Greetings!" ]],
+ tags.body[
+ tags.h1(style="font-size: large")[ "Now I will greet you:" ],
+ greet
+ ]
+ ])
+ </pre>
+
+ <p>
+ When the Greeter class is constructed, it is passed a Python object which
+ will be used as that page's data:
+ </p>
+
+ <pre class="python">
+Greeter("Your name here").renderString()
+ </pre>
+
+ <h2>Formless</h2>
+
+ <p>
+ Python is dynamically typed, which means it has no built-in controls for
+ enforcing the types of objects which are passed to one's methods. This is
+ great for programmers, but not necessarily great if you are going to be
+ passing user-entered input to those methods. Formless is a simple way to
+ describe the types of objects that can be passed to one's methods, as
+ well as coerce from string input to those types. Other code can then
+ accept user input from a command line or from a web form, validate the
+ input against the types described using formless, and call the method
+ once validation has passed. A simple example:
+ </p>
+
+ <pre class="python">
+from zope.interface import implements
+from formless.annotate import TypedInterface, Integer, String
+
+class ISimpleMethod(TypedInterface):
+ def simple(self,
+ name=String(description="Your name."),
+ age=Integer(description="Your age.")):
+ """
+ Simple
+
+ Please enter your name and age.
+ """
+
+class Implementation(object):
+ implements(ISimpleMethod)
+
+ def simple(self, name, age):
+ print "Hello, %s, who is %s" % (name, age)
+ </pre>
+
+ <h2>Webform</h2>
+
+ <p>
+ Webform is a nevow module which will automatically render web forms and
+ accept form posts based on types described using the classes in
+ formless. Used in conjunction with the twisted.web HTTP server, the
+ process is almost automatic:
+ </p>
+
+ <pre class="python">
+from nevow import rend, tags
+from formless import webform
+
+class WebForm(rend.Page):
+ document = rend.stan(
+ tags.html[
+ tags.body[
+ h1["Here is the form:"],
+ webform.renderForms('original')
+ ]
+])
+
+resource = WebForm(Implementation())
+ </pre>
+
+ <p>
+ Exposing this resource instance to the web using twisted.web and visiting
+ it will cause a form with two input boxes to be rendered. Posting the
+ form will cause form validation to occur. Upon error, the user will be
+ returned to the original page, with the form annotated with error
+ messages. Upon success, the "simple" method of the Implementation
+ instance will be called and passed a string and an integer.
+ </p>
+
+ <h2>LivePage</h2>
+
+ <p>
+ LivePage was a Woven technology which allowed programmers to receive
+ server-side notification of client-side JavaScript events, and to send
+ JavaScript to the client in response to a server-side event. New for
+ Nevow 0.3, LivePage has been updated to support Mozilla, Firefox, IE6
+ Win, and Safari. Using LivePage is very easy:
+ </p>
+
+ <pre class="python">
+from nevow.liveevil import handler
+
+def greeter(client, nodeName):
+ client.alert("Greetings. You clicked the %s node." % nodeName)
+
+# Any string arguments after the event handler function will be evaluated
+# as JavaScript in the context of the web browser and results passed to the
+# Python event handler
+handler = handler(greeter, 'node.name')
+
+class Live(rend.Page):
+ docFactory = loaders.stan(
+ tags.html[
+ tags.body[
+ ol[
+ li(onclick=handler, name="one")["One"]
+ li(onclick=handler, name="two")["Two"]
+ li(onclick=handler, name="three")["Three"]
+ ]
+ ]
+ ])
+ </pre>
+
+ <h2>More Information</h2>
+
+ <p>
+ The <a href="http://divmod.org/trac/wiki/DivmodNevow">Nevow website</a>
+ has more information. Starting with 0.3, it contains a simple WSGI
+ implementation and can also be used to render CGIs. However, the
+ recommended mode of operation is using the <a
+ href="http://twistedmatrix.com/trac/wiki/TwistedWeb">Twisted web</a>
+ server. Nevow is an active project, and many new bugfixes and features
+ are committed to the Nevow SVN repository. Information about Nevow
+ commits is available by subscribing to the <a
+ href="http://divmod.net/users/mailman.twistd/listinfo/divmod-commits">
+ Divmod commits</a> mailing list. The Nevow SVN repository can be checked
+ out using:
+ </p>
+
+ <pre>svn co svn://divmod.org/svn/Nevow/trunk Nevow</pre>
+
+ <p>
+ Discussion of Nevow occurs on the <a
+ href="http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-web">
+ twisted.web mailing list</a>. The Nevow developers are also often
+ available for real-time help on the <a
+ href="irc://irc.freenode.net/#twisted.web">#twisted.web channel</a> on
+ irc.freenode.net.
+ </p>
+ </body>
+</html>
diff -Naur Nevow-0.10.0/doc/howto/publishing.xhtml Nevow-0.10.0-new/doc/howto/publishing.xhtml
--- Nevow-0.10.0/doc/howto/publishing.xhtml 1970-01-01 01:00:00.000000000 +0100
+++ Nevow-0.10.0-new/doc/howto/publishing.xhtml 2010-03-02 20:42:55.000000000 +0100
@@ -0,0 +1,658 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>
+ Object Publishing
+ </title>
+ </head>
+ <body>
+ <h1>
+ Object Publishing
+ </h1>
+
+ <p>
+ In <a href="traversal.xhtml">Object Traversal</a>, we learned about the
+ <code class="API">nevow.inevow.IResource.renderHTTP</code> method, which
+ is the most basic way to send HTML to a browser when using
+ Nevow. However, it is not very convenient (or clean) to generate HTML
+ tags by concatenating strings in Python code. In the <a
+ href="deployment.xhtml">Deployment</a> documentation, we saw that it was
+ possible to render a <em>Hello World</em> page using a <code class="API">
+ nevow.rend.Page</code> subclass and providing a <code>docFactory</code>:
+ </p>
+
+ <pre class="python-interpreter">
+>>> from nevow import rend, loaders
+>>> class HelloWorld(rend.Page):
+... docFactory = loaders.stan("Hello, world!")
+...
+>>> HelloWorld().renderSynchronously()
+'Hello, world!'</pre>
+
+ <p>
+ This example does nothing interesting, but the concept of a loader is
+ important in Nevow. The <code>rend.Page.renderHTTP</code> implementation
+ always starts rendering HTML by loading a template from the
+ <code>docFactory</code>.
+ </p>
+
+
+ <h2>The stan DOM</h2>
+
+ <p>
+ Nevow uses a DOM-based approach to rendering HTML. A tree of objects is
+ first constructed in memory by the template loader. This tree is then
+ processed one node at a time, applying functions which transform from
+ various Python types to HTML strings.
+ </p>
+
+ <p>
+ Nevow uses a nonstandard DOM named "stan". Unlike the W3C DOM, stan is
+ made up of simple python lists, strings, and instances of the
+ nevow.stan.Tag class. During the rendering process, "Flattener"
+ functions convert from rich types to HTML strings. For example, we can
+ load a template made up of some nested lists and Python types, render it,
+ and see what happens:
+ </p>
+
+ <pre class="python-interpreter">
+>>> class PythonTypes(rend.Page):
+... docFactory = loaders.stan(["Hello", 1, 1.5, True, ["Goodbye", 3]])
+...
+>>> PythonTypes().renderSynchronously()
+'Hello11.5TrueGoodbye3'</pre>
+
+ <h2>Tag instances</h2>
+
+ <p>
+ So far, we have only rendered simple strings as output. However, the main
+ purpose of Nevow is HTML generation. In the stan DOM, HTML tags are
+ represented by instances of the <code class="API">nevow.stan.Tag</code>
+ class. <code>Tag</code> is a very simple class, whose instances have an
+ <code>attributes</code> dictionary and a <code>children</code> list. The
+ <code>Tag</code> flattener knows how to recursively flatten attributes
+ and children of the tag. To show you how <code>Tag</code>s really work
+ before you layer Nevow's convenience syntax on top, try this horrible
+ example:
+ </p>
+
+ <pre class="python-interpreter">
+>>> from nevow import stan
+>>> h = stan.Tag('html')
+>>> d = stan.Tag('div')
+>>> d.attributes['style'] = 'border: 1px solid black'
+>>> h.children.append(d)
+>>> class Tags(rend.Page):
+... docFactory = loaders.stan(h)
+...
+>>> Tags().renderSynchronously()
+'<html><div style="border: 1px solid black"></div></html>'</pre>
+
+ <p>
+ So, we see how it is possible to programatically generate HTML by
+ constructing and nesting stan <code>Tag</code> instances. However, it is
+ far more convenient to use the overloaded operators <code>Tag</code>
+ provides to manipulate them. <code>Tag</code> implements a
+ <code>__call__</code> method which takes any keyword arguments and values
+ and updates the attributes dictionary; it also implements a
+ <code>__getitem__</code> method which takes whatever is between the square
+ brackets and appends them to the children list. A simple example should
+ clarify things:
+ </p>
+
+ <pre class="python-interpreter">
+>>> class Tags2(rend.Page):
+... docFactory = loaders.stan(stan.Tag('html')[stan.Tag('div')(style="border: 1px solid black")])
+...
+>>> Tags2().renderSynchronously()
+'<html><div style="border: 1px solid black"></div></html>'</pre>
+
+ <p>
+ This isn't very easy to read, but luckily we can simplify the example
+ even further by using the nevow.tags module, which is full of "Tag
+ prototypes" for every tag type described by the XHTML 1.0 specification:
+ </p>
+
+ <pre class="python-interpreter">
+>>> class Tags3(rend.Page):
+... docFactory = loaders.stan(tags.html[tags.div(style="border: 1px solid black")])
+...
+>>> Tags3().renderSynchronously()
+'<html><div style="border: 1px solid black"></div></html>'</pre>
+
+ <p>
+ Using stan syntax is not the only way to construct template DOM for use
+ by the Nevow rendering process. Nevow also includes <code class="API"
+ base="nevow">loaders.xmlfile</code> which implements a simple tag
+ attribute language similar to the Zope Page Templates (ZPT) Tag Attribute
+ Language (TAL). However, experience with the stan DOM should give you
+ insight into how the Nevow rendering process really works. Rendering a
+ template into HTML in Nevow is really nothing more than iterating a tree
+ of objects and recursively applying "Flattener" functions to objects in
+ this tree, until all HTML has been generated.
+ </p>
+
+ <h2>Functions in the DOM</h2>
+
+ <p>
+ So far, all of our examples have generated static HTML pages, which is
+ not terribly interesting when discussing dynamic web applications. Nevow
+ takes a very simple approach to dynamic HTML generation. If you put a
+ Python function reference in the DOM, Nevow will call it when the page is
+ rendered. The return value of the function replaces the function itself
+ in the DOM, and the results are flattened further. This makes it easy to
+ express looping and branching structures in Nevow, because normal Python
+ looping and branching constructs are used to do the job:
+ </p>
+
+ <pre class="python-interpreter">
+>>> def repeat(ctx, data):
+... return [tags.div(style="color: %s" % (color, ))
+... for color in ['red', 'blue', 'green']]
+...
+>>> class Repeat(rend.Page):
+... docFactory = loaders.stan(tags.html[repeat])
+...
+>>> Repeat().renderSynchronously()
+'<html><div style="color: red"></div><div style="color: blue"></div><div style="color: green"></div></html>'</pre>
+
+ <p>
+ However, in the example above, the repeat function isn't even necessary,
+ because we could have inlined the list comprehension right where we
+ placed the function reference in the DOM. Things only really become
+ interesting when we begin writing parameterized render functions which
+ cause templates to render differently depending on the input to the web
+ application.
+ </p>
+
+ <p>
+ The required signature of functions which we can place in the DOM is
+ (ctx, data). The "context" object is essentially opaque for now, and we
+ will learn how to extract useful information out of it later. The "data"
+ object is anything we want it to be, and can change during the rendering
+ of the page. By default, the data object is whatever we pass as the first
+ argument to the Page constructor, <em>or</em> the Page instance itself if
+ nothing is passed. Armed with this knowledge, we can create a Page which
+ renders differently depending on the data we pass to the Page
+ constructor:
+ </p>
+
+ <pre class="python">
+class Root(rend.Page):
+ docFactory = loaders.stan(tags.html[
+ tags.h1["Welcome."],
+ tags.a(href="foo")["Foo"],
+ tags.a(href="bar")["Bar"],
+ tags.a(href="baz")["Baz"]])
+
+ def childFactory(self, ctx, name):
+ return Leaf(name)
+
+def greet(ctx, name):
+ return "Hello. You are visiting the ", name, " page."
+
+class Leaf(rend.Page):
+ docFactory = loaders.stan(tags.html[greet])
+ </pre>
+
+ <p>
+ Armed with this knowledge and the information in the <a
+ href="traversal.xhtml">Object Traversal</a> documentation, we now have
+ enough information to create dynamic websites with arbitrary URL
+ hierarchies whose pages render dynamically depending on which URL was
+ used to access them.
+ </p>
+
+ <h2>Accessing query parameters and form post data</h2>
+
+ <p>
+ Before we move on to more advanced rendering techniques, let us first
+ examine how one could further customize the rendering of a Page based on
+ the URL query parameters and form post information provided to us by a
+ browser. Recall that URL parameters are expressed in the form:
+ </p>
+
+ <pre>http://example.com/foo/bar?baz=1&quux=2</pre>
+
+ <p>
+ And form post data can be generated by providing a form to a browser:
+ </p>
+
+ <pre>
+<form action="" method="POST">
+ <input type="text" name="baz" />
+ <input type="text" name="quux" />
+ <input type="submit" />
+</form></pre>
+
+ <p>
+ Accessing this information is such a common procedure that Nevow provides
+ a convenience method on the context to do it. Let's examine a simple page
+ whose output can be influenced by the query parameters in the URL used to
+ access it:
+ </p>
+
+ <pre class="python">
+def showChoice(ctx, data):
+ choice = ctx.arg('choice')
+ if choice is None:
+ return ''
+ return "You chose ", choice, "."
+
+class Custom(rend.Page):
+ docFactory = loaders.stan(tags.html[
+ tags.a(href="?choice=baz")["Baz"],
+ tags.a(href="?choice=quux")["Quux"],
+ tags.p[showChoice]])
+ </pre>
+
+ <p>
+ The procedure is exactly the same for simple form post information:
+ </p>
+
+ <pre class="python">
+def greet(ctx, data):
+ name = ctx.arg('name')
+ if name is None:
+ return ''
+ return "Greetings, ", name, "!"
+
+class Form(rend.Page):
+ docFactory = loaders.stan(tags.html[
+ tags.form(action="", method="POST")[
+ tags.input(name="name"),
+ tags.input(type="submit")],
+ greet])
+</pre>
+
+ <p>
+ Note that <code>ctx.arg</code> returns only the first argument with the
+ given name. For complex cases where multiple arguments and lists of
+ argument values are required, you can access the request argument
+ dictionary directly using the syntax:
+ </p>
+
+ <pre class="python">
+def arguments(ctx, data):
+ args = inevow.IRequest(ctx).args
+ return "Request arguments are: ", str(args)
+ </pre>
+
+ <h2>Generators in the DOM</h2>
+
+ <p>
+ One common operation when building dynamic pages is iterating a list of
+ data and emitting some HTML for each item. Python generators are well
+ suited for expressing this sort of logic, and code which is written as a
+ python generator can perform tests (<code>if</code>) and loops of various
+ kinds (<code>while</code>, <code>for</code>) and emit a row of html
+ whenever it has enough data to do so. Nevow can handle generators in the
+ DOM just as gracefully as it can handle anything else:
+ </p>
+
+ <pre class="python-interpreter">
+>>> from nevow import rend, loaders, tags
+>>> def generate(ctx, items):
+... for item in items:
+... yield tags.div[ item ]
+...
+>>> class List(rend.Page):
+... docFactory = loaders.stan(tags.html[ generate ])
+...
+>>> List(['one', 'two', 'three']).renderSynchronously()
+'<html><div>one</div><div>two</div><div>three</div></html>'</pre>
+
+ <p>
+ As you can see, generating HTML inside of functions or generators can be
+ very convenient, and can lead to very rapid application
+ development. However, it is also what I would call a "template
+ abstraction violation", and we will learn how we can keep knowledge of
+ HTML out of our python code when we learn about patterns and slots.
+ </p>
+
+ <h2>Methods in the DOM</h2>
+
+ <p>
+ Up until now, we have been placing our template manipulation logic inside
+ of simple Python functions and generators. However, it is often
+ appropriate to use a method instead of a function. Nevow makes it just as
+ easy to use a method to render HTML:
+ </p>
+
+ <pre class="python">
+class MethodRender(rend.Page):
+ def __init__(self, foo):
+ self.foo = foo
+
+ def render_foo(self, ctx, data):
+ return self.foo
+
+ docFactory = loaders.stan(tags.html[ render_foo ])
+ </pre>
+
+ <p>
+ Using render methods makes it possible to parameterize your Page class
+ with more parameters. With render methods, you can also use the Page
+ instance as a state machine to keep track of the state of the
+ render. While Nevow is designed to allow you to render the same Page
+ instance repeatedly, it can also be convenient to know that a Page
+ instance will only be used one time, and that the Page instance can be
+ used as a scratch pad to manage information about the render.
+ </p>
+
+ <h2>Data specials</h2>
+
+ <p>
+ Previously we saw how passing a parameter to the default Page constructor
+ makes it available as the "data" parameter to all of our render
+ methods. This "data" parameter can change as the page render proceeds,
+ and is a useful way to ensure that render functions are isolated and only
+ act upon the data which is available to them. Render functions which do
+ not pull information from sources other than the "data" parameter are
+ more easily reusable and can be composed into larger parts more easily.
+ </p>
+
+ <p>
+ Deciding which data gets passed as the data parameter is as simple as
+ changing the "Data special" for a Tag. See the <a
+ href="glossary.xhtml">Glossary</a> under "Tag Specials" for more
+ information about specials. Assigning to the data special is as simple as
+ assigning to a tag attribute:
+ </p>
+
+ <pre class="python-interpreter">
+>>> def hello(ctx, name):
+... return "Hello, ", name
+...
+>>> class DataSpecial(rend.Page):
+... docFactory = loaders.stan(tags.html[
+... tags.div(data="foo")[ hello ],
+... tags.div(data="bar")[ hello ]])
+...
+>>> DataSpecial().renderSynchronously()
+'<html><div>Hello, foo</div><div>Hello, bar</div></html>'</pre>
+
+ <p>
+ Data specials may be assigned any python value. Data specials are only in
+ scope during the rendering of the tag they are assigned to, so if the
+ "hello" renderer were placed in the DOM inside the html node directly,
+ "Hello, None" would be output.
+ </p>
+
+ <p>
+ Before data is passed to a render function, Nevow first checks to see if
+ there is an <code class="API">IGettable</code> adapter for it. If there
+ is, it calls <code>IGettable.get()</code>, and passes the result of this
+ as the data parameter instead. Nevow includes an <code>IGettable</code>
+ adapter for python functions, which means you can set a Tag data special
+ to a function reference and Nevow will call it to obtain the data when
+ the Tag is rendered. The signature for data methods is similar to that of
+ render methods, (ctx, data). For example:
+ </p>
+
+ <pre class="python">
+def getName(ctx, data):
+ return ctx.arg('name')
+
+def greet(ctx, name):
+ return "Greetings, ", name
+
+class GreetName(rend.Page):
+ docFactory = loaders.stan(tags.html[
+ tags.form(action="")[
+ tags.input(name="name"),
+ tags.input(type="submit")],
+ tags.div(data=getName)[ greet ]])
+ </pre>
+
+ <p>
+ Data specials exist mainly to allow you to construct and enforce a
+ Model-View-Controller style separation of the Model code from the
+ View. Here we see that the greet function is capable of rendering a
+ greeting view for a name model, and that the implementation of getName
+ may change without the view code changing.
+ </p>
+
+ <h2>Render specials</h2>
+
+ <p>
+ Previously, we have seen how render functions can be placed directly in
+ the DOM, and the return value replaces the render function in the
+ DOM. However, these free functions and methods are devoid of any
+ contextual information about the template they are living in. The
+ render special is a way to associate a render function or method with a
+ particular Tag instance, which the render function can then examine to
+ decide how to render:
+ </p>
+
+ <pre class="python-interpreter">
+>>> def alignment(ctx, data):
+... align = ctx.tag.attributes.get('align')
+... if align == 'right':
+... return ctx.tag["Aligned right"]
+... elif align == 'center':
+... return ctx.tag["Aligned center"]
+... else:
+... return ctx.tag["Aligned left"]
+...
+>>> class AlignmentPage(rend.Page):
+... docFactory = loaders.stan(tags.html[
+... tags.p(render=alignment),
+... tags.p(render=alignment, align="center"),
+... tags.p(render=alignment, align="right")])
+...
+>>> AlignmentPage().renderSynchronously()
+'<html><p>Aligned left</p><p align="center">Aligned center</p><p align="right">Aligned right</p></html>'</pre>
+
+ <p>
+ Note how the alignment renderer has access to the template node as
+ <code>ctx.tag</code>. It can examine and change this node, and the return value of
+ the render function replaces the original node in the DOM. Note that
+ here we are returning the template node after changing it. We will see
+ later how we can instead mutate the context and use slots so that the
+ knowledge the renderer requires about the structure of the template is
+ reduced even more.
+ </p>
+
+ <h2>Pattern specials</h2>
+
+ <p>
+ When writing render methods, it is easy to inline the construction of
+ Tag instances to generate HTML programatically. However, this creates a
+ template abstraction violation, where part of the HTML which will show
+ up in the final page output is hidden away inside of render methods
+ instead of inside the template. Pattern specials are designed to avoid
+ this problem. A node which has been tagged with a pattern special can
+ then be located and copied by a render method. The render method does
+ not need to know anything about the structure or location of the
+ pattern, only it's name.
+ </p>
+
+ <p>
+ We can rewrite our previous generator example so that the generator
+ does not have to know what type of tag the template designer would like
+ repeated for each item in the list:
+ </p>
+
+ <pre class="python-interpreter">
+>>> from nevow import rend, loaders, tags, inevow
+>>> def generate(ctx, items):
+... pat = inevow.IQ(ctx).patternGenerator('item')
+... for item in items:
+... ctx.tag[ pat(data=item) ]
+... return ctx.tag
+...
+>>> def string(ctx, item):
+... return ctx.tag[ str(item) ]
+...
+>>> class List(rend.Page):
+... docFactory = loaders.stan(tags.html[
+... tags.ul(render=generate)[
+... tags.li(pattern="item", render=string)]])
+...
+>>> List([1, 2, 3]).renderSynchronously()
+'<html><ol><li>1</li><li>2</li><li>3</li></ol></html>'</pre>
+
+ <p>
+ Note that we have to mutate the tag in place and repeatedly copy the
+ item pattern, applying the item as the data special to the resulting
+ Tag. It turns out that this is such a common operation that nevow comes
+ out of the box with these two render functions:
+ </p>
+
+ <pre class="python-interpreter">
+>>> class List(rend.Page):
+... docFactory = loaders.stan(tags.html[
+... tags.ul(render=rend.sequence)[
+... tags.li(pattern="item", render=rend.data)]])
+...
+>>> List([1, 2, 3]).renderSynchronously()
+'<html><ul><li>1</li><li>2</li><li>3</li></ul></html>'</pre>
+
+ <h2>Slot specials</h2>
+
+ <p>
+ The problem with render methods is that they are only capable of making
+ changes to their direct children. Because of the architecture of Nevow,
+ they should not attempt to change grandchildren or parent nodes. It is
+ possible to write one render method for every node you wish to change,
+ but there is a better way. A node with a slot special can be "filled"
+ with content by any renderer above the slot. Creating a slot special is
+ such a frequent task that there is a prototype in <code>nevow.tags</code>
+ which is usually used.
+ </p>
+
+ <p>
+ Let us examine a renderer which fills a template with information about
+ a person:
+ </p>
+
+ <pre class="python-interpreter">
+>>> from nevow import loaders, rend, tags
+...
+>>> person = ('Donovan', 'Preston', 'Male', 'California')
+...
+>>> def render_person(ctx, person):
+... firstName, lastName, sex, location = person
+... ctx.fillSlots('firstName', firstName)
+... ctx.fillSlots('lastName', lastName)
+... ctx.fillSlots('sex', sex)
+... ctx.fillSlots('location', location)
+... return ctx.tag
+...
+>>> class PersonPage(rend.Page):
+... docFactory = loaders.stan(tags.html(render=render_person)[
+... tags.table[
+... tags.tr[
+... tags.td[tags.slot('firstName')],
+... tags.td[tags.slot('lastName')],
+... tags.td[tags.slot('sex')],
+... tags.td[tags.slot('location')]]]])
+...
+>>> PersonPage(person).renderSynchronously()
+'<html><table><tr><td>Donovan</td><td>Preston</td><td>Male</td><td>California</td></tr></table></html>'</pre>
+
+ <p>
+ Using patterns in combination with slots can lead to very powerful
+ template abstraction. Nevow also includes another standard renderer
+ called "mapping" which takes any data which responds to the "items()"
+ message and inserts the items into appropriate slots:
+ </p>
+
+ <pre class="python-interpreter">
+>>> class DictPage(rend.Page):
+... docFactory = loaders.stan(tags.html(render=rend.mapping)[
+... tags.span[ tags.slot('foo') ], tags.span[ tags.slot('bar') ]])
+...
+>>> DictPage(dict(foo=1, bar=2)).renderSynchronously()
+'<html><span>1</span><span>2</span></html>'</pre>
+
+ <h2>Data directives</h2>
+
+ <p>
+ So far, we have always placed data functions directly in the Data
+ special attribute of a Tag. Sometimes, it is preferable to look up a
+ data method from the Page class as the Page has being rendered. For
+ example, a base class may define a template and a subclass may provide
+ the implementation of the data method. We can accomplish this effect by
+ using a data directive as a Tag's data special:
+ </p>
+
+ <pre class="python">
+class Base(rend.Page):
+ docFactory = loaders.stan(tags.html[
+ tags.div(data=tags.directive('name'), render=rend.data)])
+
+class Subclass(Base):
+ def data_name(self, ctx, data):
+ return "Your name"
+ </pre>
+
+ <p>
+ The data directive is resolved by searching for the
+ <code>IContainer</code> implementation in the context.
+ <code>rend.Page</code> implements <code>IContainer.get</code> by
+ performing an attribute lookup on the Page with the prefix 'data_*'. You
+ can provide your own <code>IContainer</code> implementation if you wish,
+ and also you should know that <code>IContainer</code> implementations for
+ list and dict are included in the <code class="API">nevow.accessors</code>
+ module.
+ </p>
+
+ <p>
+ A common gotcha is that the closest <code>IContainer</code> is used to
+ resolve data directives. This means that if a list is being used as the
+ data during the rendering process, data directives below this will be
+ resolved against the <code>IContainer</code> implementation in
+ <code>nevow.accessors.ListAccessor</code>. If you are expecting a data
+ directive to invoke a Page's data_* method but instead get a
+ <code>KeyError</code>, this is why.
+ </p>
+
+ <h2>Render directives</h2>
+
+ <p>
+ Render directives are almost exactly the same, except they are resolved
+ using the closest <code>IRendererFactory</code> implementation in the
+ context. Render directives can be used to allow subclasses to override
+ certain render methods, and also can be used to allow Fragments to
+ locate their own prefixed render methods.
+ </p>
+
+ <h2>Flatteners</h2>
+
+ <p>
+ TODO This section isn't done yet.
+ </p>
+
+ <p>
+ Nevow's flatteners use a type/function registry to determine how to
+ render objects which Nevow encounters in the DOM during the rendering
+ process. "Explicit is better than implicit", so in most cases,
+ explicitly applying render methods to data will be better than
+ registering a flattener, but in some cases it can be useful:
+ </p>
+
+ <pre class="python">
+class Person(object):
+ def __init__(self, firstName, lastName):
+ self.firstName = firstName
+ self.lastName = lastName
+
+def flattenPerson(person, ctx):
+ return flat.partialflatten(ctx, (person.firstName, " ", person.lastName))
+
+from nevow import flat
+flat.registerFlattener(flattenPerson, Person)
+
+def insertData(ctx, data):
+ return data
+
+class PersonPage(rend.Page):
+ docFactory = loaders.stan(tags.html[insertData])
+ </pre>
+ </body>
+</html>
diff -Naur Nevow-0.10.0/doc/howto/template.tpl Nevow-0.10.0-new/doc/howto/template.tpl
--- Nevow-0.10.0/doc/howto/template.tpl 1970-01-01 01:00:00.000000000 +0100
+++ Nevow-0.10.0-new/doc/howto/template.tpl 2010-03-02 20:42:55.000000000 +0100
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
+ <head>
+ <title>
+ Nevow:
+ </title>
+ <link type="text/css" rel="stylesheet" href="stylesheet.css" />
+ </head>
+
+ <body bgcolor="white">
+ <h1 class="title"></h1>
+ <div class="toc"></div>
+ <div class="body">
+
+ </div>
+
+ <p><a href="index.html">Index</a></p>
+ <span class="version">Version: </span>
+ </body>
+</html>
+
diff -Naur Nevow-0.10.0/doc/howto/traversal.xhtml Nevow-0.10.0-new/doc/howto/traversal.xhtml
--- Nevow-0.10.0/doc/howto/traversal.xhtml 1970-01-01 01:00:00.000000000 +0100
+++ Nevow-0.10.0-new/doc/howto/traversal.xhtml 2010-03-02 20:42:55.000000000 +0100
@@ -0,0 +1,448 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>
+ Object Traversal
+ </title>
+ </head>
+ <body>
+ <h1>Object Traversal</h1>
+
+ <p>
+ <strong>Object traversal</strong> is the process Nevow uses to determine
+ what object to use to render HTML for a particular URL. When an HTTP
+ request comes in to the web server, the object publisher splits the URL
+ into segments, and repeatedly calls methods which consume path segments
+ and return objects which represent that path, until all segments have
+ been consumed. At the core, the Nevow traversal API is very
+ simple. However, it provides some higher level functionality layered on
+ top of this to satisfy common use cases.
+ </p>
+
+ <h2>Object Traversal Basics</h2>
+
+ <p>
+ The <strong>root resource</strong> is the top-level object in the URL
+ space; it conceptually represents the URI <code>/</code>. The Nevow
+ <strong>object traversal</strong> and <strong>object publishing</strong>
+ machinery uses only two methods to locate an object suitable for
+ publishing and to generate the HTML from it; these methods are described
+ in the interface <code class="API">nevow.inevow.IResource</code>:
+ </p>
+
+ <pre class="python">
+class IResource(Interface):
+ def locateChild(self, ctx, segments):
+ """Locate another object which can be adapted to IResource
+ Return a tuple of resource, path segments
+ """
+
+ def renderHTTP(self, ctx):
+ """Render a request
+ """
+ </pre>
+
+ <p>
+ <code class="API" base="nevow.inevow.IResource">renderHTTP</code> can be
+ as simple as a method which simply returns a string of HTML. Let's
+ examine what happens when object traversal occurs over a very simple root
+ resource:
+ </p>
+
+ <pre class="python">
+from zope.interface import implements
+
+class SimpleRoot(object):
+ implements(inevow.IResource)
+
+ def locateChild(self, ctx, segments):
+ return self, ()
+
+ def renderHTTP(self, ctx):
+ return "Hello, world!"
+ </pre>
+
+ <p>
+ This resource, when passed as the root resource to <code class="API"
+ base="nevow">appserver.NevowSite</code> or <code class="API"
+ base="nevow">wsgi.createWSGIApplication</code>, will immediately return
+ itself, consuming all path segments. This means that for every URI a user
+ visits on a web server which is serving this root resource, the text
+ <code>"Hello, world!"</code> will be rendered. Let's examine the value of
+ <code>segments</code> for various values of URI:
+ </p>
+
+ <ul>
+ <li><code>/</code> - <code>('',)</code></li>
+ <li><code>/foo/bar</code> - <code>('foo', 'bar')</code></li>
+ <li>
+ <code>/foo/bar/baz.html</code> -
+ <code>('foo', 'bar', 'baz.html')</code>
+ </li>
+ <li>
+ <code>/foo/bar/directory/</code> -
+ <code>('foo', 'bar', 'directory', '')</code>
+ </li>
+ </ul>
+
+ <p>
+ So we see that Nevow does nothing more than split the URI on the string
+ <code>/</code> and pass these path segments to our application for
+ consumption. Armed with these two methods alone, we already have enough
+ information to write applications which service any form of URL
+ imaginable in any way we wish. However, there are some common URL
+ handling patterns which Nevow provides higher level support for.
+ </p>
+
+ <h2><code>locateChild</code> In Depth</h2>
+
+ <p>
+ One common URL handling pattern involves parents which only know about
+ their direct children. For example, a ``Directory`` object may only know
+ about the contents of a single directory, but if it contains other
+ directories, it does not know about the contents of them. Let's examine a
+ simple ``Directory`` object which can provide directory listings and
+ serves up objects for child directories and files:
+ </p>
+
+ <pre class="python">
+from zope.interface import implements
+
+class Directory(object):
+ implements(inevow.IResource)
+
+ def __init__(self, directory):
+ self.directory = directory
+
+ def renderHTTP(self, ctx):
+ html = ['<ul>']
+ for child in os.listdir(self.directory):
+ fullpath = os.path.join(self.directory, child)
+ if os.path.isdir(fullpath):
+ child += '/'
+ html.extend(['<li><a href="', child, '">', child, '</a></li>'])
+ html.append('</ul>')
+ return ''.join(html)
+
+ def locateChild(self, ctx, segments):
+ name = segments[0]
+ fullpath = os.path.join(self.directory, name)
+ if not os.path.exists(fullpath):
+ return None, () # 404
+
+ if os.path.isdir(fullpath):
+ return Directory(fullpath), segments[1:]
+ if os.path.isfile(fullpath):
+ return static.File(fullpath), segments[1:]
+ </pre>
+
+ <p>
+ Because this implementation of <code>locateChild</code> only consumed one
+ segment and returned the rest of them (<code>segments[1:]</code>), the
+ object traversal process will continue by calling
+ <code>locateChild</code> on the returned resource and passing the
+ partially-consumed segments. In this way, a directory structure of any
+ depth can be traversed, and directory listings or file contents can be
+ rendered for any existing directories and files.
+ </p>
+
+ <p>
+ So, let us examine what happens when the URI
+ <code>"/foo/bar/baz.html"</code> is traversed, where <code>"foo"</code>
+ and <code>"bar"</code> are directories, and <code>"baz.html"</code> is a
+ file.
+ </p>
+
+ <ol>
+ <li>
+ <code>
+ Directory('/').locateChild(ctx, ('foo', 'bar', 'baz.html'))
+ </code>
+ returns
+ <code>Directory('/foo'), ('bar', 'baz.html')</code>
+ </li>
+ <li>
+ <code>
+ Directory('/foo').locateChild(ctx, ('bar', 'baz.html'))
+ </code>
+ returns
+ <code>Directory('/foo/bar'), ('baz.html, )</code>
+ </li>
+ <li>
+ <code>
+ Directory('/foo/bar').locateChild(ctx, ('baz.html'))
+ </code>
+ returns
+ <code>File('/foo/bar/baz.html'), ()</code>
+ </li>
+ <li>
+ No more segments to be consumed;
+ <code>File('/foo/bar/baz.html').renderHTTP(ctx)</code> is called, and
+ the result is sent to the browser.
+ </li>
+ </ol>
+
+
+ <h2><code>childFactory</code> Method</h2>
+
+ <p>
+ Consuming one URI segment at a time by checking to see if a requested
+ resource exists and returning a new object is a very common
+ pattern. Nevow's default implementation of <code class="API"
+ base="nevow.inevow">IResource</code>, <code
+ class="API">nevow.rend.Page</code>, contains an implementation of
+ <code>locateChild</code> which provides more convenient hooks for
+ implementing object traversal. One of these hooks is
+ <code>childFactory</code>. Let us imagine for the sake of example that we
+ wished to render a tree of dictionaries. Our data structure might look
+ something like this:
+ </p>
+
+ <pre class="python">
+tree = dict(
+ one=dict(
+ foo=None,
+ bar=None),
+ two=dict(
+ baz=dict(
+ quux=None)))
+ </pre>
+
+ <p>
+ Given this data structure, the valid URIs would be:
+ </p>
+
+ <ul>
+ <li>/</li>
+ <li>/one</li>
+ <li>/one/foo</li>
+ <li>/one/bar</li>
+ <li>/two</li>
+ <li>/two/baz</li>
+ <li>/two/baz/quux</li>
+ </ul>
+
+ <p>
+ Let us construct a <code class="API" base="nevow">rend.Page</code>
+ subclass which uses the default <code>locateChild</code> implementation
+ and overrides the <code>childFactory</code> hook instead:
+ </p>
+
+ <pre class="python">
+class DictTree(rend.Page):
+ def __init__(self, dataDict):
+ self.dataDict = dataDict
+
+ def renderHTTP(self, ctx):
+ if self.dataDict is None:
+ return "Leaf"
+ html = ['<ul>']
+ for key in self.dataDict.keys():
+ html.extend(['<li><a href="', key, '">', key, '</a></li>'])
+ html.append('</ul>')
+ return ''.join(html)
+
+ def childFactory(self, ctx, name):
+ if name not in self.dataDict:
+ return rend.NotFound # 404
+ return DictTree(self.dataDict[name])
+ </pre>
+
+ <p>
+ As you can see, the <code>childFactory</code> implementation is
+ considerably shorter than the equivalent <code>locateChild</code>
+ implementation would have been.
+ </p>
+
+ <h2><code>child_*</code> methods and attributes</h2>
+
+ <p>
+ Often we may wish to have some hardcoded URLs which are not dynamically
+ generated based on some data structure. For example, we might have an
+ application which uses an external CSS stylesheet, an external JavaScript
+ file, and a folder full of images. The <code class="API"
+ base="nevow">rend.Page.locateChild</code> implementation provides a
+ convenient way for us to express these relationships by using
+ child-prefixed methods:
+ </p>
+
+ <pre class="python">
+class Linker(rend.Page):
+ def renderHTTP(self, ctx):
+ return """<html>
+<head>
+ <link href="css" rel="stylesheet" />
+ <script type="text/javascript" src="scripts" />
+ <body>
+ <img src="images/logo.png" />
+ </body>
+</html>"""
+
+ def child_css(self, ctx):
+ return static.File('styles.css')
+
+ def child_scripts(self, ctx):
+ return static.File('scripts.js')
+
+ def child_images(self, ctx):
+ return static.File('images/')
+ </pre>
+
+ <p>
+ One thing you may have noticed is that all of the examples so far have
+ returned new object instances whenever they were implementing a traversal
+ API. However, there is no reason these instances cannot be shared. One
+ could for example return a global resource instance, an instance which
+ was previously inserted in a dict, or lazily create and cache dynamic
+ resource instances on the fly. The <code>rend.Page.locateChild</code>
+ implementation also provides a convenient way to express that one global
+ resource instance should always be used for a particular URL, the
+ child-prefixed attribute:
+ </p>
+
+ <pre class="python">
+class FasterLinker(Linker):
+ child_css = static.File('styles.css')
+ child_scripts = static.File('scripts.js')
+ child_images = static.File('images/')
+ </pre>
+
+ <h2>Dots in child names</h2>
+
+ <p>
+ When a URL contains dots, which is quite common in normal URLs, it is
+ simple enough to handle these URL segments in <code>locateChild</code> or
+ <code>childFactory</code> -- one of the passed segments will simply be a
+ string containing a dot. However, it is not immediately obvious how one
+ would express a URL segment with a dot in it when using child-prefixed
+ methods. The solution is really quite simple:
+ </p>
+
+ <pre class="python">
+class DotChildren(rend.Page):
+ def renderHTTP(self, ctx):
+ return """
+ <html>
+ <head>
+ <script type="text/javascript" src="scripts.js" />
+ </head>
+ </html>"""
+
+setattr(DotChildren, 'child_scripts.js', static.File('scripts.js'))
+ </pre>
+
+ <p>
+ The same technique could be used to install a child method with a dot in
+ the name.
+ </p>
+
+
+ <h2>children dictionary</h2>
+
+ <p>
+ The final hook supported by the default implementation of
+ <code>locateChild</code> is the <code>rend.Page.children</code>
+ dictionary:
+ </p>
+
+ <pre class="python">
+class Main(rend.Page):
+ children = {
+ 'people': People(),
+ 'jobs': Jobs(),
+ 'events': Events()}
+
+ def renderHTTP(self, ctx):
+ return """
+ <html>
+ <head>
+ <title>Our Site</title>
+ </head>
+ <body>
+ <p>bla bla bla</p>
+ </body>
+ </html>"""
+ </pre>
+
+ <p>
+ Hooks are checked in the following order:
+ </p>
+
+ <ol>
+ <li><code>self.children</code></li>
+ <li><code>self.child_*</code></li>
+ <li><code>self.childFactory</code></li>
+ </ol>
+
+ <h2>The default trailing slash handler</h2>
+
+ <p>
+ When a URI which is being handled ends in a slash, such as when the
+ <code>/</code> URI is being rendered or when a directory-like URI is
+ being rendered, the string <code>''</code> appears in the path segments
+ which will be traversed. Again, handling this case is trivial inside
+ either <code>locateChild</code> or <code>childFactory</code>, but it may
+ not be immediately obvious what child-prefixed method or attribute will
+ be looked up. The method or attribute name which will be used is simply
+ <code>child</code> with a single trailing underscore.
+ </p>
+
+ <p>
+ The <code>rend.Page</code> class provides an implementation of this
+ method which can work in two different ways. If the attribute
+ <code>addSlash</code> is <code>True</code>, the default trailing slash
+ handler will return <code>self</code>. In the case when
+ <code>addSlash</code> is <code>True</code>, the default
+ <code>rend.Page.renderHTTP</code> implementation will simply perform a
+ redirect which adds the missing slash to the URL.
+ </p>
+
+ <p>
+ The default trailing slash handler also returns self if
+ <code>addSlash</code> is <code>False</code>, but emits a warning as it
+ does so. This warning may become an exception at some point in the
+ future.
+ </p>
+
+ <h2><code>ICurrentSegments</code> and <code>IRemainingSegments</code></h2>
+
+ <p>
+ During the object traversal process, it may be useful to discover which
+ segments have already been handled and which segments are remaining to be
+ handled. This information may be obtained from the <code>context</code>
+ object which is passed to all the traversal APIs. The interfaces <code
+ class="API">nevow.inevow.ICurrentSegments</code> and <code
+ class="API">nevow.inevow.IRemainingSegments</code> are used to retrieve
+ this information. To retrieve a tuple of segments which have previously
+ been consumed during object traversal, use this syntax:
+ </p>
+
+ <pre class="python">
+segs = ICurrentSegments(ctx)
+ </pre>
+
+ <p>
+ The same is true of <code>IRemainingSegments</code>.
+ <code>IRemainingSegments</code> is the same value which is passed as
+ <code>segments</code> to <code>locateChild</code>, but may also be useful
+ in the implementations of <code>childFactory</code> or a child-prefixed
+ method, where this information would not otherwise be available.
+ </p>
+
+ <h2>Conclusion</h2>
+
+ <p>
+ Nevow makes it easy to handle complex URL hierarchies. The most basic
+ object traversal interface, <code
+ class="API">nevow.inevow.IResource.locateChild</code>, provides powerful
+ and flexible control over the entire object traversal process. Nevow's
+ canonical <code>IResource</code> implementation, <code>rend.Page</code>,
+ also includes the convenience hooks <code>childFactory</code> along with
+ child-prefixed method and attribute semantics to simplify common use
+ cases.
+ </p>
+ </body>
+</html>
diff -Naur Nevow-0.10.0/doc/howto/xmltemplates.xhtml Nevow-0.10.0-new/doc/howto/xmltemplates.xhtml
--- Nevow-0.10.0/doc/howto/xmltemplates.xhtml 1970-01-01 01:00:00.000000000 +0100
+++ Nevow-0.10.0-new/doc/howto/xmltemplates.xhtml 2010-03-02 20:42:55.000000000 +0100
@@ -0,0 +1,407 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>
+ XML Templates
+ </title>
+ </head>
+ <body>
+ <h1>Nevow XML Templates</h1>
+
+ <p>
+ Stan syntax is cool, but eventually you are going to want to integrate
+ your Python code with a template designed by an HTML monkey. Nevow
+ accomplishes this by providing an xmlfile loader which uses the built-in
+ Python SAX libraries to generate a tree of stan behind the scenes. The
+ general rule is anything that is possible in stan should be possible in a
+ pure XML template; of course, the XML syntax is generally going to be
+ much more verbose.
+ </p>
+
+ <h2>loaders.xmlfile</h2>
+
+ <p>
+ Wherever you have seen a loaders.stan being created in any of the example
+ code, a <code class="API" base="nevow">loaders.xmlfile</code> can be
+ substituted instead. At the most basic, <code>xmlfile</code> merely
+ requires the name of an xml template:
+ </p>
+
+ <pre class="python">
+class HelloXML(rend.Page):
+ docFactory = loaders.xmlfile('hello.xml')
+ </pre>
+
+ <p>
+ Placing the following xml in the <code>hello.xml</code> file will cause
+ <code>HelloXML</code> to display a static page when it is rendered:
+ </p>
+
+ <pre><html>Hello, world!</html></pre>
+
+ <p>
+ The following additional keyword arguments may be given to
+ <code>xmlfile</code> to configure it:
+ </p>
+
+ <ul>
+ <li>
+ <code>templateDirectory</code>:
+ The path to the directory which contains the template file. Defaults to ''.
+ </li>
+ <li>
+ <code>ignoreDocType</code>:
+ If True, discard any DOCTYPE declaration when building the DOM from
+ this template. When false, preserve the DOCTYPE, causing it to show up
+ in the final output. Useful for when you are inserting an XML fragment
+ into a larger page and do not wish to generate invalid XML as
+ output. Defaults to False.
+ </li>
+ <li>
+ <code>ignoreComment</code>:
+ If True, discard XML comments, causing them to disappear from the
+ output. If False, preserve comments and render them in the final output
+ unchanged. Defaults to False.
+ </li>
+ <li>
+ <code>pattern</code>:
+ If present, the given pattern name will be looked up and used as the
+ root of the template. If not present, the entire document will be used
+ as the template. Useful for embedding fragments of an XML document in a
+ larger page. Defaults to None.
+ </li>
+ </ul>
+
+ <h2>Nevow's xmlns declaration</h2>
+
+ <p>
+ In order for Nevow to notice and process any XML directives in the
+ template file, you must declare the Nevow xmlns at the top of your XML
+ document. Nevow's xmlns is:
+ </p>
+
+ <pre>http://nevow.com/ns/nevow/0.1</pre>
+
+ <p>
+ The syntax for declaring that your xml document uses this namespace is:
+ </p>
+
+ <pre><html xmlns:nevow="http://nevow.com/ns/nevow/0.1"></html></pre>
+
+ <p>
+ You may replace the text "nevow" in the above example with any name you
+ choose. For example, many people use "n" because it is shorter to
+ type. If you do so, be sure to replace all occurrences of the nevow
+ namespace in the examples with the namespace name you choose.
+ </p>
+
+ <h2>Nevow's Tag Attribute Language</h2>
+
+ <p>
+ The markup you will add to your XHTML file in order to invoke Nevow code
+ consists mostly of namespaced tag attributes. This approach was
+ influenced heavily by the Zope Page Templates (ZPT) Tag Attribute
+ Language (TAL). However, I felt that TAL did not go far enough in
+ removing control flow and branching possibilities from the XML
+ template. Nevow's main philosophy is that it should be as easy as
+ possible to move from the XML document into Python code, and that the
+ Python code should have ultimate control over manipulating the structure
+ of the XML template.
+ </p>
+
+ <p>
+ The key is that it is easy to expose Python methods that you write to
+ your XML template, and it is easy for the XML templates to mark nodes
+ which it wishes the Python method to manipulate. In this way, if either
+ the Python implementation changes or the location or content of the
+ marked nodes change in the XML template, the other side will be isolated
+ from these changes.
+ </p>
+
+ <p>
+ Nevow's XML templating has two attributes which invoke Python code:
+ </p>
+
+ <ul>
+ <li>
+ <code>nevow:render</code> --
+ Invokes a Python method and replaces the template node with the result
+ </li>
+ <li>
+ <code>nevow:data</code> --
+ Invokes a Python method and sets the data special for the node to the
+ result
+ </li>
+ </ul>
+
+ <p>
+ It has one attribute which marks nodes as manipulatable by Python code:
+ </p>
+
+ <ul>
+ <li>
+ <code>nevow:pattern</code> --
+ Gives a node a name so that Python code may clone and mutate copies of
+ this node
+ </li>
+ </ul>
+
+ <p>
+ It also has two namespaced tags:
+ </p>
+
+ <ul>
+ <li>
+ <code>nevow:slot</code> --
+ Works in the same way as the slot attribute
+ </li>
+ <li>
+ <code>nevow:attr</code> --
+ Indicates that an attribute of the parent tag should be manipulated by
+ Python code in some way
+ </li>
+ </ul>
+
+ <h2>nevow:render</h2>
+
+ <p>
+ When the <code>nevow:render</code> attribute is encountered, the xmlfile
+ loader sets the render special to a directive constructed with the
+ attribute value. When the template is rendered, this means that the
+ appropriate render_* method will be looked up on the
+ <code>IRendererFactory</code> (generally the Page instance):
+ </p>
+
+ <pre><html><div nevow:render="foo" /></html></pre>
+
+ <p>
+ With the <code>render_foo</code> method::
+ </p>
+
+ <pre class="python">
+def render_foo(self, ctx, data):
+ return "Hello"
+ </pre>
+
+ <p>
+ Will result in the document:
+ </p>
+
+ <pre><html>Hello</html></pre>
+
+ <p>
+ Note that the return value of the render method replaces the template
+ node in the DOM, so if you want the template node to remain, you should
+ use <code>ctx.tag</code>.
+ </p>
+
+ <h2>Built-in renderers</h2>
+
+ <p>
+ Nevow comes with various built in renderers on the Page class.
+ </p>
+
+ <ul>
+ <li>
+ <code>data</code>:
+ Renders the current data as-is inside the current node.
+ </li>
+ <li>
+ <code>string</code>:
+ Renders the current data as a string inside the current node.
+ </li>
+ <li>
+ <code>sequence</code>:
+ Iterates the current data, copying the "item" pattern for each
+ item. Sets the the data special of the new node to the item, and
+ inserts the result in the current node. See the nevow.rend.sequence
+ docstring for information about other used patterns, including
+ "header", "divider", "footer" and "empty".
+ </li>
+ <li>
+ <code>mapping</code>:
+ Calls .items() on the current data, and calls ctx.fillSlots(key, value)
+ for every key, value pair in the result. Returns the template tag.
+ </li>
+ <li>
+ <code>xml</code>:
+ Inserts the current data into the template after wrapping it in an xml
+ instance. Not very useful in practice.
+ </li>
+ </ul>
+
+ <h2>nevow:data</h2>
+
+ <p>
+ When the <code>nevow:data</code> attribute is encountered, the xmlfile
+ loader sets the data special of the current node to a directive
+ constructed with the attribute value. When the template is rendered,
+ this means that the appropriate data_* method will be looked up on the
+ current <code>IContainer</code> (generally the Page instance). The data_*
+ method will be called, and the result will be set as the data special of
+ the current Tag:
+ </p>
+
+ <pre><html><div nevow:data="name" nevow:render="data" /></html></pre>
+
+ <p>
+ With the <code>data_name</code> method:
+ </p>
+
+ <pre class="python">
+def data_name(self, ctx, data):
+ return "Hello!"
+ </pre>
+
+ <p>
+ Will result in the document:
+ </p>
+
+ <pre><html><div>Hello!</div></html></pre>
+
+ <p>
+ Note that with a data attribute on a node but no renderer, the result of
+ the data method will be set as the data special for that tag, and child
+ render methods will be passed this data.
+ </p>
+
+ <h2>nevow:pattern</h2>
+
+ <p>
+ When the <code>nevow:pattern</code> attribute is encountered, the xmlfile
+ loader sets the pattern special of the current node to the attribute
+ value as a string. Renderers which are above this node may then make
+ copies of it using the <code class="API">nevow.inevow.IQ</code> of the
+ current context. With the template:
+ </p>
+
+ <pre><html nevow:render="stuff"><div nevow:pattern="somePattern" nevow:render="data" /></html></pre>
+
+ <p>
+ And the renderer:
+ </p>
+
+ <pre class="python">
+def render_stuff(self, ctx, data):
+ pat = inevow.IQ(ctx).patternGenerator('somePattern')
+ return [pat(data=1), pat(data=2)]
+ </pre>
+
+ <p>
+ Will result in the document:
+ </p>
+
+ <pre><html><div>1</div><div>2</div></html></pre>
+
+ <h2>nevow:slot</h2>
+
+ <p>
+ When the <code>nevow:slot</code> tag is encountered, the xmlfile loader
+ constructs a <code class="API">nevow.stan.slot</code> instance, passing
+ the name attribute value as the slot name. The children of the slot node
+ are added as children of the new slot instance. This is useful if you
+ wish to put patterns inside the slot. With the template:
+ </p>
+
+ <pre><html nevow:render="stuff"><nevow:slot name="slotName" /></html></pre>
+
+ <p>
+ And the render method:
+ </p>
+
+ <pre class="python">
+def render_stuff(self, ctx, data):
+ ctx.fillSlots('slotName', "Hello.")
+ return ctx.tag
+ </pre>
+
+ <p>
+ This document will be produced:
+ </p>
+
+ <pre><html>Hello.</html></pre>
+
+ <h2>nevow:attr</h2>
+
+ <p>
+ When the <code>nevow:attr</code> tag is encountered, the contents of the
+ nevow:attr node will be assigned to the attribute of the parent tag with
+ the name of the value of the name attribute. Perhaps an example will be a
+ little clearer:
+ </p>
+
+ <pre><html><a><nevow:attr name="href">HELLO!</nevow:attr>Goodbye</a></html></pre>
+
+ <p>
+ This document will be produced:
+ </p>
+
+ <pre><html><a href="HELLO!">Goodbye</a></html></pre>
+
+ <p>
+ While this syntax is somewhat awkward, every other type of nevow tag and
+ attribute may be used inside the <code>nevow:attr</code> node. This makes
+ setting attributes of tags uniform with every other method of
+ manipulating the XML template.
+ </p>
+
+ <h2>nevow:invisible</h2>
+
+ <p>
+ Sometimes you need to group some elements, because you need to use a
+ renderer for a group of children.
+ </p>
+
+ <p>
+ However, it may not be desirable to give these elements a parent/child
+ relationship in your XML structure. For these cases, use
+ <code>nevow:invisible</code>.
+ </p>
+
+ <p>
+ As suggested by the name, a <code>nevow:invisible</code> tag is removed
+ in the rendered XML. Here is an example:
+ </p>
+
+ <pre><html><nevow:invisible nevow:data="name" nevow:render="data" /></html></pre>
+
+ <p>
+ With the <code>data_name</code> method:
+ </p>
+
+ <pre class="python">
+def data_name(self, ctx, data):
+ return "Hello!"
+ </pre>
+
+ <p>
+ Will result in the document:
+ </p>
+
+ <pre><html>Hello!</html></pre>
+
+ <h2>xmlstr, htmlfile, and htmlstr</h2>
+
+ <p>
+ xmlstr is a loader which is identical to xmlfile except it takes a string
+ of XML directly.
+ </p>
+
+ <p>
+ htmlfile and htmlstr should generally be avoided. They are similar to
+ xmlfile and xmlstr, except they use twisted.web.microdom in
+ beExtremelyLenient mode to attempt to parse badly-formed HTML (non-XHTML)
+ templates. See the nevow.loaders docstrings for more information.
+ </p>
+
+ <h2>Conclusions</h2>
+
+ <p>
+ Nevow's xmlfile tag attribute language allows you to integrate
+ externally-designed XHTML templates into the Nevow rendering process.
+ </p>
+ </body>
+</html>