Merge lp:~exarkun/divmod.org/remove-nevow into lp:divmod.org

Proposed by Jean-Paul Calderone on 2014-06-08
Status: Merged
Approved by: Tristan Seligmann on 2014-06-08
Approved revision: 2749
Merged at revision: 2749
Proposed branch: lp:~exarkun/divmod.org/remove-nevow
Merge into: lp:divmod.org
Diff against target: 70998 lines
To merge this branch: bzr merge lp:~exarkun/divmod.org/remove-nevow
Reviewer Review Type Date Requested Status
Tristan Seligmann 2014-06-08 Approve on 2014-06-08
Review via email: mp+222457@code.launchpad.net

Description of the change

To post a comment you must log in.
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Divmod.pth'
2--- Divmod.pth 2014-05-18 17:48:04 +0000
3+++ Divmod.pth 2014-06-08 12:16:37 +0000
4@@ -1,9 +1,8 @@
5-# -*- test-case-name: axiom,combinator,epsilon,xmantissa,nevow,formless,xquotient,reverend,sine,hyperbola -*-
6+# -*- test-case-name: axiom,combinator,epsilon,xmantissa,xquotient,reverend,sine,hyperbola -*-
7 Axiom
8 Combinator
9 Epsilon
10 Mantissa
11-Nevow
12 Quotient
13 Reverend
14 Sine
15
16=== removed directory 'Nevow'
17=== removed file 'Nevow/ChangeLog'
18--- Nevow/ChangeLog 2006-06-14 11:54:41 +0000
19+++ Nevow/ChangeLog 1970-01-01 00:00:00 +0000
20@@ -1,743 +0,0 @@
21-2006-06-12 Glyph Lefkowitz <glyph@divmod.com>
22-
23- * Nevow 0.9.0: see NEWS.txt for details.
24-
25-2006-04-07 Jp Calderone <exarkun@divmod.com>
26-
27- * Nevow 0.8.0 released
28-
29-2006-03-30 Tommi Virtanen <tv@twistedmatrix.com>
30-
31- * nevow/static.py: Fix handling of range requests on static files.
32-
33-2006-03-30 Jp Calderone <exarkun@divmod.com>
34-
35- * formless/freeform-defaults.css, formless/annotate.py: Style and
36- feedback improvements.
37-
38-2006-03-29 Jp Calderone <exarkun@divmod.com>
39-
40- * examples/formbuilder/: Apply Cory Dodt's patch to make this
41- example work again.
42-
43-2006-03-27 Jp Calderone <exarkun@divmod.com>
44-
45- * nevow/athena.py: Add getInitialArguments method which will be
46- invoked during rendering and may return a list or tuple of objects
47- which will be be passed to the client-side Widget's __init__ method.
48-
49-2006-03-24 Allen Short <washort@divmod.com>
50-
51- * Upgrade MochiKit to 1.2
52-
53-2006-03-17 Tristan Seligmann <mithrandi@mithrandi.za.net>
54-
55- * Remove usage of twisted.python.components.Interface from formless.
56- Convert TypedInterface to zope.interface.
57-
58-2006-03-17 Jp Calderone <exarkun@divmod.com>
59-
60- * nevow/json.py: Improve (hopefully correct this time ;) unicode
61- support.
62-
63-2006-03-08 Valentino Volonghi <dialtone@divmod.com>
64-
65- * Remove usage of twisted.python.components.Interface from nevow.
66- Remove compyCompat.
67-
68-2006-02-28 Jp Calderone <exarkun@divmod.com>
69-
70- * nevow/athena.py: Make the "Connection: Close" header of Athena
71- transport responses optional (toggleable by a flag on LivePage) to
72- allow TCP connection setup overhead to be avoided.
73-
74-2006-02-15 Tristan Seligmann <mithrandi@mithrandi.za.net>
75-
76- * nevow/athena.js, nevow/athena.py: Pass JavaScript call-stack
77- information back to the server and include it in logged tracebacks
78- (Firefox only).
79-
80-2006-02-14 Jp Calderone <exarkun@divmod.com>
81-
82- * nevow/util.py: Delete a bunch of code duplicated from Twisted.
83-
84-2006-02-06 Glyph Lefkowitz <glyph@twistedmatrix.com>
85-
86- * nevow/athena.py, nevow/athena.js: Pop up an obnoxious widget when
87- an Athena connection is lost.
88-
89-2006-02-06 Jp Calderone <exarkun@divmod.com>
90-
91- * nevow/runtime.js: Add Platform.getPage, a wrapper around the
92- browser-provided HTTP request function.
93-
94-2006-02-01 Tristan Seligmann <mithrandi@mithrandi.za.net>
95-
96- * nevow/athena.js: Add support for <athena:handler> element, a
97- declarative mechanism for attaching event handlers to nodes.
98-
99-2006-02-01 Tristan Seligmann <mithrandi@mithrandi.za.net>
100-
101- * bin/nit: Test collector/runner for Athena widgets.
102-
103-2006-02-01 Jp Calderone <exarkun@divmod.com>
104-
105- * nevow/defer.js: Deferred implementation to replace MochiKit
106- Deferreds.
107-
108-2006-01-21 Valentino Volonghi <dialtone@divmod.com>
109-
110- * nevow/rend.py, formless/webform.py: Support Deferreds returned
111- from bind_ methods.
112-
113-2006-01-21 Valentino Volonghi <dialtone@divmod.com>
114-
115- * nevow/flat/flatstan.py: Fix macros inside of other specials.
116-
117-2006-01-19 Jp Calderone <exarkun@divmod.com>
118-
119- * nevow/athena.js: Added Divmod.Class.methods() for defining
120- multiple methods at once.
121-
122-2006-01-19 Jp Calderone <exarkun@divmod.com>
123-
124- * nevow/athena.py, nevow/athena.js: Support the addition of
125- LiveFragment instances to a page after the initial render pass.
126-
127-2006-01-15 Jp Calderone <exarkun@divmod.com>
128-
129- * nevow/athena.js: Introduced new form of Divmod.Class.method() for
130- adding methods to JavaScript classes. Added a child-window based
131- log viewer.
132-
133-2006-01-08 Valentino Volonghi <dialtone@divmod.com>
134-
135- * examples/hello/hellohtml.py: Removed htmlfile usage
136- * nevow/loaders.py: Deprecated htmlfile/htmlstr
137-
138-2006-01-08 Glyph Lefkowitz <glyph@twistedmatrix.com>
139-
140- * nevow/test/, formless/test/: Removed all usage of trial's
141- deferredResult() and util.wait() functions.
142-
143-2006-01-04 Glyph Lefkowitz <glyph@twistedmatrix.com>
144-
145- * nevow/athena.py: Added fragment and widget nesting. On the
146- server side, this documents and provides a supported way of
147- setting the magical required "page" attribute. On the client
148- side, this provides a convenient hook for multiple widgets within
149- a page to communicate with each other.
150-
151-2005-12-26 Jp Calderone <exarkun@divmod.com>
152-
153- * nevow/athena.py: Added athena.js and MochiKit.js to the dictionary
154- returned by allJavascriptModules(), allowing them to be referenced
155- using the JS import mechanism, in turn allowing them both to be
156- served from a single site-wide URL, rather than once per page.
157-
158-2005-12-22 Jp Calderone <exarkun@divmod.com>
159-
160- * nevow/athena.py: Remove Python 2.4 dependencies.
161-
162-2005-12-21 Jp Calderone <exarkun@divmod.com>
163-
164- * Nevow 0.7.0 released
165-
166-2005-12-18 Jp Calderone <exarkun@divmod.com>
167-
168- * nevow/athena.py: Server-side processing of .js files to allow for
169- an import directive. Imported JavaScript modules are inserted into
170- the page during the render process in dependency order.
171-
172- * nevow/widget.js: Athena Widgets class and support code definitions
173- moved here.
174-
175-2005-12-13 Matt Goodall <matt@pollenation.net>
176-
177- * nevow/athena.js: Improved IE compatibility.
178-
179-2005-12-05 Jp Calderone <exarkun@divmod.com>
180-
181- * nevow/athena.js: Added Divmod.Class object which provides a
182- class-based object model for JavaScript programs. Added
183- Nevow.Athena.Widget, a base class for "Live Widgets" - JavaScript
184- classes which can control a particular section of a LivePage and can
185- communicate with corresponding LiveFragment instances on the server.
186-
187- * nevow/athena.py: Added a callRemote method to LiveFragment - this
188- allows the server to invoke methods on particular Widgets on the
189- client.
190-
191-2005-12-03 Jp Calderone <exarkun@divmod.com>
192-
193- * nevow/rend.py: Fixed a bug in xmlfile caching which could lead to
194- a corrupt loader cache.
195-
196-2005-11-29 Jp Calderone <exarkun@divmod.com>
197-
198- * nevow/appserver.py: Removed "support" (which consisted of logging
199- an error message and continuing) for returning objects which do not
200- provide IResource.
201-
202-2005-11-26 Jp Calderone <exarkun@divmod.com>
203-
204- * nevow/athena.py, nevow/athena.js: Use POST for the LivePage
205- transport, rather than GET.
206-
207- * nevow/json.py: Fix a bug in JSON support for floating points.
208-
209-2005-11-25 Jp Calderone <exarkun@divmod.com>
210-
211- * nevow/athena.js: Go live by default.
212-
213-2005-11-22 Glyph Lefkowitz <glyph@divmod.com>
214-
215- * nevow/guard.py: Removed __session_just_startd__.
216-
217-2005-11-15 Jp Calderone <exarkun@divmod.com>
218-
219- * nevow/athena.py: Added LiveFragment - base class for Fragments
220- which may cooperatively share a single LivePage connection.
221-
222-
223-2005-11-09 Jp Calderone <exarkun@divmod.com>
224-
225- * Athena JavaScript API unified into a pseudo-namespace hierarchy.
226-
227-2005-11-07 Jp Calderone <exarkun@divmod.com>
228-
229- * JSON serializer now quotes dict/object keys.
230-
231-2005-11-02 Jp Calderone <exarkun@divmod.com>
232-
233- * Nevow 0.6.0 released
234-
235-2005-09-21 Jp Calderone <exarkun@divmod.com>
236-
237- * nevow/athena.py: New implementation of LivePage with a
238- data-centric API: generation of JavaScript on the server is highly
239- discouraged, instead an API for passing around simple or complex
240- data structures is provided.
241-
242-2005-08-01 Matt Goodall <matt@pollenation.net>
243-
244- egg-ify the distribution. "python setup.py bdist_egg" will now build
245- a .egg in dist for Python 2.3 and Python 2.4.
246-
247-2005-07-14 Donovan Preston <dp@divmod.org>
248-
249- * It's no longer necessary to specify addSlash = True on
250- the root resource. nevow.appserver.NevowSite automatically
251- sets it on the first argument you pass to it (the root
252- resource).
253-
254-2005-07-12 Donovan Preston <dp@divmod.org>
255-
256- * Usability improvements for formless at the expense of
257- purity of abstraction. Since the only thing anybody uses
258- formless for is rendering web forms, make it a little easier
259- to do common things. For example:
260-
261- - _nevow_carryover_ does not get appended to URLs unless absolutely
262- necessary (because you return a value from an autocallable)
263-
264- - TypedInterface is being deprecated in favor of using
265- IConfigurable directly, and an IConfigurable implementation
266- on Fragment/Page that is easy to use. To expose a "foo" method
267- on a page which takes a "bar" string and a "baz" integer, do this:
268-
269- def bind_foo(self, ctx):
270- return [('bar', String()), ('baz', Integer())]
271-
272- Previously, you would have had to create a TypedInterface,
273- declare foo and the types of the arguments in the class body,
274- declare that foo is autocallable, and declare that your Page
275- class __implements__ the interface. Now, just implement
276- bind_foo to return an IBinding or a list which can be munged
277- into one.
278-
279- - It is possible to return a Page from an autocallable to have
280- that page displayed directly after posting the autocallable.
281- The URL that is used is freeform_hand, which means that the
282- Page goes into your "hand" in the session. The hand can only
283- hold one value, the most recent return result of an autocallable.
284- This isn't very back-button friendly but it makes it super
285- easy to put together a multi-step wizard interface.
286-
287- See examples/tests/testformless.py and the /testformless on
288- the example server to see how to do this.
289-
290- - It is possible to return a URL instance from an autocallable
291- to have the user redirected to that page after posting the
292- form successfully. This replaces and deprecates the old,
293- whacko method of setting IRedirectAfterPost on the Request.
294-
295- See examples/tests/testformless.py and the /formless_redirector
296- on the example server to see how to do this.
297-
298- * There is now livetest coverage of the formless examples,
299- including posting forms and checking erroneous conditions.
300-
301-2005-07-06 Donovan Preston <dp@divmod.org>
302-
303- * Major non-backwards-compatible improvements to livepage. Changes
304- are designed to avoid an uncollectable garbage problem which was
305- inherent in the previous design.
306-
307- The livepage javascript glue now includes a global object named
308- "server". This object has a "handle" method which takes at least
309- one argument, a string indicating the name of the handler to
310- invoke on the server. When called by client-side javascript,
311- LivePage.locateHandler is invoked. locateHandler should return
312- a callable which will be called with a context indicating
313- which client is invoking the method, and any additional arguments
314- which were passed to server.handle, as strings.
315-
316- The default implementation of LivePage.locateHandler looks for
317- a correspondingly named "handle_*" method. Using livepage is
318- now as simple as subclassing LivePage and providing handle_*
319- methods:
320-
321- class Foo(LivePage):
322- def handle_bar(self, ctx, something):
323- print "something!", something
324-
325- And calling server.handle in javascript:
326-
327- <a onclick="server.handle('bar', 'here is something')">Click me</a>
328-
329- The previous behavior of registering closures or other callables
330- as event handlers and then embedding them in the page is still
331- available using the IClientHandle.transient method. These one-
332- shot handlers are only invokable by the client once before being
333- garbage collected on the server. This makes it possible to
334- implement temporary dialog boxes and the like.
335-
336-2005-04-09 Tommi Virtanen <tv@twistedmatrix.com>
337-
338- * Allow remembering ILogger to specify an alternate access logging
339- method.
340-
341-2005-04-06 Matt Goodall <matt@pollenation.net>
342-
343- * Added optional context argument to Page's renderString and
344- renderSynchronously methods. This provides a site-like context that is
345- useful when rendering multiple pages that need common remembered data.
346-
347-2005-3-23 Donovan Preston <dp@divmod.org>
348-
349- * Releasing 0.4.1
350-
351-2005-3-22 Donovan Preston <dp@divmod.org>
352-
353- * Releasing 0.4
354-
355-2005-02-22 Matt Goodall <matt@pollenation.net>
356-
357- * Added a "data" renderer (rend.data) that replaces the tag's content
358- with the current data. i.e. <p n:data="name" n:render="data">Foo Bar</p>.
359-
360-2005-02-17 Matt Goodall <matt@pollenation.net>
361-
362- * Added i18n - a gettext-like mechanism for marking translatable content
363- in an application's Python modules by wrapping a string in _(). Standard
364- Python gettext tools can be used to generate translation files.
365-
366- Translation happens during rendering and depends on a list of languages
367- found in the context. By default, the browser's preferred languages are
368- used. The default behaviour can be overridden by remembering the languages
369- as inevow.ILanguages in the context; allowing the language to be selected
370- from user preferences, for example.
371-
372-2005-02-08 Matt Goodall <matt@pollenation.net>
373-
374- * Extended the IDocFactory interface's load method to accept an optional
375- context.
376-
377- The current loaders do not use the context but future loaders may, i.e. one
378- that loads a localised template based on some language in the context.
379-
380-2005-01-01 Donovan Preston <dp@divmod.org>
381-
382- * Rewrote LivePage quoting code to be much more correct; added many unit
383- tests. Some older livepage code must be changed to use the
384- livepage.literal object instead of passing normal strings to handler or
385- the LivePage client APIs.
386-
387- * Added nevow.livepage module, LivePage, and ILivePage. The name liveevil
388- is deprecated.
389-
390-2004-12-23 Phil Frost <indigo@bitglue.com>
391-
392- * Added support for formless to return unicode objects. annotate.String
393- and subclasses (Text, Password, etc.) take a 'unicode' parameter to
394- enable unicode, like so:
395-
396- | annotate.String(unicode=True)
397-
398- The coerced value will then be a unicode object.
399-
400-2004-12-16 Matt Goodall <matt@pollenation.net>
401-
402- * Added ObjectContainer - a data directive accessor for retrieving an
403- attribute of an object. If the current data in the context (the IData) is an
404- object you can register ObjectContainer as the IContainer adapter for the
405- object's class and Nevow will automatically look inside the object to fetch
406- the attribute.
407-
408- Note: ObjectContainer is *not* registered as the adapter for all object
409- types. You must explicitly register the adapter for application classes as
410- needed.
411-
412-2004-12-08 Matt Goodall <matt@pollenation.net>
413-
414- * Applied the foom/mesozoic patch to make Page.remember work correctly and
415- without the hack. You can now use the method reliably to remember objects at
416- Page construction time or any other time before the PageContext is created.
417- The remembered objects can be found from the context in the usual way.
418-
419- class MyPage(rend.Page):
420-
421- def __init__(self, original):
422- # Make original available as ISomething(ctx) for later.
423- self.remember(original, ISomething)
424- rend.Page.__init__(self, original)
425-
426- * Added a similar remember method for NevowSite (and made a SiteContext
427- object the ultimate parent). You can know remember objects on the site and
428- have them available anywhere there's a context. A typical use case is making
429- some object store available to the site. This was often achieved using a
430- wrapper resource but now it's as easy as:
431-
432- store = makeStore()
433- site = NevowSite(rootResource)
434- site.remember(store, IStore)
435-
436-2004-12-08 Matt Goodall <matt@pollenation.net>
437-
438- * Renamed URL.fromRequest to URL.fromContext. URL.fromRequest was a little
439- confusing - the URL it returned only included the segments that had been
440- consumed so far by the locateChild process and not the whole URL as the name
441- might suggest. Eventually, fromRequest will change to return a full URL but,
442- for now, its use is deprecated.
443-
444- * Renamed URL.parent to URL.parentdir. URL.parent() was logically equivalent
445- to '..' and so removed more segments than expected. URL.parent's use is now
446- deprecated and in a future release will be changed to remove exactly one
447- segment.
448-
449- * Improve URL.click to normalise any segments of '.' or '..'. Browsers
450- normalise the URL so, according to the docstring, click should too.
451-
452-2004-12-04 Donovan Preston <dp@divmod.org>
453-
454- * Added macros! This is the same patch as the one I attached to my
455- "Macros in Nevow" mail, with the addition of an IMacroFactory,
456- a MacroFactory implementation on rend.Page, and macro directive
457- support. Macros are like render functions that take only the
458- context (no data parameter) and run only once during the lifetime
459- of a template loader. Here is an example of the difference between
460- a macro and a renderer:
461-
462- >>> class Bumper(object):
463- ... num = 0
464- ... def bump(self):
465- ... self.num += 1
466- ... return self.num
467- ...
468- >>> staysTheSame = Bumper()
469- >>> changes = Bumper()
470- >>> from nevow import flat, tags, loaders
471- >>> document = loaders.stan([tags.invisible(macro=lambda ctx: staysTheSame.bump()), tags.invisible(render=lambda ctx, data: changes.bump())])
472- >>> flat.flatten(document)
473- '11'
474- >>> flat.flatten(document)
475- '12'
476- >>> flat.flatten(document)
477- '13'
478-
479-2004-12-01 Donovan Preston <dp@divmod.org>
480-
481- * Added __iter__ to nevow.stan.slot to prevent infinite loops by
482- trying to do "for x in slot('foo'): print x".
483-
484- * Added an IGettable adapter for nevow.stan.slot. It is now possible
485- to specify a slot as the data for a node, so the following example
486- would work:
487-
488- from nevow import rend, tags
489-
490- def fillEm(ctx, data):
491- ctx.fillSlots('value', [1, 2])
492- return ctx.tag
493-
494- tags.html(render=fillEm)[
495- tags.ul(data=tags.slot('value'), render=rend.sequence)[
496- tags.li(pattern='item')[
497- str ]]]
498-
499-2004-09-26 Donovan Preston <dp@divmod.org>
500-
501- * Added nevow.inevow.IQ interface, an interface for querying the
502- stan DOM. Eventually, this interface will contain APIs for doing
503- traditional DOM introspection, such as iterating children,
504- examining tag names, and examining attributes. For now, it contains
505- only the patternGenerator, onePattern, and allPatterns APIs. These
506- APIs have been deprecated from Context.
507-
508- The main benefit of this is the ability to do:
509-
510- IQ(loaders.xmlfile(...)).patternGenerator(...)
511-
512- which would be nice for creating "pattern library" files containing
513- common skin idioms which can then be copied and used throughout
514- the app.
515-
516-2004-09-25 Donovan Preston <dp@divmod.org>
517-
518- * Chatola received a major facelift, bringing it from cool demo
519- up to almost a full fledged web-based chat server. The helper API
520- LiveEvil.call(...) was added, which deprecates
521- LiveEvil.sendScript(callJS(...))
522-
523-2004-09-23 Tommi Virtanen <tv@twistedmatrix.com>
524-
525- * Make guard.SessionWrapper store its URL location in all requests it
526- passes to its children. This allows the children know where to post
527- the __login__ and __logout__ forms, even deep inside the resource
528- tree (fixes issue59).
529-
530- * Guard now works as a non-root resource, with help from the above
531- change. Semantics of __login__ clarified in unit tests; if your guard
532- is at /foo, posting to /foo/__login__ redirects to /foo, and posting
533- to /foo/__login__/ redirects to /foo/. The two unit tests that failed
534- earlier now pass (with that change in their __login__ URLs).
535-
536- * If URL-based sessions are used, login no longer loses session
537- information due to redirect to / (fixes issue56).
538-
539-2004-09-20 Matt Goodall <matt@pollenation.net>
540-
541- * Added URL.secure() method to make switching between http and
542- https easier.
543-
544-2004-09-08 Donovan Preston <dp@divmod.org>
545-
546- * Nevow now includes a very simple proof-of-concept WSGI Application
547- implementation, and can be used with no Twisted dependency. Nevow can
548- also be used to write CGIs, either using a simple CGI WSGI gateway
549- (which supports URL traversal), or by using Page.renderString (which does not).
550-
551- * Two new context interfaces, ICurrentSegments and IRemainingSegments,
552- replace the need to examine the Request prepath and postpath attributes
553- directly.
554-
555- * ISerializable is deprecated, and has been replaced with a simple
556- Flattener registry. nevow.flat.registerFlattener and
557- nevow.flat.getFlattener have been added to support this.
558-
559-2004-09-06 Donovan Preston <dp@divmod.org>
560-
561- * BACKWARDS INCOMPATIBLE CHANGE. Page.configurable_ *always* returns
562- self, and a new Page.configurable_original *always* returns
563- self.original. If you were relying on Page.configurable_'s
564- introspection behavior and are now getting errors about adapting
565- to IConfigurable, change your renderForms() calls to:
566-
567- renderForms('original')
568-
569- This causes Page.configurable_original to be invoked and
570- introspected for form rendering.
571-
572-2004-08-23 Donovan Preston <dp@divmod.org>
573-
574- * LivePage uses a simpler implementation strategy which requires
575- the browser to make one request per output event. As a result,
576- LivePage now works on Mozilla, Safari, and Internet Explorer Windows.
577-
578-2004-08-05 Donovan Preston <dp@divmod.org>
579-
580- * Implemented support for IFoo(ctx) synonym syntax. It does the
581- same thing as ctx.locate(IFoo)
582-
583- * Removed Resource Generators, a feature of NevowSite that nobody
584- used and wasn't really useful.
585-
586- * Changed all inevow.IResource apis to take a Context object
587- where they used to take the request. Remembering objects in
588- PageContexts is now much easier, and fewer hacks are required to
589- build the context chain. The context chain now looks like:
590-
591- SiteContext->RequestContext->PageContext(s)->WovenContext(s)
592-
593-2004-7-28 Donovan Preston <dp@divmod.org>
594-
595- * Parameterize data_* methods in the same way as render_* methods.
596- Patch by k3mper.
597-
598- For example, <div nevow:data="foo bar,baz" /> will cause
599- data_foo(self, bar, baz) to be called with the strings "bar" and
600- "baz". This data method should return a callable taking ctx, data.
601- The return value of this callable will be remembered as IData at
602- this point in the context stack.
603-
604- * Added list-slicing support to ListContainer. You may now use
605- list slicing syntax in a data directive in addition to a simple
606- index. For example:
607-
608- def data_aList(self, ctx, data):
609- return ["Buckle", "My", "Shoe"]
610-
611- <div nevow:data="aList">
612- <span nevow:data="1:-1" nevow:render="string" />
613- </div>
614-
615- Will render as <div><span>My</span></div>
616-
617-2004-7-20 Matt Goodall <matt@pollenation.net>
618-
619- * Modified sax loader to retain doctypes, comments and xmlns attributes.
620- It's now possible to build XHTML valid pages :).
621-
622- xmlns attributes are always kept but there are options to ignore the doctype
623- and comment (at the request of foom, not sure why yet). Right now, the default
624- is to retain doctypes and comments but you can use the ignoreDocType and
625- ignoreComment args to the xml loaders and flatsax parse functions. This bit
626- may change.
627-
628- * Add a URL -> IResource adapter that performs a HTTP redirect. URLs can then
629- be returned from locateChild().
630-
631-2004-06-07 Donovan Preston <dp@divmod.org>
632-
633- * Added nevow.canvas, an experimental module similar to LivePage
634- which provides a Python server-side API for drawing arbitrary lines,
635- curves, and text in the browser. The implementation is socket-based
636- and asynchronous, so the server can issue drawing commands to the
637- client at any time.
638-
639- The idea is to provide a server-side API to the Python programmer
640- and shield them from implementation details, but the current
641- implementation uses a pre-compiled Flash movie (which never changes;
642- we are not generating Flash bytecodes). An implementation using SVG
643- or Safari's Canvas (nevow.canvas was written before the Safari Canvas
644- announcement) would be possible.
645-
646-2004-05-26 Donovan Preston <dp@divmod.org>
647-
648- * Add URLOverlay.keep, an API which lets you specify which query args
649- will be carried on from the current page render into the new URL.
650-
651-2004-05-24 Matt Goodall <matt@pollenation.net>
652-
653- * Extracted Fragment from Page. Hopefully, it will make it more obvious
654- that embedding an object with data_ and render_ methods in a stan tree is
655- possible without using something as "heavy" as Page which is really meant
656- to be a web resource.
657-
658-2004-05-23 Donovan Preston <dp@divmod.org>
659-
660- * Added some useful APIs to LiveEvil for manipulating the client-side
661- page:
662-
663- - flt(stan): Flatten some stan, quoting apostrophes as
664- as appropriate for embedding in javascript
665-
666- - set(what, to): Set the contents of the client-side node
667- with the id 'what' to the stan 'to'.
668-
669- - append(where, what): Append the stan 'what' to the client-
670- side node with the id 'where'
671-
672- - alert(what): Show an alert to the user with the text "what"
673-
674-2004-05-19 Jonathan Simms <slyphon@divmod.com>
675-
676- * 0.2 released.
677-
678-2004-05-14 Donovan Preston <dp@divmod.org>
679-
680- * nevow.url.URLPath is renamed nevow.url.URL
681-
682- * URL objects are now lazier about casting things to strings; they will
683- keep track of path segments in a list and defer to the nevow rendering
684- machinery to do the conversion; This means you can do things like
685- here.child(deferred) or here.child(function)
686-
687- * URL objects have a better api for manipulating query arguments
688- - add(key, value=None) adds a new query arg at the end; the value may
689- be None if only a query key needs to be added
690- - replace(key, value) removes all occurrences of 'key' and inserts a
691- new (key, value) at the same location as the previous first
692- occurrence of key
693- - clear() clears all args
694-
695-2004-05-06 Donovan Preston <dp@divmod.org>
696-
697- * Merged freeform-patterned branch, a large formless/freeform refactor.
698- It is now possible to influence the rendering of forms by providing
699- "patterns" to renderForms.
700-
701- * Formless is now a top-level package. Freeform has been renamed
702- formless.webform. It should be possible to use formless outside
703- the context of nevow for doing things such as validating network
704- input based on method argument type annotations.
705-
706- * TypedInterface, autocallable, and all the Typed subclasses are now
707- in the formless.annotate module.
708-
709-2004-04-30 Donovan Preston <dp@divmod.org>
710-
711- * Created nevow.blocks, a module containing helpful code for working
712- around display: inline-block bugs in Mozilla.
713-
714-2004-04-27 Donovan Preston <dp@divmod.org>
715-
716- * IRenderer.__call__ was renamed IRenderer.rend to be more explicit.
717-
718-2004-04-21 Donovan Preston <dp@divmod.org>
719-
720- * Implemented nevow.flat.flatten and nevow.flat.precompile, functions
721- useful for using stan outside of the context of Page classes. Useful
722- for generating some XML or even raw text; use it any time you want
723- to convert a tree data structure into a contiguous string!
724-
725- import random
726- import string
727-
728- from nevow import flat
729-
730- def letters(howMany):
731- for i in range(howMany):
732- yield ' ', string.letters[i], '\n'
733-
734- def outline():
735- for i in range(5):
736- yield i, '\n'
737- yield letters(random.choice(range(7)))
738- yield '\n'
739-
740- print flat.flatten(outline())
741-
742-2004-04-20 Donovan Preston <dp@divmod.org>
743-
744- * guard sessions are no longer required to use formless.
745-
746-2004-04-19 Donovan Preston <dp@divmod.org>
747-
748- * Implemented lazy context factories. It is now possible to register
749- an adapter against various *Context classes and an interface. They
750- will be invoked if *Context.locate(interface) is called.
751-
752- Implemented a lazy ISession adapter against RequestContext, making
753- it possible to do ctx.locate(ISession), which is nice.
754-
755-2004-04-16 Donovan Preston <dp@divmod.org>
756-
757- * Added nevow.entities module, a module containing literals for all of
758- the valid XHTML entities. For example:
759-
760- def render_nbsp(self, ctx, data):
761- from nevow import entities
762- return entities.nbsp
763-
764
765=== removed file 'Nevow/LICENSE'
766--- Nevow/LICENSE 2005-10-14 17:36:24 +0000
767+++ Nevow/LICENSE 1970-01-01 00:00:00 +0000
768@@ -1,35 +0,0 @@
769-Copyright (c) 2004
770-Donovan Preston
771-Matt Goodall
772-James Y. Knight
773-Glyph Lefkowitz
774-JP Calderone
775-Allen Short
776-Alex Levy
777-Justin Johnson
778-Christopher Armstrong
779-Jonathan Simms
780-Phil Frost
781-Tommi Virtanen
782-Michal Pasternak
783-Valentino Volonghi
784-
785-
786-Permission is hereby granted, free of charge, to any person obtaining
787-a copy of this software and associated documentation files (the
788-"Software"), to deal in the Software without restriction, including
789-without limitation the rights to use, copy, modify, merge, publish,
790-distribute, sublicense, and/or sell copies of the Software, and to
791-permit persons to whom the Software is furnished to do so, subject to
792-the following conditions:
793-
794-The above copyright notice and this permission notice shall be
795-included in all copies or substantial portions of the Software.
796-
797-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
798-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
799-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
800-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
801-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
802-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
803-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
804
805=== removed file 'Nevow/MANIFEST.in'
806--- Nevow/MANIFEST.in 2010-04-06 11:05:45 +0000
807+++ Nevow/MANIFEST.in 1970-01-01 00:00:00 +0000
808@@ -1,24 +0,0 @@
809-include ChangeLog
810-include LICENSE
811-include zomne.c
812-include formless/freeform-default.css
813-include nevow/Canvas.swf
814-include nevow/athena_private/*.png
815-include debian/*
816-recursive-include twisted *.py
817-recursive-include nevow *.css *.js
818-include bin/nevow-xmlgettext
819-graft doc
820-recursive-include examples *.css *.gif *.html *.jpg *.js *.py *.png *.tac *.mo *.po *.pot *.xml *.sql *.xul
821-include examples/i18n/update-l10n
822-include examples/files/words
823-include examples/pastebin/data
824-include examples/pastebin/static/robots.txt
825-include examples/pastebin/TODO
826-include examples/wsgi/README
827-include extras/xhtml-nevow.rnc
828-include nevow/Canvas.fla
829-include nevow/canvas.as
830-include win32/*
831-prune */.svn
832-prune doc/html/*.html
833
834=== removed file 'Nevow/NEWS.txt'
835--- Nevow/NEWS.txt 2009-11-30 01:08:55 +0000
836+++ Nevow/NEWS.txt 1970-01-01 00:00:00 +0000
837@@ -1,244 +0,0 @@
838-0.10.0 (2009-11-25):
839- - Added a system for CSS dependency declarations similar to the one in
840- Athena for JavaScript.
841- - Fix Athena's transport cleanup on page unload in Internet Explorer.
842- - Fix nit's results coloring in Internet Explorer.
843- - Added an API for declaring JavaScript classes which involves less
844- repetition than the existing Divmod.Class.subclass API.
845- - Added human-readable formatting for the new flattener's error reporting;
846- rendering error stacks will now display lines from Python code as well
847- as stan and XML templates.
848- - Override the setuptools sdist command with the original distutils sdist
849- command to avoid setuptools' version number transformation.
850- - Added support for default values for slots in XML templates.
851- - Fixed a problem with setup.py which led to css files not being
852- installed.
853- - Removed the old Chatola example and replaced it with a link to the new
854- chat example.
855- - Sped up some of the JavaScript dependency calculations.
856-
857-0.9.33 (2008-12-09):
858- - Add error handling to the integration between the old flattener
859- and the new flattener so that if the new flattener fails with an
860- exception or a Failure the error is propagated properly to the old
861- flattener which invoked it.
862- - Changed nit so that it doesn't use private `twistd` APIs and
863- instead just sets up a server and runs the reactor. This makes
864- nit work with all versions of Twisted supported by Nevow.
865- - Changed Nevow's setup.py to use setuptools if setuptools is
866- available. This has the user-facing consequence of installing
867- Nevow as an egg if setuptools is available at installation time
868- and of making Nevow installable using the `easy_installĀ“ tool.
869- - TabbedPane naively set DOM attributes, making it unusable in
870- Internet Explorer 6 and 7. Introduced a reliable method for
871- setting DOM node attributes, with name mangling, to address the
872- issue.
873-
874-0.9.32 (2008-08-12):
875- - A resource wrapper for on-the-fly gzip compression has been added.
876- - A twistd plugin, 'athena-widget', is now available for serving
877- single Athena widgets.
878- - Basic Athena support for Safari added.
879- - Added file name, line number, and column number information to
880- slots and tags parsed from XML files in order to make debugging
881- template/renderer interactions simpler.
882- - A context-free flattener has been added. Fragment and its
883- subclasses are now deprecated in favor of Element.
884- - Javascript classes derived from the tabbedpane class can now
885- override how tab selection is handled.
886-
887-0.9.31 (2008-02-06):
888- - Fixed Guard's request parameter save/restore feature to not
889- clobber request state after login succeeds when a session has
890- already been negotiated.
891- - Added a hook to nevow.guard.SessionWrapper which allows the
892- domain parameter of the session cookie to be specified.
893-
894-0.9.30 (2008-01-16):
895- - Change DeferredSerializer so that it passes failures from the
896- Deferred being serialized on to the Deferred returned by the
897- flattening function. Without this behavior, the Deferred
898- returned by the flattening function is never fired when a
899- Deferred which fails is serialized.
900-
901-0.9.29 (2008-01-02):
902- - Prevent NevowSite.handleSegment from raising IndexError in certain
903- situations.
904- - Deprecated wsgi and zomne modules.
905-
906-0.9.28 (2007-12-10):
907- - Added two APIs to Athena, one for creating the string used as the id
908- attribute of the top node of a widget and one for creating the string
909- used as the id attribute of a node which had an id attribute in the
910- widget's template document.
911-
912-0.9.27 (2007-11-27):
913- - Unicode URLs now supported.
914-
915-0.9.26 (2007-11-02):
916- - url.URL.path now correctly escapes segments in the string it
917- evaluates to.
918- - inevow.IAthenaTransportable added, along with support for
919- serialization of custom types for server-to-client Athena
920- messages.
921- - Global client-side behaviour is now customizable via a client
922- PageWidget class.
923-
924-0.9.25 (2007-10-16):
925- - The Athena message queue implementation has been improved, fixing problems
926- masked by bugs in Firebug/YSlow.
927-
928-0.9.24 (2007-09-05):
929- - ESC key no longer disconnects Athena connections.
930- - Fixed a bug where URLs with quote characters will cause the Athena
931- connection to be lost.
932- - Fixed 'twistd athena-widget' to create a fresh widget instance for each
933- hit.
934-
935-0.9.23 (2007-08-01):
936- - Fixed install script to include all JavaScript files.
937-
938-0.9.22 (2007-07-06):
939- - Mock DOM implementation for easier browser testing added.
940- - JavaScript source files are now read using universal newlines mode.
941- - athena.AutoJSPackage now excludes dotfiles.
942- - url.URL now properly subclassable.
943- - User-agent parsing added to Athena, to detect known-unsupported browsers.
944-
945-0.9.21 (2007-06-06):
946- - Debug logging messages from the reliable message delivery queue
947- disabled.
948-
949-0.9.20 (2007-05-24):
950- - Athena now no longer holds more than one idle transport open to
951- the browser.
952-
953-0.9.19 (2007-04-27):
954- - Changed the styling of the progressbar to work on IE6.
955- - Athena.Widget.detach added, to allow widgets to cleanly be removed
956- from a page.
957- - Athena.Widget.callLater added, a wrapper around setTimeout and
958- clearTimeout.
959- - 'athena-widget' twistd command added, for starting a server which
960- serves a single LiveFragment or LiveElement.
961-
962-0.9.18 (2007-02-23):
963- - Athena 'connection lost' notification now styleable via the
964- 'nevow-connection-lost' CSS class.
965- - The 'runjstests' script has been removed, now that JS tests can be
966- run with trial.
967-
968-0.9.17 (2006-12-08):
969- - More efficient JSON string parsing.
970- - Give FakeRequests a default status code of OK. Accept all of
971- FakeRequest.__init__'s arguments in the __init__ of
972- AccumulatingFakeRequest.
973-
974-0.9.16 (2006-11-17):
975- - Updated nit to work with Twisted trunk.
976- - Athena module import caching has been fixed.
977-
978-0.9.15 (2006-11-08):
979- - Changed _LiveMixin rendering to be idempotent to support the case
980- where a transport hiccup causes a LiveFragment or LiveElement to
981- be sent to the browser multiple times.
982- - Improvements to the tests.
983-
984-0.9.14 (2006-10-31):
985- - Support code for running non-browser javascript tests has been added.
986- - Added a workaround for nodeById on widgets not yet added to the document in
987- IE.
988- - Athena will now invoke the nodeInserted method (if it exists) on a widget
989- that it instantiates statically.
990- - ID rewriting, similar to existing rewriting support for 'id' attributes,
991- has been added in 'for' and 'headers' attributes of 'label' and 'td'/'th'
992- elements, respectively.
993-
994-0.9.13 (2006-10-21):
995- - Adjust non-selected panes in tabbedpane to be further out of the viewport.
996- - Convert to using the Javascript module plugin system for Nevow-provided
997- modules.
998-
999-0.9.12 (2006-10-17):
1000- - Added id rewriting for LiveElement and LiveFragment, such that id
1001- attributes in a widget template are rewritten so that they are unique to
1002- the widget instance. A client-side API, Nevow.Athena.Widget.nodeById(),
1003- is provided to allow location of these nodes.
1004-
1005-0.9.11 (2006-10-10):
1006- - Fixed dynamic widget instantiation in IE.
1007- - Added support for correctly quoting the values of slots which are used as
1008- attributes.
1009-
1010-0.9.10 (2006-10-05):
1011- - Minor update to nevow.testutil.
1012-
1013-0.9.9 (2006-09-26):
1014- - Several nit changes, including the addition of the "check" method to
1015- Failure, and the addition of an "assertFailure" method.
1016- - The ability to pass Python exceptions to Javascript has been added to
1017- Athena.
1018- - Dynamic module import has been added for the cases where it is necessary
1019- to dynamically add a widget to an existing page.
1020-
1021-0.9.8 (2009-09-20):
1022- - A bug in nit that caused it to fail if there were too many tests in a
1023- test case, and swallow failures in some cases, has been fixed.
1024- - Widgets can no longer be added to a page after render time using
1025- Divmod.Runtime.Platform.{set,append}NodeContent. Instead, they must be
1026- added using Nevow.Athena.Widget.addChildWidgetFromWidgetInfo.
1027-
1028-0.9.7 (2009-09-12):
1029- - Automatic Athena event handler registration is fixed for all supported browsers
1030- and is no longer document-sensitive (ie, it works inside tables now).
1031- - Nit has gained a new assertion method, assertIn.
1032-
1033-0.9.6 (2008-08-30):
1034- - Fixed a bug in the IE implementation of the runtime.js node fetching
1035- functions.
1036-
1037-0.9.5 (2006-08-22):
1038- - Instance attributes can now be exposed to Athena with nevow.utils.Expose
1039- and Expose.exposedMethodNames() no longer returns unexposed names.
1040-
1041-0.9.4 (2006-08-14):
1042- - Added test method discovery to nit test cases, so multiple test methods
1043- may be put in a single test case.
1044- - use XPath for certain DOM traversals when available. This yields
1045- significant speedups on Opera.
1046- - Made Divmod.Runtime.Platform.getAttribute deal with IE attribute
1047- name-mangling properly.
1048- - Javascript logging is now done in Firebug 0.4 style rather than 0.3.
1049- - Some cases where Deferred-returning render methods raised
1050- exceptions or buried failures were fixed.
1051- - Removed MochiKit. The pieces Nevow depends on have been moved to
1052- Divmod.Base in nevow/base.js.
1053- - Various doc fixes.
1054-
1055-0.9.3 (2006-07-17):
1056- - Page rendering now supports preprocessors.
1057-
1058-0.9.2 (2006-07-08):
1059- - Fixes to the typeahead demo.
1060- - Elements are now automatically serialized by json, just like Fragments.
1061-
1062-0.9.1 (2006-07-05):
1063- - Made nevow.athena.expose the mandatory means of publishing a method to
1064- the browser. The allowedMethods dictionary will no longer be respected.
1065- - Added nevow.page.Element and nevow.athena.LiveElement: these are
1066- preferred over nevow.rend.Fragment and nevow.athena.LiveFragment for all
1067- new development.
1068-
1069-0.9.0 (2006-06-12):
1070- - Fixed a bug where nested fragment sending rarely worked.
1071- - Sending large strings in Athena arguments and results is now faster due to
1072- less unnecessary unicode character quoting.
1073- - Module objects are now automatically created for all Athena imports.
1074- - Better error reporting for fragments which are rendered without a parent.
1075- - Disconnect notifiers in Athena pages will no longer clobber each other.
1076- - Many optimizations to javascript initialization.
1077- - Javascript packages are now defined with less boilerplate: a filesystem
1078- convention similar to Python's for module naming, plus one declaration in a
1079- Nevow plugin which indicates the directory, rather than a declaration for
1080- each module.
1081- - Updated README to refer to Athena rather than LivePage
1082
1083=== removed file 'Nevow/README'
1084--- Nevow/README 2006-06-14 11:54:41 +0000
1085+++ Nevow/README 1970-01-01 00:00:00 +0000
1086@@ -1,69 +0,0 @@
1087-
1088-Divmod Nevow
1089-============
1090-
1091-Divmod Nevow is a web application construction kit written in Python. It is
1092-designed to allow the programmer to express as much of the view logic as
1093-desired in Python, and includes a pure Python XML expression syntax named stan
1094-to facilitate this. However it also provides rich support for designer-edited
1095-templates, using a very small XML attribute language to provide bi-directional
1096-template manipulation capability.
1097-
1098-Nevow also includes Divmod Athena, a "two way web" or "`COMET`_"
1099-implementation, providing a two-way bridge between Python code on the server
1100-and JavaScript code on the client. Modular portions of a page, known as
1101-"athena fragments" in the server python and "athena widgets" in the client
1102-javascript, can be individually developed and placed on any Nevow-rendered page
1103-with a small template renderer. Athena abstracts the intricacies of HTTP
1104-communication, session security, and browser-specific bugs behind a simple
1105-remote-method-call interface, where individual widgets or fragments can call
1106-remote methods on their client or server peer with one method: "callRemote".
1107-
1108-Installation
1109-------------
1110-
1111-Before installing Nevow, you should install `Twisted`_, unless you are going to
1112-write very simple CGI applications. Nevow integrates fully with the twisted.web
1113-server providing easy deployment.
1114-
1115-Nevow uses the standard distutils method of installation::
1116-
1117- python setup.py install
1118-
1119-If you do not have Twisted installed, you can run a subset of the tests using
1120-the test.py script. If you have twisted installed, the test.py script will
1121-issue the following trial command::
1122-
1123- trial -v nevow.test formless.test
1124-
1125-.. _`Twisted`: http://twistedmatrix.com/
1126-
1127-Documentation
1128--------------
1129-
1130-More detailed introductory documentation is available in the doc/ directory,
1131-along with the beginnings of a reference manual. A large number of examples are
1132-available in the examples/ directory. These examples require Twisted to run. A
1133-tac file (twisted application configuration) can be started by invoking twistd,
1134-the twisted daemon::
1135-
1136- twistd -noy foo.tac
1137-
1138-More Information
1139-----------------
1140-
1141-Nevow is an active project, and many new bugfixes and features are committed to
1142-the Nevow SVN repository. Information about Nevow commits is available by
1143-subscribing to the `Nevow commits`_ mailing list. The Nevow SVN repository can
1144-be checked out using::
1145-
1146- svn co http://divmod.org/svn/Divmod/trunk/Nevow Nevow
1147-
1148-Discussion of Nevow occurs on the `twisted.web mailing list`_. The Nevow
1149-developers are also often available for real-time help on the `#twisted.web
1150-channel`_ on irc.freenode.net.
1151-
1152-.. _`Nevow commits`: http://divmod.org/users/mailman.twistd/listinfo/nevow-commits
1153-.. _`twisted.web mailing list`: http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-web
1154-.. _`#twisted.web channel`: irc://irc.freenode.net/#twisted.web
1155-.. _`COMET`: http://alex.dojotoolkit.org/?p=545
1156
1157=== removed directory 'Nevow/benchmarks'
1158=== removed file 'Nevow/benchmarks/fragmentvselement.py'
1159--- Nevow/benchmarks/fragmentvselement.py 2008-05-22 18:46:50 +0000
1160+++ Nevow/benchmarks/fragmentvselement.py 1970-01-01 00:00:00 +0000
1161@@ -1,147 +0,0 @@
1162-
1163-from twisted.internet import reactor
1164-from twisted.internet.defer import succeed
1165-
1166-from nevow.appserver import NevowSite
1167-
1168-from nevow.rend import Page, Fragment
1169-from nevow.page import Element, renderer
1170-from nevow.loaders import stan
1171-from nevow.tags import directive, div, span
1172-
1173-
1174-class Static:
1175- docFactory = stan("Hello, world. " * 100)
1176-
1177-
1178-
1179-class StaticFragment(Static, Fragment):
1180- pass
1181-
1182-
1183-
1184-class StaticElement(Static, Element):
1185- pass
1186-
1187-
1188-
1189-class Tiny:
1190- docFactory = stan(div(render=directive("foo")))
1191-
1192-
1193-
1194-class TinyFragment(Tiny, Fragment):
1195- def render_foo(self, ctx, data):
1196- return ctx.tag[span["result"]]
1197-
1198-
1199-
1200-class TinyElement(Tiny, Element):
1201- def foo(self, request, tag):
1202- return tag[span["result"]]
1203- renderer(foo)
1204-
1205-
1206-
1207-class Huge:
1208- docFactory = stan(div[[
1209- div(render=directive("foo"))
1210- for x in range(100)]])
1211-
1212-
1213-
1214-class HugeFragment(Huge, Fragment):
1215- def render_foo(self, ctx, data):
1216- return ctx.tag[span["Hello, ", "world", "!"]]
1217-
1218-
1219-
1220-class HugeElement(Huge, Element):
1221- def foo(self, request, tag):
1222- return tag[span["Hello, ", "world", "!"]]
1223- renderer(foo)
1224-
1225-
1226-
1227-class Nested:
1228- docFactory = stan(div(render=directive("foo")))
1229-
1230- def __init__(self, count=6):
1231- self.count = count
1232-
1233-
1234-
1235-class NestedFragment(Nested, Fragment):
1236- def render_foo(self, ctx, data):
1237- if self.count:
1238- return span[NestedFragment(self.count - 1)]
1239- return ctx.tag["Hello"]
1240-
1241-
1242-
1243-class NestedElement(Nested, Element):
1244- def foo(self, request, tag):
1245- if self.count:
1246- return span[NestedFragment(self.count - 1)]
1247- return tag["Hello"]
1248- renderer(foo)
1249-
1250-
1251-
1252-class Deferred:
1253- docFactory = stan(div(render=directive('foo')))
1254-
1255-
1256-
1257-class DeferredFragment(Deferred, Fragment):
1258- def render_foo(self, ctx, data):
1259- return ctx.tag[succeed("foo")]
1260-
1261-
1262-
1263-class DeferredElement(Deferred, Element):
1264- def foo(self, request, tag):
1265- return tag[succeed("foo")]
1266- renderer(foo)
1267-
1268-
1269-
1270-class Compare(Page):
1271- def __init__(self, fragment, element):
1272- self.fragment = fragment
1273- self.element = element
1274-
1275- def child_fragment(self, ctx):
1276- return Page(docFactory=stan(self.fragment))
1277-
1278-
1279- def child_element(self, ctx):
1280- return Page(docFactory=stan(self.element))
1281-
1282-
1283-
1284-class Root(Page):
1285- def child_static(self, ctx):
1286- return Compare(StaticFragment(), StaticElement())
1287-
1288-
1289- def child_tiny(self, ctx):
1290- return Compare(TinyFragment(), TinyElement())
1291-
1292-
1293- def child_huge(self, ctx):
1294- return Compare(HugeFragment(), HugeElement())
1295-
1296-
1297- def child_nested(self, ctx):
1298- return Compare(NestedFragment(), NestedElement())
1299-
1300-
1301- def child_deferred(self, ctx):
1302- return Compare(DeferredFragment(), DeferredElement())
1303-
1304-
1305-
1306-if __name__ == '__main__':
1307- reactor.listenTCP(8080, NevowSite(Root()))
1308- reactor.run()
1309
1310=== removed file 'Nevow/benchmarks/json_string_tokenizer.py'
1311--- Nevow/benchmarks/json_string_tokenizer.py 2006-11-24 23:15:26 +0000
1312+++ Nevow/benchmarks/json_string_tokenizer.py 1970-01-01 00:00:00 +0000
1313@@ -1,48 +0,0 @@
1314-
1315-from time import time
1316-
1317-from twisted.python.usage import Options
1318-
1319-from nevow.json import serialize, parse
1320-
1321-if __name__ == '__main__':
1322- from json_string_tokenizer import main
1323- raise SystemExit(main())
1324-
1325-
1326-
1327-class StringTokenizer(Options):
1328- optParameters = [
1329- ('iterations', 'i', '1000', 'Number of iterations for which to run the benchmark.'),
1330- ('scale', 's', '100', 'Factor determining the overall input size.')]
1331-
1332-
1333- def postOptions(self):
1334- self['iterations'] = int(self['iterations'])
1335- self['scale'] = int(self['scale'])
1336-
1337-
1338-BASE = u'Hello, world. "Quotes".'
1339-def benchmark(iterations, scale):
1340- """
1341- Deserialize a string C{iterations} times. Make the string longer based
1342- on C{scale}.
1343-
1344- Prints the mean time per parse call.
1345- """
1346- s = serialize(BASE * scale)
1347- before = time()
1348- for i in xrange(iterations):
1349- parse(s)
1350- after = time()
1351- print (after - before) / iterations, 'per call'
1352-
1353-
1354-
1355-def main(args=None):
1356- """
1357- Benchmark nevow.json string parsing, maybe with some parameters.
1358- """
1359- options = StringTokenizer()
1360- options.parseOptions(args)
1361- benchmark(options['iterations'], options['scale'])
1362
1363=== removed directory 'Nevow/bin'
1364=== removed file 'Nevow/bin/nevow-xmlgettext'
1365--- Nevow/bin/nevow-xmlgettext 2005-10-14 17:36:24 +0000
1366+++ Nevow/bin/nevow-xmlgettext 1970-01-01 00:00:00 +0000
1367@@ -1,3 +0,0 @@
1368-#!/usr/bin/env python
1369-from nevow.scripts.xmlgettext import run
1370-run()
1371
1372=== removed file 'Nevow/bin/nit'
1373--- Nevow/bin/nit 2006-11-17 00:50:34 +0000
1374+++ Nevow/bin/nit 1970-01-01 00:00:00 +0000
1375@@ -1,3 +0,0 @@
1376-#!/usr/bin/python
1377-from nevow.scripts.nit import run
1378-run()
1379
1380=== removed directory 'Nevow/debian'
1381=== removed file 'Nevow/debian/changelog'
1382--- Nevow/debian/changelog 2005-11-06 18:46:50 +0000
1383+++ Nevow/debian/changelog 1970-01-01 00:00:00 +0000
1384@@ -1,56 +0,0 @@
1385-nevow (0.6.0-1.snapshot) unstable; urgency=low
1386-
1387- * SVN snapshot.
1388-
1389- -- Tommi Virtanen <tv@debian.org> Sun, 6 Nov 2005 20:45:27 +0200
1390-
1391-nevow (0.6.0-1) unstable; urgency=low
1392-
1393- * New upstream version. (Closes: #336027)
1394- * Acknowledge NMU (Closes: #319230), but please be more careful in the
1395- future; no NMU patch was sent to BTS
1396- * Remove setupcommon.pyc when cleaning, or dpkg-source will see a binary
1397- file content change.
1398- * Run unit tests when building.
1399- * Clean build tree, distutils fails to remove all of it.
1400- * Change priority to extra, as twisted is extra and nevow depends on it.
1401-
1402- -- Tommi Virtanen <tv@debian.org> Sun, 6 Nov 2005 20:26:39 +0200
1403-
1404-nevow (0.4.1-1.1) unstable; urgency=low
1405-
1406- * NMU
1407- * Add missing build depends in python2.4-dev (Closes: #319230)
1408- * lintian error: fix package description indent for list items.
1409-
1410- -- Bastian Kleineidam <calvin@debian.org> Sat, 13 Aug 2005 18:48:20 +0200
1411-
1412-nevow (0.4.1-1) unstable; urgency=low
1413-
1414- * New upstream version.
1415- * Python 2.4 support.
1416- * Not using upstream tarball as it is too broken compared to
1417- SVN tag; specifically it is missing nevow/Canvas.fla, which
1418- is considered source code.
1419-
1420- -- Tommi Virtanen <tv@debian.org> Mon, 27 Jun 2005 15:35:57 +0200
1421-
1422-nevow (0.3.0-1) unstable; urgency=low
1423-
1424- * New upstream version.
1425-
1426- -- Tommi Virtanen <tv@debian.org> Thu, 30 Sep 2004 12:12:44 +0300
1427-
1428-nevow (0.2.0-2) unstable; urgency=low
1429-
1430- * Build-depend on both python2.3-dev and python-dev, it seems that is
1431- what cdbs wants. (Closes: #257911)
1432-
1433- -- Tommi Virtanen <tv@debian.org> Tue, 13 Jul 2004 16:39:17 +0300
1434-
1435-nevow (0.2.0-1) unstable; urgency=low
1436-
1437- * Initial Release.
1438-
1439- -- Tommi Virtanen <tv@debian.org> Tue, 29 Jun 2004 10:26:36 +0300
1440-
1441
1442=== removed file 'Nevow/debian/compat'
1443--- Nevow/debian/compat 2005-10-14 17:36:24 +0000
1444+++ Nevow/debian/compat 1970-01-01 00:00:00 +0000
1445@@ -1,1 +0,0 @@
1446-4
1447
1448=== removed file 'Nevow/debian/control'
1449--- Nevow/debian/control 2005-11-06 18:46:50 +0000
1450+++ Nevow/debian/control 1970-01-01 00:00:00 +0000
1451@@ -1,64 +0,0 @@
1452-Source: nevow
1453-Section: devel
1454-Priority: extra
1455-Maintainer: Tommi Virtanen <tv@debian.org>
1456-Standards-Version: 3.6.2
1457-Build-Depends-Indep: python-dev, python2.3-dev, python2.4-dev, cdbs, debhelper (>= 4.1.68)
1458-
1459-Package: python-nevow
1460-Architecture: all
1461-Depends: python (>= 2.3), python (<< 2.4), python2.3-nevow
1462-Description: Web application templating system for Python and Twisted
1463- This is a dummy package that only depends on python2.3-nevow.
1464-
1465-Package: python2.3-nevow
1466-Architecture: all
1467-Depends: python2.3, python2.3-twisted
1468-Description: Web application templating system for Python and Twisted
1469- Nevow's main focus is on separating the HTML template from both the
1470- business logic and the display logic, while allowing the programmer
1471- to write pure Python code as much as possible. It separates your code
1472- into 'data' and 'render' functions, a simplified implementation of
1473- traditional MVC. It has various parts which can be used individually
1474- or as a whole, integrated web solution:
1475- .
1476- - XHTML templates: contain no programming logic, only nodes tagged
1477- with nevow attributes
1478- - data/render methods: simplified MVC
1479- - stan: An s-expression-like syntax for expressing xml in pure python
1480- - formless: For describing the types of objects which may be passed
1481- to methods of your classes, validating and coercing string input from
1482- either web or command-line sources, and calling your methods
1483- automatically once validation passes
1484- - freeform: For rendering web forms based on formless type
1485- descriptions, accepting form posts and passing them to formless
1486- validators, and rendering error forms in the event validation fails
1487- - livepage: Cross-browser JavaScript glue for sending client side
1488- events to the server and server side events to the client after the
1489- page has loaded, without causing the entire page to refresh
1490-
1491-Package: python2.4-nevow
1492-Architecture: all
1493-Depends: python2.4, python2.4-twisted
1494-Description: Web application templating system for Python and Twisted
1495- Nevow's main focus is on separating the HTML template from both the
1496- business logic and the display logic, while allowing the programmer
1497- to write pure Python code as much as possible. It separates your code
1498- into 'data' and 'render' functions, a simplified implementation of
1499- traditional MVC. It has various parts which can be used individually
1500- or as a whole, integrated web solution:
1501- .
1502- - XHTML templates: contain no programming logic, only nodes tagged
1503- with nevow attributes
1504- - data/render methods: simplified MVC
1505- - stan: An s-expression-like syntax for expressing xml in pure python
1506- - formless: For describing the types of objects which may be passed
1507- to methods of your classes, validating and coercing string input from
1508- either web or command-line sources, and calling your methods
1509- automatically once validation passes
1510- - freeform: For rendering web forms based on formless type
1511- descriptions, accepting form posts and passing them to formless
1512- validators, and rendering error forms in the event validation fails
1513- - livepage: Cross-browser JavaScript glue for sending client side
1514- events to the server and server side events to the client after the
1515- page has loaded, without causing the entire page to refresh
1516
1517=== removed file 'Nevow/debian/copyright'
1518--- Nevow/debian/copyright 2005-10-14 17:36:24 +0000
1519+++ Nevow/debian/copyright 1970-01-01 00:00:00 +0000
1520@@ -1,10 +0,0 @@
1521-This package was debianized by Tommi Virtanen tv@debian.org on
1522-Sun, 28 Mar 2004 16:44:10 +0300.
1523-
1524-It was originally downloaded from http://www.divmod.org/Home/Projects/Nevow/
1525-
1526-Upstream Author: Donovan Preston et al <dp@divmod.org>
1527-
1528-Copyright:
1529-
1530-# See the file LICENSE at the top of the source tree.
1531
1532=== removed file 'Nevow/debian/python2.3-nevow.manpages'
1533--- Nevow/debian/python2.3-nevow.manpages 2005-10-14 17:36:24 +0000
1534+++ Nevow/debian/python2.3-nevow.manpages 1970-01-01 00:00:00 +0000
1535@@ -1,1 +0,0 @@
1536-doc/man/nevow-xmlgettext.1
1537
1538=== removed file 'Nevow/debian/python2.4-nevow.manpages'
1539--- Nevow/debian/python2.4-nevow.manpages 2005-10-14 17:36:24 +0000
1540+++ Nevow/debian/python2.4-nevow.manpages 1970-01-01 00:00:00 +0000
1541@@ -1,1 +0,0 @@
1542-doc/man/nevow-xmlgettext.1
1543
1544=== removed file 'Nevow/debian/rules'
1545--- Nevow/debian/rules 2005-11-06 18:46:50 +0000
1546+++ Nevow/debian/rules 1970-01-01 00:00:00 +0000
1547@@ -1,71 +0,0 @@
1548-#!/usr/bin/make -f
1549-# -*- mode: makefile; coding: utf-8 -*-
1550-# Copyright Ā© 2002,2003 Colin Walters <walters@debian.org>
1551-
1552-include /usr/share/cdbs/1/rules/debhelper.mk
1553-include /usr/share/cdbs/1/class/python-distutils.mk
1554-
1555-DEB_INSTALL_DOCS_python2.3-nevow := doc/*
1556-DEB_INSTALL_EXAMPLES_python2.3-nevow := examples/*
1557-DEB_INSTALL_DOCS_python2.4-nevow := doc/*
1558-DEB_INSTALL_EXAMPLES_python2.4-nevow := examples/*
1559-DEB_DH_ALWAYS_EXCLUDE := .svn
1560-
1561-docdir = debian/$(1)/usr/share/doc/$(1)
1562-binary-post-install/%::
1563- grep -v '^# See the file LICENSE' \
1564- '$(call docdir,$*)/copyright' \
1565- >'$(call docdir,$*)/copyright.tmp'
1566- cat LICENSE \
1567- >>'$(call docdir,$*)/copyright.tmp'
1568- mv \
1569- '$(call docdir,$*)/copyright.tmp' \
1570- '$(call docdir,$*)/copyright'
1571-
1572-# see http://bugs.debian.org/295906
1573-cdbs_python_ver = $(filter-out -%,$(subst -, -,$(patsubst python%,%,$(cdbs_curpkg))))
1574-
1575-$(patsubst %,binary-post-install/%,$(DEB_PYTHON_REAL_LIB_PACKAGES)):: binary-post-install/%:
1576- set -e; for file in debian/$(cdbs_curpkg)/usr/bin/*; do \
1577- sed '1s|.*|#!/usr/bin/python$(cdbs_python_ver)|' $$file >\
1578- "$${file}$(cdbs_python_ver)";\
1579- rm -- "$$file";\
1580- chmod 755 "$${file}$(cdbs_python_ver)";\
1581- mv "debian/$(cdbs_curpkg)/usr/share/man/man1/$$(basename "$$file").1" \
1582- "debian/$(cdbs_curpkg)/usr/share/man/man1/$$(basename "$$file")$(cdbs_python_ver).1";\
1583- done
1584-
1585-binary-post-install/python2.3-nevow::
1586- set -e; for file in debian/$(cdbs_curpkg)/usr/bin/*;\
1587- do target="$$(echo "$$file" | sed 's/$(cdbs_python_ver)$$//')";\
1588- ln -s "$$(basename "$$file")" "$$target";\
1589- manname="$$(basename "$$target").1.gz";\
1590- ln -s "$$(basename "$$file").1.gz" \
1591- "debian/$(cdbs_curpkg)/usr/share/man/man1/$$manname";\
1592- done
1593-
1594-clean::
1595- rm -f setupcommon.pyc
1596-
1597-
1598-ifeq (,$(findstring nocheck,$(DEB_BUILD_OPTIONS)))
1599-TRIAL=trial$(cdbs_python_ver)
1600-TOPMODULES:=nevow formless
1601-$(patsubst %,binary-post-install/%,$(DEB_PYTHON_REAL_LIB_PACKAGES)):: binary-post-install/%:
1602- PYTHONPATH='debian/$(cdbs_curpkg)/usr/lib/python$(cdbs_python_ver)/site-packages/' \
1603- '$(TRIAL)' --bwverbose -R $(TOPMODULES)
1604-
1605- # Importing the modules generates .pyc files, and dh_python (which
1606- # normally cleans them) has already been run. Remove them manually.
1607- find 'debian/$(cdbs_curpkg)' -name '*.py[co]' -print0 \
1608- | xargs -0 rm -f --
1609-endif
1610-
1611-clean::
1612- rm -rf _trial_temp
1613-
1614-
1615-# distutils is sloppy and only cleans with the default python version,
1616-# leaving all the other stuff still in build
1617-clean::
1618- rm -rf build
1619
1620=== removed directory 'Nevow/doc'
1621=== removed file 'Nevow/doc/README'
1622--- Nevow/doc/README 2010-04-06 11:05:45 +0000
1623+++ Nevow/doc/README 1970-01-01 00:00:00 +0000
1624@@ -1,5 +0,0 @@
1625-This is Nevow's documentation. The preferred format is Lore XHTML. You can
1626-generate the pretty version of the documentation with by running the
1627-following command in the howto directory:
1628-
1629- lore
1630
1631=== removed directory 'Nevow/doc/howto'
1632=== removed directory 'Nevow/doc/howto/chattutorial'
1633=== removed file 'Nevow/doc/howto/chattutorial/concepts.xhtml'
1634--- Nevow/doc/howto/chattutorial/concepts.xhtml 2008-09-03 20:03:47 +0000
1635+++ Nevow/doc/howto/chattutorial/concepts.xhtml 1970-01-01 00:00:00 +0000
1636@@ -1,136 +0,0 @@
1637-<?xml version="1.0"?>
1638-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
1639- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1640-<html xmlns="http://www.w3.org/1999/xhtml">
1641- <head>
1642- <title>Concepts</title>
1643- </head>
1644-<body>
1645-
1646-<h1>Concepts</h1>
1647-
1648-<h2>Servers and Clients</h2>
1649-
1650-<p>COMET applications can seem an almost impenetrable mess when one is first
1651-learning about them, much like when writing event-based desktop
1652-applications. However, there are some basic concepts that we can emphasize now
1653-to circumvent or alleviate most of the confusion.</p>
1654-
1655-<p>In principle, the problem is very simple:</p>
1656-<ul>
1657-<li>We want out users to interact with a <q>web page</q> with out having to refresh
1658-the page, and we want new data and/or views to be rendered in response to our
1659-users' actions;</li>
1660-<li>We want the ability to push updates to user pages from the server to the
1661-browser, when the server has new data or views that are ready.</li>
1662-</ul>
1663-
1664-<p>As usual, the implementation of the solution is much more complicated than
1665-the statement of the problem, but hopefully the way that we have designed
1666-Athena will hide those implementation details while providing powerful tools to
1667-build the applications you envision. So, let's take a look at what you need to
1668-know about servers and clients when building Athena web applications.</p>
1669-
1670-<p>It is crucial that one understands that when we write Athena applications,
1671-we are doing a few different things:</p>
1672-<ul>
1673-<li>Writing server code in Python that performs server actions</li>
1674-<li>Writing server code in Python that makes remote calls to the browser</li>
1675-<li>Writing browser code in JavaScript that performs browser actions</li>
1676-<li>Writing browser code in JavaScript that makes remote calls to the server</li>
1677-</ul>
1678-
1679-<p>Since server-on-server and client-on-client are rather common place and
1680-generally well understood, we will ignore those for now. As the other two
1681-are the focus of AJAX/COMET and thus also the primary domain of Athena, that is
1682-what we will discuss below.</p>
1683-
1684-<p>Browser-to-server calls are made by Athena via the now-famous
1685- XMLHttpRequest. Server-to-browser calls are opened by the browser ahead of
1686-time, and when the server is ready, the data is sent to the browser via that
1687-connection.</p>
1688-
1689-<h2>JavaScript: Making Calls to the Server</h2>
1690-
1691-<p>When creating the JavaScript portion of our applications, we subclass
1692-an Athena JavaScript widget, which has a method named
1693-<code>callRemote()</code>. By utilizing this method, we can send messages from
1694-our JavaScript client to the server (as long as the method we call exists in
1695-the server code).</p>
1696-
1697-<p>For example, in the chat application we will be building in this series
1698-of tutorials, we will have a JavaScript class called <code>ChatterBox</code> with a
1699-<code>say()</code> method, like the following:</p>
1700-<pre>
1701-function say(self, msg) {
1702- self.callRemote("say", msg);
1703- // Now show the text to the user somehow...
1704-}
1705-</pre>
1706-<p>This will make a remote call to the Python server code, executing the
1707-<code>say()</code> method and passing the <code>msg</code> variable as a
1708-parameter.</p>
1709-
1710-<p>In Athena, the relationship between the browser code and the server code is
1711-established by declaring the JavaScript module in the Python server code, in
1712-the following manner:</p>
1713-<pre class="python">
1714-class ChatterBox(LiveElement):
1715- jsClass = u'ChatThing.ChatterBox'
1716-</pre>
1717-<p>Additionally, in order for the JS to be able to make a call to remote Python
1718-code, the Python method has to be exposed. This is a security feature,
1719-implemented to ensure the JavaScript code can only call Python methods that
1720-have been specifically marked as safe. Appropriately enough, this is done in
1721-your Python class with the <code>expose</code> decorator:</p>
1722-
1723-<pre class="python">
1724-def say(self, text):
1725- for chatter in chatRoom:
1726- chatter.youHeardSomething(text)
1727-say = expose(say)
1728-</pre>
1729-
1730-<h2>Python: Making Calls to the Browser</h2>
1731-
1732-<p>Now what about the COMET side of the equation? If we want our server to
1733-update data in the browser, we need to be able to call JavaScript code from our
1734-Python server. We use a similar Python method as the JavaScript one (when
1735-making calls from the browser to the server), acquired when our Python class
1736-inherited from <code>nevow.athena.LiveElement</code>:</p>
1737-
1738-<pre class="python">
1739-def hear(self, sayer, text):
1740- self.callRemote("hear", sayer, text)
1741-</pre>
1742-
1743-<p>In order for this call to work, we need to have the <code>hear()</code>
1744-method defined in our <code>ChatterBox</code> JavaScript class, and that will
1745-look like this:</p>
1746-<pre>
1747-function hear(self, avatarName, text) {
1748- // Here, you'd show the user some text.
1749-}
1750-</pre>
1751-
1752-<p>Unlike on our Python classes, no special annotations need to be made on the
1753-JavaScript side: all JavaScript methods on browser-side Widget objects are
1754-allowed to be called by the server. If you've sent code to the browser, you've
1755-already forfeited the ability to control when it's called. There wouldn't be a
1756-point to limiting the server's rights to run its code when the user can freely
1757-run it herself.</p>
1758-
1759-<h2>Summary</h2>
1760-
1761-<p>With the samples above, you should have a growing sense of how Python and
1762-JavaScript interact as servers and clients in the world of Athena. In
1763-particular, you should be getting a sense of how JavaScript and Python will be
1764-interacting in your Athena applications.</p>
1765-
1766-<p>This has just been a taste of Athena with a few peeks into the code we
1767-will be writing. We will cover these topics in greater detail in the following
1768-pages, within the context of creating a functional Athena application,
1769-complete with step-by-step instructions and rationale.</p>
1770-
1771-</body>
1772-</html>
1773
1774=== removed file 'Nevow/doc/howto/chattutorial/env.xhtml'
1775--- Nevow/doc/howto/chattutorial/env.xhtml 2008-09-03 20:03:47 +0000
1776+++ Nevow/doc/howto/chattutorial/env.xhtml 1970-01-01 00:00:00 +0000
1777@@ -1,122 +0,0 @@
1778-<?xml version="1.0"?>
1779-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
1780-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1781-<html xmlns="http://www.w3.org/1999/xhtml">
1782- <head>
1783- <title>Setting up an Environment</title>
1784- </head>
1785-<body>
1786-
1787-<h1>Setting up an Environment</h1>
1788-
1789-<h2>Install</h2>
1790-
1791-To run this tutorial, you need to have nevow available to python and
1792-you'll need the files in the doc/howto tree. You don't even have to
1793-install nevow; the examples will run within the source tree.
1794-
1795-
1796-<h3>Combinator: The Divmod Way</h3>
1797-
1798-<p>Using SVN
1799-with <a href="http://divmod.org/trac/wiki/DivmodCombinator">Combinator</a>
1800-is the best way to try out the example code in-place (and hop between
1801-other SVN branches in the future). This is how we develop and test our
1802-applications at Divmod. If you have a system installation of Twisted
1803-that you don't want to update or interfere with, you can use this
1804-method without installing anything.
1805-</p>
1806-
1807-<ol>
1808-
1809-<li>Create a projects directory or change to some other test directory
1810-of your choice:
1811-<pre class="shell">
1812-$ mkdir ~/Projects
1813-$ cd ~/Projects
1814-</pre>
1815-</li>
1816-
1817-
1818-<li>If you don't have the
1819-<a href="http://twistedmatrix.com/trac/">twisted library</a>, check it out now:
1820-<pre class="shell">
1821-$ svn co svn://svn.twistedmatrix.com/svn/Twisted/trunk Twisted/trunk
1822-</pre>
1823-</li>
1824-
1825-<li>Then get Combinator and Nevow (and the rest of Divmod). See the
1826-<a href="http://divmod.org/trac/wiki/CombinatorTutorial">Combinator
1827-Tutorial</a> for more about these special checkout paths.
1828-<pre class="shell">
1829-$ svn co http://divmod.org/svn/Divmod/trunk Divmod/trunk
1830-</pre>
1831-</li>
1832-
1833-<li>Set up the Combinator environment in this shell. You'll need this
1834-step in any future test shells since it adjusts PATH and PYTHONPATH:
1835-<pre class="shell">
1836-$ eval `python Divmod/trunk/Combinator/environment.py`
1837-(some "link:" lines are normal)
1838-</pre>
1839-</li>
1840-
1841-<li>Register both the Twisted and Divmod (and thus Nevow+Athena) codebases with
1842-Combinator:
1843-<pre class="shell">
1844-$ chbranch Twisted trunk
1845-$ chbranch Divmod trunk
1846-</pre>
1847-</li>
1848-
1849-<li>You can check to see if your environment is ready to go by running the
1850-tutorial tests (from any directory, after executing the previous command):
1851-<pre class="shell">
1852-$ trial nevow.test.test_howtolistings
1853-</pre>
1854-If they all pass, you're ready to begin the tutorial.
1855-</li>
1856-</ol>
1857-
1858-
1859-
1860-<h3>Standard distutils Installation</h3>
1861-
1862-<p>If you don't want to manage branches and environments with
1863-Combinator, you can install our code in the
1864-standard <code>site-packages</code> directory. You'll still need the
1865-source tree so you can use the files in doc/howto.</p>
1866-
1867-<p>For those that would prefer the <q>old way,</q> here's how you do it:</p>
1868-
1869-<ol>
1870-
1871-<li>Create a projects directory:
1872-<pre class="shell">
1873-$ mkdir ~/Projects
1874-$ cd ~/Projects
1875-</pre>
1876-</li>
1877-
1878-<li>Checkout and install the latest Twisted:
1879-<pre class="shell">
1880-$ svn co svn://svn.twistedmatrix.com/svn/Twisted/trunk Twisted
1881-$ cd Twisted
1882-$ sudo python setup.py install
1883-$ cd ../
1884-</pre>
1885-</li>
1886-
1887-<li>Checkout and install Nevow:
1888-<pre class="shell">
1889-$ svn co http://divmod.org/svn/Divmod/trunk/Nevow Nevow
1890-$ cd Nevow
1891-$ sudo python setup.py install
1892-$ cd ../
1893-</pre>
1894-</li>
1895-
1896-</ol>
1897-
1898-</body>
1899-</html>
1900
1901=== removed file 'Nevow/doc/howto/chattutorial/index.xhtml'
1902--- Nevow/doc/howto/chattutorial/index.xhtml 2008-09-03 20:03:47 +0000
1903+++ Nevow/doc/howto/chattutorial/index.xhtml 1970-01-01 00:00:00 +0000
1904@@ -1,56 +0,0 @@
1905-<?xml version="1.0"?>
1906-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
1907-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1908-<html xmlns="http://www.w3.org/1999/xhtml">
1909- <head>
1910- <title>Nevow Athena from Scratch, or The Evolution of a Chat Application</title>
1911- </head>
1912-<body>
1913-
1914- <h1>Nevow Athena from Scratch, or The Evolution of a Chat Application</h1>
1915-
1916-<h2>The <q>Chat Tutorial</q> Series</h2>
1917-
1918-<p>
1919-Athena is the JavaScript engine behind Nevow, providing a great deal of
1920-resources and power to the developer of asynchronous web applications. To
1921-demonstrate this, we are using a web chat application as our primary example
1922-in this tutorial. The tutorial is split into several parts: a few introductory
1923-pages and then independent (but related) tutorials of increasing complexity.
1924-</p>
1925-
1926-<ol>
1927- <li>Basics
1928- <ul>
1929- <li><a href="intro.xhtml">Introduction</a></li>
1930- <li><a href="concepts.xhtml">Concepts of Athena: AJAX, COMET, and Python</a></li>
1931- <li><a href="env.xhtml">Setting Up the Tutorial Environment and Running Tutorial Source Code</a></li>
1932- </ul>
1933- </li>
1934- <li><a href="part00/index.xhtml">Toy <q>Echo</q> Application </a></li>
1935- <li><a href="part01/index.xhtml">Simple Chat and Two-Way Communications</a></li>
1936-</ol>
1937-
1938-<h2>History</h2>
1939-<p>
1940-Nevow's predecessor was Woven (and prior to that, WebMVC). Woven had something
1941-called <code>LivePage</code> that was doing DOM manipulation as far back as
1942-2002. In early 2003, Woven event handlers supported sending JavaScript back to
1943-the user's browser, allowing pages to be updated in response to user-generated
1944-events. The earliest publicly visible revisions of Nevow made use of XHR
1945-(XMLHttpRequest) in early 2004. These facts are notable because Nevow was using
1946-AJAX a year before the term was coined in 2005 and had working code in 2002 and
1947-2003 that predated Netscape publishing articles on what they called <q>Inner
1948-Browsing</q> where all navigation takes place withing a single page.
1949-</p>
1950-
1951-<p>
1952-Again taking the lead, Athena offers features which developers cannot find
1953-elsewhere. In this series, we attempt to expose these excellent qualities
1954-to the world of application
1955-developers.
1956-</p>
1957-
1958-</body>
1959-</html>
1960-
1961
1962=== removed file 'Nevow/doc/howto/chattutorial/intro.xhtml'
1963--- Nevow/doc/howto/chattutorial/intro.xhtml 2008-09-03 20:03:47 +0000
1964+++ Nevow/doc/howto/chattutorial/intro.xhtml 1970-01-01 00:00:00 +0000
1965@@ -1,106 +0,0 @@
1966-<?xml version="1.0"?>
1967-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1968-<html xmlns="http://www.w3.org/1999/xhtml">
1969- <head>
1970- <title>Introduction</title>
1971- </head>
1972-<body>
1973-
1974-<h1>Introduction</h1>
1975-
1976-<h2>Who is this tutorial for?</h2>
1977-
1978-<p>This tutorial is for people who want to build interactive client-server
1979-functionality where a web-browser is the client. It will show you how to build
1980-a live, interactive chat application that requires nothing more than a web
1981-browser that supports JavaScript.</p>
1982-
1983-<p>The interesting thing about a chat application, which shows why Nevow Athena
1984-is special, is that it involves two-way communication. In other words, it
1985-involves not only the recently-popular AJAX (the web browser sending commands
1986-to the server without loading a new page) but also the trickier and, in our
1987-opinion, somewhat cooler technique known as COMET (the web server
1988-sending commands to the <em>browser</em>).</p>
1989-
1990-<h2>Who is this tutorial <em>not</em> for?</h2>
1991-
1992-<p>Nevow Athena is <em>not</em> for people who want a normal web application
1993-framework. If you want one of those, you should use
1994-non-Athena-<a href="http://divmod.org/trac/wiki/DivmodNevow">Nevow</a>,
1995-<a href="http://www.djangoproject.com/">Django</a>,
1996-<a href="http://turbogears.org/">TurboGears</a>, or maybe even
1997-<a href="http://rubyonrails.org/">Ruby On Rails</a>. Athena doesn't work in terms
1998-of pages, links, or HTTP requests and responses; it is a client-server
1999-framework that works in terms of widgets, JavaScript objects, and symmetric
2000-asynchronous message queues.</p>
2001-
2002-<p>However, as alluded to above, Athena is part of a larger framework, Nevow,
2003-which can be used to build more general-purpose and <q>traditional</q>
2004-web applications.</p>
2005-
2006-<h2>AJAX</h2>
2007-
2008-<p>AJAX isn't a technology in and of itself, bur rather an amalgam of
2009-technologies used together in order to accomplish the goal of making web
2010-applications more responsive than traditional delivery and interactive
2011-mechanisms, such as HTML forms submitted to a server.</p>
2012-
2013-<p>In particular, AJAX consists of the following:</p>
2014-<ul>
2015-<li>Asynchronous communications from a user's browser to a server</li>
2016-<li>JavaScript</li>
2017-<li>Exchanged data (usually XML or JSON)</li>
2018-</ul>
2019-
2020-<h2>COMET</h2>
2021-
2022-<p>Historically, the focus of AJAX technologies was user-event driven. However,
2023-with the need to update the user's browser with events generated at the server,
2024-a solution more sophisticated than AJAX was needed; this has been dubbed COMET.
2025-Athena is implemented using both AJAX and COMET techniques, and therefore
2026-allows two-way browser &lt;-&gt; server communications.</p>
2027-
2028-<h2>Athena Basics</h2>
2029-
2030-<p>We've provided brief background information on AJAX/COMET, but what is the
2031-purpose of Athena? What makes Athena different than other solutions? Here are a
2032-few key points that should help with these questions::</p>
2033-<ul>
2034-<li>Athena exists to make writing COMET web applications easy.</li>
2035-<li>Athena is written in Python and JavaScript</li>
2036-<li>It is written to be used with Nevow, a <a
2037-href="http://twistedmatrix.com/">Twisted</a>-based web framework.</li>
2038-<li>Similar to Twisted's <a
2039-href="http://twistedmatrix.com/projects/core/documentation/howto/pb-intro.html">Perspective
2040-Broker</a>, Athena employs remote calls.</li>
2041-</ul>
2042-
2043-<p>Athena was written by Twisted and Divmod developers (in addition to
2044-contributing members of the community) in order to bring the outdated and
2045-Nevow-incompatible Woven LivePage technology to Nevow. In addition, it was an
2046-opportunity to improve upon the original design and incorporate new features to
2047-address the growing needs of developers.</p>
2048-
2049-<h2>Target Applications</h2>
2050-
2051-<p>Good candidates for Athena web applications would include those where the
2052-application needs to respond to user input and/or updates from servers, such
2053-as the following:</p>
2054-<ul>
2055-<li>conference software (e.g. whiteboard, shared text, chat, etc.)</li>
2056-<li>mail clients</li>
2057-<li>interactive, multi-player games</li>
2058-<li>social networking tools</li>
2059-<li>office applications (e.g., spreadsheets, word processors, etc.)</li>
2060-</ul>
2061-
2062-<h2>Target Developers</h2>
2063-
2064-<p>Anyone who wants to create interactive, web-based applications is a
2065-potential Nevow/Athena user. It's best to have some background in writing web
2066-applications, and in addition, to know how to use Nevow. However, we hope that
2067-this tutorial will be just as useful for beginners as experienced
2068-developers.</p>
2069-
2070-</body>
2071-</html>
2072
2073=== removed directory 'Nevow/doc/howto/chattutorial/part00'
2074=== removed file 'Nevow/doc/howto/chattutorial/part00/index.xhtml'
2075--- Nevow/doc/howto/chattutorial/part00/index.xhtml 2008-09-03 20:03:47 +0000
2076+++ Nevow/doc/howto/chattutorial/part00/index.xhtml 1970-01-01 00:00:00 +0000
2077@@ -1,230 +0,0 @@
2078-<?xml version="1.0"?>
2079-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2080-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2081-<html xmlns="http://www.w3.org/1999/xhtml">
2082- <head>
2083- <title>Nevow Athena from Scratch: Echo Application</title>
2084- </head>
2085-<body>
2086-
2087-<h2>What is an "Echo Application?"</h2>
2088-
2089-<p>
2090-Our first foray into building an Athena application will be an easy venture:
2091-we want to type something in an input box and have it echoed back to us on
2092-the same page, without having to reload anything. Why? Well, our eventual
2093-goal is to have a working chat server, with all sorts of technical bells
2094-and whistles (persistent storage, authentication,
2095-etc.), but that's a bit heady for right now. Many of the same principles
2096-which we will eventually employ in our chat application exist for a simple
2097-case of sending textual messages between a web browser and a server. This
2098-is the essence of our "Echo" application.
2099-</p>
2100-
2101-<h2>Mental Preparation</h2>
2102-
2103-<p>In the
2104-<a href="../intro.html">Introduction</a> and the
2105-<a href="../concepts.html">Concepts</a> pages, we had a refresher on AJAX and
2106-COMET and we learned a little bit about what that looks like for Athena. But
2107-as we sit down to actually write an Athena application, what do we need to
2108-wrap our heads around?
2109-</p>
2110-
2111-<p>Given the introductory knowledge we have, we know that we will need to
2112-write some JavaScript, some Python, and if our past experience in developing
2113-web applications is any guide, some form of template. This indeed is the
2114-case, but here's something big: we're not working with pages and page
2115-templates; we're working with "elements", or parts of the DOM tree. We will
2116-not be creating page resources; we will be creating just the parts of a
2117-"traditional" page that will be dynamic and interactive.
2118-</p>
2119-
2120-<h2>Architecture</h2>
2121-
2122-<p>Now that we've pumped ourselves up and before we start clacking away at the
2123-keyboard, we need to get pointed in the right direction. We need a
2124-plan. Here's what we know:</p>
2125-
2126-<ol>
2127-<li>We will have a server that:
2128- <ul>
2129- <li>serves dynamic elements in a resource accessible via a URL;</li>
2130- <li>communicates with a client.</li>
2131- </ul>
2132-</li>
2133-<li>We will have a client that:
2134- <ul>
2135- <li>communicates with the server;</li>
2136- <li>updates its DOM tree.</li>
2137- </ul>
2138-</li>
2139-</ol>
2140-
2141-<p>The user experience of this application will be the following:</p>
2142-<ol>
2143-<li>they will type text in an input on a form; and</li>
2144-<li>the typed text will be rendered to a different part of the page upon
2145-hitting a submit button.</li>
2146-</ol>
2147-
2148-<p>We will not simply write user input to a <code>div</code> with JavaScript
2149-DOM manipulation, but will instead pass data like we expect will be necessary
2150-when we write our chat application. After all, it's probably best to build
2151-towards our goal. In order to accomplish this, the application will do
2152-something like the following:</p>
2153-
2154-<ol>
2155-<li>JavaScript client code will extract user input and send
2156-it to our server;</li>
2157-<li>Python code will receive messages from the client;</li>
2158-<li>Python code will send messages to the client; and</li>
2159-<li>a template file (or <code>stan</code> code) will be used for
2160-presentation.</li>
2161-</ol>
2162-
2163-<p></p>
2164-
2165-<h2>Let the Coding Begin</h2>
2166-
2167-<p>In a future installment, we will outline the development process from
2168-the perspective of test-driven development, in order to not only show how
2169-to write unit tests for Athena (Python and JavaScript), but to encourage
2170-good programming practices while working with Athena. For now, though, we will
2171-just dive right in.</p>
2172-
2173-<h3>Presentation</h3>
2174-
2175-<p>Let's start with the easy bit: what our app will look like. Here is the
2176-template for our echo application:</p>
2177-
2178-<a href="listings/echothing/template.html" class="html-listing" />
2179-
2180-<p>Things to note:</p>
2181-<ul>
2182-<li>This is not a complete HTML document, but is an XHTML template for an
2183-"element".</li>
2184-<li>The name space declarations in the top <code>div</code> tag are necessary
2185-for the operation of Athena.</li>
2186-<li>When we hit the "Send" button, our JavaScript class will call the
2187-<code>doSay()</code> method.</li>
2188-</ul>
2189-
2190-<h3>Writing the Client</h3>
2191-
2192-<p>Next up is the JavaScript. We need to send our data to the server. In a
2193-full chat application, it would be necessary to send the data to the server
2194-so that we could propagate the message to all connected clients. In this
2195-case, with the simple echo, we're not going to do anything with the data
2196-that gets sent to the server, except send it back, of course.</p>
2197-
2198-<p>Our JavaScript will need to do several things:</p>
2199-<ol>
2200-<li>import required modules;</li>
2201-<li>inherit <code>callRemote</code> functionality from the base
2202-<code>Widget</code> class;</li>
2203-<li>setup convenience attributes;</li>
2204-<li>implement the <code>doSay()</code> method we put in our template above;
2205-and</li>
2206-<li>implement a method for updating the DOM with data it receives from
2207-the server</li>
2208-</ol>
2209-
2210-<a href="listings/echothing/js/EchoThing.js" class="py-listing" />
2211-
2212-<p>Points to note:</p>
2213-<ul>
2214-<li>Those import statements aren't just pretty: they are necessary! In Athena,
2215-you need to treat those like you treat the import statements in Python.
2216-</li>
2217-<li>The attributes set in the <code>__init__()</code> method are for
2218-convenience when we reference them in other methods.</li>
2219-<li>Note the <code>callRemote()</code> method in <code>doSay()</code>,
2220-As mentioned in the <a href="../concepts.html">Concepts</a> section, this
2221-is how JavaScript is communicating with our Python server.</li>
2222-<li>Another thing about <code>doSay</code>: this is the submit handler. As
2223-such, it needs to return false so that the browser is prevented from doing a
2224-normal form submission.</li>
2225-<li><code>addText()</code> is the method that will be updating the browser
2226-DOM once the server sends the data back.</li>
2227-</ul>
2228-
2229-<p>There's not much to say about the next one. This is what sets up the
2230-relationship between our module name and the actual file itself (so that
2231-the JavaScript can be loaded):</p>
2232-
2233-<a href="listings/nevow/plugins/echothing_package.py" class="py-listing" />
2234-
2235-<h3>Writing the Server</h3>
2236-
2237-<p>Despite what one might think, writing the server may be the easiest
2238-part! If you've created Nevow applications before, then this will look
2239-very familiar. The only method we need is one that will send data back to
2240-the client. Besides importing the necessary modules and creating a class
2241-with some boilerplate, that's about it.
2242-</p>
2243-
2244-<p>Let's take a look at the code:</p>
2245-
2246-<a href="listings/echothing/echobox.py" class="py-listing" />
2247-
2248-<p>As promised, simple as can be. We do make use of a Twisted utility that
2249-simplifies typing the path to our template. Some very important points:</p>
2250-<ul>
2251-<li>The <code>jsClass</code> assignment is what connects this code to your
2252-JavaScript code.</li>
2253-<li>As discussed in the <a href="../concepts.html">Concepts</a> section,
2254-the <code>expose</code> decorator is required if our JavaScript is going
2255-to be able to call the <code>say()</code> method.</li>
2256-</ul>
2257-
2258-<h3>Putting it All Together</h3>
2259-
2260-<p>Now that we've got all the code in front of us, we can trace out exactly
2261-what happens:</p>
2262-<ol>
2263-<li>the user loads the resource in their browser, and the template is
2264-rendered;</li>
2265-<li>after typing a message in the input box, the user hits submit;</li>
2266-<li>upon hitting submit, the client code <code>doSay()</code> method is
2267-called;</li>
2268-<li><code>doSay()</code> makes a remote call to the Python server method
2269-<code>say()</code>;</li>
2270-<li>the Python server receives the data when <code>say()</code> is called, and
2271-then it passes that data to the client code's <code>addText()</code> method;</li>
2272-<li>with control back in the client code and data fresh from the server,
2273-JavaScript can now update the page's DOM with the new data, and this is
2274-what the <code>addText()</code> method does;</li>
2275-<li>when <code>addText()</code> finishes, the cycle has completed and the
2276-browser now displays the latest data input by the user.</li>
2277-</ol>
2278-
2279-<h3>The Fruits of Our Labor</h3>
2280-
2281-<p>Now we get to run it! This is a little different than what you may be
2282-used to, if you have written Twisted applications in the past. We are using
2283-the plugin architecture of Twisted and Nevow such that <code>twistd</code>
2284-will publish our element in an HTTP service. To do this, we will use
2285-<code>twistd</code>'s <code>athena-widget</code> command:</p>
2286-
2287-<pre class="shell">
2288-cd Nevow/doc/howto/chattutorial/part00/listings
2289-twistd -n athena-widget --element=echothing.echobox.EchoElement
2290-</pre>
2291-
2292-<p>If you executed this against the tutorial code on your local machine,
2293-you can now visit <a href="http://localhost:8080">localhost:8080</a> and start
2294-echoing to your heart's content.</p>
2295-
2296-<h2>Summary</h2>
2297-
2298-<p>As you can see, our echo application is a toy app that doesn't do
2299-anything very useful. However, it has provided us with a basis for learning how
2300-to write working Athena code that lets a browser and server communicate
2301-with each other, both sending and receiving data. As such, we now have a
2302-solid foundation upon which we can build a functional, useful <i>and</i>
2303-instructional chat application.</p>
2304-
2305-</body>
2306-</html>
2307-
2308
2309=== removed directory 'Nevow/doc/howto/chattutorial/part00/listings'
2310=== removed directory 'Nevow/doc/howto/chattutorial/part00/listings/echothing'
2311=== removed file 'Nevow/doc/howto/chattutorial/part00/listings/echothing/__init__.py'
2312--- Nevow/doc/howto/chattutorial/part00/listings/echothing/__init__.py 2008-09-03 20:03:47 +0000
2313+++ Nevow/doc/howto/chattutorial/part00/listings/echothing/__init__.py 1970-01-01 00:00:00 +0000
2314@@ -1,1 +0,0 @@
2315-
2316
2317=== removed file 'Nevow/doc/howto/chattutorial/part00/listings/echothing/echobox.py'
2318--- Nevow/doc/howto/chattutorial/part00/listings/echothing/echobox.py 2008-09-03 20:03:47 +0000
2319+++ Nevow/doc/howto/chattutorial/part00/listings/echothing/echobox.py 1970-01-01 00:00:00 +0000
2320@@ -1,12 +0,0 @@
2321-from twisted.python.util import sibpath
2322-from nevow.athena import LiveElement, expose
2323-from nevow.loaders import xmlfile
2324-
2325-class EchoElement(LiveElement):
2326-
2327- docFactory = xmlfile(sibpath(__file__, 'template.html'))
2328- jsClass = u'EchoThing.EchoWidget'
2329-
2330- def say(self, message):
2331- self.callRemote('addText', message)
2332- say = expose(say)
2333
2334=== removed directory 'Nevow/doc/howto/chattutorial/part00/listings/echothing/js'
2335=== removed file 'Nevow/doc/howto/chattutorial/part00/listings/echothing/js/EchoThing.js'
2336--- Nevow/doc/howto/chattutorial/part00/listings/echothing/js/EchoThing.js 2009-01-21 22:58:03 +0000
2337+++ Nevow/doc/howto/chattutorial/part00/listings/echothing/js/EchoThing.js 1970-01-01 00:00:00 +0000
2338@@ -1,22 +0,0 @@
2339-// import Nevow.Athena
2340-
2341-Nevow.Athena.Widget.subclass(EchoThing, 'EchoWidget').methods(
2342- function __init__(self, node) {
2343- EchoThing.EchoWidget.upcall(self, "__init__", node);
2344- self.echoWidget = self.nodeByAttribute('name', 'echoElement');
2345- self.scrollArea = self.nodeByAttribute('name', 'scrollArea');
2346- self.message = self.nodeByAttribute('name', 'message');
2347- },
2348-
2349- function doSay(self) {
2350- self.callRemote("say", self.message.value);
2351- self.message.value = "";
2352- return false;
2353- },
2354-
2355- function addText(self, text) {
2356- var newNode = document.createElement('div');
2357- newNode.appendChild(document.createTextNode(text));
2358- self.scrollArea.appendChild(newNode);
2359- document.body.scrollTop = document.body.scrollHeight;
2360- });
2361
2362=== removed file 'Nevow/doc/howto/chattutorial/part00/listings/echothing/template.html'
2363--- Nevow/doc/howto/chattutorial/part00/listings/echothing/template.html 2008-09-03 20:03:47 +0000
2364+++ Nevow/doc/howto/chattutorial/part00/listings/echothing/template.html 1970-01-01 00:00:00 +0000
2365@@ -1,11 +0,0 @@
2366-<div xmlns:nevow="http://nevow.com/ns/nevow/0.1"
2367- xmlns:athena="http://divmod.org/ns/athena/0.7"
2368- nevow:render="liveElement">
2369- <h2>Echo Element</h2>
2370- <form name="echoElement">
2371- <athena:handler event="onsubmit" handler="doSay" />
2372- <div name="scrollArea">
2373- </div>
2374- <input name="message" /><input type="submit" value="Send" />
2375- </form>
2376-</div>
2377
2378=== removed directory 'Nevow/doc/howto/chattutorial/part00/listings/nevow'
2379=== removed directory 'Nevow/doc/howto/chattutorial/part00/listings/nevow/plugins'
2380=== removed file 'Nevow/doc/howto/chattutorial/part00/listings/nevow/plugins/echothing_package.py'
2381--- Nevow/doc/howto/chattutorial/part00/listings/nevow/plugins/echothing_package.py 2008-09-03 20:03:47 +0000
2382+++ Nevow/doc/howto/chattutorial/part00/listings/nevow/plugins/echothing_package.py 1970-01-01 00:00:00 +0000
2383@@ -1,8 +0,0 @@
2384-
2385-from twisted.python import util
2386-
2387-from nevow import athena
2388-
2389-import echothing
2390-
2391-chatthingPkg = athena.AutoJSPackage(util.sibpath(echothing.__file__, 'js'))
2392
2393=== removed directory 'Nevow/doc/howto/chattutorial/part01'
2394=== removed file 'Nevow/doc/howto/chattutorial/part01/index.xhtml'
2395--- Nevow/doc/howto/chattutorial/part01/index.xhtml 2008-09-03 20:03:47 +0000
2396+++ Nevow/doc/howto/chattutorial/part01/index.xhtml 1970-01-01 00:00:00 +0000
2397@@ -1,236 +0,0 @@
2398-<?xml version="1.0"?>
2399-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2400-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2401-<html xmlns="http://www.w3.org/1999/xhtml">
2402- <head>
2403- <title>Nevow Athena from Scratch: Chat Application</title>
2404- </head>
2405-<body>
2406-
2407-<h2>Architecture</h2>
2408-
2409-<p>We'll assume that you've read all the preceding sections of this tutorial
2410-and have just finished the "Echo" application example. As such, we don't need
2411-to do any more "mental preparation" and can skip straight to a description of
2412-the architecture.</p>
2413-
2414-<p>Fundamentally, this is no different than our echo application: there is
2415-a little more chatter that takes place between the client and server;
2416-there's another object involved (a <code>ChatRoom</code>); and we'll have
2417-to run the server a little differently.
2418-</p>
2419-
2420-<p>Here are the new features we want to support:</p>
2421-<ul>
2422-<li>login form;</li>
2423-<li>in-memory user storage;</li>
2424-<li>the ability to send global alerts to all users; and</li>
2425-<li>the ability for all users to "hear" when another user speaks in the
2426-chat room;</li>
2427-</ul>
2428-
2429-<p>A general rule we can establish about our architecture is that if something
2430-has to happen for everyone, that code needs to appear on the server side,
2431-since it's the server that is keeping track of all users. If something is
2432-going to happen irrespective of other users or if browser DOM manipulation
2433-is required, then we know the client will be the recipient of the code.</p>
2434-
2435-<p>As such, in the features above, the login form will be client code. The
2436-user storage, global alerts, and "hearing" will be implemented in server
2437-code for the data; updating the DOM with that data will be implemented in
2438-client code.</p>
2439-
2440-<p>The user experience of this application will be the following:</p>
2441-<ol>
2442-<li>they will be presented with a login box (no password, only username);</li>
2443-<li>upon logging in, a message will be sent to all logged in users that
2444-this person has joined, they will see a message at the bottom of the
2445-chat that states their login name, and the login form will be replaced with
2446-a chat area and a text input field;</li>
2447-<li>they will type text in the input field; and</li>
2448-<li>the typed text will appear in the browser of every person who is
2449-logged in.</li>
2450-</ol>
2451-
2452-<p>Building upon our previous example, our application will do the
2453-following:</p>
2454-
2455-<ol>
2456-<li>JavaScript client code will extract user input and send
2457-it to our server;</li>
2458-<li>Python code will receive messages from the client;</li>
2459-<li>Python code will process these messages;</li>
2460-<li>Python code will send messages to the all clients; and</li>
2461-<li>a template file (or <code>stan</code> code) will be used for
2462-presentation.</li>
2463-</ol>
2464-
2465-<h2>More Coding</h2>
2466-
2467-<h3>Presentation</h3>
2468-
2469-<p>The template is very similar as it was in the previous example, with
2470-the differences being a new login box, a "logged in as"
2471-area, and some name changes:</p>
2472-
2473-<a href="listings/chatthing/template.html" class="html-listing" />
2474-
2475-<p>We've now got two JavaScript methods that need to be defined:
2476-<code>doSetUsername()</code> and <code>doSay()</code>. We can also infer
2477-from this template that elements will be hidden and shown after login
2478-(note the presence of <code>style="display:none"</code> in two places). With
2479-these observations in hand, let's proceed to the JavaScript code.</p>
2480-
2481-<h3>Writing the Client</h3>
2482-
2483-<p>Referring back to our thoughts in the "Architecture" section above, we
2484-can establish that the JavaScript code needs the following:</p>
2485-
2486-<ul>
2487-<li>have the same basic boilerplate as in the "echo" example (imports,
2488-inheritance, attribute-setting in the constructor);</li>
2489-<li>implement the <code>doSetUsername()</code> and <code>doSay()</code>
2490-methods;</li>
2491-<li>create a method that will send a message to all users; and</li>
2492-<li>create a method that will let everyone know when someone says
2493-something. Let's see how this is done.</li>
2494-</ul>
2495-
2496-<a href="listings/chatthing/js/ChatThing.js" class="py-listing" />
2497-
2498-<p>There is a little abstraction here:</p>
2499-<ul>
2500-<li>we need a general message-sending method (<code>displayMessage()</code>) for any
2501-message that gets sent to all users;</li>
2502-<li>for user chat messages, we need something that will prepend the username so
2503-that everyone knows who said what (<code>displayUserMessage()</code>), and once this method
2504-does its thing, it passes the adjusted message on to <code>displayMessage()</code>.</li>
2505-</ul>
2506-
2507-<p>Other than that, this is very straight-forward code; it's pretty much
2508-the same as the "Echo" tutorial. The <code>display*()</code> methods
2509-are only responsible for updating the UI, just as we would expect.</p>
2510-
2511-We also need the same glue that we demonstrated in the "Echo" example:
2512-
2513-<a href="listings/nevow/plugins/chatthing_package.py" class="py-listing" />
2514-
2515-<h3>Writing the Server</h3>
2516-
2517-<p>The server code is a bit more complicated. We
2518-anticipated this above in the "Architecture" section where we noted that
2519-the Python code needs to receive, process and send messages.</p>
2520-
2521-<a href="listings/chatthing/chatterbox.py" class="py-listing" />
2522-
2523-<p>There is something in our "Chat" code that is not at all present in the
2524-"Echo" application: the <code>ChatRoom</code> object. We need this object for the
2525-following functionality:</p>
2526-<ul>
2527-<li>a means of instantiating new <code>ChatterElement</code> clients;</li>
2528-<li>a "singleton" instance for keeping track of all <code>ChatterElement</code> clients;</li>
2529-<li>a means sending messages to all clients;</li>
2530-</ul>
2531-
2532-<p>Let's look at the second two reasons first. In our "Chat" application,
2533-a new <code>ChatterElement</code> is created whenever a user connects,
2534-so we will have potentially many of these instances. In order
2535-for our chat server to function as designed, it will need a way to
2536-communicate with each of these. If we create an object that can keep the
2537-<code>ChatterElement</code>es in a list, then it will be able to iterate that
2538-list and call methods that, in turn, make remote calls to the JavaScript.
2539-</p>
2540-
2541-<p>Because we need the chat room to be a singleton object, it
2542-can only be instantiated once. But we need many instantiations of
2543-<code>ChatterElement</code> -- one for each connection, in fact. So what do
2544-we do? Well, in this case, we make one of the methods
2545-of <code>ChatRoom</code> a factory for instantiating a
2546-<code>ChatterElement</code>. Before we return the instance, though, we
2547-append it to the list of instances that the <code>ChatRoom</code>
2548-is keeping track of.
2549-</p>
2550-
2551-<h3>Putting it All Together</h3>
2552-
2553-
2554-<p>Now that we've got all the code in front of us, we can trace out exactly what happens:</p>
2555-
2556-<ol>
2557-<li>the user loads the resource in their browser, and the template is rendered;</li>
2558-<li>after typing a message in the input box, the user hits submit;</li>
2559-<li>JavaScript client code calls to the server with the text the user submitted;</li>
2560-<li>the server gets the message and shares it with all the connected
2561-<code>ChatterElement</code>s;</li>
2562-<li>each <code>ChatterElement</code> hears this message and passes it back to the JavaScript client;</li>
2563-<li>the client prepends the username to the message and then updates the display with the complete message.</li>
2564-</ol>
2565-
2566-<p>
2567-Keep in mind that <code>ChatterElement</code> entails several duties: it
2568-establishes a relationship with a room object, it "registers" a user (there's a
2569-one-to-one mapping between users and <code>ChatterElement</code>), it sends
2570-messages to the browser, and it receives messages from the chat room. Being a
2571-<code>LiveElement</code> subclass, <code>ChatterElement</code> is also
2572-responsible for the view (via the document factory).
2573-</p>
2574-
2575-
2576-<h3>Running with <code>twistd</code></h3>
2577-
2578-<p>One last bit of code that may seem odd is the <code>chat</code>
2579-variable we define right after the <code>ChatRoom</code> class. What
2580-is this? This is how we make all this cleverness work as a twisted
2581-plugin. </p>
2582-
2583-<p>If you recall, in our "Echo" application, we ran the code with
2584-the following command:
2585-</p>
2586-
2587-<pre class="shell">
2588-twistd -n athena-widget --element=echothing.echobox.EchoElement
2589-</pre>
2590-
2591-<p>The value we pass as the <code>--element</code> argument is the dotted
2592-name of the <code>LiveElement</code> object of which our "web page"
2593-is primarily comprised: the <code>EchoElement</code> object. In
2594-our "Chat" application, we have more moving parts: not only
2595-do we have the <code>ChatterElement</code> object, but we have the
2596-<code>ChatRoom</code> object which is responsible for keeping track of
2597-many <code>ChatterElement</code>es. By defining the <code>chat</code>
2598-variable, we are accomplishing the following all at once:
2599-</p>
2600-
2601-<ul>
2602-<li>providing a variable that can be accessed as a dotted name and thus
2603-used when starting the server (<code>chatthing.chatterbox.chat</code>);</li>
2604-<li>creating a singleton of <code>ChatRoom</code> (via the "magic"
2605-of Python module-level instantiations);</li>
2606-<li>making use of a factory, that when called, will both return a
2607-new <code>ChatterElement</code> instance <i>and</i> add itself to the
2608-<code>ChatRoom</code>.</li>
2609-</ul>
2610-
2611-<p>Running this version of our code is a little bit different than the
2612-"Echo" version. This is because of the <code>ChatRoom</code> code we
2613-discussed above. As such, we pass a factory as our element, like so:</p>
2614-
2615-<pre class="shell">
2616-cd Nevow/doc/howto/chattutorial/part01/listings
2617-twistd -n athena-widget --element=chatthing.chatterbox.chat
2618-</pre>
2619-
2620-<p>If you executed this against the tutorial code on your local machine,
2621-you can now visit <a href="http://localhost:8080/">http://localhost:8080/</a>
2622-and start chatting to your heart's content.</p>
2623-
2624-<h2>Summary</h2>
2625-<p>
2626-Unlike our echo application, the chat application has some real functionality
2627-and does some useful stuff: supporting user chats via browser/server two-way
2628-communications. It should be evident now how the echo application provided a
2629-basic conceptual and (partially) functional foundation upon which our chat work
2630-could be based.
2631-</p>
2632-</body>
2633-</html>
2634
2635=== removed directory 'Nevow/doc/howto/chattutorial/part01/listings'
2636=== removed directory 'Nevow/doc/howto/chattutorial/part01/listings/chatthing'
2637=== removed file 'Nevow/doc/howto/chattutorial/part01/listings/chatthing/__init__.py'
2638--- Nevow/doc/howto/chattutorial/part01/listings/chatthing/__init__.py 2008-09-03 20:03:47 +0000
2639+++ Nevow/doc/howto/chattutorial/part01/listings/chatthing/__init__.py 1970-01-01 00:00:00 +0000
2640@@ -1,1 +0,0 @@
2641-
2642
2643=== removed file 'Nevow/doc/howto/chattutorial/part01/listings/chatthing/chatterbox.py'
2644--- Nevow/doc/howto/chattutorial/part01/listings/chatthing/chatterbox.py 2008-09-03 20:03:47 +0000
2645+++ Nevow/doc/howto/chattutorial/part01/listings/chatthing/chatterbox.py 1970-01-01 00:00:00 +0000
2646@@ -1,48 +0,0 @@
2647-from twisted.python.util import sibpath
2648-from nevow.loaders import xmlfile
2649-from nevow.athena import LiveElement, expose
2650-
2651-class ChatRoom(object):
2652-
2653- def __init__(self):
2654- self.chatters = []
2655-
2656- def wall(self, message):
2657- for chatter in self.chatters:
2658- chatter.wall(message)
2659-
2660- def tellEverybody(self, who, what):
2661- for chatter in self.chatters:
2662- chatter.hear(who.username, what)
2663-
2664- def makeChatter(self):
2665- elem = ChatterElement(self)
2666- self.chatters.append(elem)
2667- return elem
2668-
2669-# element to be run with twistd
2670-chat = ChatRoom().makeChatter
2671-
2672-class ChatterElement(LiveElement):
2673-
2674- docFactory = xmlfile(sibpath(__file__, 'template.html'))
2675- jsClass = u'ChatThing.ChatterWidget'
2676-
2677- def __init__(self, room):
2678- self.room = room
2679-
2680- def setUsername(self, username):
2681- self.username = username
2682- message = ' * user '+username+' has joined the room'
2683- self.room.wall(message)
2684- setUsername = expose(setUsername)
2685-
2686- def say(self, message):
2687- self.room.tellEverybody(self, message)
2688- say = expose(say)
2689-
2690- def wall(self, message):
2691- self.callRemote('displayMessage', message)
2692-
2693- def hear(self, username, what):
2694- self.callRemote('displayUserMessage', username, what)
2695
2696=== removed directory 'Nevow/doc/howto/chattutorial/part01/listings/chatthing/js'
2697=== removed file 'Nevow/doc/howto/chattutorial/part01/listings/chatthing/js/ChatThing.js'
2698--- Nevow/doc/howto/chattutorial/part01/listings/chatthing/js/ChatThing.js 2009-01-21 22:58:03 +0000
2699+++ Nevow/doc/howto/chattutorial/part01/listings/chatthing/js/ChatThing.js 1970-01-01 00:00:00 +0000
2700@@ -1,42 +0,0 @@
2701-// import Nevow.Athena
2702-
2703-Nevow.Athena.Widget.subclass(ChatThing, 'ChatterWidget').methods(
2704- function __init__(self, node) {
2705- ChatThing.ChatterWidget.upcall(self, "__init__", node);
2706- self.chooseBox = self.nodeByAttribute('name', 'chooseBox');
2707- self.scrollArea = self.nodeByAttribute('name', 'scrollArea');
2708- self.sendLine = self.nodeByAttribute('name', 'sendLine');
2709- self.usernameField = self.nodeByAttribute('name', 'username');
2710- self.userMessage = self.nodeByAttribute('name', 'userMessage');
2711- self.loggedInAs = self.nodeByAttribute('name', 'loggedInAs');
2712- },
2713-
2714- function doSetUsername(self) {
2715- var username = self.usernameField.value;
2716- self.callRemote("setUsername", username).addCallback(
2717- function (result) {
2718- self.chooseBox.style.display = "none";
2719- self.sendLine.style.display = "block";
2720- self.loggedInAs.appendChild(document.createTextNode(username));
2721- self.loggedInAs.style.display = "block";
2722- });
2723- return false;
2724- },
2725-
2726- function doSay(self) {
2727- self.callRemote("say", self.userMessage.value);
2728- self.nodeByAttribute('name', 'userMessage').value = "";
2729- return false;
2730- },
2731-
2732- function displayMessage(self, message) {
2733- var newNode = document.createElement('div');
2734- newNode.appendChild(document.createTextNode(message));
2735- self.scrollArea.appendChild(newNode);
2736- document.body.scrollTop = document.body.scrollHeight;
2737- },
2738-
2739- function displayUserMessage(self, avatarName, text) {
2740- var msg = avatarName+': '+text;
2741- self.displayMessage(msg);
2742- });
2743
2744=== removed file 'Nevow/doc/howto/chattutorial/part01/listings/chatthing/template.html'
2745--- Nevow/doc/howto/chattutorial/part01/listings/chatthing/template.html 2008-09-03 20:03:47 +0000
2746+++ Nevow/doc/howto/chattutorial/part01/listings/chatthing/template.html 1970-01-01 00:00:00 +0000
2747@@ -1,20 +0,0 @@
2748-<div xmlns:nevow="http://nevow.com/ns/nevow/0.1"
2749- xmlns:athena="http://divmod.org/ns/athena/0.7"
2750- nevow:render="liveElement">
2751- <h2>Chatter Element</h2>
2752- <form name="chatBox">
2753- <athena:handler event="onsubmit" handler="doSay" />
2754- <div name="scrollArea"
2755- style="border: 1px solid gray; padding: 5; margin: 5">
2756- </div>
2757- <div name="sendLine" style="display: none">
2758- <input name="userMessage" /><input type="submit" value="Send" />
2759- </div>
2760- </form>
2761- <form name="chooseBox">
2762- <athena:handler event="onsubmit" handler="doSetUsername" />
2763- Choose your username: <input name="username" />
2764- <input type="submit" name="GO" value="Enter"/>
2765- </form>
2766- <div name="loggedInAs" style="display:none"><span>Logged in as </span></div>
2767-</div>
2768
2769=== removed directory 'Nevow/doc/howto/chattutorial/part01/listings/nevow'
2770=== removed directory 'Nevow/doc/howto/chattutorial/part01/listings/nevow/plugins'
2771=== removed file 'Nevow/doc/howto/chattutorial/part01/listings/nevow/plugins/chatthing_package.py'
2772--- Nevow/doc/howto/chattutorial/part01/listings/nevow/plugins/chatthing_package.py 2008-09-03 20:03:47 +0000
2773+++ Nevow/doc/howto/chattutorial/part01/listings/nevow/plugins/chatthing_package.py 1970-01-01 00:00:00 +0000
2774@@ -1,8 +0,0 @@
2775-
2776-from twisted.python import util
2777-
2778-from nevow import athena
2779-
2780-import chatthing
2781-
2782-chatthingPkg = athena.AutoJSPackage(util.sibpath(chatthing.__file__, 'js'))
2783
2784=== removed file 'Nevow/doc/howto/deployment.xhtml'
2785--- Nevow/doc/howto/deployment.xhtml 2008-08-26 13:45:59 +0000
2786+++ Nevow/doc/howto/deployment.xhtml 1970-01-01 00:00:00 +0000
2787@@ -1,300 +0,0 @@
2788-<?xml version="1.0"?>
2789-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2790- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2791-
2792-<html xmlns="http://www.w3.org/1999/xhtml">
2793- <head>
2794- <title>
2795- Deployment
2796- </title>
2797- </head>
2798- <body>
2799- <h1>Deployment</h1>
2800-
2801- <p>
2802- Nevow includes two major phases for deciding what HTML to render. <a
2803- href="traversal.xhtml">Object Traversal</a> is the procedure by which a
2804- URL is mapped to a Python object which will perform the HTML
2805- generation. <a href="glossary.xhtml">Page Rendering</a> is the process by
2806- which data objects are combined with an HTML template to produce the
2807- final output.
2808- </p>
2809-
2810- <p>
2811- Before any of this can take place, however, we must have an environment
2812- in which our Python code can run in response to an HTTP request, and HTML
2813- can be returned to the browser for rendering. This is called the
2814- <a href="glossary.xhtml">Deployment Environment</a>.
2815- </p>
2816-
2817- <p>
2818- There are various deployment options for Nevow page code:
2819- </p>
2820-
2821- <ul>
2822- <li>
2823- CGI: Simple deployment in almost any HTTP server
2824- </li>
2825- <li>
2826- WSGI: A more complete and flexible way for deploying on many HTTP
2827- servers
2828- </li>
2829- <li>
2830- Twisted.Web: A standalone application server process which includes a
2831- built-in HTTP server
2832- </li>
2833- <li>
2834- Zomne: A small CGI which hands off HTTP requests to a long-running
2835- application server process, similar to FastCGI or SCGI
2836- </li>
2837- </ul>
2838-
2839- <h2>CGI</h2>
2840-
2841- <p>
2842- You can deploy Nevow on any webserver which uses the Common Gateway
2843- Interface. Using this method, your code is responsible for properly
2844- formatting and outputting the HTTP response headers, and Nevow is used
2845- only to generate the HTML body of your page. Here is the simplest
2846- possible CGI:
2847- </p>
2848-
2849- <pre class="python">
2850-#!/usr/bin/env python
2851-
2852-print "Content-type: text/plain\r\n\r\n",
2853-
2854-from nevow import rend, loaders
2855-
2856-class HelloWorld(rend.Page):
2857- docFactory = loaders.stan("Hello, world!")
2858-
2859-print HelloWorld().renderSynchronously()
2860- </pre>
2861-
2862- <p>
2863- With this simple CGI you can use the Nevow template loaders and standard
2864- nevow template interpolation techniques in your CGIs. However, you do not
2865- get any <a href="traversal.xhtml">Object Traversal</a> features, and you
2866- have to generate HTTP headers yourself. WSGI is a slightly higher-level
2867- deployment option which does not suffer these problems.
2868- </p>
2869-
2870- <h2>WSGI</h2>
2871-
2872- <p>
2873- WSGI is a python interface for plugging web applications into various
2874- HTTP server architectures. It is described in <a
2875- href="http://www.python.org/peps/pep-0333.html">PEP 333</a>, the Python
2876- Web Services Gateway Interface Python Enhancement Proposal. Nevow
2877- includes the <code class="API">nevow.wsgi</code> module, which includes a
2878- <code>createWSGIApplication</code> function which takes a Page and
2879- returns a standard WSGI application callable. With the help of the
2880- <code>run_with_cgi</code> example gateway from the PEP (which I will omit
2881- here), our CGI example becomes shorter:
2882- </p>
2883-
2884- <pre class="python">
2885-#!/usr/bin/env python
2886-
2887-from nevow import rend, loaders, wsgi
2888-
2889-class HelloWorld(rend.Page):
2890- docFactory = loaders.stan("Hello, world!")
2891-
2892-run_with_cgi(wsgi.createWSGIApplication(HelloWorld()))
2893- </pre>
2894-
2895- <p>
2896- Of course, you can use any available WSGI gateway to publish your
2897- application object, such as one of the gateways which comes with the <a
2898- href="http://peak.telecommunity.com/">PEAK</a> toolkit. For example, here
2899- is a simple python module which creates a WSGI application which we will
2900- then deploy with PEAK's SimpleHTTPServer gateway::
2901- </p>
2902-
2903- <pre class="python">
2904-## helloworld.py
2905-
2906-from nevow import rend, loaders, wsgi
2907-
2908-class HelloWorld(rend.Page):
2909- docFactory = loaders.stan("Hello, world!")
2910-
2911-application = wsgi.createWSGIApplication(HelloWorld())
2912- </pre>
2913-
2914- <p>
2915- Save this file as "helloworld.py" somewhere on your PYTHONPATH and then
2916- run the following command:
2917- </p>
2918-
2919- <pre>peak launch WSGI import:helloworld.application</pre>
2920-
2921- <p>
2922- This will bring up a SimpleHTTPServer running your Nevow code and launch
2923- a web browser to view the output. (TODO: I couldn't get this working
2924- immediately but I will seek assistance with PEAK and update the
2925- instructions once I do.)
2926- </p>
2927-
2928- <h2>Twisted.Web</h2>
2929-
2930- <p>
2931- A convenient and powerful way to deploy Nevow applications is inside a
2932- process running the twisted.web HTTP server. With Python, Twisted, and
2933- Nevow installed, you have all you need to run a Web Application, with no
2934- other dependencies or external HTTP servers such as Apache
2935- required. Running your Nevow applications under twisted.web also gives
2936- you access to some of the more advanced "Live" features of Nevow, such as
2937- <code>nevow.livepage</code> and <code>nevow.canvas</code>. Currently,
2938- these modules require more control over the HTTP socket than CGI or WSGI
2939- can provide. (This may change in the future.)
2940- </p>
2941-
2942- <p>
2943- Deploying a Nevow application under twisted.web requires a little more
2944- boilerplate, but can be considerably easier to set up than other
2945- deployment options because there are no external dependencies. Note that
2946- normally you should declare your Page classes in modules external to the
2947- twisted configuration file, but everything is included in one file here
2948- for brevity. Here is the minimal configuration file required to use
2949- Nevow with twisted.web:
2950- </p>
2951-
2952- <pre class="python">
2953-from nevow import rend, loaders, appserver
2954-
2955-class HelloWorld(rend.Page):
2956- docFactory = loaders.stan("Hello, world!")
2957-
2958-from twisted.application import service, internet
2959-application = service.Application("hello-world")
2960-internet.TCPServer(8080, appserver.NevowSite(HelloWorld())).setServiceParent(application)
2961- </pre>
2962-
2963- <p>
2964- Save this file as "helloworld.tac" and start the server using the
2965- command:
2966- </p>
2967-
2968- <pre>twistd -noy helloworld.tac</pre>
2969-
2970- <p>
2971- Then visit your twisted.web server by viewing the url
2972- "http://localhost:8080/" in your browser. See the twistd man page for
2973- more information about what twistd is capable of, including daemonizing
2974- the HTTP server.
2975- </p>
2976-
2977- <h2>Zomne</h2>
2978-
2979- <p>
2980- <em>Warning</em> Zomne is experimental. It may blow up your computer and
2981- require your first born son as a sacrifice. Zomne also only works in
2982- UNIX-like environments where unix domain sockets are available, and may
2983- not work on windows.
2984- </p>
2985-
2986- <p>
2987- Zomne, or "Zombie Nevow", is a CGI written in C which can start up a
2988- long-running Application Server process if one is not already running. It
2989- then uses a simple custom protocol to transmit information about the HTTP
2990- request from the CGI process to the application server process.
2991- </p>
2992-
2993- <p>
2994- Zomne combines the ease of deployment of the CGI environment with the
2995- speed and flexibility of the twisted.web long-running application server
2996- process model.
2997- </p>
2998-
2999- <p>
3000- To use Zomne, you must first compile the CGI. cd into the directory
3001- created when unpacking the Nevow tarball, and compile the CGI:
3002- </p>
3003-
3004- <pre>% gcc zomne.c</pre>
3005-
3006- <p>
3007- Move it into your cgi-bin:
3008- </p>
3009-
3010- <pre>% mv a.out /Library/WebServer/CGI-Executables/nevow.cgi</pre>
3011-
3012- <p>
3013- Create a file which tells the cgi where to look for the application:
3014- </p>
3015-
3016- <pre>
3017-% cat &gt; /Library/WebServer/CGI-Executables/.nevow.cgi.dir
3018-/Users/dp/zomne-test
3019-^D</pre>
3020-
3021- <p>
3022- The CGI name can be anything, as long as there is a file with a prepended
3023- "." and a postfixed ".dir" in the same directory which contains the full
3024- path of a zomne application directory. Next, create the application
3025- directory:
3026- </p>
3027-
3028- <pre>mkdir /Users/dp/zomne-test</pre>
3029-
3030- <p>
3031- Finally, create the zomne.tac file which the zomne.cgi will execute to
3032- start the long-running application server process:
3033- </p>
3034-
3035- <pre class="python">
3036-from nevow import rend, loaders, zomnesrv
3037-
3038-class HelloWorld(rend.Page):
3039- docFactory = loaders.stan("Hello, world!")
3040-
3041-from twisted.application import service, internet
3042-application = service.Application('nevow-zomne-test')
3043-internet.UNIXServer('zomne.socket', zomnesrv.ZomneFactory(HelloWorld())).setServiceParent(application)
3044- </pre>
3045-
3046- <p>
3047- Now, visiting the nevow.cgi URL through the web should render the Hello
3048- World page, after a pause while the server is starting up. Subsequent
3049- requests should be very fast, because the application server is already
3050- running, and the CGI merely has to forward the request to it.
3051- </p>
3052-
3053- <p>
3054- Another useful capability of the zomne CGI process is the ability to
3055- control environment variables the CGI will use. Create a directory named
3056- "zomne_environ" in the application directory, and fill it with text files
3057- whose name will be the environment key and whose contents will be the
3058- environment value:
3059- </p>
3060-
3061- <pre>
3062-% cd zomne-test
3063-% mkdir zomne-environ
3064-% cd zomne-environ
3065-% cat &gt; PYTHONPATH
3066-/Users/dp/Projects/Nevow:/Users/dp/Projects/helloworld
3067-^D</pre>
3068-
3069- <h2>Conclusion</h2>
3070-
3071- <p>
3072- Nevow may be deployed in a number of environments, from the most
3073- restrictive to the most permissive. Writing a CGI can be an easy way to
3074- try out the Nevow templating mechanism, but can be slow. A long-running
3075- application server process can be a good way to get good performance as
3076- well as additional features such as in-memory server-side sessions,
3077- advanced automatic form handling with formless, and live page updating
3078- features such as nevow.livepage and nevow.canvas.
3079- </p>
3080-
3081- <p>
3082- Which deployment option you choose will depend on the amount of control
3083- you have over your deployment environment, and what advanced features
3084- your application will require.
3085- </p>
3086- </body>
3087-</html>
3088
3089=== removed file 'Nevow/doc/howto/gettingstarted.xhtml'
3090--- Nevow/doc/howto/gettingstarted.xhtml 2008-08-26 13:45:59 +0000
3091+++ Nevow/doc/howto/gettingstarted.xhtml 1970-01-01 00:00:00 +0000
3092@@ -1,110 +0,0 @@
3093-<?xml version="1.0"?>
3094-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
3095- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3096-
3097-<html xmlns="http://www.w3.org/1999/xhtml">
3098- <head>
3099- <title>
3100- Getting Started
3101- </title>
3102- </head>
3103- <body>
3104- <h1>Getting Started</h1>
3105-
3106- <p>
3107- Warning: This document has only just been started. It's not going to get
3108- you very far right now.
3109- </p>
3110-
3111- <p>
3112- Nevow is a reasonably large library and can be quite daunting at
3113- first. This document's aim is to guide the first time user in building a
3114- Nevow application.
3115- </p>
3116-
3117- <h2>Our First Application</h2>
3118-
3119- <p>
3120- Let's dive straight in, here's the code for our first (very, very simple)
3121- application. Create the following module, helloworld.py:
3122- </p>
3123-
3124- <a href="listings/gettingstarted/helloworld.py" class="py-listing">
3125- helloworld.py
3126- </a>
3127-
3128- <p>
3129- It looks quite simple but let's walk through it anyway.
3130- </p>
3131-
3132- <p>
3133- First, we import two Nevow modules. <code
3134- class="API">nevow.loaders</code> contains template loaders of which the
3135- two most useful are <code class="API" base="nevow.loaders">xmlfile</code>
3136- and <code class="API" base="nevow.loaders">stan</code>.
3137- <code>xmlfile</code> can load any well-formed XML (i.e. XHTML) file;
3138- <code>stan</code> loads a stan tree (more on these later). The other
3139- module, <code class="API">nevow.rend</code>, contains all Nevow's
3140- standard renders, many of which we'll meet in this document.
3141- </p>
3142-
3143- <p>
3144- We then define the <code>HelloWorld</code> class that subclasses <code
3145- class="API" base="nevow">rend.Page</code>, Nevow's main resource
3146- class. <code>HelloWorld</code> has two class
3147- attributes. <code>addSlash</code> tells <code>rend.Page</code> to
3148- redirect to a version of the request URL that ends in a <code>/</code> if
3149- necessary. You generally want to set this to <code>True</code> for the
3150- root resource. <code>docFactory</code> tells the page instance where to
3151- get the template from. In this case we're providing a loader that parses
3152- an HTML file (not shown) from disk.
3153- </p>
3154-
3155- <p>
3156- Hmm, ok I hear you say but how do I see it. Well, Twisted provides a good
3157- web server which we can use. Twisted also includes a clever little
3158- application for starting Twisted applications. Here's the helloworld.tac
3159- file, a Twisted Application Configuration:
3160- </p>
3161-
3162- <a href="listings/gettingstarted/helloworld.tac" class="py-listing">
3163- helloworld.tac
3164- </a>
3165-
3166- <p>
3167- Give it a go, run the following and connect to <a
3168- href="http://localhost:8080/">http://localhost:8080/</a> to see your
3169- application:
3170- </p>
3171-
3172- <pre>twistd -ny helloworld.tac</pre>
3173-
3174- <p>
3175- You'll probably notice that you get log output on the console. This is
3176- just one of the good things that twistd does. It can also daemonize the
3177- application, shed privileges if run as root, etc.
3178- </p>
3179-
3180- <p>
3181- TAC files are covered in more detail in the Twisted documentation but
3182- let's quickly explain what all this does anyway.
3183- </p>
3184-
3185- <p>
3186- When <code class="shell">twistd</code> starts up it loads the
3187- <code>.tac</code> file (it's just Python) and looks for the attribute
3188- called <code>application</code>. When <code class="shell">twistd</code>
3189- is all ready to go it starts the <code>application</code>.
3190- </p>
3191-
3192- <p>
3193- The application is not much use unless it actually does something so the
3194- next thing we do is create a <code class="API"
3195- base="nevow.appserver">NevowSite</code> instance, <code>site</code>, and
3196- pass it a root resource, a <code>HelloWorld</code> instance. Finally, we
3197- create a TCP server that makes the site available on port 8080 and bind
3198- the server to the application to ensure the server is started when the
3199- application is started.
3200- </p>
3201- </body>
3202-</html>
3203
3204=== removed file 'Nevow/doc/howto/glossary.xhtml'
3205--- Nevow/doc/howto/glossary.xhtml 2010-04-06 11:05:45 +0000
3206+++ Nevow/doc/howto/glossary.xhtml 1970-01-01 00:00:00 +0000
3207@@ -1,82 +0,0 @@
3208-<?xml version="1.0"?>
3209-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
3210- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3211-
3212-<html xmlns="http://www.w3.org/1999/xhtml">
3213- <head>
3214- <title>
3215- Glossary
3216- </title>
3217- </head>
3218- <body>
3219- <h1>Glossary</h1>
3220-
3221- <h2>Object Traversal</h2>
3222-
3223- <p>
3224- The process by which a Python object is located to render HTML for a
3225- given HTTP URL. For example, given the URL http://example.com/foo/bar,
3226- Object Traversal will begin at the "Root Resource" object by asking it
3227- for an object which is capable of rendering the page at ('foo',
3228- 'bar'). The "Root Resource" returns an object and a list of unhandled
3229- path segments, and the traversal continues across this new Resource
3230- object until all path segments have been consumed.
3231- </p>
3232-
3233- <h2>Page Rendering</h2>
3234-
3235- <p>
3236- The process by which a Python object, usually a rend.Page subclass, turns
3237- itself into HTML. Page Rendering involves locating some page data,
3238- loading a template document, and applying the template to the data, in
3239- the process generating HTML.
3240- </p>
3241-
3242- <h2>Deployment Environment</h2>
3243-
3244- <p>
3245- The environment in which a Nevow application is deployed. Generally
3246- involves an HTTP server which is configured to route certain (or all)
3247- HTTP requests through the Nevow Object Traversal and Page Rendering
3248- process. Deployment environments include CGI, WSGI, and twisted.web.
3249- </p>
3250-
3251- <h2>DOM</h2>
3252-
3253- <p>
3254- Document Object Model. A tree of objects which represent the structure of
3255- an XHTML document in memory. Nevow uses a nonstandard DOM named "stan",
3256- which is made up of simple Python lists, dicts, strings, and
3257- nevow.stan.Tag instances.
3258- </p>
3259-
3260- <h2>Flattener</h2>
3261-
3262- <p>
3263- A Python function which knows how to translate from a rich type to a
3264- string containing HTML. For example, the integer flattener calls str() on
3265- the integer. The string flattener escapes characters which are unsafe in
3266- HTML, such as &lt;, &gt;, and &amp;.
3267- </p>
3268-
3269- <h2>Tag</h2>
3270-
3271- <p>
3272- A class, defined at nevow.stan.Tag, which holds information about a
3273- single HTML tag in a DOM. Tag instances have three attributes: tagName,
3274- attributes, and children. tagName is a string indicating the tag
3275- name. attributes is a dict indicating the HTML attributes of that
3276- node. children is a list indicating the child nodes of that node.
3277- </p>
3278-
3279- <h2>Tag Specials</h2>
3280-
3281- <p>
3282- A Tag attribute which is "special" to nevow. Tag specials include data,
3283- render, pattern, slot, and macro. Tag Specials will never be output as
3284- HTML attributes of tags, but will be used by the internal Nevow rendering
3285- process to influence how the Tag is rendered.
3286- </p>
3287-
3288- </body>
3289-</html>
3290
3291=== removed file 'Nevow/doc/howto/index.xhtml'
3292--- Nevow/doc/howto/index.xhtml 2008-09-20 01:06:47 +0000
3293+++ Nevow/doc/howto/index.xhtml 1970-01-01 00:00:00 +0000
3294@@ -1,49 +0,0 @@
3295-<?xml version="1.0"?>
3296-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
3297- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3298-
3299-<html xmlns="http://www.w3.org/1999/xhtml">
3300- <head>
3301- <title>
3302- Manual
3303- </title>
3304- </head>
3305- <body>
3306- <h1>
3307- Manual
3308- </h1>
3309- <ul class="toc">
3310- <li>
3311- <a href="intro.xhtml">Introduction</a>
3312- </li>
3313- <li>
3314- <a href="gettingstarted.xhtml">Getting Started</a>
3315- <p>A basic introduction to rendering a web page in Nevow.</p>
3316- </li>
3317- <li>
3318- <a href="traversal.xhtml">Object Traversal</a>
3319- <p>Getting from an URL to a Python page object you want to render.</p>
3320- </li>
3321- <li>
3322- <a href="publishing.xhtml">Object Publishing</a>
3323- <p>Exposing Python objects as parts of a web page in Nevow.</p>
3324- </li>
3325- <li>
3326- <a href="xmltemplates.xhtml">XML Templates</a>
3327- <p>Using standard XHTML as a template for Nevow.</p>
3328- </li>
3329- <li>
3330- <a href="deployment.xhtml">Deployment</a>
3331- <p>How to get your Nevow application running on different types of
3332- servers.</p>
3333- </li>
3334- <li>
3335- <a href="chattutorial/index.xhtml">Nevow Athena</a>
3336- <p>Two-way communication with JavaScript in a web browser.</p>
3337- </li>
3338- <li>
3339- <a href="glossary.xhtml">Glossary</a>
3340- </li>
3341- </ul>
3342- </body>
3343-</html>
3344
3345=== removed file 'Nevow/doc/howto/intro.xhtml'
3346--- Nevow/doc/howto/intro.xhtml 2008-08-26 13:45:59 +0000
3347+++ Nevow/doc/howto/intro.xhtml 1970-01-01 00:00:00 +0000
3348@@ -1,294 +0,0 @@
3349-<?xml version="1.0"?>
3350-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
3351- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3352-
3353-<html xmlns="http://www.w3.org/1999/xhtml">
3354- <head>
3355- <title>
3356- A Web Application Construction Kit
3357- </title>
3358- </head>
3359- <body>
3360- <h1>A Web Application Construction Kit</h1>
3361-
3362- <h2>Summary</h2>
3363-
3364- <p>
3365- Nevow is a next-generation web application templating system, based on
3366- the ideas developed in the Twisted Woven package. Its main focus is on
3367- separating the HTML template from both the business logic and the display
3368- logic, while allowing the programmer to write pure Python code as much as
3369- possible. It separates your code into 'data' and 'render' functions, a
3370- simplified implementation of traditional MVC. It has various parts which
3371- can be used individually or as a whole, integrated web solution:
3372- </p>
3373-
3374- <ul>
3375- <li>
3376- XHTML templates: contain no programming logic, only nodes tagged with
3377- nevow attributes
3378- </li>
3379- <li>
3380- data/render methods: simplified MVC
3381- </li>
3382- <li>
3383- stan: An s-expression-like syntax for expressing xml in pure python
3384- </li>
3385- <li>
3386- formless: For describing the types of objects which may be passed to
3387- methods of your classes, validating and coercing string input from
3388- either web or command-line sources, and calling your methods
3389- automatically once validation passes
3390- </li>
3391- <li>
3392- formless.webform: For rendering web forms based on formless type
3393- descriptions, accepting form posts and passing them to formless
3394- validators, and rendering error forms in the event validation fails
3395- </li>
3396- <li>
3397- livepage: Cross-browser JavaScript glue for sending client side events
3398- to the server and server side events to the client after the page has
3399- loaded, without causing the entire page to refresh
3400- </li>
3401- </ul>
3402-
3403- <h2>Disk based templates</h2>
3404-
3405- <p>
3406- Nevow includes the ability to load templates off disk. These templates
3407- may have processing directives which cause the execution of python
3408- methods at render time. The attribute technique was inspired by the
3409- attributes used by ZPT. However, no actual code may be embedded in the
3410- HTML template:
3411- </p>
3412-
3413- <pre>
3414-&lt;html xmlns:nevow="http://nevow.com/ns/nevow/0.1"&gt;
3415- &lt;head&gt;
3416- &lt;title&gt;Greetings!&lt;/title&gt;
3417- &lt;/head&gt;
3418- &lt;body&gt;
3419- &lt;h1 style="font-size: large"&gt;Now I will greet you:&lt;/h1&gt;
3420- &lt;span nevow:render="greet" /&gt;
3421- &lt;/body&gt;
3422-&lt;/html&gt;</pre>
3423-
3424- <p>
3425- This template can then be loaded and rendered like so:
3426- </p>
3427-
3428- <pre class="python">
3429-class Greeter(rend.Page):
3430- docFactory = loaders.xmlfile("Greeting.html")
3431-
3432- def render_greet(self, context, data):
3433- return random.choice(["Hello", "Greetings", "Hi"]), " ", data
3434-
3435-Greeter("My name is").renderString()
3436- </pre>
3437-
3438- <h2>data/render methods</h2>
3439-
3440- <p>
3441- To allow clean isolation between code which fetches data from a data
3442- source and code which renders the data into HTML, nevow allows you to
3443- write both 'data' methods and 'render' methods. These concepts are
3444- inspired by MVC, but simpler, since the framework can handle most of the
3445- controller aspect. An example:
3446- </p>
3447-
3448- <pre>
3449-&lt;html xmlns:nevow="http://nevow.com/ns/nevow/0.1"&gt;
3450- &lt;body&gt;
3451- &lt;span nevow:data="name" nevow:render="colorful" /&gt;
3452- &lt;span nevow:data="fun" nevow:render="colorful" /&gt;
3453- &lt;/body&gt;
3454-&lt;/html&gt;</pre>
3455-
3456- <p>
3457- This template can be loaded and rendered using a class such as this:
3458- </p>
3459-
3460- <pre class="python">
3461-class Colorful(rend.Page):
3462- docFactory = loaders.xmlfile("Colorful.html")
3463-
3464- def render_colorful(self, context, data):
3465- color = random.choice(['red', 'green', 'blue'])
3466- return context.tag(style="color: %s" % color)
3467-
3468- def data_name(self, context, data):
3469- return "Your name here"
3470-
3471- def data_fun(self, context, data):
3472- return "Are we having fun yet?"
3473- </pre>
3474-
3475- <h2>Stan</h2>
3476-
3477- <p>
3478- One of the most powerful things about nevow is stan, an s-expression-like
3479- syntax for producing XML fragments in pure Python syntax. Stan is not
3480- required for using nevow, but it is both a simple and powerful way to
3481- both lay out one's XHTML templates and express one's display logic. A
3482- brief example will illustrate its utility:
3483- </p>
3484-
3485- <pre class="python">
3486-import random
3487-from nevow import rend, tags
3488-
3489-class Greeter(rend.Page):
3490- def greet(self, context, data):
3491- return random.choice(["Hello", "Greetings", "Hi"]), " ", data
3492-
3493- docFactory = loaders.stan(
3494- tags.html[
3495- tags.head[ tags.title[ "Greetings!" ]],
3496- tags.body[
3497- tags.h1(style="font-size: large")[ "Now I will greet you:" ],
3498- greet
3499- ]
3500- ])
3501- </pre>
3502-
3503- <p>
3504- When the Greeter class is constructed, it is passed a Python object which
3505- will be used as that page's data:
3506- </p>
3507-
3508- <pre class="python">
3509-Greeter("Your name here").renderString()
3510- </pre>
3511-
3512- <h2>Formless</h2>
3513-
3514- <p>
3515- Python is dynamically typed, which means it has no built-in controls for
3516- enforcing the types of objects which are passed to one's methods. This is
3517- great for programmers, but not necessarily great if you are going to be
3518- passing user-entered input to those methods. Formless is a simple way to
3519- describe the types of objects that can be passed to one's methods, as
3520- well as coerce from string input to those types. Other code can then
3521- accept user input from a command line or from a web form, validate the
3522- input against the types described using formless, and call the method
3523- once validation has passed. A simple example:
3524- </p>
3525-
3526- <pre class="python">
3527-from zope.interface import implements
3528-from formless.annotate import TypedInterface, Integer, String
3529-
3530-class ISimpleMethod(TypedInterface):
3531- def simple(self,
3532- name=String(description="Your name."),
3533- age=Integer(description="Your age.")):
3534- """
3535- Simple
3536-
3537- Please enter your name and age.
3538- """
3539-
3540-class Implementation(object):
3541- implements(ISimpleMethod)
3542-
3543- def simple(self, name, age):
3544- print "Hello, %s, who is %s" % (name, age)
3545- </pre>
3546-
3547- <h2>Webform</h2>
3548-
3549- <p>
3550- Webform is a nevow module which will automatically render web forms and
3551- accept form posts based on types described using the classes in
3552- formless. Used in conjunction with the twisted.web HTTP server, the
3553- process is almost automatic:
3554- </p>
3555-
3556- <pre class="python">
3557-from nevow import rend, tags
3558-from formless import webform
3559-
3560-class WebForm(rend.Page):
3561- document = rend.stan(
3562- tags.html[
3563- tags.body[
3564- h1["Here is the form:"],
3565- webform.renderForms('original')
3566- ]
3567-])
3568-
3569-resource = WebForm(Implementation())
3570- </pre>
3571-
3572- <p>
3573- Exposing this resource instance to the web using twisted.web and visiting
3574- it will cause a form with two input boxes to be rendered. Posting the
3575- form will cause form validation to occur. Upon error, the user will be
3576- returned to the original page, with the form annotated with error
3577- messages. Upon success, the "simple" method of the Implementation
3578- instance will be called and passed a string and an integer.
3579- </p>
3580-
3581- <h2>LivePage</h2>
3582-
3583- <p>
3584- LivePage was a Woven technology which allowed programmers to receive
3585- server-side notification of client-side JavaScript events, and to send
3586- JavaScript to the client in response to a server-side event. New for
3587- Nevow 0.3, LivePage has been updated to support Mozilla, Firefox, IE6
3588- Win, and Safari. Using LivePage is very easy:
3589- </p>
3590-
3591- <pre class="python">
3592-from nevow.liveevil import handler
3593-
3594-def greeter(client, nodeName):
3595- client.alert("Greetings. You clicked the %s node." % nodeName)
3596-
3597-# Any string arguments after the event handler function will be evaluated
3598-# as JavaScript in the context of the web browser and results passed to the
3599-# Python event handler
3600-handler = handler(greeter, 'node.name')
3601-
3602-class Live(rend.Page):
3603- docFactory = loaders.stan(
3604- tags.html[
3605- tags.body[
3606- ol[
3607- li(onclick=handler, name="one")["One"]
3608- li(onclick=handler, name="two")["Two"]
3609- li(onclick=handler, name="three")["Three"]
3610- ]
3611- ]
3612- ])
3613- </pre>
3614-
3615- <h2>More Information</h2>
3616-
3617- <p>
3618- The <a href="http://divmod.org/trac/wiki/DivmodNevow">Nevow website</a>
3619- has more information. Starting with 0.3, it contains a simple WSGI
3620- implementation and can also be used to render CGIs. However, the
3621- recommended mode of operation is using the <a
3622- href="http://twistedmatrix.com/trac/wiki/TwistedWeb">Twisted web</a>
3623- server. Nevow is an active project, and many new bugfixes and features
3624- are committed to the Nevow SVN repository. Information about Nevow
3625- commits is available by subscribing to the <a
3626- href="http://divmod.net/users/mailman.twistd/listinfo/divmod-commits">
3627- Divmod commits</a> mailing list. The Nevow SVN repository can be checked
3628- out using:
3629- </p>
3630-
3631- <pre>svn co svn://divmod.org/svn/Nevow/trunk Nevow</pre>
3632-
3633- <p>
3634- Discussion of Nevow occurs on the <a
3635- href="http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-web">
3636- twisted.web mailing list</a>. The Nevow developers are also often
3637- available for real-time help on the <a
3638- href="irc://irc.freenode.net/#twisted.web">#twisted.web channel</a> on
3639- irc.freenode.net.
3640- </p>
3641- </body>
3642-</html>
3643
3644=== removed directory 'Nevow/doc/howto/listings'
3645=== removed directory 'Nevow/doc/howto/listings/gettingstarted'
3646=== removed file 'Nevow/doc/howto/listings/gettingstarted/helloworld.py'
3647--- Nevow/doc/howto/listings/gettingstarted/helloworld.py 2008-08-26 13:45:59 +0000
3648+++ Nevow/doc/howto/listings/gettingstarted/helloworld.py 1970-01-01 00:00:00 +0000
3649@@ -1,6 +0,0 @@
3650-from nevow import loaders, rend
3651-
3652-class HelloWorld(rend.Page):
3653- addSlash = True
3654- docFactory = loaders.xmlfile('helloworld.html')
3655-
3656
3657=== removed file 'Nevow/doc/howto/listings/gettingstarted/helloworld.tac'
3658--- Nevow/doc/howto/listings/gettingstarted/helloworld.tac 2008-08-26 13:45:59 +0000
3659+++ Nevow/doc/howto/listings/gettingstarted/helloworld.tac 1970-01-01 00:00:00 +0000
3660@@ -1,10 +0,0 @@
3661-from twisted.application import internet
3662-from twisted.application import service
3663-from nevow import appserver
3664-import helloworld
3665-
3666-application = service.Application('helloworld')
3667-site = appserver.NevowSite(helloworld.HelloWorld())
3668-webServer = internet.TCPServer(8080, site)
3669-webServer.setServiceParent(application)
3670-
3671
3672=== removed file 'Nevow/doc/howto/publishing.xhtml'
3673--- Nevow/doc/howto/publishing.xhtml 2008-08-26 13:45:59 +0000
3674+++ Nevow/doc/howto/publishing.xhtml 1970-01-01 00:00:00 +0000
3675@@ -1,658 +0,0 @@
3676-<?xml version="1.0"?>
3677-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
3678- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3679-
3680-<html xmlns="http://www.w3.org/1999/xhtml">
3681- <head>
3682- <title>
3683- Object Publishing
3684- </title>
3685- </head>
3686- <body>
3687- <h1>
3688- Object Publishing
3689- </h1>
3690-
3691- <p>
3692- In <a href="traversal.xhtml">Object Traversal</a>, we learned about the
3693- <code class="API">nevow.inevow.IResource.renderHTTP</code> method, which
3694- is the most basic way to send HTML to a browser when using
3695- Nevow. However, it is not very convenient (or clean) to generate HTML
3696- tags by concatenating strings in Python code. In the <a
3697- href="deployment.xhtml">Deployment</a> documentation, we saw that it was
3698- possible to render a <em>Hello World</em> page using a <code class="API">
3699- nevow.rend.Page</code> subclass and providing a <code>docFactory</code>:
3700- </p>
3701-
3702- <pre class="python-interpreter">
3703-&gt;&gt;&gt; from nevow import rend, loaders
3704-&gt;&gt;&gt; class HelloWorld(rend.Page):
3705-... docFactory = loaders.stan("Hello, world!")
3706-...
3707-&gt;&gt;&gt; HelloWorld().renderSynchronously()
3708-'Hello, world!'</pre>
3709-
3710- <p>
3711- This example does nothing interesting, but the concept of a loader is
3712- important in Nevow. The <code>rend.Page.renderHTTP</code> implementation
3713- always starts rendering HTML by loading a template from the
3714- <code>docFactory</code>.
3715- </p>
3716-
3717-
3718- <h2>The stan DOM</h2>
3719-
3720- <p>
3721- Nevow uses a DOM-based approach to rendering HTML. A tree of objects is
3722- first constructed in memory by the template loader. This tree is then
3723- processed one node at a time, applying functions which transform from
3724- various Python types to HTML strings.
3725- </p>
3726-
3727- <p>
3728- Nevow uses a nonstandard DOM named "stan". Unlike the W3C DOM, stan is
3729- made up of simple python lists, strings, and instances of the
3730- nevow.stan.Tag class. During the rendering process, "Flattener"
3731- functions convert from rich types to HTML strings. For example, we can
3732- load a template made up of some nested lists and Python types, render it,
3733- and see what happens:
3734- </p>
3735-
3736- <pre class="python-interpreter">
3737-&gt;&gt;&gt; class PythonTypes(rend.Page):
3738-... docFactory = loaders.stan(["Hello", 1, 1.5, True, ["Goodbye", 3]])
3739-...
3740-&gt;&gt;&gt; PythonTypes().renderSynchronously()
3741-'Hello11.5TrueGoodbye3'</pre>
3742-
3743- <h2>Tag instances</h2>
3744-
3745- <p>
3746- So far, we have only rendered simple strings as output. However, the main
3747- purpose of Nevow is HTML generation. In the stan DOM, HTML tags are
3748- represented by instances of the <code class="API">nevow.stan.Tag</code>
3749- class. <code>Tag</code> is a very simple class, whose instances have an
3750- <code>attributes</code> dictionary and a <code>children</code> list. The
3751- <code>Tag</code> flattener knows how to recursively flatten attributes
3752- and children of the tag. To show you how <code>Tag</code>s really work
3753- before you layer Nevow's convenience syntax on top, try this horrible
3754- example:
3755- </p>
3756-
3757- <pre class="python-interpreter">
3758-&gt;&gt;&gt; from nevow import stan
3759-&gt;&gt;&gt; h = stan.Tag('html')
3760-&gt;&gt;&gt; d = stan.Tag('div')
3761-&gt;&gt;&gt; d.attributes['style'] = 'border: 1px solid black'
3762-&gt;&gt;&gt; h.children.append(d)
3763-&gt;&gt;&gt; class Tags(rend.Page):
3764-... docFactory = loaders.stan(h)
3765-...
3766-&gt;&gt;&gt; Tags().renderSynchronously()
3767-'&lt;html&gt;&lt;div style="border: 1px solid black"&gt;&lt;/div&gt;&lt;/html&gt;'</pre>
3768-
3769- <p>
3770- So, we see how it is possible to programatically generate HTML by
3771- constructing and nesting stan <code>Tag</code> instances. However, it is
3772- far more convenient to use the overloaded operators <code>Tag</code>
3773- provides to manipulate them. <code>Tag</code> implements a
3774- <code>__call__</code> method which takes any keyword arguments and values
3775- and updates the attributes dictionary; it also implements a
3776- <code>__getitem__</code> method which takes whatever is between the square
3777- brackets and appends them to the children list. A simple example should
3778- clarify things:
3779- </p>
3780-
3781- <pre class="python-interpreter">
3782-&gt;&gt;&gt; class Tags2(rend.Page):
3783-... docFactory = loaders.stan(stan.Tag('html')[stan.Tag('div')(style="border: 1px solid black")])
3784-...
3785-&gt;&gt;&gt; Tags2().renderSynchronously()
3786-'&lt;html&gt;&lt;div style="border: 1px solid black"&gt;&lt;/div&gt;&lt;/html&gt;'</pre>
3787-
3788- <p>
3789- This isn't very easy to read, but luckily we can simplify the example
3790- even further by using the nevow.tags module, which is full of "Tag
3791- prototypes" for every tag type described by the XHTML 1.0 specification:
3792- </p>
3793-
3794- <pre class="python-interpreter">
3795-&gt;&gt;&gt; class Tags3(rend.Page):
3796-... docFactory = loaders.stan(tags.html[tags.div(style="border: 1px solid black")])
3797-...
3798-&gt;&gt;&gt; Tags3().renderSynchronously()
3799-'&lt;html&gt;&lt;div style="border: 1px solid black"&gt;&lt;/div&gt;&lt;/html&gt;'</pre>
3800-
3801- <p>
3802- Using stan syntax is not the only way to construct template DOM for use
3803- by the Nevow rendering process. Nevow also includes <code class="API"
3804- base="nevow">loaders.xmlfile</code> which implements a simple tag
3805- attribute language similar to the Zope Page Templates (ZPT) Tag Attribute
3806- Language (TAL). However, experience with the stan DOM should give you
3807- insight into how the Nevow rendering process really works. Rendering a
3808- template into HTML in Nevow is really nothing more than iterating a tree
3809- of objects and recursively applying "Flattener" functions to objects in
3810- this tree, until all HTML has been generated.
3811- </p>
3812-
3813- <h2>Functions in the DOM</h2>
3814-
3815- <p>
3816- So far, all of our examples have generated static HTML pages, which is
3817- not terribly interesting when discussing dynamic web applications. Nevow
3818- takes a very simple approach to dynamic HTML generation. If you put a
3819- Python function reference in the DOM, Nevow will call it when the page is
3820- rendered. The return value of the function replaces the function itself
3821- in the DOM, and the results are flattened further. This makes it easy to
3822- express looping and branching structures in Nevow, because normal Python
3823- looping and branching constructs are used to do the job:
3824- </p>
3825-
3826- <pre class="python-interpreter">
3827-&gt;&gt;&gt; def repeat(ctx, data):
3828-... return [tags.div(style="color: %s" % (color, ))
3829-... for color in ['red', 'blue', 'green']]
3830-...
3831-&gt;&gt;&gt; class Repeat(rend.Page):
3832-... docFactory = loaders.stan(tags.html[repeat])
3833-...
3834-&gt;&gt;&gt; Repeat().renderSynchronously()
3835-'&lt;html&gt;&lt;div style="color: red"&gt;&lt;/div&gt;&lt;div style="color: blue"&gt;&lt;/div&gt;&lt;div style="color: green"&gt;&lt;/div&gt;&lt;/html&gt;'</pre>
3836-
3837- <p>
3838- However, in the example above, the repeat function isn't even necessary,
3839- because we could have inlined the list comprehension right where we
3840- placed the function reference in the DOM. Things only really become
3841- interesting when we begin writing parameterized render functions which
3842- cause templates to render differently depending on the input to the web
3843- application.
3844- </p>
3845-
3846- <p>
3847- The required signature of functions which we can place in the DOM is
3848- (ctx, data). The "context" object is essentially opaque for now, and we
3849- will learn how to extract useful information out of it later. The "data"
3850- object is anything we want it to be, and can change during the rendering
3851- of the page. By default, the data object is whatever we pass as the first
3852- argument to the Page constructor, <em>or</em> the Page instance itself if
3853- nothing is passed. Armed with this knowledge, we can create a Page which
3854- renders differently depending on the data we pass to the Page
3855- constructor:
3856- </p>
3857-
3858- <pre class="python">
3859-class Root(rend.Page):
3860- docFactory = loaders.stan(tags.html[
3861- tags.h1["Welcome."],
3862- tags.a(href="foo")["Foo"],
3863- tags.a(href="bar")["Bar"],
3864- tags.a(href="baz")["Baz"]])
3865-
3866- def childFactory(self, ctx, name):
3867- return Leaf(name)
3868-
3869-def greet(ctx, name):
3870- return "Hello. You are visiting the ", name, " page."
3871-
3872-class Leaf(rend.Page):
3873- docFactory = loaders.stan(tags.html[greet])
3874- </pre>
3875-
3876- <p>
3877- Armed with this knowledge and the information in the <a
3878- href="traversal.xhtml">Object Traversal</a> documentation, we now have
3879- enough information to create dynamic websites with arbitrary URL
3880- hierarchies whose pages render dynamically depending on which URL was
3881- used to access them.
3882- </p>
3883-
3884- <h2>Accessing query parameters and form post data</h2>
3885-
3886- <p>
3887- Before we move on to more advanced rendering techniques, let us first
3888- examine how one could further customize the rendering of a Page based on
3889- the URL query parameters and form post information provided to us by a
3890- browser. Recall that URL parameters are expressed in the form:
3891- </p>
3892-
3893- <pre>http://example.com/foo/bar?baz=1&amp;quux=2</pre>
3894-
3895- <p>
3896- And form post data can be generated by providing a form to a browser:
3897- </p>
3898-
3899- <pre>
3900-&lt;form action="" method="POST"&gt;
3901- &lt;input type="text" name="baz" /&gt;
3902- &lt;input type="text" name="quux" /&gt;
3903- &lt;input type="submit" /&gt;
3904-&lt;/form&gt;</pre>
3905-
3906- <p>
3907- Accessing this information is such a common procedure that Nevow provides
3908- a convenience method on the context to do it. Let's examine a simple page
3909- whose output can be influenced by the query parameters in the URL used to
3910- access it:
3911- </p>
3912-
3913- <pre class="python">
3914-def showChoice(ctx, data):
3915- choice = ctx.arg('choice')
3916- if choice is None:
3917- return ''
3918- return "You chose ", choice, "."
3919-
3920-class Custom(rend.Page):
3921- docFactory = loaders.stan(tags.html[
3922- tags.a(href="?choice=baz")["Baz"],
3923- tags.a(href="?choice=quux")["Quux"],
3924- tags.p[showChoice]])
3925- </pre>
3926-
3927- <p>
3928- The procedure is exactly the same for simple form post information:
3929- </p>
3930-
3931- <pre class="python">
3932-def greet(ctx, data):
3933- name = ctx.arg('name')
3934- if name is None:
3935- return ''
3936- return "Greetings, ", name, "!"
3937-
3938-class Form(rend.Page):
3939- docFactory = loaders.stan(tags.html[
3940- tags.form(action="", method="POST")[
3941- tags.input(name="name"),
3942- tags.input(type="submit")],
3943- greet])
3944-</pre>
3945-
3946- <p>
3947- Note that <code>ctx.arg</code> returns only the first argument with the
3948- given name. For complex cases where multiple arguments and lists of
3949- argument values are required, you can access the request argument
3950- dictionary directly using the syntax:
3951- </p>
3952-
3953- <pre class="python">
3954-def arguments(ctx, data):
3955- args = inevow.IRequest(ctx).args
3956- return "Request arguments are: ", str(args)
3957- </pre>
3958-
3959- <h2>Generators in the DOM</h2>
3960-
3961- <p>
3962- One common operation when building dynamic pages is iterating a list of
3963- data and emitting some HTML for each item. Python generators are well
3964- suited for expressing this sort of logic, and code which is written as a
3965- python generator can perform tests (<code>if</code>) and loops of various
3966- kinds (<code>while</code>, <code>for</code>) and emit a row of html
3967- whenever it has enough data to do so. Nevow can handle generators in the
3968- DOM just as gracefully as it can handle anything else:
3969- </p>
3970-
3971- <pre class="python-interpreter">
3972-&gt;&gt;&gt; from nevow import rend, loaders, tags
3973-&gt;&gt;&gt; def generate(ctx, items):
3974-... for item in items:
3975-... yield tags.div[ item ]
3976-...
3977-&gt;&gt;&gt; class List(rend.Page):
3978-... docFactory = loaders.stan(tags.html[ generate ])
3979-...
3980-&gt;&gt;&gt; List(['one', 'two', 'three']).renderSynchronously()
3981-'&lt;html&gt;&lt;div&gt;one&lt;/div&gt;&lt;div&gt;two&lt;/div&gt;&lt;div&gt;three&lt;/div&gt;&lt;/html&gt;'</pre>
3982-
3983- <p>
3984- As you can see, generating HTML inside of functions or generators can be
3985- very convenient, and can lead to very rapid application
3986- development. However, it is also what I would call a "template
3987- abstraction violation", and we will learn how we can keep knowledge of
3988- HTML out of our python code when we learn about patterns and slots.
3989- </p>
3990-
3991- <h2>Methods in the DOM</h2>
3992-
3993- <p>
3994- Up until now, we have been placing our template manipulation logic inside
3995- of simple Python functions and generators. However, it is often
3996- appropriate to use a method instead of a function. Nevow makes it just as
3997- easy to use a method to render HTML:
3998- </p>
3999-
4000- <pre class="python">
4001-class MethodRender(rend.Page):
4002- def __init__(self, foo):
4003- self.foo = foo
4004-
4005- def render_foo(self, ctx, data):
4006- return self.foo
4007-
4008- docFactory = loaders.stan(tags.html[ render_foo ])
4009- </pre>
4010-
4011- <p>
4012- Using render methods makes it possible to parameterize your Page class
4013- with more parameters. With render methods, you can also use the Page
4014- instance as a state machine to keep track of the state of the
4015- render. While Nevow is designed to allow you to render the same Page
4016- instance repeatedly, it can also be convenient to know that a Page
4017- instance will only be used one time, and that the Page instance can be
4018- used as a scratch pad to manage information about the render.
4019- </p>
4020-
4021- <h2>Data specials</h2>
4022-
4023- <p>
4024- Previously we saw how passing a parameter to the default Page constructor
4025- makes it available as the "data" parameter to all of our render
4026- methods. This "data" parameter can change as the page render proceeds,
4027- and is a useful way to ensure that render functions are isolated and only
4028- act upon the data which is available to them. Render functions which do
4029- not pull information from sources other than the "data" parameter are
4030- more easily reusable and can be composed into larger parts more easily.
4031- </p>
4032-
4033- <p>
4034- Deciding which data gets passed as the data parameter is as simple as
4035- changing the "Data special" for a Tag. See the <a
4036- href="glossary.xhtml">Glossary</a> under "Tag Specials" for more
4037- information about specials. Assigning to the data special is as simple as
4038- assigning to a tag attribute:
4039- </p>
4040-
4041- <pre class="python-interpreter">
4042-&gt;&gt;&gt; def hello(ctx, name):
4043-... return "Hello, ", name
4044-...
4045-&gt;&gt;&gt; class DataSpecial(rend.Page):
4046-... docFactory = loaders.stan(tags.html[
4047-... tags.div(data="foo")[ hello ],
4048-... tags.div(data="bar")[ hello ]])
4049-...
4050-&gt;&gt;&gt; DataSpecial().renderSynchronously()
4051-'&lt;html&gt;&lt;div&gt;Hello, foo&lt;/div&gt;&lt;div&gt;Hello, bar&lt;/div&gt;&lt;/html&gt;'</pre>
4052-
4053- <p>
4054- Data specials may be assigned any python value. Data specials are only in
4055- scope during the rendering of the tag they are assigned to, so if the
4056- "hello" renderer were placed in the DOM inside the html node directly,
4057- "Hello, None" would be output.
4058- </p>
4059-
4060- <p>
4061- Before data is passed to a render function, Nevow first checks to see if
4062- there is an <code class="API">IGettable</code> adapter for it. If there
4063- is, it calls <code>IGettable.get()</code>, and passes the result of this
4064- as the data parameter instead. Nevow includes an <code>IGettable</code>
4065- adapter for python functions, which means you can set a Tag data special
4066- to a function reference and Nevow will call it to obtain the data when
4067- the Tag is rendered. The signature for data methods is similar to that of
4068- render methods, (ctx, data). For example:
4069- </p>
4070-
4071- <pre class="python">
4072-def getName(ctx, data):
4073- return ctx.arg('name')
4074-
4075-def greet(ctx, name):
4076- return "Greetings, ", name
4077-
4078-class GreetName(rend.Page):
4079- docFactory = loaders.stan(tags.html[
4080- tags.form(action="")[
4081- tags.input(name="name"),
4082- tags.input(type="submit")],
4083- tags.div(data=getName)[ greet ]])
4084- </pre>
4085-
4086- <p>
4087- Data specials exist mainly to allow you to construct and enforce a
4088- Model-View-Controller style separation of the Model code from the
4089- View. Here we see that the greet function is capable of rendering a
4090- greeting view for a name model, and that the implementation of getName
4091- may change without the view code changing.
4092- </p>
4093-
4094- <h2>Render specials</h2>
4095-
4096- <p>
4097- Previously, we have seen how render functions can be placed directly in
4098- the DOM, and the return value replaces the render function in the
4099- DOM. However, these free functions and methods are devoid of any
4100- contextual information about the template they are living in. The
4101- render special is a way to associate a render function or method with a
4102- particular Tag instance, which the render function can then examine to
4103- decide how to render:
4104- </p>
4105-
4106- <pre class="python-interpreter">
4107-&gt;&gt;&gt; def alignment(ctx, data):
4108-... align = ctx.tag.attributes.get('align')
4109-... if align == 'right':
4110-... return ctx.tag["Aligned right"]
4111-... elif align == 'center':
4112-... return ctx.tag["Aligned center"]
4113-... else:
4114-... return ctx.tag["Aligned left"]
4115-...
4116-&gt;&gt;&gt; class AlignmentPage(rend.Page):
4117-... docFactory = loaders.stan(tags.html[
4118-... tags.p(render=alignment),
4119-... tags.p(render=alignment, align="center"),
4120-... tags.p(render=alignment, align="right")])
4121-...
4122-&gt;&gt;&gt; AlignmentPage().renderSynchronously()
4123-'&lt;html&gt;&lt;p&gt;Aligned left&lt;/p&gt;&lt;p align="center"&gt;Aligned center&lt;/p&gt;&lt;p align="right"&gt;Aligned right&lt;/p&gt;&lt;/html&gt;'</pre>
4124-
4125- <p>
4126- Note how the alignment renderer has access to the template node as
4127- <code>ctx.tag</code>. It can examine and change this node, and the return value of
4128- the render function replaces the original node in the DOM. Note that
4129- here we are returning the template node after changing it. We will see
4130- later how we can instead mutate the context and use slots so that the
4131- knowledge the renderer requires about the structure of the template is
4132- reduced even more.
4133- </p>
4134-
4135- <h2>Pattern specials</h2>
4136-
4137- <p>
4138- When writing render methods, it is easy to inline the construction of
4139- Tag instances to generate HTML programatically. However, this creates a
4140- template abstraction violation, where part of the HTML which will show
4141- up in the final page output is hidden away inside of render methods
4142- instead of inside the template. Pattern specials are designed to avoid
4143- this problem. A node which has been tagged with a pattern special can
4144- then be located and copied by a render method. The render method does
4145- not need to know anything about the structure or location of the
4146- pattern, only it's name.
4147- </p>
4148-
4149- <p>
4150- We can rewrite our previous generator example so that the generator
4151- does not have to know what type of tag the template designer would like
4152- repeated for each item in the list:
4153- </p>
4154-
4155- <pre class="python-interpreter">
4156-&gt;&gt;&gt; from nevow import rend, loaders, tags, inevow
4157-&gt;&gt;&gt; def generate(ctx, items):
4158-... pat = inevow.IQ(ctx).patternGenerator('item')
4159-... for item in items:
4160-... ctx.tag[ pat(data=item) ]
4161-... return ctx.tag
4162-...
4163-&gt;&gt;&gt; def string(ctx, item):
4164-... return ctx.tag[ str(item) ]
4165-...
4166-&gt;&gt;&gt; class List(rend.Page):
4167-... docFactory = loaders.stan(tags.html[
4168-... tags.ul(render=generate)[
4169-... tags.li(pattern="item", render=string)]])
4170-...
4171-&gt;&gt;&gt; List([1, 2, 3]).renderSynchronously()
4172-'&lt;html&gt;&lt;ol&gt;&lt;li&gt;1&lt;/li&gt;&lt;li&gt;2&lt;/li&gt;&lt;li&gt;3&lt;/li&gt;&lt;/ol&gt;&lt;/html&gt;'</pre>
4173-
4174- <p>
4175- Note that we have to mutate the tag in place and repeatedly copy the
4176- item pattern, applying the item as the data special to the resulting
4177- Tag. It turns out that this is such a common operation that nevow comes
4178- out of the box with these two render functions:
4179- </p>
4180-
4181- <pre class="python-interpreter">
4182-&gt;&gt;&gt; class List(rend.Page):
4183-... docFactory = loaders.stan(tags.html[
4184-... tags.ul(render=rend.sequence)[
4185-... tags.li(pattern="item", render=rend.data)]])
4186-...
4187-&gt;&gt;&gt; List([1, 2, 3]).renderSynchronously()
4188-'&lt;html&gt;&lt;ul&gt;&lt;li&gt;1&lt;/li&gt;&lt;li&gt;2&lt;/li&gt;&lt;li&gt;3&lt;/li&gt;&lt;/ul&gt;&lt;/html&gt;'</pre>
4189-
4190- <h2>Slot specials</h2>
4191-
4192- <p>
4193- The problem with render methods is that they are only capable of making
4194- changes to their direct children. Because of the architecture of Nevow,
4195- they should not attempt to change grandchildren or parent nodes. It is
4196- possible to write one render method for every node you wish to change,
4197- but there is a better way. A node with a slot special can be "filled"
4198- with content by any renderer above the slot. Creating a slot special is
4199- such a frequent task that there is a prototype in <code>nevow.tags</code>
4200- which is usually used.
4201- </p>
4202-
4203- <p>
4204- Let us examine a renderer which fills a template with information about
4205- a person:
4206- </p>
4207-
4208- <pre class="python-interpreter">
4209-&gt;&gt;&gt; from nevow import loaders, rend, tags
4210-...
4211-&gt;&gt;&gt; person = ('Donovan', 'Preston', 'Male', 'California')
4212-...
4213-&gt;&gt;&gt; def render_person(ctx, person):
4214-... firstName, lastName, sex, location = person
4215-... ctx.fillSlots('firstName', firstName)
4216-... ctx.fillSlots('lastName', lastName)
4217-... ctx.fillSlots('sex', sex)
4218-... ctx.fillSlots('location', location)
4219-... return ctx.tag
4220-...
4221-&gt;&gt;&gt; class PersonPage(rend.Page):
4222-... docFactory = loaders.stan(tags.html(render=render_person)[
4223-... tags.table[
4224-... tags.tr[
4225-... tags.td[tags.slot('firstName')],
4226-... tags.td[tags.slot('lastName')],
4227-... tags.td[tags.slot('sex')],
4228-... tags.td[tags.slot('location')]]]])
4229-...
4230-&gt;&gt;&gt; PersonPage(person).renderSynchronously()
4231-'&lt;html&gt;&lt;table&gt;&lt;tr&gt;&lt;td&gt;Donovan&lt;/td&gt;&lt;td&gt;Preston&lt;/td&gt;&lt;td&gt;Male&lt;/td&gt;&lt;td&gt;California&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/html&gt;'</pre>
4232-
4233- <p>
4234- Using patterns in combination with slots can lead to very powerful
4235- template abstraction. Nevow also includes another standard renderer
4236- called "mapping" which takes any data which responds to the "items()"
4237- message and inserts the items into appropriate slots:
4238- </p>
4239-
4240- <pre class="python-interpreter">
4241-&gt;&gt;&gt; class DictPage(rend.Page):
4242-... docFactory = loaders.stan(tags.html(render=rend.mapping)[
4243-... tags.span[ tags.slot('foo') ], tags.span[ tags.slot('bar') ]])
4244-...
4245-&gt;&gt;&gt; DictPage(dict(foo=1, bar=2)).renderSynchronously()
4246-'&lt;html&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/html&gt;'</pre>
4247-
4248- <h2>Data directives</h2>
4249-
4250- <p>
4251- So far, we have always placed data functions directly in the Data
4252- special attribute of a Tag. Sometimes, it is preferable to look up a
4253- data method from the Page class as the Page has being rendered. For
4254- example, a base class may define a template and a subclass may provide
4255- the implementation of the data method. We can accomplish this effect by
4256- using a data directive as a Tag's data special:
4257- </p>
4258-
4259- <pre class="python">
4260-class Base(rend.Page):
4261- docFactory = loaders.stan(tags.html[
4262- tags.div(data=tags.directive('name'), render=rend.data)])
4263-
4264-class Subclass(Base):
4265- def data_name(self, ctx, data):
4266- return "Your name"
4267- </pre>
4268-
4269- <p>
4270- The data directive is resolved by searching for the
4271- <code>IContainer</code> implementation in the context.
4272- <code>rend.Page</code> implements <code>IContainer.get</code> by
4273- performing an attribute lookup on the Page with the prefix 'data_*'. You
4274- can provide your own <code>IContainer</code> implementation if you wish,
4275- and also you should know that <code>IContainer</code> implementations for
4276- list and dict are included in the <code class="API">nevow.accessors</code>
4277- module.
4278- </p>
4279-
4280- <p>
4281- A common gotcha is that the closest <code>IContainer</code> is used to
4282- resolve data directives. This means that if a list is being used as the
4283- data during the rendering process, data directives below this will be
4284- resolved against the <code>IContainer</code> implementation in
4285- <code>nevow.accessors.ListAccessor</code>. If you are expecting a data
4286- directive to invoke a Page's data_* method but instead get a
4287- <code>KeyError</code>, this is why.
4288- </p>
4289-
4290- <h2>Render directives</h2>
4291-
4292- <p>
4293- Render directives are almost exactly the same, except they are resolved
4294- using the closest <code>IRendererFactory</code> implementation in the
4295- context. Render directives can be used to allow subclasses to override
4296- certain render methods, and also can be used to allow Fragments to
4297- locate their own prefixed render methods.
4298- </p>
4299-
4300- <h2>Flatteners</h2>
4301-
4302- <p>
4303- TODO This section isn't done yet.
4304- </p>
4305-
4306- <p>
4307- Nevow's flatteners use a type/function registry to determine how to
4308- render objects which Nevow encounters in the DOM during the rendering
4309- process. "Explicit is better than implicit", so in most cases,
4310- explicitly applying render methods to data will be better than
4311- registering a flattener, but in some cases it can be useful:
4312- </p>
4313-
4314- <pre class="python">
4315-class Person(object):
4316- def __init__(self, firstName, lastName):
4317- self.firstName = firstName
4318- self.lastName = lastName
4319-
4320-def flattenPerson(person, ctx):
4321- return flat.partialflatten(ctx, (person.firstName, " ", person.lastName))
4322-
4323-from nevow import flat
4324-flat.registerFlattener(flattenPerson, Person)
4325-
4326-def insertData(ctx, data):
4327- return data
4328-
4329-class PersonPage(rend.Page):
4330- docFactory = loaders.stan(tags.html[insertData])
4331- </pre>
4332- </body>
4333-</html>
4334
4335=== removed file 'Nevow/doc/howto/stylesheet.css'
4336--- Nevow/doc/howto/stylesheet.css 2008-09-20 01:06:47 +0000
4337+++ Nevow/doc/howto/stylesheet.css 1970-01-01 00:00:00 +0000
4338@@ -1,129 +0,0 @@
4339-body
4340-{
4341- margin-left: 2em;
4342- margin-right: 2em;
4343- border: 0px;
4344- padding: 0px;
4345- font-family: sans-serif;
4346-}
4347-
4348-pre
4349-{
4350- padding: 1em;
4351- font-family: Monospace, Neep Alt, Courier New, Courier;
4352- font-size: 12pt;
4353- border: thin black solid;
4354-}
4355-
4356-.python
4357-{
4358- background-color: #dddddd;
4359-}
4360-
4361-.py-listing, .html-listing, .listing
4362-{
4363- margin: 1ex;
4364- border: thin solid black;
4365- background-color: #eee;
4366-}
4367-
4368-.py-listing pre, .html-listing pre, .listing pre
4369-{
4370- margin: 0px;
4371- border: none;
4372- border-bottom: thin solid black;
4373-}
4374-
4375-.py-listing .python
4376-{
4377- margin-top: 0;
4378- margin-bottom: 0;
4379- border: none;
4380- border-bottom: thin solid black;
4381-}
4382-
4383-.py-src-comment
4384-{
4385- color: #1111CC
4386-}
4387-
4388-.py-src-keyword
4389-{
4390- color: #3333CC;
4391- font-weight: bold;
4392-}
4393-
4394-.py-src-parameter
4395-{
4396- color: #000066;
4397- font-weight: bold;
4398-}
4399-
4400-.py-src-identifier
4401-{
4402- color: #CC0000
4403-}
4404-
4405-.py-src-string
4406-{
4407- color: #115511
4408-}
4409-
4410-.py-src-endmarker
4411-{
4412- display: block; /* IE hack; prevents following line from being sucked into the py-listing box. */
4413-}
4414-
4415-hr
4416-{
4417- display: inline;
4418-}
4419-
4420-ul
4421-{
4422- padding: 0px;
4423- margin: 0px;
4424- margin-left: 1em;
4425- padding-left: 1em;
4426- border-left: 1em;
4427-}
4428-
4429-li
4430-{
4431- padding: 2px;
4432-}
4433-
4434-dt
4435-{
4436- font-weight: bold;
4437- margin-left: 1ex;
4438-}
4439-
4440-dd
4441-{
4442- margin-bottom: 1em;
4443-}
4444-
4445-div.note
4446-{
4447- background-color: #FFFFCC;
4448- margin-top: 1ex;
4449- margin-left: 5%;
4450- margin-right: 5%;
4451- padding-top: 1ex;
4452- padding-left: 5%;
4453- padding-right: 5%;
4454- border: thin black solid;
4455-}
4456-
4457-.caption
4458-{
4459- text-align: center;
4460- padding-top: 0.5em;
4461- padding-bottom: 0.5em;
4462-}
4463-
4464-.filename
4465-{
4466- font-style: italic;
4467-}
4468
4469=== removed file 'Nevow/doc/howto/template.tpl'
4470--- Nevow/doc/howto/template.tpl 2008-08-26 13:45:59 +0000
4471+++ Nevow/doc/howto/template.tpl 1970-01-01 00:00:00 +0000
4472@@ -1,24 +0,0 @@
4473-<?xml version="1.0"?>
4474-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
4475- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4476-
4477-<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
4478- <head>
4479- <title>
4480- Nevow:
4481- </title>
4482- <link type="text/css" rel="stylesheet" href="stylesheet.css" />
4483- </head>
4484-
4485- <body bgcolor="white">
4486- <h1 class="title"></h1>
4487- <div class="toc"></div>
4488- <div class="body">
4489-
4490- </div>
4491-
4492- <p><a href="index.html">Index</a></p>
4493- <span class="version">Version: </span>
4494- </body>
4495-</html>
4496-
4497
4498=== removed file 'Nevow/doc/howto/traversal.xhtml'
4499--- Nevow/doc/howto/traversal.xhtml 2008-09-26 16:30:04 +0000
4500+++ Nevow/doc/howto/traversal.xhtml 1970-01-01 00:00:00 +0000
4501@@ -1,448 +0,0 @@
4502-<?xml version="1.0"?>
4503-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
4504- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
4505-
4506-<html xmlns="http://www.w3.org/1999/xhtml">
4507- <head>
4508- <title>
4509- Object Traversal
4510- </title>
4511- </head>
4512- <body>
4513- <h1>Object Traversal</h1>
4514-
4515- <p>
4516- <strong>Object traversal</strong> is the process Nevow uses to determine
4517- what object to use to render HTML for a particular URL. When an HTTP
4518- request comes in to the web server, the object publisher splits the URL
4519- into segments, and repeatedly calls methods which consume path segments
4520- and return objects which represent that path, until all segments have
4521- been consumed. At the core, the Nevow traversal API is very
4522- simple. However, it provides some higher level functionality layered on
4523- top of this to satisfy common use cases.
4524- </p>
4525-
4526- <h2>Object Traversal Basics</h2>
4527-
4528- <p>
4529- The <strong>root resource</strong> is the top-level object in the URL
4530- space; it conceptually represents the URI <code>/</code>. The Nevow
4531- <strong>object traversal</strong> and <strong>object publishing</strong>
4532- machinery uses only two methods to locate an object suitable for
4533- publishing and to generate the HTML from it; these methods are described
4534- in the interface <code class="API">nevow.inevow.IResource</code>:
4535- </p>
4536-
4537- <pre class="python">
4538-class IResource(Interface):
4539- def locateChild(self, ctx, segments):
4540- """Locate another object which can be adapted to IResource
4541- Return a tuple of resource, path segments
4542- """
4543-
4544- def renderHTTP(self, ctx):
4545- """Render a request
4546- """
4547- </pre>
4548-
4549- <p>
4550- <code class="API" base="nevow.inevow.IResource">renderHTTP</code> can be
4551- as simple as a method which simply returns a string of HTML. Let's
4552- examine what happens when object traversal occurs over a very simple root
4553- resource:
4554- </p>
4555-
4556- <pre class="python">
4557-from zope.interface import implements
4558-
4559-class SimpleRoot(object):
4560- implements(inevow.IResource)
4561-
4562- def locateChild(self, ctx, segments):
4563- return self, ()
4564-
4565- def renderHTTP(self, ctx):
4566- return "Hello, world!"
4567- </pre>
4568-
4569- <p>
4570- This resource, when passed as the root resource to <code class="API"
4571- base="nevow">appserver.NevowSite</code> or <code class="API"
4572- base="nevow">wsgi.createWSGIApplication</code>, will immediately return
4573- itself, consuming all path segments. This means that for every URI a user
4574- visits on a web server which is serving this root resource, the text
4575- <code>"Hello, world!"</code> will be rendered. Let's examine the value of
4576- <code>segments</code> for various values of URI:
4577- </p>
4578-
4579- <ul>
4580- <li><code>/</code> - <code>('',)</code></li>
4581- <li><code>/foo/bar</code> - <code>('foo', 'bar')</code></li>
4582- <li>
4583- <code>/foo/bar/baz.html</code> -
4584- <code>('foo', 'bar', 'baz.html')</code>
4585- </li>
4586- <li>
4587- <code>/foo/bar/directory/</code> -
4588- <code>('foo', 'bar', 'directory', '')</code>
4589- </li>
4590- </ul>
4591-
4592- <p>
4593- So we see that Nevow does nothing more than split the URI on the string
4594- <code>/</code> and pass these path segments to our application for
4595- consumption. Armed with these two methods alone, we already have enough
4596- information to write applications which service any form of URL
4597- imaginable in any way we wish. However, there are some common URL
4598- handling patterns which Nevow provides higher level support for.
4599- </p>
4600-
4601- <h2><code>locateChild</code> In Depth</h2>
4602-
4603- <p>
4604- One common URL handling pattern involves parents which only know about
4605- their direct children. For example, a ``Directory`` object may only know
4606- about the contents of a single directory, but if it contains other
4607- directories, it does not know about the contents of them. Let's examine a
4608- simple ``Directory`` object which can provide directory listings and
4609- serves up objects for child directories and files:
4610- </p>
4611-
4612- <pre class="python">
4613-from zope.interface import implements
4614-
4615-class Directory(object):
4616- implements(inevow.IResource)
4617-
4618- def __init__(self, directory):
4619- self.directory = directory
4620-
4621- def renderHTTP(self, ctx):
4622- html = ['&lt;ul&gt;']
4623- for child in os.listdir(self.directory):
4624- fullpath = os.path.join(self.directory, child)
4625- if os.path.isdir(fullpath):
4626- child += '/'
4627- html.extend(['&lt;li&gt;&lt;a href="', child, '"&gt;', child, '&lt;/a&gt;&lt;/li&gt;'])
4628- html.append('&lt;/ul&gt;')
4629- return ''.join(html)
4630-
4631- def locateChild(self, ctx, segments):
4632- name = segments[0]
4633- fullpath = os.path.join(self.directory, name)
4634- if not os.path.exists(fullpath):
4635- return None, () # 404
4636-
4637- if os.path.isdir(fullpath):
4638- return Directory(fullpath), segments[1:]
4639- if os.path.isfile(fullpath):
4640- return static.File(fullpath), segments[1:]
4641- </pre>
4642-
4643- <p>
4644- Because this implementation of <code>locateChild</code> only consumed one
4645- segment and returned the rest of them (<code>segments[1:]</code>), the
4646- object traversal process will continue by calling
4647- <code>locateChild</code> on the returned resource and passing the
4648- partially-consumed segments. In this way, a directory structure of any
4649- depth can be traversed, and directory listings or file contents can be
4650- rendered for any existing directories and files.
4651- </p>
4652-
4653- <p>
4654- So, let us examine what happens when the URI
4655- <code>"/foo/bar/baz.html"</code> is traversed, where <code>"foo"</code>
4656- and <code>"bar"</code> are directories, and <code>"baz.html"</code> is a
4657- file.
4658- </p>
4659-
4660- <ol>
4661- <li>
4662- <code>
4663- Directory('/').locateChild(ctx, ('foo', 'bar', 'baz.html'))
4664- </code>
4665- returns
4666- <code>Directory('/foo'), ('bar', 'baz.html')</code>
4667- </li>
4668- <li>
4669- <code>
4670- Directory('/foo').locateChild(ctx, ('bar', 'baz.html'))
4671- </code>
4672- returns
4673- <code>Directory('/foo/bar'), ('baz.html, )</code>
4674- </li>
4675- <li>
4676- <code>
4677- Directory('/foo/bar').locateChild(ctx, ('baz.html'))
4678- </code>
4679- returns
4680- <code>File('/foo/bar/baz.html'), ()</code>
4681- </li>
4682- <li>
4683- No more segments to be consumed;
4684- <code>File('/foo/bar/baz.html').renderHTTP(ctx)</code> is called, and
4685- the result is sent to the browser.
4686- </li>
4687- </ol>
4688-
4689-
4690- <h2><code>childFactory</code> Method</h2>
4691-
4692- <p>
4693- Consuming one URI segment at a time by checking to see if a requested
4694- resource exists and returning a new object is a very common
4695- pattern. Nevow's default implementation of <code class="API"
4696- base="nevow.inevow">IResource</code>, <code
4697- class="API">nevow.rend.Page</code>, contains an implementation of
4698- <code>locateChild</code> which provides more convenient hooks for
4699- implementing object traversal. One of these hooks is
4700- <code>childFactory</code>. Let us imagine for the sake of example that we
4701- wished to render a tree of dictionaries. Our data structure might look
4702- something like this:
4703- </p>
4704-
4705- <pre class="python">
4706-tree = dict(
4707- one=dict(
4708- foo=None,
4709- bar=None),
4710- two=dict(
4711- baz=dict(
4712- quux=None)))
4713- </pre>
4714-
4715- <p>
4716- Given this data structure, the valid URIs would be:
4717- </p>
4718-
4719- <ul>
4720- <li>/</li>
4721- <li>/one</li>
4722- <li>/one/foo</li>
4723- <li>/one/bar</li>
4724- <li>/two</li>
4725- <li>/two/baz</li>
4726- <li>/two/baz/quux</li>
4727- </ul>
4728-
4729- <p>
4730- Let us construct a <code class="API" base="nevow">rend.Page</code>
4731- subclass which uses the default <code>locateChild</code> implementation
4732- and overrides the <code>childFactory</code> hook instead:
4733- </p>
4734-
4735- <pre class="python">
4736-class DictTree(rend.Page):
4737- def __init__(self, dataDict):
4738- self.dataDict = dataDict
4739-
4740- def renderHTTP(self, ctx):
4741- if self.dataDict is None:
4742- return "Leaf"
4743- html = ['&lt;ul&gt;']
4744- for key in self.dataDict.keys():
4745- html.extend(['&lt;li&gt;&lt;a href="', key, '"&gt;', key, '&lt;/a&gt;&lt;/li&gt;'])
4746- html.append('&lt;/ul&gt;')
4747- return ''.join(html)
4748-
4749- def childFactory(self, ctx, name):
4750- if name not in self.dataDict:
4751- return rend.NotFound # 404
4752- return DictTree(self.dataDict[name])
4753- </pre>
4754-
4755- <p>
4756- As you can see, the <code>childFactory</code> implementation is
4757- considerably shorter than the equivalent <code>locateChild</code>
4758- implementation would have been.
4759- </p>
4760-
4761- <h2><code>child_*</code> methods and attributes</h2>
4762-
4763- <p>
4764- Often we may wish to have some hardcoded URLs which are not dynamically
4765- generated based on some data structure. For example, we might have an
4766- application which uses an external CSS stylesheet, an external JavaScript
4767- file, and a folder full of images. The <code class="API"
4768- base="nevow">rend.Page.locateChild</code> implementation provides a
4769- convenient way for us to express these relationships by using
4770- child-prefixed methods:
4771- </p>
4772-
4773- <pre class="python">
4774-class Linker(rend.Page):
4775- def renderHTTP(self, ctx):
4776- return """&lt;html&gt;
4777-&lt;head&gt;
4778- &lt;link href="css" rel="stylesheet" /&gt;
4779- &lt;script type="text/javascript" src="scripts" /&gt;
4780- &lt;body&gt;
4781- &lt;img src="images/logo.png" /&gt;
4782- &lt;/body&gt;
4783-&lt;/html&gt;"""
4784-
4785- def child_css(self, ctx):
4786- return static.File('styles.css')
4787-
4788- def child_scripts(self, ctx):
4789- return static.File('scripts.js')
4790-
4791- def child_images(self, ctx):
4792- return static.File('images/')
4793- </pre>
4794-
4795- <p>
4796- One thing you may have noticed is that all of the examples so far have
4797- returned new object instances whenever they were implementing a traversal
4798- API. However, there is no reason these instances cannot be shared. One
4799- could for example return a global resource instance, an instance which
4800- was previously inserted in a dict, or lazily create and cache dynamic
4801- resource instances on the fly. The <code>rend.Page.locateChild</code>
4802- implementation also provides a convenient way to express that one global
4803- resource instance should always be used for a particular URL, the
4804- child-prefixed attribute:
4805- </p>
4806-
4807- <pre class="python">
4808-class FasterLinker(Linker):
4809- child_css = static.File('styles.css')
4810- child_scripts = static.File('scripts.js')
4811- child_images = static.File('images/')
4812- </pre>
4813-
4814- <h2>Dots in child names</h2>
4815-
4816- <p>
4817- When a URL contains dots, which is quite common in normal URLs, it is
4818- simple enough to handle these URL segments in <code>locateChild</code> or
4819- <code>childFactory</code> -- one of the passed segments will simply be a
4820- string containing a dot. However, it is not immediately obvious how one
4821- would express a URL segment with a dot in it when using child-prefixed
4822- methods. The solution is really quite simple:
4823- </p>
4824-
4825- <pre class="python">
4826-class DotChildren(rend.Page):
4827- def renderHTTP(self, ctx):
4828- return """
4829- &lt;html&gt;
4830- &lt;head&gt;
4831- &lt;script type="text/javascript" src="scripts.js" /&gt;
4832- &lt;/head&gt;
4833- &lt;/html&gt;"""
4834-
4835-setattr(DotChildren, 'child_scripts.js', static.File('scripts.js'))
4836- </pre>
4837-
4838- <p>
4839- The same technique could be used to install a child method with a dot in
4840- the name.
4841- </p>
4842-
4843-
4844- <h2>children dictionary</h2>
4845-
4846- <p>
4847- The final hook supported by the default implementation of
4848- <code>locateChild</code> is the <code>rend.Page.children</code>
4849- dictionary:
4850- </p>
4851-
4852- <pre class="python">
4853-class Main(rend.Page):
4854- children = {
4855- 'people': People(),
4856- 'jobs': Jobs(),
4857- 'events': Events()}
4858-
4859- def renderHTTP(self, ctx):
4860- return """
4861- &lt;html&gt;
4862- &lt;head&gt;
4863- &lt;title&gt;Our Site&lt;/title&gt;
4864- &lt;/head&gt;
4865- &lt;body&gt;
4866- &lt;p&gt;bla bla bla&lt;/p&gt;
4867- &lt;/body&gt;
4868- &lt;/html&gt;"""
4869- </pre>
4870-
4871- <p>
4872- Hooks are checked in the following order:
4873- </p>
4874-
4875- <ol>
4876- <li><code>self.children</code></li>
4877- <li><code>self.child_*</code></li>
4878- <li><code>self.childFactory</code></li>
4879- </ol>
4880-
4881- <h2>The default trailing slash handler</h2>
4882-
4883- <p>
4884- When a URI which is being handled ends in a slash, such as when the
4885- <code>/</code> URI is being rendered or when a directory-like URI is
4886- being rendered, the string <code>''</code> appears in the path segments
4887- which will be traversed. Again, handling this case is trivial inside
4888- either <code>locateChild</code> or <code>childFactory</code>, but it may
4889- not be immediately obvious what child-prefixed method or attribute will
4890- be looked up. The method or attribute name which will be used is simply
4891- <code>child</code> with a single trailing underscore.
4892- </p>
4893-
4894- <p>
4895- The <code>rend.Page</code> class provides an implementation of this
4896- method which can work in two different ways. If the attribute
4897- <code>addSlash</code> is <code>True</code>, the default trailing slash
4898- handler will return <code>self</code>. In the case when
4899- <code>addSlash</code> is <code>True</code>, the default
4900- <code>rend.Page.renderHTTP</code> implementation will simply perform a
4901- redirect which adds the missing slash to the URL.
4902- </p>
4903-
4904- <p>
4905- The default trailing slash handler also returns self if
4906- <code>addSlash</code> is <code>False</code>, but emits a warning as it
4907- does so. This warning may become an exception at some point in the
4908- future.
4909- </p>
4910-
4911- <h2><code>ICurrentSegments</code> and <code>IRemainingSegments</code></h2>
4912-
4913- <p>
4914- During the object traversal process, it may be useful to discover which
4915- segments have already been handled and which segments are remaining to be
4916- handled. This information may be obtained from the <code>context</code>
4917- object which is passed to all the traversal APIs. The interfaces <code
4918- class="API">nevow.inevow.ICurrentSegments</code> and <code
4919- class="API">nevow.inevow.IRemainingSegments</code> are used to retrieve
4920- this information. To retrieve a tuple of segments which have previously
4921- been consumed during object traversal, use this syntax:
4922- </p>
4923-
4924- <pre class="python">
4925-segs = ICurrentSegments(ctx)
4926- </pre>
4927-
4928- <p>
4929- The same is true of <code>IRemainingSegments</code>.
4930- <code>IRemainingSegments</code> is the same value which is passed as
4931- <code>segments</code> to <code>locateChild</code>, but may also be useful
4932- in the implementations of <code>childFactory</code> or a child-prefixed
4933- method, where this information would not otherwise be available.
4934- </p>
4935-
4936- <h2>Conclusion</h2>
4937-
4938- <p>
4939- Nevow makes it easy to handle complex URL hierarchies. The most basic
4940- object traversal interface, <code
4941- class="API">nevow.inevow.IResource.locateChild</code>, provides powerful
4942- and flexible control over the entire object traversal process. Nevow's
4943- canonical <code>IResource</code> implementation, <code>rend.Page</code>,
4944- also includes the convenience hooks <code>childFactory</code> along with
4945- child-prefixed method and attribute semantics to simplify common use
4946- cases.
4947- </p>
4948- </body>
4949-</html>
4950
4951=== removed file 'Nevow/doc/howto/xmltemplates.xhtml'
4952--- Nevow/doc/howto/xmltemplates.xhtml 2008-08-26 13:45:59 +0000
4953+++ Nevow/doc/howto/xmltemplates.xhtml 1970-01-01 00:00:00 +0000
4954@@ -1,407 +0,0 @@
4955-<?xml version="1.0"?>
4956-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
4957- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
4958-
4959-<html xmlns="http://www.w3.org/1999/xhtml">
4960- <head>
4961- <title>
4962- XML Templates
4963- </title>
4964- </head>
4965- <body>
4966- <h1>Nevow XML Templates</h1>
4967-
4968- <p>
4969- Stan syntax is cool, but eventually you are going to want to integrate
4970- your Python code with a template designed by an HTML monkey. Nevow
4971- accomplishes this by providing an xmlfile loader which uses the built-in
4972- Python SAX libraries to generate a tree of stan behind the scenes. The
4973- general rule is anything that is possible in stan should be possible in a
4974- pure XML template; of course, the XML syntax is generally going to be
4975- much more verbose.
4976- </p>
4977-
4978- <h2>loaders.xmlfile</h2>
4979-
4980- <p>
4981- Wherever you have seen a loaders.stan being created in any of the example
4982- code, a <code class="API" base="nevow">loaders.xmlfile</code> can be
4983- substituted instead. At the most basic, <code>xmlfile</code> merely
4984- requires the name of an xml template:
4985- </p>
4986-
4987- <pre class="python">
4988-class HelloXML(rend.Page):
4989- docFactory = loaders.xmlfile('hello.xml')
4990- </pre>
4991-
4992- <p>
4993- Placing the following xml in the <code>hello.xml</code> file will cause
4994- <code>HelloXML</code> to display a static page when it is rendered:
4995- </p>
4996-
4997- <pre>&lt;html&gt;Hello, world!&lt;/html&gt;</pre>
4998-
4999- <p>
5000- The following additional keyword arguments may be given to
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches