divmod-dev team mailing list archive
-
divmod-dev team
-
Mailing list archive
-
Message #00051
[Merge] lp:~divmod-dev/divmod.org/811792-remove-formless into lp:divmod.org
Tristan Seligmann has proposed merging lp:~divmod-dev/divmod.org/811792-remove-formless into lp:divmod.org.
Requested reviews:
Divmod-dev (divmod-dev)
Related bugs:
Bug #811792 in zope.interface: "AttributeError: 'MetaTypedInterface' object has no attribute '__name__'"
https://bugs.launchpad.net/zope.interface/+bug/811792
For more details, see:
https://code.launchpad.net/~divmod-dev/divmod.org/811792-remove-formless/+merge/69186
--
https://code.launchpad.net/~divmod-dev/divmod.org/811792-remove-formless/+merge/69186
Your team Divmod-dev is requested to review the proposed merge of lp:~divmod-dev/divmod.org/811792-remove-formless into lp:divmod.org.
=== removed directory 'Nevow/examples/advanced_manualform'
=== removed file 'Nevow/examples/advanced_manualform/__init__.py'
=== removed file 'Nevow/examples/advanced_manualform/advanced_manualform.py'
--- Nevow/examples/advanced_manualform/advanced_manualform.py 2006-03-08 14:28:41 +0000
+++ Nevow/examples/advanced_manualform/advanced_manualform.py 1970-01-01 00:00:00 +0000
@@ -1,106 +0,0 @@
-from time import time as now
-
-import twisted.python.components as tpc
-
-from nevow import rend, inevow, url, util, loaders, tags as t
-from nevow.rend import _CARRYOVER
-from formless import iformless
-
-#
-# This example is meant to be of some inspiration to those people
-# who need to have some inspiration to handle forms without using
-# formless. It _WILL_ raise an exception when you submit a form
-# without filling all values. This example should NOT be used as-is
-# but should be modified and enhanced to fit one's need.
-#
-# To sum up: it's just a starting point.
-#
-
-SUBMIT="_submit"
-BUTTON = 'post_btn'
-
-class WebException(Exception): pass
-
-class ManualFormMixin(rend.Page):
- def locateChild(self, ctx, segments):
- # Handle the form post
- if segments[0].startswith(SUBMIT):
- # Get a method name from the action in the form plus
- # the firt word in the button name (or simply the form action if
- # no button name is specified
- kwargs = {}
- args = inevow.IRequest(ctx).args
- bindingName = ''
- for key in args:
- if key != BUTTON:
- if args[key] != ['']:
- kwargs[key] = (args[key][0], args[key])[len(args[key])>1]
- else:
- bindingName = args[key][0]
- name_prefix = segments[0].split('!!')[1]
- if bindingName == '': name = name_prefix
- else: name = name_prefix + '_' + bindingName.split()[0].lower()
- method = getattr(self, 'form_'+name, None)
- if method is not None:
- return self.onManualPost(ctx, method, bindingName, kwargs)
- else:
- raise WebException("You should define a form_action_button method")
- return super(ManualFormMixin, self).locateChild(ctx, segments)
-
- def onManualPost(self, ctx, method, bindingName, kwargs):
- # This is copied from rend.Page.onWebFormPost
- def redirectAfterPost(aspects):
- redirectAfterPost = request.getComponent(iformless.IRedirectAfterPost, None)
- if redirectAfterPost is None:
- ref = request.getHeader('referer') or ''
- else:
- ## Use the redirectAfterPost url
- ref = str(redirectAfterPost)
- from nevow import url
- refpath = url.URL.fromString(ref)
- magicCookie = str(now())
- refpath = refpath.replace('_nevow_carryover_', magicCookie)
- _CARRYOVER[magicCookie] = C = tpc.Componentized()
- for k, v in aspects.iteritems():
- C.setComponent(k, v)
- request.redirect(str(refpath))
- from nevow import static
- return static.Data('You posted a form to %s' % bindingName, 'text/plain'), ()
- request = inevow.IRequest(ctx)
- return util.maybeDeferred(method, **kwargs
- ).addCallback(self.onPostSuccess, request, ctx, bindingName,redirectAfterPost
- ).addErrback(self.onPostFailure, request, ctx, bindingName,redirectAfterPost)
-
-
-class Page(ManualFormMixin, rend.Page):
-
- addSlash = True
- docFactory = loaders.stan(
- t.html[
- t.head[
- t.title['Advanced Manualform']
- ],
- t.body[
- t.p['Use the form to find out how to easily and manually handle them'],
- t.form(action=url.here.child('_submit!!post'),
- enctype="multipart/form-data",
- method='post'
- )[
- t.input(type='text', name='what'),
- # the name attribute must be present and must be
- # post_btn for all the buttons in the form
- t.input(type='submit', value='btn1', name=BUTTON),
- t.input(type='submit', value='btn2', name=BUTTON)
- ]
- ]
- ]
- )
-
- def form_post_btn1(self, what=None):
- # 'what' is a keyword argument, and must be the same name that you
- # give to the widget.
- print "btn1:", what
-
- def form_post_btn2(self, what=None):
- # see above for 'what'.
- print "btn2:", what
=== removed directory 'Nevow/examples/athenademo'
=== removed file 'Nevow/examples/athenademo/__init__.py'
=== removed file 'Nevow/examples/athenademo/benchmark.js'
--- Nevow/examples/athenademo/benchmark.js 2006-04-12 17:49:24 +0000
+++ Nevow/examples/athenademo/benchmark.js 1970-01-01 00:00:00 +0000
@@ -1,35 +0,0 @@
-
-// import Nevow.Athena
-
-function timer() {
- var d = new Date();
- return d.getSeconds() + ':' + d.getMilliseconds();
-}
-
-document.documentElement.insertBefore(
- document.createTextNode(timer()),
- document.documentElement.firstChild);
-
-Nevow.Benchmarks.InitializationBenchmark = Nevow.Athena.Widget.subclass('Nevow.Benchmarks.InitializationBenchmark');
-Nevow.Benchmarks.InitializationBenchmark.methods(
- function __init__(self, node) {
- Nevow.Benchmarks.InitializationBenchmark.upcall(self, '__init__', node);
- self.stamptime();
- self.colorize('yellow');
- },
-
- function loaded(self) {
- self.stamptime();
- self.colorize('purple');
- var d = self.callRemote('activate');
- d.addCallback(function() { self.stamptime(); self.colorize('green'); });
- d.addErrback(function() { self.stamptime(); self.colorize('red'); });
- },
-
- function stamptime(self) {
- self.node.appendChild(document.createTextNode(' ' + timer()));
- },
-
- function colorize(self, color) {
- self.node.style.color = color;
- });
=== removed file 'Nevow/examples/athenademo/benchmark.py'
--- Nevow/examples/athenademo/benchmark.py 2006-03-30 16:16:29 +0000
+++ Nevow/examples/athenademo/benchmark.py 1970-01-01 00:00:00 +0000
@@ -1,47 +0,0 @@
-
-from __future__ import division
-
-from twisted.python import filepath
-
-from nevow import tags, loaders, athena
-
-class Benchmark(athena.LivePage):
- docFactory = loaders.stan(tags.html[
- tags.head(render=tags.directive('liveglue')),
- tags.body(render=tags.directive('body'))])
-
- def __init__(self, maxNodes, maxDepth):
- self.maxNodes = maxNodes
- self.maxDepth = maxDepth
- super(Benchmark, self).__init__()
-
- here = filepath.FilePath(__file__).parent().child('benchmark.js')
-
- self.jsModules.mapping.update({
- 'Nevow.Benchmarks': here.path})
-
- def render_body(self, ctx, data):
- for j in range(self.maxNodes // self.maxDepth):
- top = t = tags.div()
- for i in range(self.maxDepth):
- m = tags.div()
- t[m]
- t = m
- t[InitializationBenchmark(self)]
- yield top
-
-class InitializationBenchmark(athena.LiveFragment):
- jsClass = u'Nevow.Benchmarks.InitializationBenchmark'
-
- docFactory = loaders.stan(
- tags.div(render=tags.directive('liveFragment'))[
- "Initialization Benchmark"])
-
- def __init__(self, page):
- super(InitializationBenchmark, self).__init__()
- self.page = page
-
-
- def activate(self):
- pass
- athena.expose(activate)
=== removed file 'Nevow/examples/athenademo/calculator.html'
--- Nevow/examples/athenademo/calculator.html 2008-05-20 20:21:26 +0000
+++ Nevow/examples/athenademo/calculator.html 1970-01-01 00:00:00 +0000
@@ -1,62 +0,0 @@
-<html xmlns:n="http://nevow.com/ns/nevow/0.1";>
- <head>
- <n:invisible n:render="liveglue" />
- <style type="text/css">
- .calculator {
- font-family: monospace;
- margin-top: 5em;
- margin-left: auto;
- margin-right: auto;
- }
- input {
- width: 2em;
- border: 1px solid #999;
- }
- .output {
- border: 1px solid #999;
- text-align: right;
- }
- </style>
- </head>
- <body>
- <div n:render="calculator">Calculator Goes Here</div>
-
- <table class="calculator" id="calculator" n:pattern="CalculatorPattern" n:render="liveElement"
- xmlns:athena="http://divmod.org/ns/athena/0.7";>
- <tr>
- <td colspan="4" class="output" id="output">0</td>
- </tr>
- <tr>
- <td></td>
- <td></td>
- <td></td>
- <td><input type="button" value="C"><athena:handler event="onclick" handler="buttonClicked" /></input></td>
- </tr>
- <tr>
- <td><input type="button" value="7"><athena:handler event="onclick" handler="buttonClicked" /></input></td>
- <td><input type="button" value="8"><athena:handler event="onclick" handler="buttonClicked" /></input></td>
- <td><input type="button" value="9"><athena:handler event="onclick" handler="buttonClicked" /></input></td>
- <td><input type="button" value="/"><athena:handler event="onclick" handler="buttonClicked" /></input></td>
- </tr>
- <tr>
- <td><input type="button" value="4"><athena:handler event="onclick" handler="buttonClicked" /></input></td>
- <td><input type="button" value="5"><athena:handler event="onclick" handler="buttonClicked" /></input></td>
- <td><input type="button" value="6"><athena:handler event="onclick" handler="buttonClicked" /></input></td>
- <td><input type="button" value="*"><athena:handler event="onclick" handler="buttonClicked" /></input></td>
- </tr>
- <tr>
- <td><input type="button" value="1"><athena:handler event="onclick" handler="buttonClicked" /></input></td>
- <td><input type="button" value="2"><athena:handler event="onclick" handler="buttonClicked" /></input></td>
- <td><input type="button" value="3"><athena:handler event="onclick" handler="buttonClicked" /></input></td>
- <td><input type="button" value="-"><athena:handler event="onclick" handler="buttonClicked" /></input></td>
- </tr>
- <tr>
- <td><input type="button" value="0"><athena:handler event="onclick" handler="buttonClicked" /></input></td>
- <td><input type="button" value="."><athena:handler event="onclick" handler="buttonClicked" /></input></td>
- <td><input type="button" value="="><athena:handler event="onclick" handler="buttonClicked" /></input></td>
- <td><input type="button" value="+"><athena:handler event="onclick" handler="buttonClicked" /></input></td>
- </tr>
- </table>
- </body>
-</html>
-
=== removed file 'Nevow/examples/athenademo/calculator.js'
--- Nevow/examples/athenademo/calculator.js 2008-05-20 20:21:26 +0000
+++ Nevow/examples/athenademo/calculator.js 1970-01-01 00:00:00 +0000
@@ -1,20 +0,0 @@
-// import Nevow.Athena
-// import Divmod.Runtime
-
-CalculatorDemo.Calculator = Nevow.Athena.Widget.subclass("CalculatorDemo.Calculator");
-CalculatorDemo.Calculator.methods(
- /**
- * Handle click events on any of the calculator buttons.
- */
- function buttonClicked(self, node) {
- var symbol = node.value;
- d = self.callRemote("buttonClicked", symbol);
- d.addCallback(
- function(expression) {
- var output = self.nodeById("output");
- output.replaceChild(
- document.createTextNode(expression),
- output.firstChild);
- });
- return false;
- });
=== removed file 'Nevow/examples/athenademo/calculator.py'
--- Nevow/examples/athenademo/calculator.py 2008-05-20 20:21:26 +0000
+++ Nevow/examples/athenademo/calculator.py 1970-01-01 00:00:00 +0000
@@ -1,149 +0,0 @@
-# Copyright (c) 2008 Divmod. See LICENSE for details.
-
-"""
-Demonstration of an Athena Widget which accepts input from the browser and
-sends back responses.
-"""
-
-import sys
-
-from twisted.python.filepath import FilePath
-from twisted.python import log
-from twisted.internet import reactor
-
-from nevow.athena import LivePage, LiveElement, expose
-from nevow.loaders import xmlfile
-from nevow.appserver import NevowSite
-
-# Handy helper for finding external resources nearby.
-sibling = FilePath(__file__).sibling
-
-
-class Calculator(object):
- """
- The model object for the calculator demo. This is the object which
- actually knows how to perform calculations.
-
- @ivar expression: A C{str} giving the current expression which has been
- entered into the calculator. For example, if the buttons '3', '5', and
- '+' have been pressed (in that order), C{expression} will be C{'35+'}.
- """
- defaultExpression = u'0'
- errorExpression = u'E'
-
- def __init__(self):
- self.expression = self.defaultExpression
-
-
- def buttonClicked(self, symbol):
- """
- Change the current expression by performing the operation indicated by
- C{symbol} (clearing it or computing it) or by extending it (with a
- digit or operator).
-
- @param symbol: C{'C'} to clear the expression, C{'='} to evaluate the
- expression, or one of C{'0'}-C{'9'}.
-
- @rtype: C{unicode}
- @return: The expression after interpreting the new symbol.
- """
- # Clear
- if symbol == 'C':
- self.expression = self.defaultExpression
- return self.expression
- # Check the expression is currently valid
- if self.expression == self.errorExpression:
- return self.expression
- # Evaluate the expression
- if symbol == '=':
- try:
- self.expression = unicode(eval(self.expression))
- except ZeroDivisionError:
- self.expression = self.errorExpression
- return self.expression
- # Replace of add to the expression
- if self.expression == self.defaultExpression:
- self.expression = symbol
- else:
- self.expression += symbol
- return self.expression
-
-
-
-class CalculatorElement(LiveElement):
- """
- A "live" calculator.
-
- All buttons presses in the browser are sent to the server. The server
- evaluates the expression and sets the output in the browser.
-
- @ivar validSymbols: A C{str} giving all of the symbols which the browser is
- allowed to submit to us. Input is checked against this before being
- submitted to the model.
-
- @ivar calc: A L{Calculator} which will be used to handle all inputs and
- generate computed outputs.
- """
- docFactory = xmlfile(sibling('calculator.html').path, 'CalculatorPattern')
-
- jsClass = u"CalculatorDemo.Calculator"
-
- validSymbols = '0123456789/*-=+.C'
-
- def __init__(self, calc):
- LiveElement.__init__(self)
- self.calc = calc
-
-
- def buttonClicked(self, symbol):
- """
- Accept a symbol from the browser, perform input validation on it,
- provide it to the underlying L{Calculator} if appropriate, and return
- the result.
-
- @type symbol: C{unicode}
- @rtype: C{unicode}
- """
- # Remember ... never trust a browser
- if symbol not in self.validSymbols:
- raise ValueError('Invalid symbol')
- return self.calc.buttonClicked(symbol)
- expose(buttonClicked)
-
-
-
-class CalculatorParentPage(LivePage):
- """
- A "live" container page for L{CalculatorElement}.
- """
- docFactory = xmlfile(sibling('calculator.html').path)
-
- def __init__(self, *a, **kw):
- LivePage.__init__(self)
- # Update the mapping of known JavaScript modules so that the
- # client-side code for this example can be found and served to the
- # browser.
- self.jsModules.mapping[u'CalculatorDemo'] = sibling(
- 'calculator.js').path
-
-
- def render_calculator(self, ctx, data):
- """
- Replace the tag with a new L{CalculatorElement}.
- """
- c = CalculatorElement(Calculator())
- c.setFragmentParent(self)
- return c
-
-
-
-def main():
- log.startLogging(sys.stdout)
- site = NevowSite(CalculatorParentPage(calc=Calculator()))
- reactor.listenTCP(8080, site)
- reactor.run()
-
-
-
-if __name__ == '__main__':
- main()
=== removed file 'Nevow/examples/athenademo/typeahead.html'
--- Nevow/examples/athenademo/typeahead.html 2006-10-06 18:48:29 +0000
+++ Nevow/examples/athenademo/typeahead.html 1970-01-01 00:00:00 +0000
@@ -1,103 +0,0 @@
-<!DOCTYPE html
-PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";>
-<html xmlns='http://www.w3.org/1999/xhtml'
- xmlns:n='http://nevow.com/ns/nevow/0.1'>
- <!-- vi:ft=html
- -->
- <head>
- <meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />
- <n:invisible n:render="liveglue" />
- <title>TypeAhead Demo</title>
- <script type='text/javascript' language='javascript'>
-// <![CDATA[
-// add events in a cross-browser way
-function xbAddEvent(obj, evType, fn, useCapture){
- if (obj.addEventListener){
- obj.addEventListener(evType, fn, useCapture);
- return true;
- } else if (obj.attachEvent){
- var r = obj.attachEvent("on"+evType, fn);
- return r;
- } else {
- alert("Handler could not be attached");
- }
-}
-
-function selectRange(ele, start, end)
-{
- var orig = ele;
- ele = $(ele);
- if (ele == null)
- {
- alert("selectRange() can't find an element with id: " + orig + ".");
- return;
- }
-
- if (ele.setSelectionRange)
- {
- ele.setSelectionRange(start, end);
- }
- else if (ele.createTextRange)
- {
- var range = ele.createTextRange();
- range.moveStart("character", start);
- range.moveEnd("character", end - ele.value.length);
- range.select();
- }
-
- ele.focus();
-};
-
-//
-function replaceDescription(result, node)
-{
- var animal = result[0]; var descr = result[1];
-
- var widget = Nevow.Athena.Widget.get(node);
- var description = widget.nodeByAttribute('class', 'description');
- description.innerHTML = descr;
-
- // fill in the text field and select the portion that was guessed
- if (animal != null)
- {
- var typehere = node;
- var current = typehere.value;
- typehere.value = animal;
- selectRange(typehere, current.length, animal.length);
- }
-}
-
-//
-function loadDescription(ev)
-{
- // filter helpful keys like backspace
- if (ev.keyCode < 32) return;
- if (ev.keyCode >= 33 && ev.keyCode <= 46) return;
- if (ev.keyCode >= 112 && ev.keyCode <= 123) return;
-
- var typehere = ev.target;
- var typed = typehere.value;
- var d = Nevow.Athena.Widget.get(typehere).callRemote('loadDescription', typed);
- d.addCallback(replaceDescription, typehere);
-}
-
-Divmod.Base.addToCallStack(window, 'onload', function() {
- typeheres = MochiKit.DOM.getElementsByTagAndClassName('input', 'typehere');
- for (n=0; n<typeheres.length; n++) {
- xbAddEvent(typeheres[n], 'keyup', loadDescription, 1);
- }
-});
-
-// ]]>
- </script>
- </head>
- <body>
- <h2>Start typing an animal to see the description.</h2>
- <n:invisible n:render="typehereField" />
- <h2>You can also type in this one. It does the same thing, independently
- of the other one.</h2>
- <n:invisible n:render="typehereField" />
- </body>
-</html>
-
=== removed file 'Nevow/examples/athenademo/typeahead.py'
--- Nevow/examples/athenademo/typeahead.py 2006-10-06 18:48:29 +0000
+++ Nevow/examples/athenademo/typeahead.py 1970-01-01 00:00:00 +0000
@@ -1,82 +0,0 @@
-# vi:ft=python
-from nevow import tags as T, rend, loaders, athena, url
-from formless import annotate, webform
-from twisted.python import util
-
-animals = {u'elf' : u'Pointy ears. Bad attitude regarding trees.',
- u'chipmunk': u'Cute. Fuzzy. Sings horribly.',
- u'chupacabra': u'It sucks goats.',
- u'ninja': u'Stealthy and invisible, and technically an animal.',
- }
-
-
-class TypeAheadPage(athena.LivePage):
- _tmpl = util.sibpath(__file__, "typeahead.html")
- docFactory = loaders.xmlfile(_tmpl)
- def render_typehereField(self, ctx, data):
- frag = TypeAheadFieldFragment()
- frag.page = self
- return frag
-
-class TypeAheadFieldFragment(athena.LiveFragment):
- docFactory = loaders.stan(
- T.span(render=T.directive('liveFragment'))[ '\n',
- T.input(type="text", _class="typehere"), '\n',
- T.h3(_class="description"),
- ])
-
- def loadDescription(self, typed):
- if typed == u'':
- return None, u'--'
- matches = []
- for key in animals:
- if key.startswith(typed):
- matches.append(key)
- if len(matches) == 1:
- return matches[0], animals[matches[0]]
- elif len(matches) > 1:
- return None, u"(Multiple found)"
- else:
- return None, u'--'
- athena.expose(loadDescription)
-
-class DataEntry(rend.Page):
- """Add Animal"""
- addSlash = 1
-
- docFactory = loaders.stan(
- T.html[T.body[T.h1[
- "First, a Setup Form."],
- T.h2["Enter some animals as data. Click 'Done' to test looking up these animals."],
- T.h3["The neat stuff happens when you hit 'Done'."],
- webform.renderForms(),
- T.ol(data=T.directive("animals"), render=rend.sequence)[
- T.li(pattern="item", render=T.directive("string")),
- ],
- T.h1[T.a(href=url.here.child('typeahead'))["Done"]],
- ]
- ]
- )
- def bind_animals(self, ctx, ):
- """Add Animal"""
- return annotate.MethodBinding(
- 'animals',
- annotate.Method(arguments=
- [annotate.Argument('animal', annotate.String()),
- annotate.Argument('description', annotate.Text())]),
- action="Add Animal",
- )
-
- def animals(self, animal, description):
- """Add Animal"""
- if not (animal and description):
- return
- animals[animal.decode('utf-8')] = description.decode('utf-8')
- return url.here
-
- def data_animals(self, ctx, data):
- return animals.keys()
-
- def child_typeahead(self, ctx):
- return TypeAheadPage(None, None)
-
=== removed file 'Nevow/examples/athenademo/widgets.js'
--- Nevow/examples/athenademo/widgets.js 2006-04-12 17:49:24 +0000
+++ Nevow/examples/athenademo/widgets.js 1970-01-01 00:00:00 +0000
@@ -1,22 +0,0 @@
-
-// import Nevow.Athena
-
-WidgetDemo.Clock = Nevow.Athena.Widget.subclass('WidgetDemo.Clock');
-WidgetDemo.Clock.methods(
- function start(self, node, event) {
- self.callRemote('start');
- return false;
- },
-
- function stop(self, node, event) {
- self.callRemote('stop');
- return false;
- },
-
- function setTime(self, toWhat) {
- Divmod.debug("clock", "Setting time " + toWhat);
- var time = Nevow.Athena.NodeByAttribute(self.node, "class", "clock-time");
- Divmod.debug("clock", "On " + time);
- time.innerHTML = toWhat;
- Divmod.debug("clock", "Hooray");
- });
=== removed file 'Nevow/examples/athenademo/widgets.py'
--- Nevow/examples/athenademo/widgets.py 2006-03-30 16:16:29 +0000
+++ Nevow/examples/athenademo/widgets.py 1970-01-01 00:00:00 +0000
@@ -1,94 +0,0 @@
-
-import time, os
-
-from twisted.internet import task
-from twisted.python import log, util
-
-from nevow import athena, loaders, static
-
-class Clock(athena.LiveFragment):
- jsClass = u"WidgetDemo.Clock"
-
- docFactory = loaders.xmlstr('''\
-<div xmlns:nevow="http://nevow.com/ns/nevow/0.1";
- xmlns:athena="http://divmod.org/ns/athena/0.7";
- nevow:render="liveFragment">
- <div>
- <a href="#"><athena:handler event="onclick" handler="start" />
- Start
- </a>
- <a href="#"><athena:handler event="onclick" handler="stop" />
- Stop
- </a>
- </div>
- <div class="clock-time" />
-</div>
-''')
-
- running = False
-
- def start(self):
- if self.running:
- return
- self.loop = task.LoopingCall(self.updateTime)
- self.loop.start(1)
- self.running = True
- athena.expose(start)
-
- def stop(self):
- if not self.running:
- return
- self.loop.stop()
- self.running = False
- athena.expose(stop)
-
- def _oops(self, err):
- log.err(err)
- if self.running:
- self.loop.stop()
- self.running = False
-
- def updateTime(self):
- self.callRemote('setTime', unicode(time.ctime(), 'ascii')).addErrback(self._oops)
-
-class WidgetPage(athena.LivePage):
- docFactory = loaders.xmlstr("""\
-<html xmlns:nevow="http://nevow.com/ns/nevow/0.1";>
- <head>
- <nevow:invisible nevow:render="liveglue" />
- </head>
- <body>
- <div nevow:render="clock">
- First Clock
- </div>
- <div nevow:render="clock">
- Second Clock
- </div>
- <div nevow:render="debug" />
- </body>
-</html>
-""")
-
- addSlash = True
-
- def __init__(self, *a, **kw):
- super(WidgetPage, self).__init__(*a, **kw)
- self.jsModules.mapping[u'WidgetDemo'] = util.sibpath(__file__, 'widgets.js')
-
- def childFactory(self, ctx, name):
- ch = super(WidgetPage, self).childFactory(ctx, name)
- if ch is None:
- p = util.sibpath(__file__, name)
- if os.path.exists(p):
- ch = static.File(file(p))
- return ch
-
- def render_clock(self, ctx, data):
- c = Clock()
- c.page = self
- return ctx.tag[c]
-
- def render_debug(self, ctx, data):
- f = athena.IntrospectionFragment()
- f.setFragmentParent(self)
- return ctx.tag[f]
=== removed directory 'Nevow/examples/blogengine'
=== removed file 'Nevow/examples/blogengine/atom.xml'
--- Nevow/examples/blogengine/atom.xml 2005-10-14 17:36:24 +0000
+++ Nevow/examples/blogengine/atom.xml 1970-01-01 00:00:00 +0000
@@ -1,22 +0,0 @@
-<?xml version="1.0"?>
-<feed version="0.3" xmlns="http://purl.org/atom/ns#"; xml:lang="en" xmlns:n="http://nevow.com/ns/nevow/0.1";>
- <title mode="escaped">Subbacultcha</title>
- <link rel="alternate" type="text/html" href="http://localhost:8080"; />
- <tagline mode="escaped">Subbacultcha atom</tagline>
- <modified n:data="getFirstPost" n:render="modified">Page modified</modified>
- <id>tag:localhost,2004:/</id>
- <n:invisible n:data="get_posts" n:render="sequence">
- <entry n:pattern="item" n:render="post">
- <title mode="escaped"><n:slot name="title">Entry Title</n:slot></title>
- <link rel="alternate" type="text/html" href="#">
- <n:attr name="href"> <n:slot name="link" /> </n:attr>
- </link>
- <id>tag:localhost,2004:/<n:slot name="id">id</n:slot></id>
- <issued><n:slot name="created">Date created</n:slot></issued>
- <modified><n:slot name="modified">Date modified</n:slot></modified>
- <author>
- <name><n:slot name="author">Author</n:slot></name>
- </author>
- <content type="text/plain" mode="escaped"><n:slot name="content">Content</n:slot></content>
- </entry>
</n:invisible>
-</feed>
\ No newline at end of file
=== removed file 'Nevow/examples/blogengine/axiomstore.py'
--- Nevow/examples/blogengine/axiomstore.py 2006-04-14 17:23:46 +0000
+++ Nevow/examples/blogengine/axiomstore.py 1970-01-01 00:00:00 +0000
@@ -1,76 +0,0 @@
-from iblogengine import IBlog
-from zope.interface import implements
-from axiom import item, store, attributes, sequence
-from epsilon.extime import Time
-
-class Post(item.Item):
- typeName = "BlogenginePost"
- schemaVersion = 1
-
- id = attributes.integer(indexed=True, allowNone=False)
- created = attributes.timestamp(indexed=True)
- modified = attributes.timestamp(indexed=True)
- title = attributes.text(indexed=True, allowNone=False)
- author = attributes.text(indexed=True, allowNone=False)
- category = attributes.text(indexed=True)
- content = attributes.text(indexed=True)
-
- def __init__(self, **kw):
- now = Time()
- kw.update({'created':now,
- 'modified':now})
- super(Post, self).__init__(**kw)
-
- def setModified(self):
- self.modified = Time()
-
-class Blog(item.Item, item.InstallableMixin):
- implements(IBlog)
-
- typeName = "BlogengineBlog"
- schemaVersion = 1
-
- posts = attributes.reference()
- next_id = attributes.integer(default=0)
-
- def __init__(self, **kw):
- super(Blog, self).__init__(**kw)
- self.posts = sequence.List(store=self.store)
- post = Post(store=self.store,
- id=self.getNextId(),
- author=u'mike',
- title=u'FIRST POST!!!!',
- category=u'Test',
- content=u'I guess it worked.')
- self.addNewPost(post)
-
- def installOn(self, other):
- super(Blog, self).installOn(other)
- other.powerUp(self, IBlog)
-
- def addNewPost(self, post):
- # Why even let posts manage their own ids? Oh well.
- assert post.id == self.next_id,\
- "Bad post ID; is %r, should be %r" % (post.id, self.next_id)
- self.posts.append(post)
- self.next_id += 1
-
- def getPosts(self, how_many = None):
- """Return the latest 'how_many' posts, in reverse database order.
-
- XXX Really, it should be based on modtime. Which is broken.
- """
- if how_many is None or how_many > self.next_id:
- how_many = self.next_id
- return (self.getOne(self.next_id-id-1) for id in range(how_many))
-
- def getOne(self, id):
- return self.posts[id]
-
- def getNextId(self):
- return self.next_id
-
-def initialize(storename):
- s = store.Store(storename)
- s.findOrCreate(Blog).installOn(s)
- return s
=== removed file 'Nevow/examples/blogengine/blogengine.tac'
--- Nevow/examples/blogengine/blogengine.tac 2006-01-21 22:53:11 +0000
+++ Nevow/examples/blogengine/blogengine.tac 1970-01-01 00:00:00 +0000
@@ -1,12 +0,0 @@
-from twisted.application import service, strports
-from nevow import appserver
-
-import frontend, axiomstore as store, iblogengine
-from smtpserver import BlogSMTPFactory
-
-application = service.Application('blogengine')
-db = store.initialize('db.axiom')
-site = appserver.NevowSite(resource = frontend.UI())
-site.remember(db, iblogengine.IStore)
-strports.service("8080", site).setServiceParent(application)
-strports.service("2500", BlogSMTPFactory(db)).setServiceParent(application)
=== removed file 'Nevow/examples/blogengine/email_client.py'
--- Nevow/examples/blogengine/email_client.py 2005-10-14 17:36:24 +0000
+++ Nevow/examples/blogengine/email_client.py 1970-01-01 00:00:00 +0000
@@ -1,16 +0,0 @@
-import sys, smtplib
-
-fromaddr = raw_input("From: ")
-toaddrs = raw_input("To: ").split(',')
-print "Enter message, end with ^D:"
-msg = ''
-while 1:
- line = sys.stdin.readline()
- if not line:
- break
- msg = msg + line
-
-# The actual mail send
-server = smtplib.SMTP('localhost', 2500)
-server.sendmail(fromaddr, toaddrs, msg)
-server.quit()
=== removed file 'Nevow/examples/blogengine/frontend.py'
--- Nevow/examples/blogengine/frontend.py 2006-04-14 17:23:46 +0000
+++ Nevow/examples/blogengine/frontend.py 1970-01-01 00:00:00 +0000
@@ -1,241 +0,0 @@
-from time import time as now
-from zope.interface import implements, Interface
-
-from twisted.web import xmlrpc
-from twisted.python.components import registerAdapter
-
-from nevow import rend, loaders, url, static
-from nevow import tags as t, inevow
-from formless import annotate, iformless, webform
-
-from axiomstore import Post
-from iblogengine import IStore, IBlog
-
-def pptime(tt):
- return tt.asHumanly()+" UTC"
-def atompptime(tt):
- return tt.asISO8601TimeAndDate()
-class ITimer(Interface):
- pass
-
-#####################################
-categories = ['Programming', 'Test', 'Sport', 'People', 'Python',
- 'Databases', 'bench', 'woo', 'Friends']
-
-class IInsert(annotate.TypedInterface):
- def insert(
- ctx = annotate.Context(),
- title = annotate.String(strip=True, required=True, \
- requiredFailMessage="Title must be provided", tabindex='1'),
- author = annotate.String(strip=True, default="Anonymous", tabindex='2'),
- id = annotate.String(hidden=True),
- category = annotate.Choice(categories, tabindex='3'),
- content = annotate.Text(required=True, \
- requiredFailMessage="Posts with no content are not allowed", tabindex='4'),
- ):
- pass
- insert = annotate.autocallable(insert)
-
-#####################################
-class BaseUI(rend.Page):
- addSlash = True
- def renderHTTP(self, ctx):
- return IStore(ctx).transact(rend.Page.renderHTTP, self, ctx)
-
- def locateChild(self, ctx, segments):
- return IStore(ctx).transact(rend.Page.locateChild, self, ctx, segments)
-
-#############################
-class UI(BaseUI):
-
- docFactory = loaders.xmlfile ('ui.html')
- child_styles = static.File('styles')
- child_images = static.File('images')
- child_webform_css = webform.defaultCSS
-
- def render_starttimer(self, ctx, data):
- ctx.remember(now(), ITimer)
- return ctx.tag
-
- def render_stoptimer(self, ctx, data):
- start = ITimer(ctx)
- return ctx.tag['%s' % (now()-start)]
-
- def render_needForms(self, ctx, data):
- action = ctx.arg('action', 'view')
- if action == 'edit':
- form = inevow.IQ(ctx).onePattern('frm')
- return ctx.tag[form]
- return ctx.tag.clear()
-
- def data_getEntries(self, ctx, data):
- num = ctx.arg('num', '60')
- return IBlog(IStore(ctx)).getPosts(int(num))
-
- def render_entries(self, ctx, data):
- ctx.tag.fillSlots('modification', pptime(data.modified))
- ctx.tag.fillSlots('category', data.category)
- ctx.tag.fillSlots('author', data.author)
- ctx.tag.fillSlots('title', data.title)
- ctx.tag.fillSlots('content', data.content)
- ctx.tag.fillSlots('permaLink', url.root.child('%s' % (data.id)))
- return ctx.tag
-
- def render_insert(self, ctx, data):
- return ctx.tag
-
- def render_editer(self, ctx, data):
- ctx.tag.fillSlots('editPost', url.root.child('%s' % (data.id)
- ).add('action','edit'))
- return ctx.tag
-
- def render_insert(self, ctx, data):
- ctx.tag.fillSlots('insert', url.root.child('insertEntry'))
- return ctx.tag
-
- def child_insertEntry(self, ctx):
- return NewEntry()
-
- def childFactory(self, ctx, segment):
- id = segment.isdigit() and segment or '-1'
- if int(id) >= 0:
- return IBlog(IStore(ctx)).getOne(int(id))
- elif segment == 'rpc2':
- return BlogRPC(IStore(ctx))
- elif segment == 'atom.xml':
- return Atom()
-
- def child_thx(self, ctx):
- return Thx()
-
-##################################
-class NewEntry(BaseUI):
- implements(IInsert)
-
- docFactory = loaders.stan(
- t.html[
- t.head[
- t.title['Insertion form'],
- t.link(rel='stylesheet', type='text/css', href=url.root.child('webform_css')),
- ],
- t.body[
- t.h1['Insertion'],
- t.invisible(render=t.directive("forms"))
- ]
- ])
- def render_forms(self, ctx, data):
- d = iformless.IFormDefaults(ctx).getAllDefaults('insert')
- d['author'] = 'Anonymous'
- d['id'] = IBlog(IStore(ctx)).getNextId()
- return webform.renderForms()
-
- def insert(self, ctx, id, title, author, category, content):
- newPost = Post(store=IStore(ctx),
- id=int(id),
- author=unicode(author),
- title=unicode(title),
- category=unicode(category),
- content=unicode(content))
- IBlog(IStore(ctx)).addNewPost(newPost)
- inevow.IRequest(ctx).setComponent(iformless.IRedirectAfterPost, '/thx')
-
-#####################################
-class Thx(rend.Page):
- docFactory = loaders.stan(
- t.html[
- t.body[
- t.h1['Succeeded'],
- t.a(href=url.root)["Back to main"]
- ]
- ])
-
-####################################
-class Entry(UI):
- implements(IInsert)
- def data_getEntries(self, ctx, data):
- return [data]
-
- def render_forms(self, ctx, data):
- d = iformless.IFormDefaults(ctx).getAllDefaults('insert')
- d['author'] = self.original.author
- d['category'] = self.original.category
- d['title'] = self.original.title
- d['content'] = self.original.content
- d['id'] = self.original.id
- return webform.renderForms()
-
- def insert(self, ctx, id, title, author, category, content):
- self.original.author = unicode(author)
- self.original.title = unicode(title)
- self.original.category = unicode(category)
- self.original.content = unicode(content)
- inevow.IRequest(ctx).setComponent(iformless.IRedirectAfterPost, '/thx')
-
-#####################################
-class Atom(BaseUI):
- docFactory = loaders.xmlfile('atom.xml')
-
- def beforeRender(self, ctx):
- inevow.IRequest(ctx).setHeader("Content-Type", "application/application+xml; charset=UTF-8")
-
- def data_getFirstPost(self, ctx, data):
- for post in IBlog(IStore(ctx)).getPosts(1):
- return post
-
- def render_modified(self, ctx, data):
- return ctx.tag.clear()[atompptime(data.modified)]
-
- def data_get_posts(self, ctx, data):
- return IBlog(IStore(ctx)).getPosts(15)
-
- def render_post(self, ctx, data):
- #id = data.poolToUID[IBlog(IStore(ctx)).postsPool]
- # mkp: ...I don't know what that means or what it's for.
- ctx.tag.fillSlots('title', data.title)
- ctx.tag.fillSlots('link', url.root.child(data.id))
- ctx.tag.fillSlots('id', data.id)
- ctx.tag.fillSlots('created', atompptime(data.created))
- ctx.tag.fillSlots('modified', atompptime(data.modified))
- ctx.tag.fillSlots('author', data.author)
- ctx.tag.fillSlots('content', data.content)
- return ctx.tag
-
-#####################################
-from axiom.item import transacted
-class BlogRPC(xmlrpc.XMLRPC):
- """Publishes stuff"""
-
- def __init__(self, store):
- xmlrpc.XMLRPC.__init__(self)
- self.store = store
-
- def xmlrpc_publish(self, author, title, category, content):
- newid = IBlog(self.store).getNextId()
- newPost = Post(store=self.store,
- id=newid,
- author=unicode(author),
- title=unicode(title),
- category=unicode(category),
- content=unicode(content))
- IBlog(self.store).addNewPost(newPost)
- return 'Successfully added post number %s' % newid
- xmlrpc_publish = transacted(xmlrpc_publish)
-
- def xmlrpc_edit(self, id, author, title, category, content):
- post = IBlog(self.store).getOne(id)
- post.author = author
- post.title = title
- post.category = category
- post.content = content
- post.setModified()
- return 'Successfully modified post number %s' % id
- xmlrpc_edit = transacted(xmlrpc_edit)
-
- def xmlrpc_entries(self, count):
- return [(entry.id, entry.author, entry.category, entry.title, entry.content) \
- for entry in IBlog(self.store).getPosts(count)]
-
- xmlrpc_entries = transacted(xmlrpc_entries)
-
-registerAdapter(Entry, Post, inevow.IResource)
-
=== removed file 'Nevow/examples/blogengine/iblogengine.py'
--- Nevow/examples/blogengine/iblogengine.py 2006-03-17 15:00:39 +0000
+++ Nevow/examples/blogengine/iblogengine.py 1970-01-01 00:00:00 +0000
@@ -1,17 +0,0 @@
-from zope.interface import Interface
-
-class IStore(Interface):
- """ Interface used to remember the store in the site object """
-
-class IBlog(Interface):
- """ Represents the Blog Powerup in the Store """
- def addNewPost(post):
- """ Add the user provided post instance to the blog """
- def getPosts(how_many = None):
- """ Get the last X posts, if how_many is not specified, gets all of them """
-
- def getOne(id):
- """ Get the post with the corresponding id from the store """
-
- def getNextId():
- """ Get the next free id in the store """
=== removed directory 'Nevow/examples/blogengine/images'
=== removed file 'Nevow/examples/blogengine/images/bg-header2.jpg'
Binary files Nevow/examples/blogengine/images/bg-header2.jpg 2005-10-14 17:36:24 +0000 and Nevow/examples/blogengine/images/bg-header2.jpg 1970-01-01 00:00:00 +0000 differ
=== removed file 'Nevow/examples/blogengine/images/blank.gif'
Binary files Nevow/examples/blogengine/images/blank.gif 2005-10-14 17:36:24 +0000 and Nevow/examples/blogengine/images/blank.gif 1970-01-01 00:00:00 +0000 differ
=== removed file 'Nevow/examples/blogengine/images/geek-bullet.gif'
Binary files Nevow/examples/blogengine/images/geek-bullet.gif 2005-10-14 17:36:24 +0000 and Nevow/examples/blogengine/images/geek-bullet.gif 1970-01-01 00:00:00 +0000 differ
=== removed file 'Nevow/examples/blogengine/images/here-bullet.gif'
Binary files Nevow/examples/blogengine/images/here-bullet.gif 2005-10-14 17:36:24 +0000 and Nevow/examples/blogengine/images/here-bullet.gif 1970-01-01 00:00:00 +0000 differ
=== removed file 'Nevow/examples/blogengine/images/home-bullet.gif'
Binary files Nevow/examples/blogengine/images/home-bullet.gif 2005-10-14 17:36:24 +0000 and Nevow/examples/blogengine/images/home-bullet.gif 1970-01-01 00:00:00 +0000 differ
=== removed file 'Nevow/examples/blogengine/images/top.gif'
Binary files Nevow/examples/blogengine/images/top.gif 2005-10-14 17:36:24 +0000 and Nevow/examples/blogengine/images/top.gif 1970-01-01 00:00:00 +0000 differ
=== removed file 'Nevow/examples/blogengine/smtpserver.py'
--- Nevow/examples/blogengine/smtpserver.py 2006-01-21 22:53:11 +0000
+++ Nevow/examples/blogengine/smtpserver.py 1970-01-01 00:00:00 +0000
@@ -1,148 +0,0 @@
-
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-"""
-A toy email server.
-"""
-from zope.interface import implements
-
-from twisted.internet import defer
-from twisted.mail import smtp
-
-from axiom.item import transacted
-
-from axiomstore import Post
-from iblogengine import IBlog
-
-
-# You need to set this to your real SMTP_HOST
-SMTP_HOST = 'localhost'
-FROM = 'user@localhost'
-
-__doc__ = """
-This is the mail message format to post something via mail, no special
-order is required, but all those fields must be present:
-======
-[Id: ID]
-Author: AUTHOR_NAME
-Category: CATEGORY_NAME
-Title: TITLE
-Content: CONTENT
-"""
-
-class BlogMessageDelivery:
- implements(smtp.IMessageDelivery)
- def __init__(self, store):
- self.store = store
-
- def receivedHeader(self, helo, origin, recipients):
- return recipients
-
- def validateFrom(self, helo, origin):
- # All addresses are accepted
- return origin
-
- def validateTo(self, user):
- # Only messages directed to the "console" user are accepted.
- if user.dest.local == "blog":
- return lambda: BlogMessage(self.store)
- raise smtp.SMTPBadRcpt(user)
-
-class BlogMessage:
- implements(smtp.IMessage)
-
- def __init__(self, store):
- self.lines = []
- self.store = store
-
- def lineReceived(self, line):
- self.lines.append(line)
-
- def eomReceived(self):
- post = {}
- isContent = False
- ctnt_buff = []
- recipients = self.lines[0]
- addrs = []
-
- for recipient in recipients:
- if '@' not in recipient.orig.addrstr:
- # Avoid answering to bounches
- if not recipient.orig.addrstr == '<>':
- addrs.append(recipient.orig.addrstr[:-1]+'@'+recipient.orig.domain+'>')
- else:
- # Avoid answering to bounches
- if not recipient.orig.addrstr == '<#@[]>':
- addrs.append(recipient.orig.addrstr)
-
- for line in self.lines[1:]:
- if not isContent:
- try:
- field, value = line.split(':', 1)
- except ValueError:
- continue
- if field.lower() != 'content':
- post[field.lower()] = value.strip()
- else:
- isContent = True
- ctnt_buff.append(value.strip())
- else:
- ctnt_buff.append(line.strip())
- post['content'] = '\n'.join(ctnt_buff)
-
- for header in 'content author category title'.split():
- if not post.has_key(header):
- self.lines = []
- return defer.fail(None)
- if post.has_key('id'):
- oldpost = IBlog(self.store).getOne(int(post['id']))
- oldpost.author = unicode(post['author'])
- oldpost.title = unicode(post['title'])
- oldpost.category = unicode(post['category'])
- oldpost.content = unicode(post['content'])
- oldpost.setModified()
- action = 'modified'
- id = post['id']
- else:
- newid = IBlog(self.store).getNextId()
- newPost = Post(store=self.store,
- id=newid,
- author=unicode(post['author']),
- title=unicode(post['title']),
- category=unicode(post['category']),
- content=unicode(post['content']))
- IBlog(self.store).addNewPost(newPost)
- action = 'added'
- id = newid
- self.lines = []
- msg = """From: <%s>
-Subject: Successfull Post
-
-Post number %s successfully %s
-""" % (FROM, id, action)
- return self.sendNotify(addrs, msg)
- eomReceived = transacted(eomReceived)
-
- def toLog(self, what):
- print what
-
- def sendNotify(self, to_addr, msg):
- d = smtp.sendmail(SMTP_HOST, FROM, to_addr, msg)
- d.addCallback(self.toLog)
- d.addErrback(self.toLog)
- return d
-
- def connectionLost(self):
- # There was an error, throw away the stored lines
- self.lines = None
-
-class BlogSMTPFactory(smtp.SMTPFactory):
- def __init__(self, store, *a, **kw):
- smtp.SMTPFactory.__init__(self, *a, **kw)
- self.delivery = BlogMessageDelivery(store)
-
- def buildProtocol(self, addr):
- p = smtp.SMTPFactory.buildProtocol(self, addr)
- p.delivery = self.delivery
- return p
=== removed directory 'Nevow/examples/blogengine/styles'
=== removed file 'Nevow/examples/blogengine/styles/form.css'
--- Nevow/examples/blogengine/styles/form.css 2005-10-14 17:36:24 +0000
+++ Nevow/examples/blogengine/styles/form.css 1970-01-01 00:00:00 +0000
@@ -1,78 +0,0 @@
-form {
- margin: 0;
-}
-
-/*
-form div {
- margin-top: 10px;
-}
-*/
-
-form .field {
- margin-top: 10px;
-}
-
-fieldset {
- margin: 0;
- margin-top: 10px;
-
-/*border: 1px solid red;*/
- border-style: none;
- padding: 0;
-}
-
-
-label {
- display: block;
- margin-bottom: 2px;
-}
-
-label span {
- font-size: 85%;
- color: #666;
-}
-
-input, textarea {
- /* f a t font to ease input */
- font: bold 12px/100% "Lucida Console", Curier, monospace;
- color: #444;
-
- padding: 4px 2px;
- border: 1px solid #ccc;
-
- margin: 0;
-}
-
-input:focus, textarea:focus {
- border-color: #6cc;
-}
-
-
-input.btn {
- margin: 0;
- margin-right: 2px; /* space between the next button */
-
- padding: 2px 4px;
-
- color: #333;
- background: #6cc;
-
- /* raised 3d look */
- border-top: 2px solid #ccc;
- border-left: 2px solid #ccc;
- border-bottom: 2px solid #444;
- border-right: 2px solid #444;
-
- font-family: Verdana, Helvetica, sans-serif;
- line-height: 150%;
-
- font-size: xx-small; /* fake value for IE4/5.x */
- voice-family: "\"}\"";
- voice-family: inherit;
- font-size: x-small; /* real inteded value for text size */
-}
-
-blah {
- /* fake rule for IE */
-}
-
=== removed file 'Nevow/examples/blogengine/styles/site.css'
--- Nevow/examples/blogengine/styles/site.css 2005-10-14 17:36:24 +0000
+++ Nevow/examples/blogengine/styles/site.css 1970-01-01 00:00:00 +0000
@@ -1,482 +0,0 @@
-@import url("typo.css");
-@import url("form.css");
-
-/*
--------------------------------------------------
-Theme by Andrea Peltrin (http://www.deelan.com)
--------------------------------------------------
-*/
-
-
-/* basic elements */
-/*---------------------------------------------------*/
-
-body, html {
- margin: 0;
- padding: 0;
-}
-
-
-body {
- color: #222;
-
- margin: 0;
-/* background: #903 url("images/background.gif"); */
- background: #fafafa;
-}
-
-body, p, li, td, th, dd, dt, h1, h2, h3, h4, h5, h6 /* help browser to not forget */
-{
- font-family: verdana, geneva, arial, sans-serif;
-/* line-height: 200%;*/
-
- font-size: x-small; /* IE5 */
- voice-family: "\"}\"";
- voice-family: inherit;
- font-size: small;
-}
-
-html>body {
- font-size: small;
-}
-
-
-a img {
- border-style: none;
-}
-
-/* main contents */
-
-#main {
- /*border: 1px solid red; */ /* debug */
- /*border-top: none;*/
-
-
-
- margin: 0 auto;
- padding: 0;
-
- position: absolute;
-
- top: 30px;
- left: 50%;
- margin-left: -380px;
-
- width: 760px;
-}
-
-/* header */
-
-#header {
- background: #069 url("/images/bg-header2.jpg") top right no-repeat;
-
- height: 235px;
- border: 1px solid #ccc;
-}
-
-
-#header h1 {
- margin: 0;
- margin-top: 140px;
- /*margin-right: 280px;*/
-
- padding: 0;
- padding-left:30px;
-
-
- font: bold italic 52px/100% georgia, times, serif;
- color: #fff;
-}
-
-#header p {
- margin: 0;
- /*margin-left: 280px;*/ /* == #header h1 */
-
- padding: 0;
- padding-left:30px;
-
-
- text-transform: lowercase;
- font: bold 18px/100% verdana, arial, sans-serif;
-
- color: #fff;
-}
-
-
-/*---------------------------------------------------*/
-
-#content{
- padding: 35px;
- margin: 0;
-
- /*border: 1px solid red; */ /* debug */
- margin-right: 245px;
-
-}
-
-#content p {
- /* border: 1px solid red; */ /* debug */
-/* text-align: justify;*/
- line-height: 160%;
-
- margin: 1em 0;
- padding: 0;
-}
-
-#content ul, #content ol, #content dl, #content blockquote {
- line-height: 160%;
-}
-
-
-#content dd {
- margin: 0;
- margin-bottom: 10px;
-}
-
-
-/* funky titles */
-#content h2 {
-
-/* font: bold italic 24px/100% georgia, times, serif;*/
- font: bold 18px/100% verdana, arial, sans-serif;
-
- color: #069;
-
- margin: 0;
- margin-bottom: 4px; /* space up for datetime */
-
- text-transform: lowercase;
-/* font-variant: small-caps;*/
-
-}
-
-#content p.dtm {
-
- margin: 0;
- margin-bottom: 1em;
-
- font-size: 80%;
-
- text-transform: uppercase;
-}
-
-
-div.entry {
-
-}
-
-
-#content hr {
- visibility: hidden;
-
-
- padding: 0;
- margin: 2.5em auto;
-
-
-}
-
-
-
-/* ...and finally we place the list of links */
-
-#sidebar{
- float: right;
-
-/* border: 1px solid #069;*/
-
- margin: 0;
- padding: 35px;
-
- width: 250px;
- voice-family: "\"}\"";
- voice-family: inherit;
- width: 180px;
-}
-
-#main>#sidebar {
- width: 180px;
-}
-
-
-#sidebar ul {
- list-style: none;
-
- margin: 0;
- margin-bottom: 25px;
-
- padding: 0;
-}
-
-
-#sidebar ul li {
- line-height: 150%;
-
- margin: 0;
- padding: 5px 0;
-}
-
-
-#sidebar ul#nav li {
- line-height: 160%; /* restore global value */
-
- border-style: none;
- background: none;
-
- margin-bottom: 10px;
- padding: 5px 0 5px 22px; /* space for arrow gfx */
-
- border-top: 1px solid #ccc;
- border-bottom: 1px solid #ccc;
-
- text-transform: lowercase;
-}
-
-
-/* funky titles */
-#sidebar h3 {
- color: #069;
-
- margin: 0;
- margin-bottom: 15px;
-
- padding: 0;
-
-
-}
-
-
-/* styles for in-line images/photos */
-/*---------------------------------------------------*/
-#content .image img {
- display: block;
- border: 1px solid #444;
-}
-
-#content .image {
- margin: 1em auto; /* == #content p*/
-
- width: 360px;
- position: relative;
-}
-
-#content .image span {
- position: absolute;
-
- background: #069;
- color: #fff;
-
- padding: 4px 4px;
-
- bottom: 10px;
- left: 10px;
-
- z-index: 1;
-
- /* verdana looks better than arial if font is small */
- font-family: verdana, arial, helvetica, sans-serif;
-
- /* @@ fix IE5 here */
- font-size: x-small;
-}
-
-/* hyperlink */
-/*---------------------------------------------------*/
-
-a:link, a:visited, a:hover, a:active {
- color: #099;
-
- text-decoration: none;
- border-bottom: 1px solid #099;
-}
-
-a:visited {
- color: #444;
- border-bottom-color: #444;
-}
-
-a:hover {
- color: #903;
- /*border-bottom: 1px solid #903;*/
- border-bottom: none;
-}
-
-
-#footer {
- margin: 0;
- margin-top: 20px;
- padding: 15px 0;
-
-/* background: #903;*/
-
- clear: both; /* float reset */
- text-align: center;
-
-
- border-top: 1px solid #ccc;
-
- font-size: 85%;
-}
-
-
-
-/* utilities */
-/*---------------------------------------------------*/
-
-.cut {clear: both; height: 1px;}
-.hidden {display: none;}
-
-/*---------------------------------------------------*/
-
-ul#breadcrumb {
- list-style: none;
-
- /* reset both on Mozilla and IE */
- padding: 0;
-
- margin: 0;
- margin-bottom: 35px;
-}
-
-ul#breadcrumb li {
- display: inline;
- margin-right: 5px;
-
- /*text-transform: lowercase;*/
-}
-
-ul#breadcrumb li:last-child {
- font-weight: bold;
-}
-
-/*
-#searchBtn {
- margin-left: 5px;
-}
-
-
-*/
-/* -------------------------------------------------- */
-
-.photo {
-
- float: left;
-
- margin: 5px 0;
- margin-right: 10px;
-
- padding: 0;
-}
-
-.photo a:link, .photo a:visited {
- border: 1px solid #0099CC;
-
- display: block;
-}
-
-.photo a:link:hover, .photo a:visited:hover {
- border: 1px solid #903;
-}
-
-.photo img {
- display: block;
-
- margin:0;
-
- padding: 5px;
- background: #fff;
-}
-
-
-
-.transport {
-
-
- width: auto;
-
- /*border: 2px solid #069;*/
- text-align: center;
-
- padding: 5px 0;
-}
-
-
-
-#alert {
- background: #069;
- color: white;
-
- font-weight: bold;
-
- margin-bottom: 20px;
-}
-
-
-
-#alert ul {
- list-style: none;
-
- padding: 0;
- margin: 0;
-}
-
-
-#alert ul li {
- margin: 5px 10px;
-}
-
-
-/* @@ fix, it's ugly looking */
-.comment:target {
- border: 1px solid #099;
-
-}
-
-
-
-
-
-#moblog{
- text-align: center;
- background: #ddd;
- border: 1px solid #999999;
- padding: 5px;
-}
-
-
-
-#moblog {
- margin: 5px 0;
- padding: 10px;
-
-}
-
-#moblog a:link, #moblog a:visited {
- border: 1px solid #0099CC;
-
- display: block;
- width: 85px;
-
- margin: 5px auto;
-}
-
-#moblog a:link:hover, #moblog a:visited:hover {
- border: 1px solid #903;
-}
-
-#moblog img {
- display: block;
-
- margin:0;
- padding: 5px;
-
- background: #fff;
-}
-
-
-#moblog p {
- padding: 0;
- margin: 0;
-
- text-align: center;
-}
=== removed file 'Nevow/examples/blogengine/styles/typo.css'
--- Nevow/examples/blogengine/styles/typo.css 2005-10-14 17:36:24 +0000
+++ Nevow/examples/blogengine/styles/typo.css 1970-01-01 00:00:00 +0000
@@ -1,103 +0,0 @@
-/* --------------------
-definition list
----------------------*/
-
-dl {
-
-}
-
-dd {
- margin-left: 1em;
-}
-
-dt {
-
-}
-
-/* --------------------
-phrase elements
----------------------*/
-
-abbr, acronym
-{
- cursor: help;
- border-bottom: dotted 1px;
-}
-
-
-ins, del
-{
-
-}
-
-ins
-{
- text-decoration: none; /* some UAs reder as underlined, hence reset */
-}
-
-ins:before
-{
- /* content: '[' */
-}
-
-ins:after
-{
- /* content: ']' */
-}
-
-
-/* --------------------
-block/inline quotations,
-check: http://diveintomark.org/archives/2002/05/04/the_q_tag.html
----------------------*/
-
-blockquote {
- border-left: 4px double #6cc;
-
- padding: 0;
- padding-left: 10px;
-
- margin: 0.5em 5%;
-}
-
-cite, q {
- font-style: italic;
-}
-
-p>q, li>q, p>cite, li>cite { /* reset for mozilla, opera */
- font-style: normal;
-}
-
-cite, q {
- quotes: '\201C' '\201D' '\2018' '\2019'; /* quote and quote within quote */
-}
-
-cite:before, q:before {
- content: open-quote;
-}
-
-cite:after, q:after {
- content: close-quote;
-}
-
-
-/* --------------------
-geeks' markup codes
----------------------*/
-
-pre, code {
- font-size: 100%; /* reset size for IE */
-}
-
-
-#content>pre {
- width: auto; /* reset value for moz, opera */
-}
-
-
-
-/* mostly used to indicate markup/language keywords*/
-code {
- color: #6cc;
- font-weight: bold;
-}
=== removed file 'Nevow/examples/blogengine/ui.html'
--- Nevow/examples/blogengine/ui.html 2005-10-14 17:36:24 +0000
+++ Nevow/examples/blogengine/ui.html 1970-01-01 00:00:00 +0000
@@ -1,79 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html
- PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";>
-
-<html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en" lang="en" xmlns:nevow="http://nevow.com/ns/nevow/0.1"; nevow:render="starttimer">
-
- <head>
- <title>Subbacultcha</title>
- <style type="text/css">@import url('/styles/site.css');</style>
- <style type="text/css">@import url('/webform_css');</style>
- </head>
-
- <body>
-
- <div id="main">
-
- <div id="header">
- <h1>Subbacultcha</h1>
- <p>not offending anyone</p>
- </div>
-
- <div id="sidebar">
- <ul id="nav">
- <li><a id="a_home" href="/">Home</a></li>
- <!-- <li><a id="a_archives" title="" href="#">Archives</a></li> -->
- <li nevow:render="insert"><a href="#">
- <nevow:attr name="href"><nevow:slot name="insert" /></nevow:attr>
- Insert a new entry
- </a>
- </li>
- </ul>
- </div>
-
- <div id="content">
- <div nevow:data="getEntries" nevow:render="sequence">
-
- <div nevow:pattern="item" nevow:render="entries">
- <h2><nevow:slot name="title" /></h2>
-
- <!-- <p><nevow:slot name="modification"></nevow:slot></p> -->
-
- <p><nevow:slot name="content"></nevow:slot></p>
- <p>
- <a href="#">
- <nevow:attr name="href"><nevow:slot name="permaLink" /></nevow:attr>
- PermaLink
- </a>
- •
- <nevow:invisible nevow:render="editer">
- <a href="#">
- <nevow:attr name="href"><nevow:slot name="editPost" /></nevow:attr>
- Edit
- </a>
- </nevow:invisible>
- </p>
-
- <p>Posted by <nevow:slot name="author"></nevow:slot> on <nevow:slot name="modification" />, filed under <nevow:slot name="category" /></p>
- </div>
-
- </div>
-
- <!-- /content -->
- <nevow:invisible nevow:render="needForms">
- <p>Edit Entry</p>
- <div nevow:pattern="frm" nevow:render="forms" />
- </nevow:invisible>
- </div>
-
- <div id="footer">
- <p>Served in <span nevow:render="stoptimer" /></p>
- <p>CSS by Andrea 'deelan' Peltrin, <a href="http://www.deelan.com/";>website</a></p>
- </div>
-
- <!-- /main -->
- </div>
- </body>
-</html>
-
=== modified file 'Nevow/examples/children/children.py'
--- Nevow/examples/children/children.py 2005-10-14 17:36:24 +0000
+++ Nevow/examples/children/children.py 2011-07-26 00:42:36 +0000
@@ -82,10 +82,6 @@
"""
# Let parent class have a go first
- # WARNING: This 3 lines work well until you use formless in this page
- # because formless will make locateChild return only one return value
- # (a deferred) on which you should add a callback that accepts a resource and
- # an empty tuple that represents no remaining segments.
child, remainingSegments = rend.Page.locateChild(self, ctx, segments)
if child:
return child, remainingSegments
=== removed directory 'Nevow/examples/customform'
=== removed file 'Nevow/examples/customform/__init__.py'
=== removed file 'Nevow/examples/customform/customform.py'
--- Nevow/examples/customform/customform.py 2006-03-17 15:00:39 +0000
+++ Nevow/examples/customform/customform.py 1970-01-01 00:00:00 +0000
@@ -1,159 +0,0 @@
-#################################################################################
-# Example of using patterns to change the appearance of a webform.
-
-#from twisted.application import internet, service
-#from twisted.web import static
-
-from zope.interface import implements
-
-from nevow import rend
-from nevow import url
-from nevow import loaders
-from nevow import tags as T
-
-from formless import annotate
-from formless import webform
-
-
-#################################################################################
-# This beasty defines how I want the form to look. It's a table (eek!).
-# webform looks for patterns to use when rendering parts of the form and fills
-# slots with key information.
-#
-# Key patterns are:
-# freeform-form -- the form itself, mostly just the structure
-# argument -- the pattern to use for arguments when nothing better
-# is found
-# argument!!fo -- the pattern to use for the 'fo' argument
-#
-# Inside the patterns the following slots are filled:
-# freeform-form:
-# form-action -- action attribute, where the form will be posted
-# form-id -- id of the form
-# form-name -- name of the form
-# form-label -- form label, extracted from the docstring
-# form-description -- description, also extracted from the docstring
-# form-error -- "global" error
-# form-arguments -- insertion point for the arguments' HTML
-# argument:
-# label -- label
-# input -- the form element (input, textarea, etc)
-# error -- error message (if any)
-# description -- description of argument
-#
-# Note that you do not have to provide slots for all of the above. For
-# instance, you may not want to display the descriptions.
-#
-# Chances are that this block of text would be in a disk template or
-# perhaps defined using stan in a taglib module.
-
-
-FORM_LAYOUT = loaders.xmlstr(
- """<?xml version="1.0"?>
- <form xmlns:n="http://nevow.com/ns/nevow/0.1"; n:pattern="freeform-form">
-
- <!-- Replace/fill the form attributes -->
- <n:attr name="action"><n:slot name="form-action"/></n:attr>
- <n:attr name="id"><n:slot name="form-id"/></n:attr>
- <n:attr name="name"><n:slot name="form-name"/></n:attr>
-
- <!-- General form information -->
- <p><strong><n:slot name="form-label"/></strong></p>
- <p><em><n:slot name="form-description"/></em></p>
- <p><strong><em><n:slot name="form-error"/></em></strong></p>
-
- <!-- Start of the form layout table -->
- <table style="background: #eee; border: 1px solid #bbb; padding: 1em;" >
- <!-- Mark location arguments will be added -->
- <n:slot name="form-arguments"/>
- <!-- General argument layout pattern -->
- <n:invisible n:pattern="argument" n:render="remove">
- <tr>
- <th><n:slot name="label"/>:</th>
- <td><n:slot name="input"/><span class="freeform-error"><n:slot name="error"/></span></td>
- </tr>
- <tr>
- <th></th>
- <td><n:slot name="description"/></td>
- </tr>
- </n:invisible>
- <!-- Argument layout, just for fum -->
- <n:invisible n:pattern="argument!!fo" n:render="remove">
- <tr>
- <th><n:slot name="label"/>:</th>
- <td>
- <textarea cols="40" rows="5"><n:attr name="id"><n:slot name="id"/></n:attr><n:attr name="name"><n:slot name="name"/></n:attr><n:slot name="value"/></textarea>
- <span class="freeform-error"><n:slot name="error"/></span></td>
- </tr>
- <tr>
- <th></th>
- <td><n:slot name="description"/></td>
- </tr>
- </n:invisible>
- <!-- Button row -->
- <tr>
- <td colspan="2">
- <n:slot name="form-button"/>
- </td>
- </tr>
- </table>
- </form>
- """).load()
-
-
-#################################################################################
-# ISomething and Page are just something to test the form rendering on.
-
-class ISomething(annotate.TypedInterface):
-
- def doSomething(
- ctx = annotate.Context(),
- fee = annotate.String(required=True, description="Wee!"),
- fi = annotate.Integer(description="Tra-la-la"),
- fo = annotate.Text(),
- fum = annotate.String(),
- ):
- """Do Something Really Exciting
-
- Normally you would put a useful description of the interface here but,
- since the inteface is useless anyway, I cannot think of anything
- useful to say about it. Although ... did I mention it is useless?"""
- doSomething = annotate.autocallable(doSomething)
-
-
-class Root(rend.Page):
- """Render a custom and normal form for an ISomething.
- """
- implements(ISomething)
- addSlash = True
-
- child_webform_css = webform.defaultCSS
-
- def render_normalForm(self, ctx, data):
- return webform.renderForms()
-
- def render_customForm(self, ctx, data):
- return webform.renderForms()[FORM_LAYOUT]
-
- def doSomething(self, ctx, **kwargs):
- print '***** doSomething called with:', kwargs
-
- docFactory = loaders.stan(
- T.html[
- T.head[
- T.title['Example :: Custom Form Layout'],
- T.link(rel='stylesheet', type='text/css', href=url.here.child("webform_css")),
- ],
- T.body[
- T.h1['Custom'],
- render_customForm,
- T.h1['Default'],
- render_normalForm,
- ]
- ]
- )
-
-
-#application = service.Application('hellostan')
-#webServer = internet.TCPServer(8080, appserver.NevowSite(Root()))
-#webServer.setServiceParent(application)
=== removed directory 'Nevow/examples/db'
=== removed file 'Nevow/examples/db/__init__.py'
=== removed file 'Nevow/examples/db/db.py'
--- Nevow/examples/db/db.py 2006-04-14 17:23:46 +0000
+++ Nevow/examples/db/db.py 1970-01-01 00:00:00 +0000
@@ -1,132 +0,0 @@
-
-from zope.interface import implements
-
-from nevow import inevow
-from nevow import loaders
-from nevow import rend
-from nevow import tags
-from nevow.url import here
-
-from formless import annotate
-from formless import webform
-
-
-whole = [(1, 'one'), (2, 'two'), (3, 'buckle'), (4, 'my'), (5, 'shoe')]
-
-
-def doQuery(q, *args):
- """Pretend like we have a database and we are accessing it through this hypothetical interface.
- Ignore this. Use dbapi or adbapi instead, and build a real sql table. I hope that's obvious.
- """
- matchid = 'select * from foo where id ='
- setsql = 'update foo set subject = '
- insertsql = 'insert into foo values'
- if q == 'select * from foo':
- return whole
- elif q.startswith(matchid):
- theId = args[0]
- for dbid, subj in whole:
- if dbid == theId:
- return [(dbid, subj)]
- raise KeyError, theId
- elif q.startswith(setsql):
- newsubj, theId = args
- for index, (dbid, subj) in enumerate(whole):
- if dbid == theId:
- whole[index] = (dbid, newsubj)
- elif q.startswith(insertsql):
- max = whole[-1][0]
- subject, = args
- whole.append((max + 1, subject))
-
-
-class IAddItem(annotate.TypedInterface):
- def addItem(newSubject=annotate.String()):
- pass
- addItem = annotate.autocallable(addItem)
-
-
-class DBBrowser(rend.Page):
- implements(IAddItem)
- addSlash = True
-
- def addItem(self, newSubject):
- doQuery('insert into foo values subject = "%s"', newSubject)
-
- def data_queryDatabase(self, context, data):
- return doQuery('select * from foo')
-
- def render_row(self, context, data):
- theId, theSubj = data
- return context.tag[ # put our anchor in the li provided by the template
- tags.a(href=theId)[ theSubj ]
- ]
-
- docFactory = loaders.stan(
- tags.html[
- tags.body[
- tags.h1["Welcome, user"],
- tags.ul(data=tags.directive("queryDatabase"), render=tags.directive("sequence"))[
- tags.li(pattern="item", render=render_row)
- ],
- webform.renderForms()
- ]
- ]
- )
-
- def childFactory(self, ctx, name):
- """Since we created anchor tags linking to children of this resource
- directly by id, when the anchor is clicked, childFactory will be called
- with the appropriate id as the name argument."""
- try:
- ## Pass the id of the database item we want to be rendered on this page
- ## to the DBItem constructor. This integer will be used as the default data
- ## for this page.
- return DBItem(int(name))
- except ValueError:
- pass
- ## returning None results in a 404
-
-
-class IItemWithSubject(annotate.TypedInterface):
- def setSubject(newSubject=annotate.String(label="Change Subject")):
- pass
- setSubject = annotate.autocallable(setSubject)
-
-
-class DBItem(rend.Page):
- implements(IItemWithSubject)
- addSlash=True
-
- def setSubject(self, newSubject):
- ## Self.original is the data that was passed to the DBItem constructor above; the id of this record
- doQuery('update foo set subject = "%s" where id = %s', newSubject, self.original)
-
- def render_viewSelector(self, context, data):
- args = inevow.IRequest(context).args
- view = args.get('view', ['view'])[0]
- if view == 'view':
- selector = "View | ", tags.a(href=here.add('view','edit'))[ "Edit" ]
- editor = ''
- else:
- selector = tags.a(href=here.add('view','view'))["View"], " | Edit"
- editor = context.onePattern('edit')() # get one copy of the edit pattern
- viewer = context.onePattern('view')() # get one copy of the view pattern
- return selector, viewer, editor
-
- def render_itemDetail(self, context, data):
- theId, theSubject = doQuery('select * from foo where id = %s', self.original)[0]
- return tags.h2["Object ", theId], tags.span["Subject: ", theSubject]
-
- docFactory = loaders.stan(
- tags.html[
- tags.body[
- tags.p[tags.a(href=here.parent())["Up"]],
- tags.div(render=render_viewSelector)[
- tags.p(pattern="edit")[webform.renderForms()],
- tags.p(pattern="view")[render_itemDetail]
- ]
- ]
- ]
- )
-
=== modified file 'Nevow/examples/examples.tac'
--- Nevow/examples/examples.tac 2009-07-06 12:22:09 +0000
+++ Nevow/examples/examples.tac 2011-07-26 00:42:36 +0000
@@ -22,22 +22,15 @@
import sys
try:
- from advanced_manualform import advanced_manualform
- from customform import customform
from disktemplates import disktemplates
from disktemplates import disktemplates_stan
from simple import simple
from simple import simplehtml
- from tree import tree
- from formpost import formpost2
- from formpost import formpost
from children import children
from children import childrenhtml
from table import tablehtml
from irenderer import irenderer
from irenderer import simple_irenderer
- from formbuilder import formbuilder
- from db import db
from hello import hellohtml
from hello import hellostan
from canvas import canvas
@@ -58,13 +51,8 @@
from cal import cal
from tabbed import tabbed
from progress import progress
- from tests import testformless, testexamples
+ from tests import testexamples
from nevow import livetest
-
- from athenademo import calculator
- from athenademo import typeahead
- from athenademo import widgets
- from athenademo import benchmark
except ImportError, e:
if str(e).find('No module named') != -1:
msg = """
@@ -127,21 +115,15 @@
child_sources.contentTypes = {}
child_cssfile = static.File('index.css')
children = dict(
- customform=customform.Root(),
disktemplates=disktemplates.Mine(),
disktemplates_stan=disktemplates_stan.Mine(),
simple=simple.Simple(),
simplehtml=simplehtml.Simple(),
- tree=tree.Tree('base', 'base'),
- formpost2=formpost2.FormPage(formpost2.Implementation()),
- formpost=formpost.FormPage(),
children=children.RootPage(),
childrenhtml=childrenhtml.RootPage(),
tablehtml=tablehtml.Table(),
irenderer=irenderer.Page(),
simple_irenderer=simple_irenderer.Page(),
- formbuilder=formbuilder.FormBuilder(),
- db=db.DBBrowser(),
hellohtml=hellohtml.Page(),
hellostan=hellostan.Page(),
canvas=canvas.createResource(),
@@ -149,7 +131,6 @@
guarded=guarded.createResource(),
guarded2=guarded2.createResource(),
xul_nevow=xul_nevow.createResource(),
- advanced_manualform=advanced_manualform.Page(),
liveanimal=liveanimal.createResource(),
http_auth=http_auth.AuthorizationRequired(),
most_basic=most_basic.root,
@@ -165,12 +146,8 @@
tests=testexamples.createResource(),
livetests=testexamples.createLiveSuite(),
testtests=livetest.createResource(),
- testformless=testformless.NameWizard(),
- formless_redirector=testformless.Redirector(),
- formless_tests=testformless.formless_tests,
fragments=fragments.Root(),
macros=macros.Root(),
- typeahead=typeahead.DataEntry(),
)
def child_calculator(self, ctx):
=== removed directory 'Nevow/examples/formbuilder'
=== removed file 'Nevow/examples/formbuilder/__init__.py'
=== removed file 'Nevow/examples/formbuilder/formbuilder.py'
--- Nevow/examples/formbuilder/formbuilder.py 2006-04-14 17:23:46 +0000
+++ Nevow/examples/formbuilder/formbuilder.py 1970-01-01 00:00:00 +0000
@@ -1,98 +0,0 @@
-## formbuilder
-
-from zope.interface import implements
-
-from nevow import rend
-from nevow import loaders
-from nevow import tags as T
-from nevow import util
-
-from formless import annotate
-from formless import webform
-from formless import configurable
-
-from twisted.python import reflect
-
-
-class BuilderCore(configurable.Configurable):
- def __init__(self):
- configurable.Configurable.__init__(self, None)
- self.formElements = []
-
- def getBindingNames(self, ctx):
- return ['form']
-
- def bind_form(self, ctx):
- return annotate.MethodBinding(
- 'action',
- annotate.Method(arguments=self.formElements))
-
- def action(self, **kw):
- print "ACTION!", kw
-
- def addElement(self, name, type):
- self.formElements.append(
- annotate.Argument(name, type()))
-
-
-allTypes = [annotate.String, annotate.Text, annotate.Integer, annotate.Real, annotate.Password]
-typeChoice = annotate.Choice(choices=allTypes, valueToKey=reflect.qual, keyToValue=reflect.namedAny, stringify=lambda x: x.__name__)
-
-
-class IFormBuilder(annotate.TypedInterface):
- def addElement(name=annotate.String(required=True), type=typeChoice):
- """Add Element
-
- Add an element to this form.
- """
- pass
- addElement = annotate.autocallable(addElement)
-
- def clearForm():
- """Clear Form
-
- Clear this form.
- """
- clearForm = annotate.autocallable(clearForm)
-
-
-class FormBuilder(rend.Page):
- implements(IFormBuilder)
- addSlash = True
-
- def __init__(self):
- rend.Page.__init__(self)
- self.clearForm()
-
- def configurable_formBuilder(self, ctx):
- return configurable.TypedInterfaceConfigurable(self)
-
- def configurable_dynamicForm(self, ctx):
- return self.builderCore
-
- def addElement(self, name, type):
- self.builderCore.addElement(name, type)
-
- def clearForm(self):
- self.builderCore = BuilderCore()
-
- docFactory = loaders.stan(T.html[
- T.head[
- T.title["Form builder!"]],
- T.style(type="text/css")[
- open(util.resource_filename('formless', 'freeform-default.css')).read()],
- T.body[
- T.h1["Welcome to form builder"],
- webform.renderForms('formBuilder'),
- T.h2["Here is your form:"],
- webform.renderForms('dynamicForm')]])
-
-
-## Startup glue
-from nevow import appserver
-from twisted.application import service
-from twisted.application import internet
-
-application = service.Application('formbuilder')
-internet.TCPServer(8080, appserver.NevowSite(FormBuilder())).setServiceParent(application)
-
=== removed directory 'Nevow/examples/formpost'
=== removed file 'Nevow/examples/formpost/__init__.py'
=== removed file 'Nevow/examples/formpost/formpost.py'
--- Nevow/examples/formpost/formpost.py 2005-10-14 17:36:24 +0000
+++ Nevow/examples/formpost/formpost.py 1970-01-01 00:00:00 +0000
@@ -1,41 +0,0 @@
-# -*- python -*-
-
-from zope.interface import implements
-
-from nevow import loaders
-from nevow import rend
-from nevow import tags
-from nevow import url
-
-from formless import annotate
-from formless import webform
-
-class IMyForm(annotate.TypedInterface):
- foo = annotate.Integer()
-
-
-class FormPage(rend.Page):
- implements(IMyForm)
-
- addSlash = True
-
- child_webform_css = webform.defaultCSS
-
- # We need this to implement IMyForm
- foo = 5
-
- docFactory = loaders.stan(
- tags.html[
- tags.head[
- tags.link(rel='stylesheet', type='text/css', href=url.here.child('webform_css')),
- ],
- tags.body[
- "Hello! Here is a form:",
-
- # We want to render the "default" configurable.
- # This is located in Page.configurable_() and is going to be
- # 'self' (which, as you see above, implements IMyForm).
- webform.renderForms(),
- ],
- ],
- )
=== removed file 'Nevow/examples/formpost/formpost2.py'
--- Nevow/examples/formpost/formpost2.py 2006-03-22 18:03:26 +0000
+++ Nevow/examples/formpost/formpost2.py 1970-01-01 00:00:00 +0000
@@ -1,83 +0,0 @@
-# -*- python -*-
-
-from zope.interface import implements
-
-from nevow import loaders
-from nevow import rend
-from nevow import tags
-from nevow import inevow
-from nevow import url
-
-from formless import annotate
-from formless import webform
-
-from twisted.internet import defer
-
-
-#oldChoicesWay = annotate.Choice(choicesAttribute='theChoices') # Doing this gives you a DeprecationWarning now
-
-# If you still want to use an attribute or method of some other object, you should use a function as shown below,
-# but look up IResource(ctx) or IConfigurable(ctx), whichever is more appropriate.
-newChoicesWay = annotate.Choice(lambda c, d: range(30))
-deferChoicesWay = annotate.Choice(lambda c, d: defer.succeed(['abcd', 'efgh', 'ijkl']))
-radioChoices = annotate.Radio(["Old", "Tyme", "Radio"])
-
-## An example of using custom valueToKey and keyToValue functions to serialize/deserialize items
-values = {0: dict(name="Zero", stuff=1234), 1: dict(name="One", stuff=1234), 2: dict(name="Two", stuff=2345435)}
-customValueToKey = annotate.Choice(
- [0, 1, 2], # Perhaps these are primary keys in a database
- stringify=lambda x: values[x]['name'], # Do a database lookup to render a nice label in the ui
- valueToKey=str, # Convert the primary key to a value suitable for sending across the web
- keyToValue=lambda x: values[int(x)]) # Do a database lookup to get the actual value to pass to the binding
-
-
-class IMyForm(annotate.TypedInterface):
- foo = annotate.Integer()
-
- def bar(baz=annotate.Integer(),
- slam=newChoicesWay, ham=deferChoicesWay, radio=radioChoices, custom=customValueToKey):
- pass
- bar = annotate.autocallable(bar)
-
-
-class Implementation(object):
- implements(IMyForm)
-
- foo = 5
-
- def bar(self, baz, slam, ham, radio, custom):
- return "You called bar! %s %s %s %s %r" % (baz, slam, ham, radio, custom)
-
- theChoices = [1, 2, 3]
-
-
-class FormPage(rend.Page):
-
- addSlash = True
-
- child_webform_css = webform.defaultCSS
-
- def render_hand(self, ctx, data):
- hand = inevow.IHand(ctx, None)
- if hand is not None:
- return ctx.tag[hand]
- return ''
-
- docFactory = loaders.stan(
- tags.html[
- tags.head[
- tags.link(rel='stylesheet', type='text/css', href=url.here.child('webform_css')),
- ],
- tags.body[
- tags.h3(render=render_hand, style="color: red; font-size: xx-large"),
- "Hello! Here is a form:",
-
- # We want to render forms defined by the Implementation instance.
- # When we pass the Implementation instance to FormPage below,
- # rend.Page sets it as the .original attribute. To tell webform to render
- # forms described by this object, we use the configurable name "original".
- webform.renderForms('original'),
- ],
- ],
- )
-
=== removed directory 'Nevow/examples/image_uploader'
=== removed file 'Nevow/examples/image_uploader/images.py'
--- Nevow/examples/image_uploader/images.py 2006-01-22 00:10:42 +0000
+++ Nevow/examples/image_uploader/images.py 1970-01-01 00:00:00 +0000
@@ -1,35 +0,0 @@
-from zope.interface import implements, Interface
-
-from axiom import store, item
-from axiom.attributes import text, bytes
-
-class IImages(Interface):
- pass
-
-class Image(item.Item):
- title = text()
- author = text()
- image = bytes()
- hash = text()
-
-class Application(item.Item, item.InstallableMixin):
- implements(IImages)
-
- name = text()
-
- def installOn(self, other):
- super(Application, self).installOn(other)
- other.powerUp(self, IImages)
-
- def getImages(self, how_many=None):
- return self.store.query(Image, limit=how_many, sort=Image.storeID.descending)
-
- def getOne(self, hash):
- return self.store.findUnique(Image, Image.hash==hash)
-
-def initialize():
- s = store.Store('imagination.axiom')
- images = IImages(s, None)
- if not images:
- Application(store=s, name=u'Imagination').installOn(s)
- return s
=== removed file 'Nevow/examples/image_uploader/imagination.py'
--- Nevow/examples/image_uploader/imagination.py 2006-03-17 15:00:39 +0000
+++ Nevow/examples/image_uploader/imagination.py 1970-01-01 00:00:00 +0000
@@ -1,85 +0,0 @@
-from zope.interface import implements
-
-from nevow import loaders, rend, tags as t, static, url
-from formless import webform, annotate
-
-from images import Image, IImages
-
-import random
-from string import ascii_letters as alpha # ohhh...
-
-alphaDigit = alpha + '0123456789'
-
-def label(length=None):
- """
- Return one of 183,123,959,522,816 possible labels.
- """
-
- first = random.choice(alpha)
- rest = [random.choice(alphaDigit) for i in xrange(length or 7)]
- newLabel = first + ''.join(rest)
- return newLabel
-
-class IInsert(annotate.TypedInterface):
- def insert(ctx = annotate.Context(),
- title = annotate.String(),
- author = annotate.String(),
- image = annotate.FileUpload(required=True,
- requiredFailMessage="Must upload something")
- ):
- """ Insert a new image """
- insert = annotate.autocallable(insert, action="New Image")
-
-class TransactionalPage(rend.Page):
- adaptsToStore = False
- def __init__(self, store, *args, **kwargs):
- super(TransactionalPage, self).__init__(*args, **kwargs)
- self.store = store
-
- def locateChild(self, ctx, segments):
- return self.store.transact(super(TransactionalPage, self).locateChild, ctx, segments)
-
- def renderHTTP(self, ctx):
- return self.store.transact(super(TransactionalPage, self).renderHTTP, ctx)
-
-
-class Root(TransactionalPage):
- child_webform_css = webform.defaultCSS
- implements(IInsert)
-
- docFactory = loaders.stan(
- t.html[
- t.head[
- t.title['Imagination'],
- t.link(rel='stylesheet', type='text/css', href=url.root.child('webform_css'))
- ],
- t.body[
- webform.renderForms(),
- t.ul(render=t.directive("sequence"),
- data=t.directive("images"))[
- t.li(pattern="item", render=t.directive("image")),
- t.li(pattern="empty")["No images yet"]
- ]
- ]
- ]
- )
-
- def data_images(self, ctx, data):
- return IImages(self.store).getImages(15)
-
- def render_image(self, ctx, data):
- return t.a(href=url.root.child('fs').child(data.hash))[data.title]
-
- def insert(self, ctx, title, author, image):
- img = Image(store=self.store,
- image=image.value,
- title=title.decode('utf-8'),
- author=author.decode('utf-8'),
- hash=label().decode('utf-8'))
-
- def locateChild(self, ctx, segments):
- if segments[0] == 'fs':
- data = IImages(self.store).getOne(segments[1].decode('utf-8'))
- return static.Data(data.image, 'image/jpeg'), ()
- return super(Root, self).locateChild(ctx, segments)
-
=== removed file 'Nevow/examples/image_uploader/imagination.tac'
--- Nevow/examples/image_uploader/imagination.tac 2006-01-22 00:10:42 +0000
+++ Nevow/examples/image_uploader/imagination.tac 1970-01-01 00:00:00 +0000
@@ -1,9 +0,0 @@
-from twisted.application import service, strports
-from nevow import appserver
-
-import imagination, images
-
-application = service.Application('image_uploader')
-db = images.initialize()
-site = appserver.NevowSite(resource = imagination.Root(db))
-strports.service("8080", site).setServiceParent(application)
=== modified file 'Nevow/examples/index.html'
--- Nevow/examples/index.html 2009-07-06 12:22:09 +0000
+++ Nevow/examples/index.html 2011-07-26 00:42:36 +0000
@@ -69,17 +69,11 @@
<ol>
<li><a href="/tests/">Run basic tests</a></li>
- <li><a href="/formless_tests/">Run formless tests</a></li>
-
<li><a href="/livetests/">Run livepage example tests</a></li>
<li><a href="/testtests/tests/">Test test harness</a></li>
</ol>
- <p>Athena also has <a href="/athenatest/">some tests</a>, although
- there is not yet a fancy test runner like the one demonstrated
- above.</p>
-
<h1 id="examples">Examples Listing</h1>
<ol>
@@ -427,122 +421,6 @@
</li>
<li>
- <span>Advanced manual form example</span>
-
- <div class="source">
- <table border="0" cellpadding="0" cellspacing="0" width=
- "100%">
- <tbody>
- <tr>
- <td>Stan Source</td>
-
- <td width="100%"><a href=
- "sources/advanced_manualform/advanced_manualform.py">
- advanced_manualform.py</a></td>
- </tr>
- </tbody>
- </table>Live example: <a href=
- "advanced_manualform/">form</a>
- </div>
- </li>
-
- <li>
- <span>Formless example</span>
-
- <div class="source">
- <table border="0" cellpadding="0" cellspacing="0" width=
- "100%">
- <tbody>
- <tr>
- <td>Stan Source</td>
-
- <td width="100%"><a href=
- "sources/formpost/formpost.py">formpost.py</a></td>
- </tr>
- </tbody>
- </table>Live example: <a href="formpost/">formpost</a>
- </div>
- </li>
-
- <li>
- <span>Another formless example, but a little bit more
- complex</span>
-
- <div class="source">
- <table border="0" cellpadding="0" cellspacing="0" width=
- "100%">
- <tbody>
- <tr>
- <td>Stan Source</td>
-
- <td width="100%"><a href=
- "sources/formpost/formpost2.py">formpost2.py</a></td>
- </tr>
- </tbody>
- </table>Live example: <a href="formpost2/">formpost2</a>
- </div>
- </li>
-
- <li>
- <span><b>[0.5]</b>Using formless to create multi-step
- wizards by returning Page instances from
- autocallables</span>
-
- <div class="source">
- <table border="0" cellpadding="0" cellspacing="0" width=
- "100%">
- <tbody>
- <tr>
- <td>Stan Source</td>
-
- <td width="100%"><a href=
- "sources/tests/testformless.py">tests/testformless.py</a></td>
- </tr>
- </tbody>
- </table>Live example: <a href=
- "testformless">testformless</a>
- </div>
- </li>
-
- <li>
- <span><b>[0.5]</b>Using formless, return a URL instance
- from an autocallable to redirect to it</span>
-
- <div class="source">
- <table border="0" cellpadding="0" cellspacing="0" width=
- "100%">
- <tbody>
- <tr>
- <td>Stan Source</td>
-
- <td width="100%"><a href=
- "sources/tests/testformless.py">tests/testformless.py</a></td>
- </tr>
- </tbody>
- </table>Live example: <a href=
- "formless_redirector">formless_redirector</a>
- </div>
- </li>
-
- <li>
- <span>Example of interacting with a database</span>
-
- <div class="source">
- <table border="0" cellpadding="0" cellspacing="0" width=
- "100%">
- <tbody>
- <tr>
- <td>Stan Source:</td>
-
- <td width="100%"><a href=
- "sources/db/db.py">db.py</a></td>
- </tr>
- </tbody>
- </table>Live examples: <a href="db/">db</a>
- </div>
- </li>
-
- <li>
<span>An example of using HTTP Basic Auth for simple
authentication</span>
@@ -637,25 +515,6 @@
</li>
<li>
- <span>Dynamically build your forms</span>
-
- <div class="source">
- <table border="0" cellpadding="0" cellspacing="0" width=
- "100%">
- <tbody>
- <tr>
- <td>Stan Source</td>
-
- <td width="100%"><a href=
- "sources/formbuilder/formbuilder.py">formbuilder.py</a></td>
- </tr>
- </tbody>
- </table>Live example: <a href=
- "formbuilder/">formbuilder</a>
- </div>
- </li>
-
- <li>
<span>Adapting an object to the IRenderer interface in
order to make it render itself</span>
@@ -695,24 +554,6 @@
</li>
<li>
- <span>Handling and building a Tree structure dynamically on
- yor site</span>
-
- <div class="source">
- <table border="0" cellpadding="0" cellspacing="0">
- <tbody>
- <tr>
- <td>Stan Source</td>
-
- <td width="100%"><a href=
- "sources/tree/tree.py">tree.py</a></td>
- </tr>
- </tbody>
- </table>Live example: <a href="tree/">tree</a>
- </div>
- </li>
-
- <li>
<span>Simple example of text localisation</span>
<div class="source">
@@ -961,22 +802,6 @@
</li>
<li>
- <span>Pastebin example with nevow</span>
-
- <div class="source">
- Source: <a href="sources/pastebin">pastebin</a>
- </div>
- </li>
-
- <li>
- <span>Blog engine</span>
-
- <div class="source">
- Source: <a href="sources/blogengine">blogengine</a>
- </div>
- </li>
-
- <li>
<span>Link storage webservice (uses Twisted's
XML-RPC)</span>
@@ -984,23 +809,6 @@
Source: <a href="sources/postit">postit</a>
</div>
</li>
-
- <li>
- <span>Todo list with rails like file structure (requires
- pgasync 1.3b and postgres)</span>
-
- <div class="source">
- Source: <a href="sources/todo">todo</a>
- </div>
- </li>
-
- <li>
- <span>Image uploader that uses axiom</span>
-
- <div class="source">
- Source: <a href="sources/image_uploader">imagination</a>
- </div>
- </li>
</ul>
</div>
</body>
=== removed directory 'Nevow/examples/pastebin'
=== removed file 'Nevow/examples/pastebin/TODO'
--- Nevow/examples/pastebin/TODO 2005-10-14 17:36:24 +0000
+++ Nevow/examples/pastebin/TODO 1970-01-01 00:00:00 +0000
@@ -1,11 +0,0 @@
-Syntax highlighting: Python, HTML, diff etc
-Coloured diff view
-Cookie to save author
-UI - move menu etc to right
-View | Edit when viewing latest revision
-Line numbers
-Wrap the syntax highlighted bit.
-
-Syntax highligh options:
-t.p.htmlizer, enscript, webcpp, SilverCity
-copy source code highlight code from viewcvs
=== removed directory 'Nevow/examples/pastebin/data'
=== removed directory 'Nevow/examples/pastebin/pastebin'
=== removed file 'Nevow/examples/pastebin/pastebin.tac'
--- Nevow/examples/pastebin/pastebin.tac 2005-10-14 17:36:24 +0000
+++ Nevow/examples/pastebin/pastebin.tac 1970-01-01 00:00:00 +0000
@@ -1,25 +0,0 @@
-from twisted.application import strports
-from twisted.application import service
-
-from twisted.web import static
-
-from nevow import appserver
-from nevow import vhost
-
-from pastebin import interfaces
-from pastebin.service import FSPasteBinService
-from pastebin.web import pages
-
-
-application = service.Application('pastebin')
-
-pastebin = FSPasteBinService('data')
-pastebin.setServiceParent(application)
-
-appResource = pages.RootPage(pastebin)
-appResource.putChild('robots.txt', static.File('static/robots.txt'))
-vResource = vhost.VHostMonsterResource()
-appResource.putChild('vhost', vResource)
-
-
-strports.service("8080", appserver.NevowSite(appResource)).setServiceParent(application)
=== removed file 'Nevow/examples/pastebin/pastebin/__init__.py'
=== removed file 'Nevow/examples/pastebin/pastebin/interfaces.py'
--- Nevow/examples/pastebin/pastebin/interfaces.py 2006-03-08 14:28:41 +0000
+++ Nevow/examples/pastebin/pastebin/interfaces.py 1970-01-01 00:00:00 +0000
@@ -1,18 +0,0 @@
-from zope.interface import Interface
-
-class IPasteBin(Interface):
-
- def getListOfPastings(limit=None):
- """
- (oid, author, time) tuples
- """
- pass
-
- def getPasting(oid):
- pass
-
- def addPasting(author, text):
- pass
-
- def updatePasting(oid, author, text):
- pass
=== removed file 'Nevow/examples/pastebin/pastebin/pasting.py'
--- Nevow/examples/pastebin/pastebin/pasting.py 2006-03-08 14:28:41 +0000
+++ Nevow/examples/pastebin/pastebin/pasting.py 1970-01-01 00:00:00 +0000
@@ -1,25 +0,0 @@
-from zope.interface import Interface
-
-
-class IPasting(Interface):
-
- def getLatestVersion():
- """Return the latest version"""
-
- def getVersion(version):
- """Get a specific version"""
-
- def getHistory():
- """Get the history of the pasting as a list of (version, author, time) tuples."""
-
-
-class IVersion(Interface):
-
- def getAuthor():
- pass
-
- def getText():
- pass
-
- def getTime():
- pass
=== removed file 'Nevow/examples/pastebin/pastebin/service.py'
--- Nevow/examples/pastebin/pastebin/service.py 2005-10-14 17:36:24 +0000
+++ Nevow/examples/pastebin/pastebin/service.py 1970-01-01 00:00:00 +0000
@@ -1,120 +0,0 @@
-import cPickle as pickle
-import os.path
-import time
-from zope.interface import implements
-
-from twisted.application import service
-from twisted.python import log
-
-from pastebin import interfaces
-from pastebin import pasting
-
-
-class Record(object):
-
- def __init__(self, oid, author, time):
- self.oid = oid
- self.author = author
- self.time = time
- self.version = 0
-
-
-class FSPasteBinService(service.Service):
-
- implements(interfaces.IPasteBin)
-
- def __init__(self, storageDir):
- self._dir = storageDir
-
- def getListOfPastings(self, limit=None):
- if limit is None:
- limited = self._index
- else:
- limited = self._index[0:limit]
- return [(r.oid, r.author, r.time) for r in limited]
-
- def _makeFilename(self, name):
- return os.path.join(self._dir, name)
-
- def _loadPastingData(self, oid):
- f = file(self._makeFilename(str(oid)), 'rb')
- return pickle.load(f)
-
- def _savePastingData(self, oid, data):
- f = file(self._makeFilename(str(oid)), 'wb')
- pickle.dump(data, f, pickle.HIGHEST_PROTOCOL)
-
- def getPasting(self, oid):
- data = self._loadPastingData(oid)
- return Pasting(data)
-
- def addPasting(self, author, text):
- oid = self._nextOid
- now = time.gmtime()
- data = [{'author':author, 'time':now, 'text':text}]
- self._savePastingData(oid, data)
- self._index.insert(0, Record(oid, author, now))
- self._nextOid += 1
- return oid
-
- def updatePasting(self, oid, author, text):
- now = time.gmtime()
- data = self._loadPastingData(oid)
- data.append({'author':author, 'time':now, 'text':text})
- self._savePastingData(oid, data)
- for i, r in enumerate(self._index):
- if r.oid == oid:
- r.time = now
- self._index.insert(0,self._index.pop(i))
-
- def startService(self):
- log.msg('Loading index')
- try:
- f = file(self._makeFilename('index'), 'rb')
- d = pickle.load(f)
- self._index = d['index']
- self._nextOid = d['nextOid']
- except IOError:
- self._index = []
- self._nextOid = 1
-
- def stopService(self):
- log.msg('Storing index')
- d = {'index':self._index, 'nextOid':self._nextOid}
- f = file(self._makeFilename('index'), 'wb')
- pickle.dump(d, f, pickle.HIGHEST_PROTOCOL)
-
-class Pasting(object):
-
- implements(pasting.IPasting)
-
- def __init__(self, data):
- self._data = data
-
- def getLatestVersion(self):
- return self.getVersion(-1)
-
- def getVersion(self, version):
- return Version(self._data[version])
-
- def getHistory(self):
- history = [(i,d['author'],d['time']) for i,d in enumerate(self._data)]
- history.reverse()
- return history
-
-
-class Version:
-
- implements(pasting.IVersion)
-
- def __init__(self, data):
- self._data = data
-
- def getAuthor(self):
- return self._data['author']
-
- def getText(self):
- return self._data['text']
-
- def getTime(self):
- return self._data['time']
=== removed directory 'Nevow/examples/pastebin/pastebin/web'
=== removed file 'Nevow/examples/pastebin/pastebin/web/__init__.py'
=== removed file 'Nevow/examples/pastebin/pastebin/web/pages.py'
--- Nevow/examples/pastebin/pastebin/web/pages.py 2006-04-14 17:23:46 +0000
+++ Nevow/examples/pastebin/pastebin/web/pages.py 1970-01-01 00:00:00 +0000
@@ -1,212 +0,0 @@
-from cStringIO import StringIO
-import time
-from zope.interface import implements
-
-from twisted.python import htmlizer
-from twisted.web import static
-
-from nevow import loaders
-from nevow import rend
-from nevow import tags
-from nevow import url
-
-from formless import annotate
-from formless import iformless
-from formless import webform
-
-ANONYMOUS = 'anonymous'
-
-
-##
-# Text colourisers (aka syntax highlighting)
-##
-
-def _python_colouriser(text):
- out = StringIO()
- try:
- htmlizer.filter(StringIO(text), out)
- except AttributeError:
- out = StringIO("""Starting after Nevow 0.4.1 Twisted
-2.0 is a required dependency. Please install it""")
- return out.getvalue()
-
-_colourisers = {
- 'python': _python_colouriser
- }
-
-
-##
-# Formless
-##
-
-class IAddPasting(annotate.TypedInterface):
- def addPasting(
- request=annotate.Request(),
- author=annotate.String(strip=True),
- text=annotate.Text(strip=True, required=True)):
- pass
- addPasting = annotate.autocallable(addPasting)
-
-
-class IEditPasting(annotate.TypedInterface):
- def editPasting(
- request=annotate.Request(),
- postedBy=annotate.String(immutable=1),
- author=annotate.String(strip=True),
- text=annotate.Text(strip=True, required=True)):
- pass
- editPasting = annotate.autocallable(editPasting)
-
-
-##
-# "Standard" renderers
-##
-
-def render_time(theTime):
- def _(context, data):
- return time.strftime('%Y-%m-%d %H:%M:%S %Z', theTime)
- return _
-
-def render_pastingText(text):
- def _(context, data):
- colouriser = _colourisers.get('python')
- if colouriser:
- return tags.xml(colouriser(text))
- return tags.pre[tags.xml(text)]
- return _
-
-def render_pasting(version):
- def _(context, data):
- context.fillSlots('author', version.getAuthor() or ANONYMOUS)
- time = context.fillSlots('time', render_time(version.getTime()))
- text = context.fillSlots('text', render_pastingText(version.getText()))
- return context.tag
- return _
-
-
-class BasePage(rend.Page):
-
- docFactory = loaders.htmlfile(templateDir='templates', template='site.html')
-
- child_css = static.File('static/css')
- child_images = static.File('static/images')
-
- def data_pastings(self, context, data):
- return self.pastebin.getListOfPastings(20)
-
- def render_pasting(self, context, data):
- oid, author, time = data
- context.tag.fillSlots('url', url.root.child(str(oid)))
- context.tag.fillSlots('id', oid)
- context.tag.fillSlots('author', author or ANONYMOUS)
- return context.tag
-
- def render_content(self, context, data):
- tag = context.tag.clear()
- tag[loaders.htmlfile(templateDir='templates', template=self.contentTemplateFile)]
- return tag
-
-
-class RootPage(BasePage):
- implements(IAddPasting)
-
- addSlash = True
-
- def __init__(self, pastebin):
- BasePage.__init__(self)
- self.pastebin = pastebin
-
- def locateChild(self, context, segments):
- try:
- return Pasting(self.pastebin, int(segments[0])), segments[1:]
- except ValueError:
- pass
- return BasePage.locateChild(self, context, segments)
-
- def render_content(self, context, data):
- tag = context.tag.clear()
- return tag[webform.renderForms()]
-
- def addPasting(self, request, author, text):
- oid = self.pastebin.addPasting(author, text)
- request.setComponent(iformless.IRedirectAfterPost, '/'+str(oid))
-
-
-class Pasting(BasePage):
-
- implements(IEditPasting)
- contentTemplateFile = 'pasting.html'
-
- def __init__(self, pastebin, pastingOid, version=-1):
- BasePage.__init__(self)
- self.pastebin = pastebin
- self.pastingOid = pastingOid
- self.version = version
- self.pasting = self.pastebin.getPasting(self.pastingOid)
-
- def locateChild(self, context, segments):
- try:
- return Pasting(self.pastebin, self.pastingOid, int(segments[0])), segments[1:]
- except:
- pass
- return BasePage.locateChild(self, context, segments)
-
- def data_history(self, context, data):
- return self.pasting.getHistory()
-
- def render_aPasting(self, context, data):
- return render_pasting(self.pasting.getVersion(self.version))
-
- def render_form(self, context, data):
- if self.version != -1:
- return ''
- version = self.pasting.getVersion(self.version)
- formDefaults = context.locate(iformless.IFormDefaults)
- formDefaults.setDefault('editPasting.text', version.getText())
- formDefaults.setDefault('editPasting.postedBy', version.getAuthor())
- return webform.renderForms()
-
- def render_version(self, context, data):
- version, author, theTime = data
- if self.version == -1:
- u = url.here.child
- else:
- u = url.here.sibling
- context.tag.fillSlots('url', u(version))
- context.tag.fillSlots('time', render_time(theTime))
- context.tag.fillSlots('author', author or ANONYMOUS)
-## context.fillSlots('link', a(href=[u(version)])[
-## render_time(theTime), ' (',author or ANONYMOUS,')'
-## ])
- return context.tag
-
- def editPasting(self, request, postedBy, author, text):
- self.pastebin.updatePasting(self.pastingOid, author, text)
- request.setComponent(iformless.IRedirectAfterPost, '/%s'%self.pastingOid)
-
-
-class Version(BasePage):
-
- contentTemplateFile = "pasting.html"
-
- child_ = rend.FourOhFour()
-
- def __init__(self, pastebin, pasting, version):
- BasePage.__init__(self)
- self.pastebin = pastebin
- self.pasting = pasting
- self.version = version
-
- def data_history(self, context, data):
- return self.pasting.getHistory()
-
- def render_aPasting(self, context, data):
- return render_pasting(self.pasting.getVersion(self.version))
-
- def render_version(self, context, data):
- version, author, theTime = data
- context.fillSlots('link', tags.a(href=[url.here.sibling(str(version))])[
- render_time(theTime), ' (',author,')'
- ])
- return context.tag
-
=== removed directory 'Nevow/examples/pastebin/static'
=== removed directory 'Nevow/examples/pastebin/static/css'
=== removed file 'Nevow/examples/pastebin/static/css/default.css'
--- Nevow/examples/pastebin/static/css/default.css 2005-10-14 17:36:24 +0000
+++ Nevow/examples/pastebin/static/css/default.css 1970-01-01 00:00:00 +0000
@@ -1,100 +0,0 @@
-body
-{
- margin: 0;
- padding: 1em 1em;
- color: #330033;
- font-size: 10pt;
-}
-
-a
-{
- color: inherit;
-}
-
-a:visited
-{
- color: #996699;
-}
-
-#header
-{
- border-bottom: 1px solid #cccc99;
-}
-
-#header h1
-{
- padding: 0;
- margin: 0;
- color: #cccc66;
-}
-
-#footer
-{
- padding: 0.1em 0.5em;
- margin-top: 1em;
- clear: both;
- border-top: 1px solid #cccc99;
- font-size: 77%;
- color: #666699;
-}
-
-#content-container
-{
- margin: 2em 0.5em;
-}
-
-#nav
-{
- position: relative;
- float: left;
- width: 10em;
-}
-
-#menu, #pastings
-{
- list-style: url(/images/pasting.gif);
- padding: 0 0 0 18px;
- margin-top: 0;
-}
-
-#content
-{
- margin-left: 10em;
-}
-
-div.pastingText
-{
- padding: 0.5em;
- background-color: #fafafa;
- color: #333;
- border: 1px solid #ccc;
- overflow: auto;
-}
-
-div.pastingText pre
-{
- margin: 0;
-}
-
-.revision-history
-{
- font-size: 86%;
-}
-
-.view-menu
-{
- list-style: none;
- margin: 1em 0;
- padding: 0;
-}
-
-.view-menu li
-{
- display: inline;
- margin-right: 1em;
-}
-
-.view-menu li a
-{
- color: inherit;
-}
=== removed file 'Nevow/examples/pastebin/static/css/freeform.css'
--- Nevow/examples/pastebin/static/css/freeform.css 2005-10-14 17:36:24 +0000
+++ Nevow/examples/pastebin/static/css/freeform.css 1970-01-01 00:00:00 +0000
@@ -1,27 +0,0 @@
-
-.freeform-typed { clear: both; }
-.freeform-property-binding { clear: both; border: 1px solid blue; padding: 0.5em; width: auto }
-.freeform-method-binding { clear: both; border: 1px solid black; padding: 0.5em; width: auto }
-.freeform-argument-binding { clear: both; border: 1px solid blue; padding: 0.5em; width: auto }
-.freeform-binding-content { border-top: 1px dashed #bdedfe; margin-top: 0.5em; padding-top: 0.5em }
-.freeform-label { float: left; width: 200px; }
-.freeform-input { float: left; width: 200px; }
-.freeform-error { color: red; }
-.freeform-description { clear: both; border-bottom: 1px dashed #bdedfe; margin-bottom: 0.5em; padding-bottom: 0.5em }
-.freeform-list-item { clear: both; width: auto }
-.freeform-form-label { color: #666666 }
-
-.freeform-textarea { width: 5in; height: 3in }
-
-.freeform-success { padding: 0.5em; border: 1px dashed green; }
-.freeform-failure { padding: 0.5em; color: red; border: 1px dashed red; }
-
-.freeform-list { border: 1px dashed #cdcdcd; }
-.freeform-dictionary { border: 1px dashed #dedede; }
-.freeform-action-group { margin: 0px }
-.freeform-action { color: green }
-.freeform-action-selection { background-color: red; height: 1em; width: 1em; }
-
-.freeform-group-binding { border: 1px dashed #efabab }
-.freeform-grouped-property-binding {}
-.freeform-grouped-method-binding {}
=== removed file 'Nevow/examples/pastebin/static/css/python.css'
--- Nevow/examples/pastebin/static/css/python.css 2005-10-14 17:36:24 +0000
+++ Nevow/examples/pastebin/static/css/python.css 1970-01-01 00:00:00 +0000
@@ -1,32 +0,0 @@
-.py-src-comment
-{
- color: #1111CC
-}
-
-.py-src-keyword
-{
- color: #3333CC;
- font-weight: bold;
-}
-
-.py-src-parameter
-{
- color: #000066;
- font-weight: bold;
-}
-
-.py-src-identifier
-{
- color: #CC0000
-}
-
-.py-src-string
-{
-
- color: #115511
-}
-
-.py-src-endmarker
-{
- display: block; /* IE hack; prevents following line from being sucked into the py-listing box. */
-}
=== removed file 'Nevow/examples/pastebin/static/css/standard.css'
--- Nevow/examples/pastebin/static/css/standard.css 2005-10-14 17:36:24 +0000
+++ Nevow/examples/pastebin/static/css/standard.css 1970-01-01 00:00:00 +0000
@@ -1,25 +0,0 @@
-body
-{
- font-family: Verdana, Geneva, "Bitstream Vera Sans", Helvetica;
- /* font-family: Georgia, "Bitstream Vera Serif", "New York", Palatino; */
- font-size: 103%;
-}
-
-th, td /* Needed for NN4 as its tables do not inherit styles */
-{
- font-family: Verdana, Geneva, "Bitstream Vera Sans", Helvetica;
- /* font-family: Georgia, "Bitstream Vera Serif", "New York", Palatino; */
- font-size: 103%;
-}
-
-/* Headers */
-h1 { font-size: 160%; }
-h2 { font-size: 130%; }
-h3 { font-size: 116%; }
-
-
-/* Standard sizes */
-.normal-size { font-size: 103%; }
-.small { font-size: 88%; }
-.smaller { font-size: 77%; }
-.smallest { font-size: 68%; }
=== removed directory 'Nevow/examples/pastebin/static/images'
=== removed file 'Nevow/examples/pastebin/static/images/pasting.gif'
Binary files Nevow/examples/pastebin/static/images/pasting.gif 2005-10-14 17:36:24 +0000 and Nevow/examples/pastebin/static/images/pasting.gif 1970-01-01 00:00:00 +0000 differ
=== removed file 'Nevow/examples/pastebin/static/robots.txt'
--- Nevow/examples/pastebin/static/robots.txt 2005-10-14 17:36:24 +0000
+++ Nevow/examples/pastebin/static/robots.txt 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-User-agent: *
-Disallow: /
=== removed directory 'Nevow/examples/pastebin/templates'
=== removed file 'Nevow/examples/pastebin/templates/pasting.html'
--- Nevow/examples/pastebin/templates/pasting.html 2005-10-14 17:36:24 +0000
+++ Nevow/examples/pastebin/templates/pasting.html 1970-01-01 00:00:00 +0000
@@ -1,14 +0,0 @@
-<div nevow:render="aPasting">
-
- <p>Pasted by <nevow:slot name="author">author</nevow:slot> at <nevow:slot name="time">time</nevow:slot>.</p>
- <div class="pastingText"><nevow:slot name="text">Pasting goes here</nevow:slot></div>
- <div class="revision-history">
- <p>Revision history:</p>
- <ul nevow:render="sequence" nevow:data="history">
- <li nevow:pattern="item" nevow:render="version"><a href=""><nevow:attr name="href"><nevow:slot name="url"/></nevow:attr><nevow:slot name="time"/> (<nevow:slot name="author"/>)</a></li>
- </ul>
- </div>
-
- <form nevow:render="form"/>
-
-</div>
=== removed file 'Nevow/examples/pastebin/templates/site.html'
--- Nevow/examples/pastebin/templates/site.html 2005-10-14 17:36:24 +0000
+++ Nevow/examples/pastebin/templates/site.html 1970-01-01 00:00:00 +0000
@@ -1,50 +0,0 @@
-<?xml version="1.0"?>
-
-<html xmlns="http://www.w3.org/1999/xhtml";>
-
- <head>
- <title>Twisted Pastebin</title>
- <link rel="stylesheet" type="text/css" href="/css/standard.css"/>
- <link rel="stylesheet" type="text/css" href="/css/default.css"/>
- <link rel="stylesheet" type="text/css" href="/css/freeform.css"/>
- <link rel="stylesheet" type="text/css" href="/css/python.css"/>
- </head>
-
- <body>
-
- <div id="header">
- <h1>Twisted Pastebin</h1>
- </div>
-
- <div id="content-container">
-
- <div id="nav">
-
- Menu:
- <ul id="menu">
- <li><a href="/">Add pasting</a></li>
- </ul>
-
- Recent pastings:
- <ul id="pastings" nevow:data="pastings" nevow:render="sequence">
- <li nevow:pattern="empty"><em>none</em></li>
- <li nevow:pattern="item" nevow:render="pasting">
- <a href="#"><nevow:attr name="href"><nevow:slot name="url"/></nevow:attr><nevow:slot name="id" /> (<nevow:slot name="author"/>)</a>
- </li>
- </ul>
-
- </div>
-
- <div id="content" nevow:render="content">
- </div>
-
- </div>
-
- <div id="footer">
- Powered by <a href="http://www.twistedmatrix.com/";>Twisted</a> and
- <a href="http://divmod.org/users/wiki.twistd/nevow/moin.cgi";>Nevow</a>.
- </div>
-
- </body>
-
-</html>
=== removed file 'Nevow/examples/tests/testformless.py'
--- Nevow/examples/tests/testformless.py 2006-04-14 17:23:46 +0000
+++ Nevow/examples/tests/testformless.py 1970-01-01 00:00:00 +0000
@@ -1,105 +0,0 @@
-
-from twisted.internet import defer
-
-from formless import annotate, webform
-
-from nevow import rend, loaders, tags, livetest, url, livepage
-
-
-"""WWWWizard functionality!
-"""
-
-
-test_suite = [
- ('visit', '/formpost/', ''),
- ('value', 'foo-foo', '5'),
- ('post', 'foo', {'foo-foo': 'asdf'}),
- ('assert', livetest.xpath('//form[@id="foo"]//div[@class="freeform-form-error"]'), "'asdf' is not an integer."),
- ## Check to make sure we repopulate the user's input with the erronious input
- ('value', 'foo-foo', 'asdf'),
- ('post', 'foo', {'foo-foo': '10'}),
- ('value', 'foo-foo', '10'),
- ]
-
-
-test_suite += [
- ('visit', '/formpost2/', ''),
- ('post', 'bar', {'bar-baz': '5', 'bar-slam': '5', 'bar-ham': 'efgh', 'bar-custom': '1'}),
- ## XXX TODO: Can't post a radio button, so there is "None" below
- ('assert', livetest.xpath('//h3'), "You called bar! 5 5 efgh None {'stuff': 1234, 'name': 'One'}")
-]
-
-test_suite += [
- ('visit', '/testformless', ''),
- ('post', 'name', {'name-name': 'Fred'}),
- ('post', 'quest', {'quest-quest': 'Find the Grail'}),
- ('post', 'speed', {'speed-speed': '123'}),
- ('assert', 'body', "Thanks for taking our survey! You said: 'Fred' 'Find the Grail' 123")]
-
-
-class NameWizard(rend.Page):
- docFactory = loaders.stan(tags.html[tags.h1["What is your name"], webform.renderForms()])
-
- def bind_name(self, ctx):
- return [('name', annotate.String())]
-
- def name(self, name):
- return QuestWizard(name)
-
-
-class QuestWizard(rend.Page):
- docFactory = loaders.stan(tags.html[tags.h1["What is your quest"], webform.renderForms()])
-
- def bind_quest(self, ctx):
- return [('quest', annotate.Choice(['Find the Grail', 'Get laid', 'Earn twenty bucks', 'Destroy the sun']))]
-
- def quest(self, quest):
- return FinalWizard((self.original, quest))
-
-
-class FinalWizard(rend.Page):
- docFactory = loaders.stan(tags.html[tags.h1["What is the airspeed velocity of an unladen swallow"], webform.renderForms()])
-
- def bind_speed(self, ctx):
- return [('speed', annotate.Integer())]
-
- def speed(self, speed):
- return rend.Page(
- docFactory=loaders.stan(
- tags.html[
- tags.body(id='body')[
- "Thanks for taking our survey! You said: %r %r %r" % (
- self.original[0], self.original[1], speed)]]))
-
-
-def checkLocation(client):
- d = defer.Deferred()
- def gotResult(ctx, location):
- from urlparse import urlparse
- if urlparse(location)[2] == '/':
- d.callback(None)
- else:
- d.errback(None)
- client.send(client.transient(gotResult, livepage.js.testFrameNode.contentDocument.location))
- return d
-
-
-test_suite += [
- ('visit', '/formless_redirector', ''),
- ('post', 'goHome', {}),
- ('call', checkLocation, ())]
-
-
-class Redirector(rend.Page):
- docFactory = loaders.stan(tags.html[tags.body[webform.renderForms()]])
-
- def bind_goHome(self, ctx):
- return []
-
- def goHome(self):
- return url.root
-
-
-formless_tests = livetest.Tester(test_suite)
-
-
=== removed directory 'Nevow/examples/todo'
=== removed file 'Nevow/examples/todo/controller.py'
--- Nevow/examples/todo/controller.py 2006-03-17 15:00:39 +0000
+++ Nevow/examples/todo/controller.py 1970-01-01 00:00:00 +0000
@@ -1,83 +0,0 @@
-from zope.interface import implements
-
-from nevow import rend, loaders, tags as t
-from formless import annotate, webform
-from time import time as now
-import itodo
-
-class ITodo(annotate.TypedInterface):
- def insert(ctx=annotate.Context(),
- description=annotate.String(required=True,
- requiredFailMessage="Description Missing")
- ):
- pass
- insert = annotate.autocallable(insert, action="New Todo")
- def delete(ctx=annotate.Context(), id=annotate.Integer()):
- pass
- delete = annotate.autocallable(delete, invisible=True)
- def update(ctx=annotate.Context(),
- id=annotate.Integer(),
- oldstate=annotate.Integer()):
- pass
- update = annotate.autocallable(update, invisible=True)
-
-class Root(rend.Page):
- implements(ITodo)
-
- child_css = webform.defaultCSS
-
- docFactory = loaders.stan(
- t.html(render=t.directive("time"))[
- t.head[
- t.title['todo'],
- t.style(type="text/css")[".done { color: #dddddd; }"],
- t.style(type="text/css")["@import url(/css);"]
- ],
- t.body[
- webform.renderForms(),
- t.ul(data=t.directive("findAll"),
- render=t.directive("sequence"))[
- t.li(pattern="item",render=t.directive('todo')),
- t.li(pattern="empty",render=t.directive('empty')),
- ],
- t.p(render=t.directive("end"))
- ]
- ]
- )
-
- def insert(self, ctx, description):
- return itodo.ITodos(ctx).add(description, 0)
-
- def delete(self, ctx, id):
- return itodo.ITodos(ctx).delete(id)
-
- def update(self, ctx, id, oldstate):
- newstate = [1, 0][oldstate]
- return itodo.ITodos(ctx).update(id, newstate)
-
- def data_findAll(self, ctx, data):
- return itodo.ITodos(ctx).findAll()
-
- def render_todo(self, ctx, data):
- deluri = "freeform_post!!delete?id="+str(data[0])
- updateuri = "freeform_post!!update?id="+str(data[0])+"&oldstate="+str(data[2])
- state = [" Done", " To Do"][int(data[2])==0]
- tag = ctx.tag
- if data[2]:
- tag = ctx.tag(_class="done")
- return tag[data[1]+" - ",
- t.a(href=deluri)["Delete"], " / ",
- t.a(href=updateuri)[("Mark Done", "Mark Undone")[data[2]]],
- state]
-
- def render_empty(self, ctx, data):
- return ctx.tag["No Todos"]
-
- def render_time(self, ctx, data):
- ctx.remember(now(), itodo.ITimer)
- return ctx.tag
-
- def render_end(self, ctx, data):
- return ctx.tag["%.3f"%(now()-itodo.ITimer(ctx))]
-
-root = Root()
=== removed file 'Nevow/examples/todo/database.sql'
--- Nevow/examples/todo/database.sql 2005-10-14 17:36:24 +0000
+++ Nevow/examples/todo/database.sql 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-CREATE TABLE todos (
- id serial primary key,
- description varchar(100) not null,
- done int not null
-)
\ No newline at end of file
=== removed file 'Nevow/examples/todo/dispatcher.py'
--- Nevow/examples/todo/dispatcher.py 2005-10-14 17:36:24 +0000
+++ Nevow/examples/todo/dispatcher.py 1970-01-01 00:00:00 +0000
@@ -1,13 +0,0 @@
-from nevow import rend
-import itodo
-import controller
-
-# All this is only useful to dynamically update the web page code
-# without restarting the server each time. As you can see below, you can
-# disable this by putting a false value in the Env object.
-
-class Dispatch(rend.Page):
- def locateChild(self, ctx, segments):
- if itodo.IEnv(ctx).development:
- reload(controller)
- return controller.root.locateChild(ctx,segments)
=== removed file 'Nevow/examples/todo/environment.py'
--- Nevow/examples/todo/environment.py 2005-10-14 17:36:24 +0000
+++ Nevow/examples/todo/environment.py 1970-01-01 00:00:00 +0000
@@ -1,8 +0,0 @@
-class Env(object):
- user='test'
- password='test'
- port=5432
- host='localhost'
- dbname='todo'
- development=False
-env = Env()
=== removed file 'Nevow/examples/todo/itodo.py'
--- Nevow/examples/todo/itodo.py 2006-03-08 14:28:41 +0000
+++ Nevow/examples/todo/itodo.py 1970-01-01 00:00:00 +0000
@@ -1,16 +0,0 @@
-from zope.interface import Interface
-
-class ITimer(Interface):
- """ """
-
-class IEnv(Interface):
- """ """
-
-class ITodos(Interface):
- """ """
- def add(description, done):
- pass
- def delete(id):
- pass
- def edit(id, description, done):
- pass
=== removed file 'Nevow/examples/todo/store.py'
--- Nevow/examples/todo/store.py 2005-10-14 17:36:24 +0000
+++ Nevow/examples/todo/store.py 1970-01-01 00:00:00 +0000
@@ -1,29 +0,0 @@
-from zope.interface import implements
-import pgasync
-import itodo
-
-class Todos(object):
- implements(itodo.ITodos)
- def __init__(self, dbname, user, password, host):
- self.original = pgasync.ConnectionPool("pgasync", dbname=dbname,
- user=user, password=password, host=host)
-
- def add(self, description, done):
- query = "INSERT INTO todos (description, done) VALUES (%(description)s,%(done)s)"
- args = dict(description=description, done=done)
- return self.original.runOperation(query, args)
-
- def delete(self, id):
- query="DELETE FROM todos WHERE id=%(id)s"
- args = dict(id=id)
- return self.original.runOperation(query, args)
-
- def update(self, id, state):
- query = "UPDATE todos SET done=%(done)s WHERE id=%(id)s"
- args = dict(id=id, done=state)
- return self.original.runOperation(query, args)
-
- def findAll(self):
- query = "SELECT * FROM todos"
- return self.original.runQuery(query)
-
=== removed file 'Nevow/examples/todo/todo.tac'
--- Nevow/examples/todo/todo.tac 2005-10-14 17:36:24 +0000
+++ Nevow/examples/todo/todo.tac 1970-01-01 00:00:00 +0000
@@ -1,18 +0,0 @@
-from twisted.application import service, strports
-from nevow import appserver
-
-from environment import env as e
-import store
-import dispatcher
-import itodo
-
-application = service.Application('todo')
-db = store.Todos(e.dbname, e.user, e.password, e.host)
-disp = dispatcher.Dispatch()
-
-site = appserver.NevowSite(resource=disp)
-site.remember(db, itodo.ITodos)
-site.remember(e, itodo.IEnv)
-
-webserver = strports.service("tcp:8080", site)
-webserver.setServiceParent(application)
=== removed directory 'Nevow/examples/tree'
=== removed file 'Nevow/examples/tree/__init__.py'
=== removed file 'Nevow/examples/tree/tree.py'
--- Nevow/examples/tree/tree.py 2006-03-17 15:00:39 +0000
+++ Nevow/examples/tree/tree.py 1970-01-01 00:00:00 +0000
@@ -1,73 +0,0 @@
-from zope.interface import implements
-
-from twisted.python.components import registerAdapter
-
-from nevow import loaders, rend, inevow, tags as T
-from formless import annotate, webform
-
-class Tree(dict):
- def __init__(self, name, description, *children):
- self.name = name
- self.description = description
- for child in children:
- self.add(child)
- def add(self, child):
- self[child.name] = child
- def __nonzero__(self):
- return True
-
-class ITreeEdit(annotate.TypedInterface):
- def setDescription(description=annotate.String()):
- pass
- setDescription = annotate.autocallable(setDescription)
- def deleteChild(name=annotate.String(required=True)):
- pass
- deleteChild = annotate.autocallable(deleteChild, invisible=True)
- def addChild(name=annotate.String(required=True),
- description=annotate.String()):
- pass
- addChild = annotate.autocallable(addChild)
-
-class TreeRenderer(rend.Page):
- implements(ITreeEdit)
- addSlash = True
- docFactory = loaders.htmlstr("""
-<html>
-<head><title>Tree Editor</title></head>
-<body><h1><span nevow:data="description"
- nevow:render="string">Tree Description</span></h1>
-<span nevow:render="descriptionForm"/>
-<ol nevow:data="children" nevow:render="sequence">
-<li nevow:pattern="item"><span nevow:render="childLink"/>
-<span nevow:render="childDel"/>
-</li>
-</ol>
-<a href="..">Up</a>
-</body>
-</html>
- """)
- def setDescription(self, description):
- self.original.description = description
- def addChild(self, name, description):
- self.original.add(Tree(name, description))
- def deleteChild(self, name):
- del self.original[name]
- def data_description(self, context, data):
- return self.original.description
- def data_children(self, context, data):
- return self.original.items()
- def render_childLink(self, context, data):
- return T.a(href='subtree_%s/'%data[0])[data[1].description]
- def childFactory(self, ctx, name):
- if name.startswith('subtree_'):
- return self.original[name[len('subtree_'):]]
- def render_descriptionForm(self, context, data):
- return webform.renderForms()
- def render_childDel(self, context, (name, _)):
- ret = T.form(action="./freeform_post!!deleteChild",
- enctype="multipart/form-data", method="POST")[
- T.input(type="hidden", name="name", value=name),
- T.input(type="submit", value="Delete")]
- return ret
-
-registerAdapter(TreeRenderer, Tree, inevow.IResource)
=== removed directory 'Nevow/formless'
=== removed file 'Nevow/formless/__init__.py'
--- Nevow/formless/__init__.py 2005-10-14 17:36:24 +0000
+++ Nevow/formless/__init__.py 1970-01-01 00:00:00 +0000
@@ -1,10 +0,0 @@
-# Copyright (c) 2004 Divmod.
-# See LICENSE for details.
-
-# FIXME: remove next two lines after fixing compyCompat to have lazy importing.
-# or else moving formless' adapter registration here.
-import nevow
-del nevow
-
-from formless.annotate import *
-from formless.processors import process
=== removed file 'Nevow/formless/annotate.py'
--- Nevow/formless/annotate.py 2010-02-06 04:33:05 +0000
+++ Nevow/formless/annotate.py 1970-01-01 00:00:00 +0000
@@ -1,852 +0,0 @@
-# -*- test-case-name: formless.test -*-
-# Copyright (c) 2004 Divmod.
-# See LICENSE for details.
-
-
-"""And the earth was without form, and void; and darkness was upon the face of the deep.
-"""
-
-import os
-import sys
-import inspect
-import warnings
-from zope.interface import implements
-from zope.interface.interface import InterfaceClass, Attribute
-
-from nevow import util
-
-
-from formless import iformless
-
-
-class count(object):
- def __init__(self):
- self.id = 0
- def next(self):
- self.id += 1
- return self.id
-
-nextId = count().next
-
-
-class InputError(Exception):
- """A Typed instance was unable to coerce from a string to the
- appropriate type.
- """
- def __init__(self, reason):
- self.reason = reason
-
- def __str__(self):
- return self.reason
-
-
-class ValidateError(Exception):
- """A Binding instance was unable to coerce all it's arguments from a
- dictionary of lists of strings to the appropriate types.
-
- One use of this is to raise from an autocallable if an input is invalid.
- For example, a password is incorrect.
-
- errors must be a dictionary mapping argument names to error messages
- to display next to the arguments on the form.
-
- formErrorMessage is a string to display at the top of the form, not tied to
- any specific argument on the form.
-
- partialForm is a dict mapping argument name to argument value, allowing
- you to have the form save values that were already entered in the form.
- """
- def __init__(self, errors, formErrorMessage=None, partialForm=None):
- self.errors = errors
- self.formErrorMessage = formErrorMessage
- if partialForm is None:
- self.partialForm = {}
- else:
- self.partialForm = partialForm
-
- def __str__(self):
- return self.formErrorMessage
-
-
-
-class Typed(Attribute):
- """A typed value. Subclasses of Typed are constructed inside of
- TypedInterface class definitions to describe the types of properties,
- the parameter types to method calls, and method return types.
-
- @ivar label: The short label which will describe this
- parameter/proerties purpose to the user.
-
- @ivar description: A long description which further describes the
- sort of input the user is expected to provide.
-
- @ivar default: A default value that may be used as an initial
- value in the form.
-
- @ivar required: Whether the user is required to provide a value
-
- @ivar null: The value which will be produced if required is False
- and the user does not provide a value
-
- @ivar unicode: Iff true, try to determine the character encoding
- of the data from the browser and pass unicode strings to
- coerce.
- """
- implements(iformless.ITyped)
-
- complexType = False
- strip = False
- label = None
- description = None
- default = ''
- required = False
- requiredFailMessage = 'Please enter a value'
- null = None
- unicode = False
-
- __name__ = ''
-
- def __init__(
- self,
- label=None,
- description=None,
- default=None,
- required=None,
- requiredFailMessage=None,
- null=None,
- unicode=None,
- **attributes):
-
- self.id = nextId()
- if label is not None:
- self.label = label
- if description is not None:
- self.description = description
- if default is not None:
- self.default = default
- if required is not None:
- self.required = required
- if requiredFailMessage is not None:
- self.requiredFailMessage = requiredFailMessage
- if null is not None:
- self.null = null
- if unicode is not None:
- self.unicode = unicode
- self.attributes = attributes
-
- def getAttribute(self, name, default=None):
- return self.attributes.get(name, default)
-
- def coerce(self, val, configurable):
- raise NotImplementedError, "Implement in %s" % util.qual(self.__class__)
-
-
-#######################################
-## External API; your code will create instances of these objects
-#######################################
-
-class String(Typed):
- """A string that is expected to be reasonably short and contain no
- newlines or tabs.
-
- strip: remove leading and trailing whitespace.
- """
-
- requiredFailMessage = 'Please enter a string.'
- # iff true, return the stripped value.
- strip = False
-
- def __init__(self, *args, **kwargs):
- try:
- self.strip = kwargs['strip']
- del kwargs['strip']
- except KeyError:
- pass
- Typed.__init__(self, *args, **kwargs)
-
- def coerce(self, val, configurable):
- if self.strip:
- val = val.strip()
- return val
-
-
-class Text(String):
- """A string that is likely to be of a significant length and
- probably contain newlines and tabs.
- """
-
-
-class Password(String):
- """Password is used when asking a user for a new password. The renderer
- user interface will possibly ask for the password multiple times to
- ensure it has been entered correctly. Typical use would be for
- registration of a new user."""
- requiredFailMessage = 'Please enter a password.'
-
-
-class PasswordEntry(String):
- """PasswordEntry is used to ask for an existing password. Typical use
- would be for login to an existing account."""
- requiredFailMessage = 'Please enter a password.'
-
-
-class FileUpload(Typed):
- requiredFailMessage = 'Please enter a file name.'
-
- def coerce(self, val, configurable):
- return val.filename
-
-
-class Integer(Typed):
-
- requiredFailMessage = 'Please enter an integer.'
-
- def coerce(self, val, configurable):
- if val is None:
- return None
- try:
- return int(val)
- except ValueError:
- if sys.version_info < (2,3): # Long/Int aren't integrated
- try:
- return long(val)
- except ValueError:
- raise InputError("'%s' is not an integer." % val)
-
- raise InputError("'%s' is not an integer." % val)
-
-
-class Real(Typed):
-
- requiredFailMessage = 'Please enter a real number.'
-
- def coerce(self, val, configurable):
- # TODO: This shouldn't be required; check.
- # val should never be None, but always a string.
- if val is None:
- return None
- try:
- return float(val)
- except ValueError:
- raise InputError("'%s' is not a real number." % val)
-
-
-class Boolean(Typed):
- def coerce(self, val, configurable):
- if val == 'False':
- return False
- elif val == 'True':
- return True
- raise InputError("'%s' is not a boolean" % val)
-
-
-class FixedDigitInteger(Integer):
-
- def __init__(self, digits = 1, *args, **kw):
- Integer.__init__(self, *args, **kw)
- self.digits = digits
- self.requiredFailMessage = \
- 'Please enter a %d digit integer.' % self.digits
-
- def coerce(self, val, configurable):
- v = Integer.coerce(self, val, configurable)
- if len(str(v)) != self.digits:
- raise InputError("Number must be %s digits." % self.digits)
- return v
-
-
-class Directory(Typed):
-
- requiredFailMessage = 'Please enter a directory name.'
-
- def coerce(self, val, configurable):
- # TODO: This shouldn't be required; check.
- # val should never be None, but always a string.
- if val is None:
- return None
- if not os.path.exists(val):
- raise InputError("The directory '%s' does not exist." % val)
- return val
-
-
-class Choice(Typed):
- """Allow the user to pick from a list of "choices", presented in a drop-down
- menu. The elements of the list will be rendered by calling the function
- passed to stringify, which is by default "str".
- """
-
- requiredFailMessage = 'Please choose an option.'
-
- def __init__(self, choices=None, choicesAttribute=None, stringify=str,
- valueToKey=str, keyToValue=None, keyAndConfigurableToValue=None,
- *args, **kw):
- """
- Create a Choice.
-
- @param choices: an object adaptable to IGettable for an iterator (such
- as a function which takes (ctx, data) and returns a list, a list
- itself, a tuple, a generator...)
-
- @param stringify: a pretty-printer. a function which takes an object
- in the list of choices and returns a label for it.
-
- @param valueToKey: a function which converts an object in the list of
- choices to a string that can be sent to a client.
-
- @param keyToValue: a 1-argument convenience version of
- keyAndConfigurableToValue
-
- @param keyAndConfigurableToValue: a 2-argument function which takes a string such as
- one returned from valueToKey and a configurable, and returns an object
- such as one from the list of choices.
- """
-
- Typed.__init__(self, *args, **kw)
- self.choices = choices
- if choicesAttribute:
- self.choicesAttribute = choicesAttribute
- if getattr(self, 'choicesAttribute', None):
- warnings.warn(
- "Choice.choicesAttribute is deprecated. Please pass a function to choices instead.",
- DeprecationWarning,
- stacklevel=2)
- def findTheChoices(ctx, data):
- return getattr(iformless.IConfigurable(ctx).original, self.choicesAttribute)
- self.choices = findTheChoices
-
- self.stringify = stringify
- self.valueToKey=valueToKey
-
- if keyAndConfigurableToValue is not None:
- assert keyToValue is None, 'This should be *obvious*'
- self.keyAndConfigurableToValue = keyAndConfigurableToValue
- elif keyToValue is not None:
- self.keyAndConfigurableToValue = lambda x,y: keyToValue(x)
- else:
- self.keyAndConfigurableToValue = lambda x,y: str(x)
-
-
- def coerce(self, val, configurable):
- """Coerce a value with the help of an object, which is the object
- we are configuring.
- """
- return self.keyAndConfigurableToValue(val, configurable)
-
-
-class Radio(Choice):
- """Type influencing presentation! horray!
-
- Show the user radio button choices instead of a picklist.
- """
-
-
-class Any(object):
- """Marker which indicates any object type.
- """
-
-
-class Object(Typed):
- complexType = True
- def __init__(self, interface=Any, *args, **kw):
- Typed.__init__(self, *args, **kw)
- self.iface = interface
-
- def __repr__(self):
- if self.iface is not None:
- return "%s(interface=%s)" % (self.__class__.__name__, util.qual(self.iface))
- return "%s(None)" % (self.__class__.__name__,)
-
-
-
-class List(Object):
- implements(iformless.IActionableType)
-
- complexType = True
- def __init__(self, actions=None, header='', footer='', separator='', *args, **kw):
- """Actions is a list of action methods which may be invoked on one
- or more of the elements of this list. Action methods are defined
- on a TypedInterface and declare that they take one parameter
- of type List. They do not declare themselves to be autocallable
- in the traditional manner. Instead, they are passed in the actions
- list of a list Property to declare that the action may be taken on
- one or more of the list elements.
- """
- if actions is None:
- actions = []
- self.actions = actions
- self.header = header
- self.footer = footer
- self.separator = separator
- Object.__init__(self, *args, **kw)
-
- def coerce(self, data, configurable):
- return data
-
- def __repr__(self):
- if self.iface is not None:
- return "%s(interface=%s)" % (self.__class__.__name__, util.qual(self.iface))
- return self.__class__.__name__ + "()"
-
- def attachActionBindings(self, possibleActions):
- ## Go through and replace self.actions, which is a list of method
- ## references, with the MethodBinding instance which holds
- ## metadata about this function.
- act = self.actions
- for method, binding in possibleActions:
- if method in act:
- act[act.index(method)] = binding
-
- def getActionBindings(self):
- return self.actions
-
-class Dictionary(List):
- pass
-
-
-class Table(Object):
- pass
-
-
-class Request(Typed):
- """Marker that indicates that an autocallable should be passed the
- request when called. Including a Request arg will not affect the
- appearance of the rendered form.
-
- >>> def doSomething(request=formless.Request(), name=formless.String()):
- ... pass
- >>> doSomething = formless.autocallable(doSomething)
- """
- complexType = True ## Don't use the regular form
-
-
-class Context(Typed):
- """Marker that indicates that an autocallable should be passed the
- context when called. Including a Context arg will not affect the
- appearance of the rendered form.
-
- >>> def doSomething(context=formless.Context(), name=formless.String()):
- ... pass
- >>> doSomething = formless.autocallable(doSomething)
- """
- complexType = True ## Don't use the regular form
-
-
-class Button(Typed):
- def coerce(self, data, configurable):
- return data
-
-
-class Compound(Typed):
- complexType = True
- def __init__(self, elements=None, *args, **kw):
- assert elements, "What is the sound of a Compound type with no elements?"
- self.elements = elements
- Typed.__init__(self, *args, **kw)
-
- def __len__(self):
- return len(self.elements)
-
- def coerce(self, data, configurable):
- return data
-
-
-class Method(Typed):
- def __init__(self, returnValue=None, arguments=(), *args, **kw):
- Typed.__init__(self, *args, **kw)
- self.returnValue = returnValue
- self.arguments = arguments
-
-
-class Group(Object):
- pass
-
-
-def autocallable(method, action=None, visible=False, **kw):
- """Describe a method in a TypedInterface as being callable through the
- UI. The "action" paramter will be used to label the action button, or the
- user interface element which performs the method call.
-
- Use this like a method adapter around a method in a TypedInterface:
-
- >>> class IFoo(TypedInterface):
- ... def doSomething():
- ... '''Do Something
- ...
- ... Do some action bla bla'''
- ... return None
- ... doSomething = autocallable(doSomething, action="Do it!!")
- """
- method.autocallable = True
- method.id = nextId()
- method.action = action
- method.attributes = kw
- return method
-
-
-#######################################
-## Internal API; formless uses these objects to keep track of
-## what names are bound to what types
-#######################################
-
-
-class Binding(object):
- """Bindings bind a Typed instance to a name. When TypedInterface is subclassed,
- the metaclass looks through the dict looking for all properties and methods.
-
- If a properties is a Typed instance, a Property Binding is constructed, passing
- the name of the binding and the Typed instance.
-
- If a method has been wrapped with the "autocallable" function adapter,
- a Method Binding is constructed, passing the name of the binding and the
- Typed instance. Then, getargspec is called. For each keyword argument
- in the method definition, an Argument is constructed, passing the name
- of the keyword argument as the binding name, and the value of the
- keyword argument, a Typed instance, as the binding typeValue.
-
- One more thing. When an autocallable method is found, it is called with
- None as the self argument. The return value is passed the Method
- Binding when it is constructed to keep track of what the method is
- supposed to return.
- """
- implements(iformless.IBinding)
-
- label = None
- description = ''
-
- def __init__(self, name, typedValue, id=0):
- self.id = id
- self.name = name
- self.typedValue = iformless.ITyped(typedValue)
-
- # pull these out to remove one level of indirection...
- if typedValue.description is not None:
- self.description = typedValue.description
- if typedValue.label is not None:
- self.label = typedValue.label
- if self.label is None:
- self.label = nameToLabel(name)
- self.default = typedValue.default
- self.complexType = typedValue.complexType
-
- def __repr__(self):
- return "<%s %s=%s at 0x%x>" % (self.__class__.__name__, self.name, self.typedValue.__class__.__name__, id(self))
-
- def getArgs(self):
- """Return a *copy* of this Binding.
- """
- return (Binding(self.name, self.original, self.id), )
-
- def getViewName(self):
- return self.original.__class__.__name__.lower()
-
- def configure(self, boundTo, results):
- raise NotImplementedError, "Implement in %s" % util.qual(self.__class__)
-
- def coerce(self, val, configurable):
- if hasattr(self.original, 'coerce'):
- return self.original.coerce(val)
- return val
-
-class Argument(Binding):
- pass
-
-
-class Property(Binding):
- action = 'Change'
- def configure(self, boundTo, results):
- ## set the property!
- setattr(boundTo, self.name, results[self.name])
-
-
-class MethodBinding(Binding):
- typedValue = None
- def __init__(self, name, typeValue, id=0, action="Call", attributes = {}):
- Binding.__init__(self, name, typeValue, id)
- self.action = action
- self.arguments = typeValue.arguments
- self.returnValue = typeValue.returnValue
- self.attributes = attributes
-
- def getAttribute(self, name):
- return self.attributes.get(name, None)
-
- def configure(self, boundTo, results):
- bound = getattr(boundTo, self.name)
- return bound(**results)
-
- def getArgs(self):
- """Make sure each form post gets a unique copy of the argument list which it can use to keep
- track of values given in partially-filled forms
- """
- return self.typedValue.arguments[:]
-
-
-class ElementBinding(Binding):
- """An ElementBinding binds a key to an element of a container.
- For example, ElementBinding('0', Object()) indicates the 0th element
- of a container of Objects. When this ElementBinding is bound to
- the list [1, 2, 3], resolving the binding will result in the 0th element,
- the object 1.
- """
- pass
-
-
-class GroupBinding(Binding):
- """A GroupBinding is a way of naming a group of other Bindings.
- The typedValue of a GroupBinding should be a Configurable.
- The Bindings returned from this Configurable (usually a TypedInterface)
- will be rendered such that all fields must/may be filled out, and all
- fields will be changed at once upon form submission.
- """
- def __init__(self, name, typedValue, id=0):
- """Hack to prevent adaption to ITyped while the adapters are still
- being registered, because we know that the typedValue should be
- a Group when we are constructing a GroupBinding.
- """
- self.id = id
- self.name = name
- self.typedValue = Group(typedValue)
-
- # pull these out to remove one level of indirection...
- self.description = typedValue.description
- if typedValue.label:
- self.label = typedValue.label
- else:
- self.label = nameToLabel(name)
- self.default = typedValue.default
- self.complexType = typedValue.complexType
-
- def configure(self, boundTo, group):
- print "CONFIGURING GROUP BINDING", boundTo, group
-
-
-def _sorter(x, y):
- return cmp(x.id, y.id)
-
-
-class _Marker(object):
- pass
-
-
-def caps(c):
- return c.upper() == c
-
-
-def nameToLabel(mname):
- labelList = []
- word = ''
- lastWasUpper = False
- for letter in mname:
- if caps(letter) == lastWasUpper:
- # Continuing a word.
- word += letter
- else:
- # breaking a word OR beginning a word
- if lastWasUpper:
- # could be either
- if len(word) == 1:
- # keep going
- word += letter
- else:
- # acronym
- # we're processing the lowercase letter after the acronym-then-capital
- lastWord = word[:-1]
- firstLetter = word[-1]
- labelList.append(lastWord)
- word = firstLetter + letter
- else:
- # definitely breaking: lower to upper
- labelList.append(word)
- word = letter
- lastWasUpper = caps(letter)
- if labelList:
- labelList[0] = labelList[0].capitalize()
- else:
- return mname.capitalize()
- labelList.append(word)
- return ' '.join(labelList)
-
-
-def labelAndDescriptionFromDocstring(docstring):
- if docstring is None:
- docstring = ''
- docs = filter(lambda x: x, [x.strip() for x in docstring.split('\n')])
- if len(docs) > 1:
- return docs[0], '\n'.join(docs[1:])
- else:
- return None, '\n'.join(docs)
-
-
-_typedInterfaceMetadata = {}
-
-
-class MetaTypedInterface(InterfaceClass):
- """The metaclass for TypedInterface. When TypedInterface is subclassed,
- this metaclass' __new__ method is invoked. The Typed Binding introspection
- described in the Binding docstring occurs, and when it is all done, there will
- be three attributes on the TypedInterface class:
-
- - __methods__: An ordered list of all the MethodBinding instances
- produced by introspecting all autocallable methods on this
- TypedInterface
-
- - __properties__: An ordered list of all the Property Binding
- instances produced by introspecting all properties which have
- Typed values on this TypedInterface
-
- - __spec__: An ordered list of all methods and properties
-
- These lists are sorted in the order that the methods and properties appear
- in the TypedInterface definition.
-
- For example:
-
- >>> class Foo(TypedInterface):
- ... bar = String()
- ... baz = Integer()
- ...
- ... def frotz(): pass
- ... frotz = autocallable(frotz)
- ...
- ... xyzzy = Float()
- ...
- ... def blam(): pass
- ... blam = autocallable(blam)
-
- Once the metaclass __new__ is done, the Foo class instance will have three
- properties, __methods__, __properties__, and __spec__,
- """
- __methods__ = property(lambda self: _typedInterfaceMetadata[self, '__methods__'])
- __id__ = property(lambda self: _typedInterfaceMetadata[self, '__id__'])
- __properties__ = property(lambda self: _typedInterfaceMetadata[self, '__properties__'])
- __spec__ = property(lambda self: _typedInterfaceMetadata[self, '__spec__'])
- name = property(lambda self: _typedInterfaceMetadata[self, 'name'])
- label = property(lambda self: _typedInterfaceMetadata[self, 'label'])
- description = property(lambda self: _typedInterfaceMetadata[self, 'description'])
- default = property(lambda self: _typedInterfaceMetadata.get((self, 'default'), 'DEFAULT'))
- complexType = property(lambda self: _typedInterfaceMetadata.get((self, 'complexType'), True))
-
- def __new__(cls, name, bases, dct):
- rv = cls = InterfaceClass.__new__(cls)
- _typedInterfaceMetadata[cls, '__id__'] = nextId()
- _typedInterfaceMetadata[cls, '__methods__'] = methods = []
- _typedInterfaceMetadata[cls, '__properties__'] = properties = []
- possibleActions = []
- actionAttachers = []
- for key, value in dct.items():
- if key[0] == '_': continue
-
- if isinstance(value, MetaTypedInterface):
- ## A Nested TypedInterface indicates a GroupBinding
- properties.append(GroupBinding(key, value, value.__id__))
-
- ## zope.interface doesn't like these
- del dct[key]
- setattr(cls, key, value)
- elif callable(value):
- names, _, _, typeList = inspect.getargspec(value)
-
- _testCallArgs = ()
-
- if typeList is None:
- typeList = []
-
- if len(names) == len(typeList) + 1:
- warnings.warn(
- "TypeInterface method declarations should not have a 'self' parameter",
- DeprecationWarning,
- stacklevel=2)
- del names[0]
- _testCallArgs = (_Marker,)
-
- if len(names) != len(typeList):
- ## Allow non-autocallable methods in the interface; ignore them
- continue
-
- argumentTypes = [
- Argument(n, argtype, argtype.id) for n, argtype in zip(names[-len(typeList):], typeList)
- ]
-
- result = value(*_testCallArgs)
-
- label = None
- description = None
- if getattr(value, 'autocallable', None):
- # autocallables have attributes that can set label and description
- label = value.attributes.get('label', None)
- description = value.attributes.get('description', None)
-
- adapted = iformless.ITyped(result, None)
- if adapted is None:
- adapted = Object(result)
-
- # ITyped has label and description we can use
- if label is None:
- label = adapted.label
- if description is None:
- description = adapted.description
-
- defaultLabel, defaultDescription = labelAndDescriptionFromDocstring(value.__doc__)
- if defaultLabel is None:
- # docstring had no label, try the action if it is an autocallable
- if getattr(value, 'autocallable', None):
- if label is None and value.action is not None:
- # no explicit label, but autocallable has action we can use
- defaultLabel = value.action
-
- if defaultLabel is None:
- # final fallback: use the function name as label
- defaultLabel = nameToLabel(key)
-
- if label is None:
- label = defaultLabel
- if description is None:
- description = defaultDescription
-
- theMethod = Method(
- adapted, argumentTypes, label=label, description=description
- )
-
- if getattr(value, 'autocallable', None):
- methods.append(
- MethodBinding(
- key, theMethod, value.id, value.action, value.attributes))
- else:
- possibleActions.append((value, MethodBinding(key, theMethod)))
- else:
- if not value.label:
- value.label = nameToLabel(key)
- if iformless.IActionableType.providedBy(value):
- actionAttachers.append(value)
- properties.append(
- Property(key, value, value.id)
- )
- for attacher in actionAttachers:
- attacher.attachActionBindings(possibleActions)
- methods.sort(_sorter)
- properties.sort(_sorter)
- _typedInterfaceMetadata[cls, '__spec__'] = spec = methods + properties
- spec.sort(_sorter)
- _typedInterfaceMetadata[cls, 'name'] = name
-
- # because attributes "label" and "description" would become Properties,
- # check for ones with an underscore prefix.
- _typedInterfaceMetadata[cls, 'label'] = dct.get('_label', None)
- _typedInterfaceMetadata[cls, 'description'] = dct.get('_description', None)
- defaultLabel, defaultDescription = labelAndDescriptionFromDocstring(dct.get('__doc__'))
- if defaultLabel is None:
- defaultLabel = nameToLabel(name)
- if _typedInterfaceMetadata[cls, 'label'] is None:
- _typedInterfaceMetadata[cls, 'label'] = defaultLabel
- if _typedInterfaceMetadata[cls, 'description'] is None:
- _typedInterfaceMetadata[cls, 'description'] = defaultDescription
-
- return rv
-
-
-#######################################
-## External API; subclass this to create a TypedInterface
-#######################################
-
-TypedInterface = MetaTypedInterface('TypedInterface', (InterfaceClass('TypedInterface'), ), {})
-
=== removed file 'Nevow/formless/configurable.py'
--- Nevow/formless/configurable.py 2006-03-17 15:00:39 +0000
+++ Nevow/formless/configurable.py 1970-01-01 00:00:00 +0000
@@ -1,173 +0,0 @@
-# Copyright (c) 2004 Divmod.
-# See LICENSE for details.
-
-from zope.interface import implements, providedBy
-
-from formless.iformless import IConfigurable, IActionableType, IBinding
-from formless.annotate import Argument, ElementBinding, GroupBinding, Object, TypedInterface
-
-from nevow import inevow
-from nevow.context import WovenContext
-
-class Configurable(object):
- implements(IConfigurable)
-
- bindingDict = None
-
- def __init__(self, original):
- self.original = original
- self.boundTo = self
-
- def getBindingNames(self, context):
- ## Todo: remove this getattr
- ifs = providedBy(getattr(self, 'boundTo', self))
- ifs = [
- x for x in ifs if x is not IConfigurable and x is not TypedInterface
- ]
- bindingNames = []
- self.bindingDict = bindingDict = {}
- for interface in ifs:
- ## TypedInterfaces have a __spec__ attribute which is a list of all Typed properties and
- ## autocallable methods
- for binding in getattr(interface, '__spec__', []):
- bindingDict[binding.name] = binding
- if binding.name not in bindingNames:
- bindingNames.append(binding.name)
- if IActionableType.providedBy(binding.typedValue):
- acts = binding.typedValue.actions
- if acts is None:
- acts = []
- for action in acts:
- bindingDict[action.name] = action
- return bindingNames
-
- def getDefault(self, forBinding):
- ## TODO: Clean this up, it's a mess
- if not isinstance(forBinding, Argument):
- name = forBinding.name
- if hasattr(self, name):
- return getattr(self, name)
- ## Todo: Only do this in ConfigurableAdapter instead of Configurable
- if hasattr(self.boundTo, name):
- return getattr(self.boundTo, name)
- if self.original is not self.boundTo and hasattr(self.original, name):
- return getattr(self.original, name)
- return forBinding.default
-
- def getBinding(self, context, name):
- if self.bindingDict is None:
- self.getBindingNames(context)
- if self.bindingDict is None:
- self.bindingDict = {}
- binding = getattr(self, 'bind_%s' % name, getattr(self.boundTo, 'bind_%s' % name, None))
- if binding is not None:
- binding = binding(context)
- else:
- try:
- binding = self.bindingDict[name]
- except KeyError:
- raise RuntimeError, "%s is not an exposed binding on object %s." % (name, self.boundTo)
- binding.boundTo = self.boundTo
- return binding
-
- def postForm(self, ctx, bindingName, args):
- """Accept a form post to the given bindingName. The bindingName
- can be dotted to indicate an attribute of this Configurable, eg
- addresses.0.changeEmail. The post arguments are given in args.
- Return a Resource which will be rendered in response.
- """
- from formless import iformless
- from nevow.tags import invisible
- request = ctx.locate(inevow.IRequest)
- pathSegs = bindingName.split('.')
- configurable = self
-
- cf = ctx.locate(iformless.IConfigurableFactory)
- ## Get the first binding
- firstSeg = pathSegs.pop(0)
- binding = configurable.getBinding(ctx, firstSeg)
- ctx.remember(binding, IBinding)
- ctx.remember(configurable, IConfigurable)
- ## I don't think this works right now, it needs to be fixed.
- ## Most cases it won't be triggered, because we're just traversing a
- ## single binding name
- for seg in pathSegs:
- assert 1 == 0, "Sorry, this doesn't work right now"
- binding = configurable.getBinding(ctx, seg)
- child = self.boundTo
- if not isinstance(binding, GroupBinding):
- accessor = inevow.IContainer(configurable.boundTo, None)
- if accessor is None:
- child = getattr(configurable.boundTo, binding.name)
- else:
- child = accessor.child(ctx, binding.name)
- ## If it's a groupbinding, we don't do anything at all for this path segment
-
- ## This won't work right now. We need to push the previous configurable
- ## as the configurableFactory somehow and ask that for hte next binding
- ## we also need to support deferreds coming back from locateConfigurable
- assert 'black' is 'white', "Deferred support is pending"
- configurable = cf.locateConfigurable(ctx, child)
- ctx = WovenContext(ctx, invisible(key=seg))
- ctx.remember(binding, IBinding)
- ctx.remember(configurable, IConfigurable)
-
- bindingProcessor = iformless.IInputProcessor(binding)
- rv = bindingProcessor.process(ctx, binding.boundTo, args)
- ctx.remember(rv, inevow.IHand)
- ctx.remember('%r success.' % bindingName, inevow.IStatusMessage)
- return rv
-
- def summary(self):
- return "An instance of %s" % self.__class__.__name__
-
- postLocation = None
-
-class NotFoundConfigurable(Configurable):
- def getBinding(self, context, name):
- raise RuntimeError, self.original
-
-
-class TypedInterfaceConfigurable(Configurable):
- def __init__(self, original):
- self.original = original
- self.boundTo = original
-
- def summary(self):
- return "An instance of %s" % self.original.__class__.__name__
-
- def __repr__(self):
- return "TypedInterfaceConfigurable(%r)" % self.original
-
-
-class ListConfigurable(TypedInterfaceConfigurable):
- def getBinding(self, context, name):
- eb = ElementBinding(name, Object())
- eb.boundTo = self.original
- return eb
-
-
-class GroupConfigurable(TypedInterfaceConfigurable):
- def __init__(self, original, groupInterface):
- TypedInterfaceConfigurable.__init__(self, original)
- self.groupInterface = groupInterface
-
- bindingDict = None
-
- def getBindingNames(self, context):
- bindingNames = []
- self.bindingDict = bindingDict = {}
- interface = self.groupInterface
- for binding in getattr(interface, '__spec__', []):
- bindingDict[binding.name] = binding
- if binding.name not in bindingNames:
- bindingNames.append(binding.name)
- if IActionableType.providedBy(binding.typedValue):
- acts = binding.typedValue.actions
- if acts is None:
- acts = []
- for action in acts:
- bindingDict[action.name] = action
- return bindingNames
-
-
=== removed file 'Nevow/formless/formutils.py'
--- Nevow/formless/formutils.py 2006-04-14 17:23:46 +0000
+++ Nevow/formless/formutils.py 1970-01-01 00:00:00 +0000
@@ -1,143 +0,0 @@
-# Copyright (c) 2004 Divmod.
-# See LICENSE for details.
-
-from __future__ import generators
-
-from zope.interface import implements
-
-from twisted.python import components
-
-from nevow import inevow
-from nevow import tags
-
-from formless import iformless
-
-
-try:
- enumerate = enumerate
-except:
- def enumerate(collection):
- i = 0
- it = iter(collection)
- while 1:
- yield (i, it.next())
- i += 1
-
-
-class PrefixerDict(dict):
- def __init__(self, prefix, errors):
- if prefix is None: prefix = ''
- self.prefix = prefix
- self.errors = errors
- dict.__init__(self)
-
- def __setitem__(self, key, value):
- if key is None:
- key = ''
- if key == '':
- pfxkey = self.prefix
- else:
- pfxkey = '.'.join((self.prefix, key))
- self.errors[pfxkey] = value
-
- def __getitem__(self, key):
- if key == '':
- pfxkey = self.prefix
- else:
- pfxkey = '.'.join((self.prefix, key))
- return self.errors[pfxkey]
-
- def update(self, other):
- for key, value in other.items():
- self[key] = value
-
-
-class FormDefaults(components.Adapter):
- def __init__(self):
- self.defaults = {}
-
- def setDefault(self, key, value, context=None):
- self.defaults[key] = value
-
- def getDefault(self, key, context=None):
- #print "getting default for key", key, self.defaults
- # 1) Check on the request
- current = self.defaults.get(key, None)
- if current is None:
- # 2) Check on the session
- if context is not None:
- sessionDefaults = context.locate(iformless.IFormDefaults)
- if sessionDefaults is not self:
- current = sessionDefaults.getDefault(key)
- if current is not None:
- return current
- # 3) Ask the Binding instance for the default values
- try:
- configurable = context.locate(iformless.IConfigurable)
- except KeyError:
- return ''
- return configurable.getDefault(context.locate(inevow.IData))
- return current
-
- def getAllDefaults(self, key):
- return PrefixerDict(key, self.defaults)
-
- def clearAll(self):
- self.defaults = {}
-
-
-class FormErrors(components.Adapter):
- """An object which keeps track of which forms have which errors
- """
- implements(iformless.IFormErrors)
- def __init__(self):
- self.errors = {}
-
- def setError(self, errorKey, error):
- self.errors[errorKey] = error
-
- def getError(self, errorKey):
- #print "get error", errorKey, self.__dict__
- return self.errors.get(errorKey)
-
- def getAllErrors(self, formName):
- return PrefixerDict(formName, self.errors)
-
- def updateErrors(self, formName, errors):
- PrefixerDict(formName, self.errors).update(errors)
-
- def clearErrors(self, formName):
- for key in self.errors.keys():
- if key.startswith(formName):
- del self.errors[key]
-
- def clearAll(self):
- self.errors = {}
-
-def calculatePostURL(context, data):
- postLocation = inevow.ICurrentSegments(context)[-1]
- if postLocation == '':
- postLocation = '.'
- try:
- configurableKey = context.locate(iformless.IConfigurableKey)
- except KeyError:
- #print "IConfigurableKey was not remembered when calculating full binding name for %s in node %s" % (configurable, context.key)
- configurableKey = ''
- bindingName = context.key
- return "%s/freeform_post!%s!%s" % (postLocation, configurableKey, bindingName)
-
-
-def keyToXMLID(key):
- """Convert a key into an XML-styleinevow.ID """
- if not key:
- #print 'keyToXMLID: no key, but why?'
- return '***Error: Unset***'
- return '-'.join(key.split('.'))
-
-
-def getError(context):
- errors = context.locate(iformless.IFormErrors)
- err = errors.getError(context.key)
- if err is not None:
- return err
- return tags.comment["\nNo error for error key: %s\n" % context.key]
=== removed file 'Nevow/formless/freeform-default.css'
--- Nevow/formless/freeform-default.css 2006-03-30 15:49:57 +0000
+++ Nevow/formless/freeform-default.css 1970-01-01 00:00:00 +0000
@@ -1,29 +0,0 @@
-
-.freeform-typed { }
-.freeform-property-binding { border: 1px solid blue; padding: 0.5em; width: auto }
-.freeform-method-binding { border: 1px solid black; padding: 0.5em; width: auto }
-.freeform-argument-binding { border: 1px solid blue; padding: 0.5em; width: auto }
-.freeform-binding-content { border-top: 1px dashed #bdedfe; margin-top: 0.5em; padding-top: 0.5em }
-.freeform-label { float: left; width: 200px; }
-.freeform-input-text { width: 250px; }
-.freeform-input-password { width: 100px; }
-.freeform-error, .freeform-form-error { color: red; margin-left: 1em;}
-.freeform-description { border-bottom: 1px dashed #bdedfe; margin-bottom: 0.5em; padding-bottom: 0.5em }
-.freeform-list-item { width: auto }
-.freeform-form-label { color: #666666 }
-
-.freeform-textarea { width: 40em; height: 16em; }
-
-.freeform-success { padding: 0.5em; border: 1px dashed green; }
-.freeform-failure { padding: 0.5em; color: red; border: 1px dashed red; }
-
-.freeform-list { border: 1px dashed #cdcdcd; }
-.freeform-dictionary { border: 1px dashed #dedede; }
-.freeform-action-group { margin: 0px }
-.freeform-action { color: green }
-.freeform-action-selection { background-color: red; height: 1em; width: 1em; }
-
-.freeform-group-binding { border: 1px dashed #efabab }
-.freeform-grouped-property-binding {}
-.freeform-grouped-method-binding {}
-.freeform-radio-option {margin-left: 200px}
=== removed file 'Nevow/formless/iformless.py'
--- Nevow/formless/iformless.py 2006-03-17 15:00:39 +0000
+++ Nevow/formless/iformless.py 1970-01-01 00:00:00 +0000
@@ -1,282 +0,0 @@
-# -*- test-case-name: nevow.test -*-
-# Copyright (c) 2004-2005 Divmod, Inc.
-# See LICENSE for details.
-
-from zope.interface import Attribute
-from zope.interface.interface import InterfaceClass, Interface
-
-class ITyped(Interface):
- """Typeds correspond roughly to <input> tags in HTML, or
- with a complex type, more than one <input> tag whose input
- is processed and coerced as a unit.
- """
- def coerce(val, configurable):
- """Coerce the input 'val' from a string into a value suitable
- for the type described by the implementor. If coercion fails,
- coerce should raise InputError with a suitable error message
- to be shown to the user. 'configurable' is the configurable object
- in whose context the coercion is taking place.
-
- May return a Deferred.
- """
-
- label = Attribute("""The short label which will describe this
- parameter/properties purpose to the user.""")
-
- description = Attribute("""A long description which further describes the sort
- of input the user is expected to provide.""")
-
- default = Attribute("""A default value that may be used as an initial value in
- the form.""")
-
- complexType = Attribute("""Whether or not this Typed
- is a "simple" type and the infrastructure should render label,
- description, and error UI automatically, or this type is
- "complex" in which case it will be required to render all UI
- including UI which is normally common to all Typed UI.
-
- This MAY BE DEPRECATED if a better implementation is
- devised.
- """)
-
-
-
-class IBinding(Interface):
- """A Binding corresponds (very) roughly to a <form> tag in HTML.
- A Binding is an object which associates a string name with a Typed
- instance. At the most basic level, Binding instances represent named
- python properties and methods.
- """
- def getArgs():
- """Return a copy of this bindings Typed instances; if this binding is a
- Property binding, it will be a list of one Typed istance; if this binding is a
- MethodBinding, it will be a list of all the Typed instances describing
- the method's arguments.
-
- These copies are used during the duration of a form post (initial
- rendering, form posting, error handling and error correction) to
- store the user-entered values temporarily in the case of an error
- in one or more input values.
- """
-
- def getViewName():
- """Todo: remove?
- """
-
- def configure(boundTo, results):
- """Configure the object "boundTo" in the manner appropriate
- to this Binding; if this binding represents a property, set the
- property; if this binding represents a method, call the method.
- """
-
- def coerce(val, configurable):
- """TODO This is dumb. remove it and leave it on ITyped
-
- Make the code that calls coerce call it on the typed directly
- """
-
- default = Attribute("""The default value for this binding.""")
-
-
-
-
-class IInputProcessor(Interface):
- """handle a post for a given binding
- """
- def process(context, boundTo, data):
- """do something to boundTo in response to some data
-
- Raise a formless.InputError if there is a problem
- """
-
-
-## Freeform interfaces
-
-class IConfigurableFactory(Interface):
- """A configurable factory is used to find and/or create configurables.
- A "Configurable" object is any object which either:
- - Implements IConfigurable directly
- - Implements a TypedInterface, thus providing enough information
- about the types of objects needed to allow the user to change
- the object as long as the input is validated
- """
- def locateConfigurable(context, name):
- """Return the configurable that responds to the name.
- """
-
-
-class IConfigurableKey(Interface):
- """The key of the configurable which is being rendered
- """
-
-
-class IFormDefaults(Interface):
- """Default values for the current form
- """
- def setDefault(key, value, context=None):
- """Sets the 'key' parameter to the default 'value'
- """
-
- def getDefault(key, context=None):
- """Gets the default value from the parameter 'key'
- """
-
- def getAllDefaults(key):
- """Gets the defaults dict for the 'key' autocallable
-
- >>> class IMyForm(annotate.TypedInterface):
- ... def doSomething(name=annotate.String()):
- ... pass
- ... doSomething = annotate.autocallable(doSomething)
- >>> class Page(rend.Page):
- ... implements(IMyForm)
- ... docFactory = loaders.stan(t.html[t.head[t.title['foo']],t.body[render_forms]])
- ...
- ... def render_forms(self, ctx, data):
- ... defaults_dict = iformless.IFormDefaults(ctx).getAllDefaults('doSomething')
- ... defaults_dict['name'] = 'fooo'
- ... return webform.renderForms()
- """
-
- def clearAll():
- """Clears all the default values
- """
-
-class IFormErrors(Interface):
- """An object which keeps track of which forms have which errors
- """
-
-
-class IBindingRenderer(Interface):
- """Something which can render a formless Binding.
-
- A Binding represents an atomic form which can be
- submitted to cause a named thing to occur;
- a MethodBinding will cause a method to be called;
- a PropertyBinding will cause a property to change.
- """
-
-
-class IActionRenderer(Interface):
- """An alternate rendering of a formless Binding which
- is usually represented as a smaller, no-input-fields
- toolbar-style button. Should call a MethodBinding.
-
- An action is distinct from a MethodBinding in that
- an action does not explicitly solicit input from the user,
- but instead gathers all the information it needs to run
- a method from implicit context, such as the render
- context, or the current state of the selection.
- """
-
-
-class ITypedRenderer(Interface):
- """Something which can render a formless Typed.
- Renders input fields in html which will gather information
- from the user which will be passed to the Typed.coerce
- method when the entire form is submitted.
- """
-
-
-class IRedirectAfterPost(Interface):
- """A marker interface which can be set to something which can be cast
- to a string to indicate that the browser should be redirected to the
- resultant url after posting the form successfully. This component can
- be set by any form post validators, or by the configurable method which
- is being automatically called if it has access to the request.
-
- Set this using the following:
-
- request.setComponent(IRedirectAfterPost, "http://example.com/";)
- """
-
-
-## Configurable interfaces
-
-class IAutomaticConfigurable(Interface):
- """An object is said to implement IAutomaticConfigurable if
- it implements any TypedInterfaces. When this object
- is configured, discovering binding names, discovering bindings,
- and posting forms along with calling methods in response to
- form posts and setting properties in response to form posts.
- """
-
-_notag = object()
-
-class _MetaConfigurable(InterfaceClass):
- """XXX this is an unpleasant implementation detail; phase it out completely
- as we move towards zope.interface.
- """
-
- def __call__(self, other, default=_notag):
- """ XXX use TypedInterfaceConfigurable as a fallback if this interface doesn't
- work for some reason
- """
-
- result = InterfaceClass.__call__(self, other, _notag)
- if result is not _notag:
- return result
-
- from formless.annotate import TypedInterface
- if TypedInterface.providedBy(other):
- from formless.configurable import TypedInterfaceConfigurable
- return TypedInterfaceConfigurable(other)
- if default is _notag:
- raise TypeError('Could not adapt', other, self)
- return default
-
-_BaseMetaConfigurable = _MetaConfigurable('_BaseMetaConfigurable', (), {})
-
-class IConfigurable(_BaseMetaConfigurable):
- """An adapter which implements TypedInterfaces for an object
- of the type for which it is registered, provides properties
- which will get and set properties of the adaptee, and methods
- which will perform operations on the adaptee when called.
-
- Web Specific Note: When you implement this interface, you should
- subclass freeform.Configurable instead of implementing directly,
- since it contains convenience functionality which eases implementing
- IConfigurable.
- """
- def getBindingNames(context):
- """Return a list of binding names which are the names of all
- the forms which will be rendered for this object when this
- object is configured.
- """
-
- def getBinding(context, name):
- """Return a Binding instance which contains Typed instances
- which describe how to render a form which will gather input
- for the 'name' binding (either a property or a method)
- """
-
- def postForm(context, bindingName, arguments):
- """Handle a form post which configures something about this
- object.
- """
-
- postLocation = Attribute("""The location of this object in the
- URL. Forms described by bindings returned from getBindingNames
- will be posted to postLocation + '/freeform_post!' + bindingName
- """)
-
-
-
-
-
-## Under consideration for deprecation
-
-
-class IActionableType(Interface):
- """A type which can have action methods associated with it.
- Currently only List. Probably can be extended to more things.
- """
- def attachActionBindings(possibleActions):
- """Attach some MethodBinding instances if they are actions
- for this ActionableType.
- """
-
- def getActionBindings():
- """Return a list of the MethodBinding instances which represent
- actions which may be taken on this ActionableType.
- """
=== removed file 'Nevow/formless/processors.py'
--- Nevow/formless/processors.py 2006-04-14 17:23:46 +0000
+++ Nevow/formless/processors.py 1970-01-01 00:00:00 +0000
@@ -1,283 +0,0 @@
-# Copyright (c) 2004 Divmod.
-# See LICENSE for details.
-
-import warnings
-from zope.interface import implements
-
-from twisted.python import components
-
-from nevow.util import Deferred, DeferredList, getPOSTCharset
-
-from nevow import inevow, tags
-from nevow.context import WovenContext
-
-import formless
-from formless.formutils import enumerate
-from formless import iformless
-
-faketag = tags.html()
-
-
-def exceptblock(f, handler, exception, *a, **kw):
- try:
- result = f(*a, **kw)
- except exception, e:
- return handler(e)
- if isinstance(result, Deferred):
- def _(fail):
- fail.trap(exception)
- return handler(fail.value)
- return result.addErrback(_)
- else:
- return result
-
-
-class ProcessGroupBinding(components.Adapter):
- implements(iformless.IInputProcessor)
-
- def process(self, context, boundTo, data):
- ## THE SPEC: self.original.typedValue.iface.__spec__
- spec = self.original.typedValue.iface.__spec__
- resultList = [None] * len(spec)
- message = ''
- results = {}
- failures = {}
- waiters = []
- for i, sub in enumerate(spec):
- def _process():
- # note, _process only works because it is called IMMEDIATELY
- # in the loop, watch out for confusing behavior if it is called
- # later when 'i' has changed
- resulti = resultList[i] = iformless.IInputProcessor(sub).process(context, boundTo, data, autoConfigure = False)
- # Merge the valid value in case another fails
- results.update(resulti)
- def _except(e):
- errors = context.locate(iformless.IFormErrors)
- # XXX: It seems like this should only ever be called with a WovenContext
- # XXX: if it's using context.key. But it seems that it's only ever called with
- # XXX: a PageContext, so context.key used to be '' always?
-
- errors.updateErrors(getattr(context, 'key', ''), e.errors)
- pf = e.partialForm
- err = e.errors
- msg = e.formErrorMessage
- ## Set an error message for this group of bindings
- errors.setError(getattr(context, 'key', ''), msg)
- # Merge the failed value
- results.update(pf)
- # Merge the error message
- failures.update(e.errors)
- maybe = exceptblock(_process, _except, formless.ValidateError)
- if isinstance(maybe, Deferred):
- waiters.append(maybe)
- def _finish(ignored):
- if not failures:
- for specobj, result in zip(spec, resultList):
- specobj.configure(boundTo, result)
- else:
- #print "There were validation errors. The errors were: ", failures
- raise formless.ValidateError(failures, 'Error:', results)
- return DeferredList(waiters).addBoth(_finish)
-
-class ProcessMethodBinding(components.Adapter):
- implements(iformless.IInputProcessor)
-
- def process(self, context, boundTo, data, autoConfigure = True):
- """Knows how to process a dictionary of lists
- where the dictionary may contain a key with the same
- name as some of the arguments to the MethodBinding
- instance.
- """
- typedValue = self.original.typedValue
- results = {}
- failures = {}
- if data.has_key('----'):
- ## ---- is the "direct object", the one argument you can specify using the command line without saying what the argument name is
- data[typedValue.arguments[0].name] = data['----']
- del data['----']
- for binding in typedValue.arguments:
- name = binding.name
- try:
- context = WovenContext(context, faketag)
- context.remember(binding, iformless.IBinding)
- results[name] = iformless.IInputProcessor(binding.typedValue).process(context, boundTo, data.get(name, ['']))
- except formless.InputError, e:
- results[name] = data.get(name, [''])[0]
- failures[name] = e.reason
-
- if failures:
- #print "There were validation errors. The errors were: ", failures
- raise formless.ValidateError(failures, "Error:", results)
-
- if autoConfigure:
- def _except(e):
- failures[''] = e.reason # self.original.name
- raise formless.ValidateError(failures, e.reason, results)
- return exceptblock(self.original.configure, _except, formless.InputError,
- boundTo, results)
- return results
-
-class ProcessPropertyBinding(components.Adapter):
- implements(iformless.IInputProcessor)
-
- def process(self, context, boundTo, data, autoConfigure = True):
- """Knows how to process a dictionary of lists
- where the dictionary may contain a key with the
- same name as the property binding's name.
- """
- binding = self.original
- context.remember(binding, iformless.IBinding)
- result = {}
- try:
- result[binding.name] = iformless.IInputProcessor(binding.typedValue).process(context, boundTo, data.get(binding.name, ['']))
- except formless.InputError, e:
- result[binding.name] = data.get(binding.name, [''])
- raise formless.ValidateError({binding.name: e.reason}, e.reason, result)
-
- if autoConfigure:
- try:
- return self.original.configure(boundTo, result)
- except formless.InputError, e:
- result[binding.name] = data.get(binding.name, [''])
- raise formless.ValidateError({binding.name: e.reason}, e.reason, result)
- return result
-
-class ProcessTyped(components.Adapter):
- implements(iformless.IInputProcessor)
-
- def process(self, context, boundTo, data):
- """data is a list of strings at this point
- """
- typed = self.original
- val = data[0]
- if typed.unicode:
- try:
- val = val.decode(getPOSTCharset(context), 'replace')
- except LookupError:
- val = val.decode('utf-8', 'replace')
- if typed.strip:
- val = val.strip()
- if val == '' or val is None:
- if typed.required:
- raise formless.InputError(typed.requiredFailMessage)
- else:
- return typed.null
- try:
- return typed.coerce(val, boundTo)
- except TypeError, e:
- warnings.warn('Typed.coerce takes two values now, the value to coerce and the configurable in whose context the coerce is taking place. %s %s' % (typed.__class__, typed))
- return typed.coerce(val)
-
-class ProcessPassword(components.Adapter):
- implements(iformless.IInputProcessor)
-
- def process(self, context, boundTo, data):
- """Password needs to look at two passwords in the data,
- """
- typed = self.original
- pw1 = data[0]
- args = context.locate(inevow.IRequest).args
- binding = context.locate(iformless.IBinding)
- pw2 = args.get("%s____2" % binding.name, [''])[0]
- if typed.strip:
- pw1 = pw1.strip()
- pw2 = pw2.strip()
- if pw1 != pw2:
- raise formless.InputError("Passwords do not match. Please reenter.")
- elif pw1 == '':
- if typed.required:
- raise formless.InputError(typed.requiredFailMessage)
- else:
- return typed.null
- val = data[0]
- if typed.unicode:
- try:
- val = val.decode(getPOSTCharset(context), 'replace')
- except LookupError:
- val = val.decode('utf-8', 'replace')
- try:
- return typed.coerce(val, boundTo)
- except TypeError:
- warnings.warn('Typed.coerce takes two values now, the value to coerce and the configurable in whose context the coerce is taking place. %s %s' % (typed.__class__, typed))
- return typed.coerce(data[0])
-
-class ProcessRequest(components.Adapter):
- implements(iformless.IInputProcessor)
-
- def process(self, context, boundTo, data):
- return context.locate(inevow.IRequest)
-
-
-class ProcessContext(components.Adapter):
- implements(iformless.IInputProcessor)
-
- def process(self, context, boundTo, data):
- return context
-
-
-class ProcessUpload(components.Adapter):
- implements(iformless.IInputProcessor)
-
- def process(self, context, boundTo, data):
-
- typed = self.original
- bind = context.locate(iformless.IBinding)
-
- # TOTAL HACK: this comes from outer space
- fields = context.locate(inevow.IRequest).fields
- try:
- field = fields[bind.name]
- except KeyError:
- return ''
-
- def hasContent(field):
- """Test if the uploaded file has any content by looking for a single byte.
- """
- file = field.file
- pos = file.tell()
- file.seek(0)
- ch = file.read(1)
- file.seek(pos)
- return ch != ''
-
- # Testing for required'ness is a bit of a hack (not my fault!) ...
- # The upload is only considered missing if both the file name and content
- # are empty. That allows for files with content called ' ' and empty files
- # with a sensible name.
-
- # field might be a list, if multiple files were uploaded with the same
- # name.
- if isinstance(field, list):
- fieldList = field
- else:
- fieldList = [field]
-
- for maybeEmptyField in fieldList:
- if maybeEmptyField.filename.strip() or hasContent(maybeEmptyField):
- break
- else:
- if typed.required:
- raise formless.InputError(typed.requiredFailMessage)
- else:
- return typed.null
-
- return field
-
-
-def process(typed, data, configurable=None, ctx=None):
- if ctx is None:
- from nevow.testutil import FakeRequest
- from nevow import context
- fr = FakeRequest()
- if type(data) is dict:
- fr.args = data
- ctx = context.RequestContext(tag=fr)
- ctx.remember(fr, inevow.IRequest)
- ctx.remember(None, inevow.IData)
-
- try:
- return iformless.IInputProcessor(typed).process(ctx, configurable, data, autoConfigure=False)
- except TypeError:
- return iformless.IInputProcessor(typed).process(ctx, configurable, data)
-
-
=== removed directory 'Nevow/formless/test'
=== removed file 'Nevow/formless/test/__init__.py'
--- Nevow/formless/test/__init__.py 2005-10-14 17:36:24 +0000
+++ Nevow/formless/test/__init__.py 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-# Copyright (c) 2004 Divmod.
-# See LICENSE for details.
=== removed file 'Nevow/formless/test/test_formless.py'
--- Nevow/formless/test/test_formless.py 2007-11-16 02:39:33 +0000
+++ Nevow/formless/test/test_formless.py 1970-01-01 00:00:00 +0000
@@ -1,390 +0,0 @@
-# Copyright (c) 2004 Divmod.
-# See LICENSE for details.
-
-import os
-
-from nevow.testutil import TestCase
-
-import formless
-from formless import process as flpr
-
-
-def process(typed, value):
- return flpr(typed, [value])
-
-
-class Typed(TestCase):
- def testString(self):
- s = formless.String()
- self.assertEquals(process(s, ''), None)
- self.assertEquals(process(s, "Fooo"), "Fooo")
- self.assertEquals(process(s, "This is a string"), "This is a string")
- self.assertEquals(process(s, 'C\xc3\xa9sar'), 'C\xc3\xa9sar')
-
- s = formless.String(unicode=True)
- self.assertEquals(process(s, 'C\xc3\xa9sar'), u'C\u00e9sar')
-
- s = formless.String(required=True)
- self.assertRaises(formless.InputError, process, s, "")
-
- s = formless.String(required=False)
- self.assertEquals(process(s, "Bar"), "Bar")
- self.assertEquals(process(s, ""), None)
-
- s = formless.String()
- self.assertEquals(process(s, ' abc '), ' abc ')
-
- s = formless.String(strip=True, required=True)
- self.assertEquals(process(s, ' abc '), 'abc')
- self.assertEquals(process(s, '\t abc \t \n '), 'abc')
- self.assertRaises(formless.InputError, process, s, ' ')
-
- s = formless.String(required=False, strip=True)
- self.assertEquals(process(s, ' abc '), 'abc')
- self.assertEquals(process(s, ' '), None)
-
- def testText(self):
- s = formless.Text()
- self.assertEquals(process(s, ""), None)
- self.assertEquals(process(s, "Fooo"), "Fooo")
- self.assertEquals(process(s, "This is a string"), "This is a string")
- self.assertEquals(process(s, 'C\xc3\xa9sar'), 'C\xc3\xa9sar')
-
- s = formless.Text(unicode=True)
- self.assertEquals(process(s, 'C\xc3\xa9sar'), u'C\u00e9sar')
-
- s = formless.Text(required=True)
- self.assertRaises(formless.InputError, process, s, "")
-
- s = formless.Text(required=False)
- self.assertEquals(process(s, "Bar"), "Bar")
- self.assertEquals(process(s, ""), None)
-
- s = formless.Text()
- self.assertEquals(process(s, ' abc '), ' abc ')
-
- s = formless.Text(strip=True, required=True)
- self.assertEquals(process(s, ' abc '), 'abc')
- self.assertRaises(formless.InputError, process, s, ' ')
-
- s = formless.Text(required=False, strip=True)
- self.assertEquals(process(s, ' abc '), 'abc')
- self.assertEquals(process(s, ' '), None)
-
- def testPassword(self):
-
- def process(pw, val, val2=None):
- if val2 is None: val2 = val
- return flpr(
- formless.Property('password', pw),
- {'password': [val], 'password____2': [val2]})['password']
-
- s = formless.Password()
- self.assertEquals(process(s, "Fooo"), "Fooo")
- self.assertEquals(process(s, "This is a string"), "This is a string")
- self.assertEquals(process(s, "This is a string"), "This is a string")
- self.assertEquals(process(s, 'C\xc3\xa9sar'), 'C\xc3\xa9sar')
-
- s = formless.Password(unicode=True)
- self.assertEquals(process(s, 'C\xc3\xa9sar'), u'C\u00e9sar')
-
- s = formless.Password(required=True)
- self.assertRaises(formless.ValidateError, process, s, "")
-
- s = formless.Password(required=False)
- self.assertEquals(process(s, "Bar"), "Bar")
- self.assertEquals(process(s, ""), None)
-
- s = formless.Password()
- self.assertEquals(process(s, ' abc '), ' abc ')
-
- s = formless.Password(strip=True, required=True)
- self.assertEquals(process(s, ' abc '), 'abc')
- self.assertRaises(formless.ValidateError, process, s, ' ')
-
- s = formless.Password(required=False, strip=True)
- self.assertEquals(process(s, ' abc '), 'abc')
- self.assertEquals(process(s, ' '), None)
-
- def testPasswordEntry(self):
- s = formless.PasswordEntry()
- self.assertEquals(process(s, ''), None)
- self.assertEquals(process(s, 'abc'), 'abc')
- self.assertEquals(process(s, ' blah blah blah '), ' blah blah blah ')
- self.assertEquals(process(s, 'C\xc3\xa9sar'), 'C\xc3\xa9sar')
-
- s = formless.PasswordEntry(unicode=True)
- self.assertEquals(process(s, 'C\xc3\xa9sar'), u'C\u00e9sar')
-
- s = formless.PasswordEntry(strip=True)
- self.assertEquals(process(s, ''), None)
- self.assertEquals(process(s, 'abc'), 'abc')
- self.assertEquals(process(s, ' blah blah blah '), 'blah blah blah')
-
- s = formless.PasswordEntry(strip=True, required=True)
- self.assertRaises(formless.InputError, process, s, '')
- self.assertRaises(formless.InputError, process, s, ' ')
- self.assertEquals(process(s, 'abc'), 'abc')
- self.assertEquals(process(s, ' blah blah blah '), 'blah blah blah')
-
- def testInteger(self):
- i = formless.Integer(required=True)
- self.assertEquals(process(i, "0"), 0)
- self.assertEquals(process(i, "3409823098"), 3409823098)
- self.assertRaises(formless.InputError, process, i, "")
- self.assertRaises(formless.InputError, process, i, "a string")
- self.assertRaises(formless.InputError, process, i, "1.5")
-
- i = formless.Integer(required=False)
- self.assertEquals(process(i, "1234567"), 1234567)
- self.assertEquals(process(i, ""), None)
-
- def testReal(self):
- i = formless.Real(required=True)
- self.assertApproximates(process(i, "0.0"), 0.0, 1e-10)
- self.assertApproximates(process(i, "34098.23098"), 34098.23098, 1e-10)
- self.assertRaises(formless.InputError, process, i, "")
- self.assertRaises(formless.InputError, process, i, "a string")
- self.assertRaises(formless.InputError, process, i, "1.5j")
-
- i = formless.Real(required=False)
- self.assertApproximates(process(i, "1234.567"), 1234.567, 1e-10)
- self.assertEquals(process(i, ""), None)
-
- def testBoolean(self):
- b = formless.Boolean(required=True)
- self.assertRaises(formless.InputError, process, b, "zoom")
- self.assertRaises(formless.InputError, process, b, True)
- self.assertRaises(formless.InputError, process, b, 54)
- self.assertRaises(formless.InputError, process, b, "")
- self.assertEquals(process(b, "True"), True)
- self.assertEquals(process(b, "False"), False)
-
- b = formless.Boolean(required=False)
- self.assertRaises(formless.InputError, process, b, "zoom")
- self.assertEquals(process(b, ""), None)
- self.assertEquals(process(b, "True"), True)
- self.assertEquals(process(b, "False"), False)
-
- def testFixedDigitInteger(self):
- d = formless.FixedDigitInteger(3, required=True)
- self.assertEquals(process(d, "123"), 123)
- self.assertEquals(process(d, "567"), 567)
- self.assertRaises(formless.InputError, process, d, "12")
- self.assertRaises(formless.InputError, process, d, "1234")
- self.assertRaises(formless.InputError, process, d, "012")
- self.assertRaises(formless.InputError, process, d, "foo")
- self.assertRaises(formless.InputError, process, d, " ")
- self.assertRaises(formless.InputError, process, d, "")
-
- d = formless.FixedDigitInteger(3, required=False)
- self.assertEquals(process(d, "123"), 123)
- self.assertRaises(formless.InputError, process, d, "foo")
- self.assertEquals(process(d, ""), None)
-
- def testDirectory(self):
- p1 = self.mktemp()
- os.mkdir(p1)
- p2 = self.mktemp()
-
- d = formless.Directory(required=True)
- self.assertEquals(process(d, p1), p1)
- self.assertRaises(formless.InputError, process, d, p2)
- self.assertRaises(formless.InputError, process, d, "")
-
- d = formless.Directory(required=False)
- self.assertEquals(process(d, p1), p1)
- self.assertRaises(formless.InputError, process, d, p2)
- self.assertEquals(process(d, ""), None)
-
-
-class Annotation(TestCase):
- def testTypedInterfaceProperties(self):
- class Other(formless.TypedInterface):
- pass
- _indirectOther = lambda: Other # XXX work around Python issue1569356
- class Test(formless.TypedInterface):
- foo = formless.String()
- bar = formless.Text()
- baz = formless.Integer()
- quux = formless.Object(interface=_indirectOther())
-
- self.assertEquals(Test.__properties__, Test.__spec__)
-
- bfoo, bbar, bbaz, quux = Test.__properties__
-
- self.assertEquals(bfoo.name, 'foo')
- self.assertEquals(bbar.name, 'bar')
- self.assertEquals(bbaz.name, 'baz')
-
- self.assertEquals(bfoo.typedValue.__class__, formless.String)
- self.assertEquals(bbar.typedValue.__class__, formless.Text)
- self.assertEquals(bbaz.typedValue.__class__, formless.Integer)
- self.assertEquals(quux.typedValue.__class__, formless.Object)
-
- self.assertEquals(quux.typedValue.iface, Other)
-
-
- def testTypedInterfaceMethods(self):
- class IFoo(formless.TypedInterface):
- pass
-
- _indirectIFoo = lambda: IFoo # XXX work around Python issue1569356
- class Test2(formless.TypedInterface):
- def foo(foobar=formless.String()):
- """This is a description of foo"""
- pass
- foo = formless.autocallable(foo)
-
- def bar(barbaz=formless.Integer(label="The Baz")):
- ## this has no docstring, make sure it doesn't fail
- return formless.String()
- bar = formless.autocallable(bar, someAttribute="Hello")
-
- def baz(bazfoo=formless.Boolean(label="The Foo", description="The foo to baz.")):
- """The Label
-
- The description"""
- IFoo = _indirectIFoo()
- return IFoo
- baz = formless.autocallable(baz)
-
- self.assertEquals(Test2.__methods__, Test2.__spec__)
-
- bfoo, bbar, bbaz = Test2.__methods__
-
- self.assertEquals(bfoo.name, 'foo')
- self.assertEquals(bbar.name, 'bar')
- self.assertEquals(bbar.getAttribute('someAttribute'), "Hello")
- self.assertEquals(bbaz.name, 'baz')
-
- self.assertEquals(bfoo.label, 'Foo')
- self.assertEquals(bfoo.description, 'This is a description of foo')
-
- self.assertEquals(bbar.label, 'Bar')
- self.assertEquals(bbar.description, '')
-
- self.assertEquals(bbaz.label, 'The Label')
- self.assertEquals(bbaz.description, 'The description')
-
- def getArgTypes(mbinding):
- return [x.typedValue.__class__ for x in mbinding.arguments]
-
- self.assertEquals(getArgTypes(bfoo), [formless.String])
- self.assertEquals(bfoo.returnValue.iface, None)
-
- self.assertEquals(getArgTypes(bbar), [formless.Integer])
- self.assertEquals(bbar.returnValue.__class__, formless.String)
-
- self.assertEquals(getArgTypes(bbaz), [formless.Boolean])
- self.assertEquals(bbaz.returnValue.iface, IFoo)
-
- def firstArg(mbinding):
- return mbinding.arguments[0]
-
- self.assertEquals(firstArg(bfoo).label, 'Foobar')
- self.assertEquals(firstArg(bfoo).description, '')
-
- self.assertEquals(firstArg(bbar).label, 'The Baz')
- self.assertEquals(firstArg(bbar).description, '')
-
- self.assertEquals(firstArg(bbaz).label, 'The Foo')
- self.assertEquals(firstArg(bbaz).description, 'The foo to baz.')
-
- def testTypedInterfaceMethods_actionLabel(self):
- """When no label was given, docstring is given preference compared to action."""
- class Test(formless.TypedInterface):
- def foo(foobar=formless.String()):
- """
- Label for foo
- Description for foo
- """
- pass
- foo = formless.autocallable(foo, action="Do something!")
-
- self.assertEquals(Test.__methods__, Test.__spec__)
- (bfoo,) = Test.__methods__
-
- self.assertEquals(bfoo.name, 'foo')
-
- self.assertEquals(bfoo.label, 'Label for foo')
- self.assertEquals(bfoo.description, 'Description for foo')
-
- def testTypedInterfaceMethods_explicitLabel(self):
- """When a label was given, it is given preference compared to docstring."""
- class Test(formless.TypedInterface):
- def foo(foobar=formless.String()):
- """
- Docstring label for foo
- Description for foo
- """
- pass
- foo = formless.autocallable(foo,
- action="Do something!",
- label="Explicit label for foo",
- )
-
- self.assertEquals(Test.__methods__, Test.__spec__)
- (bfoo,) = Test.__methods__
-
- self.assertEquals(bfoo.name, 'foo')
-
- self.assertEquals(bfoo.label, 'Explicit label for foo')
- self.assertEquals(bfoo.description, 'Description for foo')
-
- def testTypedInterfaceMethods_deprecated(self):
- class Test(formless.TypedInterface):
- def noArgs(self):
- pass
- noArgs = formless.autocallable(noArgs)
-
- def oneArg(self, someParam=formless.String()):
- pass
- oneArg = formless.autocallable(oneArg)
-
- self.assertEquals(Test.__methods__, Test.__spec__)
- m_noArgs, m_oneArg = Test.__methods__
-
- self.assertEquals(len(m_noArgs.arguments), 0)
- self.assertEquals(len(m_oneArg.arguments), 1)
-
- def testTypedInterfaceMethods_nonAutocallable(self):
- class Test(formless.TypedInterface):
- def notAutocallable(arg1, arg2):
- pass
-
- self.assertEquals(Test.__methods__, Test.__spec__)
- self.assertEquals(Test.__methods__, [])
-
-class IListWithActions(formless.TypedInterface):
- def actionOne(theSubset = formless.List()):
- pass
- def actionTwo(theSubset = formless.List()):
- pass
-
- theListOfStuff = formless.List(actions=[actionOne, actionTwo])
-
-
-class TestListActions(TestCase):
- def test_listActionMetadata(self):
- ## IListWithActions only has one binding, a Property binding
- ## of theListOfStuff to a List with some actions.
- actions = IListWithActions.__spec__[0].typedValue.actions
- self.failUnless(reduce, (lambda x: x.name == 'actionOne', actions))
- self.failUnless(reduce, (lambda x: x.name == 'actionTwo', actions))
-
-
-class TestPropertyGroups(TestCase):
- def test_nestedTypedInterfaces(self):
- class Outer(formless.TypedInterface):
- aSimpleProperty = formless.Object()
-
- class Inner(formless.TypedInterface):
- """Docstring
-
- This is a docstring.
- """
- anInnerProperty = formless.Integer()
-
- self.assertEquals(Outer.__spec__[1].typedValue.iface, Outer.Inner)
- inn = Outer.__spec__[1].typedValue.iface
=== removed file 'Nevow/formless/test/test_freeform.py'
--- Nevow/formless/test/test_freeform.py 2006-03-17 15:00:39 +0000
+++ Nevow/formless/test/test_freeform.py 1970-01-01 00:00:00 +0000
@@ -1,666 +0,0 @@
-# Copyright (c) 2004 Divmod.
-# See LICENSE for details.
-
-from zope.interface import implements
-
-from twisted.python import components
-
-from nevow import tags
-from nevow import inevow
-from nevow import context
-from nevow import util
-
-import formless
-from formless import webform
-from formless import iformless
-from formless import configurable
-
-from nevow.test import test_flatstan
-
-class Base(test_flatstan.Base):
- implements(iformless.IConfigurableFactory)
-
- synchronousLocateConfigurable = False
-
- def locateConfigurable(self, *args, **kw):
- r = iformless.IConfigurable(self.conf)
- if not self.synchronousLocateConfigurable:
- r = util.succeed(r)
- return r
-
- def setupContext(self, *args, **kw):
- ctx = test_flatstan.Base.setupContext(self, *args, **kw)
- return context.PageContext(tag=tags.html(), parent=ctx)
-
- def render(self, tag, setupContext=lambda c:c):
- return test_flatstan.Base.render(
- self, tag, setupContext=setupContext,
- wantDeferred=True)
-
- def renderForms(self, configurable, ctx=None, *args, **kwargs):
- self.conf = configurable
- if ctx is None:
- ctx = self.setupContext(False)
- ctx.remember(self, iformless.IConfigurableFactory)
- return self.render(
- webform.renderForms(*args, **kwargs),
- setupContext=lambda c: ctx)
-
- def postForm(self, ctx, obj, bindingName, args):
- self.conf = obj
- ctx.remember(self, iformless.IConfigurableFactory)
-
- def trapValidate(f):
- f.trap(formless.ValidateError)
- e = f.value
- errors = ctx.locate(iformless.IFormErrors)
- ## Set the overall error for this form
- errors.setError(bindingName, e.formErrorMessage)
- errors.updateErrors(bindingName, e.errors)
- ctx.locate(iformless.IFormDefaults).getAllDefaults(bindingName).update(e.partialForm)
-
- return util.maybeDeferred(self.locateConfigurable,obj).addCallback(lambda x: x.postForm(
- ctx, bindingName, args
- )).addErrback(trapValidate)
-
-
-class Complete(Base):
- def test_configureProperty(self):
- class IStupid(formless.TypedInterface):
- foo = formless.String()
-
- class StupidThing(configurable.Configurable):
- implements(IStupid)
-
- def __init__(self):
- configurable.Configurable.__init__(self, None)
- self.foo = 'foo'
-
- dumb = StupidThing()
-
- def doasserts(val):
- self.assertSubstring('freeform_post!!foo', val)
- self.assertSubstring('foo', val)
- self.assertSubstring('type="text"', val)
- self.assertSubstring('<input type="submit"', val)
- return self.renderForms(dumb).addCallback(doasserts)
-
-
- def test_configureMethod(self):
- class IDumb(formless.TypedInterface):
- def foo(bar=formless.String()):
- return formless.String()
- foo = formless.autocallable(foo)
-
- class DumbThing(configurable.Configurable):
- implements(IDumb)
-
- def foo(self, bar):
- return "baz"
-
- stupid = DumbThing(1)
-
- def doasserts(val):
- self.assertSubstring('freeform_post!!foo', val)
- self.assertSubstring('foo', val)
- self.assertSubstring('bar', val)
- return self.renderForms(stupid).addCallback(doasserts)
-
-
-class BuildingBlocksTest(Base):
- def test_1_renderTyped(self):
- binding = formless.Property('hello', formless.String(
- label="Hello",
- description="Hello, world."))
-
- ## Look up a renderer specific to the type of our binding, typedValue;
- renderer = iformless.ITypedRenderer(
- binding.typedValue, None)
-
- ## But render the binding itself with this renderer
- ## The binding has the ".name" attribute we need
- def later(val):
- self.assertSubstring('hello', val)
- self.assertSubstring('Hello', val)
- self.assertSubstring('Hello, world.', val)
- self.failIfSubstring('</form>', val)
- self.failIfSubstring('<input type="submit"', val)
- return self.render(tags.invisible(data=binding, render=renderer)).addCallback(later)
-
- test_1_renderTyped.todo = "Render binding"
-
- def test_2_renderPropertyBinding(self):
- binding = formless.Property('goodbye', formless.String(
- label="Goodbye",
- description="Goodbye cruel world"))
-
- # Look up an IBindingRenderer, which will render the form and the typed
- renderer = iformless.IBindingRenderer(binding)
- def later(val):
- self.assertSubstring('<form ', val)
- self.assertSubstring('<input type="submit"', val)
- self.assertSubstring('name="goodbye"', val)
- self.assertSubstring('Goodbye', val)
- self.assertSubstring('Goodbye cruel world', val)
- return self.render(tags.invisible(data=binding, render=renderer)).addCallback(later)
-
- def test_3_renderMethodBinding(self):
- binding = formless.MethodBinding('doit', formless.Method(
- returnValue=None,
- arguments=[formless.Argument('foo', formless.String(label="Foo"))],
- label="Do It",
- description="Do it to 'em all"))
-
- renderer = iformless.IBindingRenderer(binding)
-
- def later(val):
- self.assertSubstring('<form ', val)
- self.assertSubstring('Do It', val)
- self.assertSubstring("Do it to 'em all", val)
- self.assertSubstring("Foo", val)
- self.assertSubstring('name="foo"', val)
- return self.render(tags.invisible(data=binding, render=renderer)).addCallback(later)
-
-
-class TestDefaults(Base):
- def test_1_renderWithDefaultValues(self):
- binding = formless.MethodBinding('haveFun', formless.Method(
- returnValue=None,
- arguments=[formless.Argument('funValue', formless.Integer(label="Fun Value", default=0))]
- ))
-
- def setupCtx(ctx):
- ctx.locate(iformless.IFormDefaults).setDefault('funValue', 15)
- return ctx
-
- renderer = iformless.IBindingRenderer(binding)
- def later(val):
- self.failIfSubstring('0', val)
- self.assertSubstring('15', val)
- return self.render(tags.invisible(data=binding, render=renderer), setupContext=setupCtx).addCallback(
- later)
-
- def test_2_renderWithObjectPropertyValues(self):
- class IDefaultProperty(formless.TypedInterface):
- default = formless.Integer(default=2)
-
- class Foo(configurable.Configurable):
- implements(IDefaultProperty)
- default = 54
-
- def later(val):
- self.failIfSubstring('2', val)
- self.assertSubstring('54', val)
- return self.renderForms(Foo(None)).addCallback(later)
-
- def test_3_renderWithAdapteeAttributeValues(self):
- class IDefaultProperty(formless.TypedInterface):
- default = formless.Integer(default=2)
-
- class Adaptee(object):
- default = 69
-
- class Bar(configurable.Configurable):
- implements(IDefaultProperty)
-
- def later(val):
- self.failIfSubstring('2', val)
- self.assertSubstring('69', val)
- return self.renderForms(Bar(Adaptee())).addCallback(later)
-
- def test_4_testBindingDefaults(self):
- class IBindingDefaults(formless.TypedInterface):
- def aMethod(foo=formless.String(default="The foo")):
- pass
- aMethod = formless.autocallable(aMethod)
-
- aProperty = formless.String(default="The property")
-
- class Implements(configurable.Configurable):
- implements(IBindingDefaults)
-
- def later(val):
- self.assertSubstring("The foo", val)
- self.assertSubstring("The property", val)
- return self.renderForms(Implements(None)).addCallback(later)
-
- def test_5_testDynamicDefaults(self):
- class IDynamicDefaults(formless.TypedInterface):
- def aMethod(foo=formless.String(default="NOTFOO")):
- pass
- def bMethod(foo=formless.String(default="NOTBAR")):
- pass
- aMethod = formless.autocallable(aMethod)
- bMethod = formless.autocallable(bMethod)
-
- class Implements(configurable.Configurable):
- implements(IDynamicDefaults)
-
- def later(val):
- self.assertSubstring("YESFOO", val)
- self.assertSubstring("YESBAR", val)
- self.assertNotSubstring("NOTFOO", val)
- self.assertNotSubstring("NOTBAR", val)
-
- return self.renderForms(Implements(None), bindingDefaults={
- 'aMethod': {'foo': 'YESFOO'},
- 'bMethod': {'foo': 'YESBAR'}}).addCallback(later)
-
-
-class TestNonConfigurableSubclass(Base):
- def test_1_testSimple(self):
- class ISimpleTypedInterface(formless.TypedInterface):
- anInt = formless.Integer()
- def aMethod(aString = formless.String()):
- return None
- aMethod = formless.autocallable(aMethod)
-
- class ANonConfigurable(object): # Not subclassing Configurable
- implements(ISimpleTypedInterface) # But implements a TypedInterface
-
- def later(val):
- self.assertSubstring('anInt', val)
- self.assertSubstring('aMethod', val)
-
- return self.renderForms(ANonConfigurable()).addCallback(later)
-
-
-
-class TestPostAForm(Base):
- def test_1_failAndSucceed(self):
- class IAPasswordMethod(formless.TypedInterface):
- def password(pword = formless.Password(), integer=formless.Integer()):
- pass
- password = formless.autocallable(password)
-
- class APasswordImplementation(object):
- implements(IAPasswordMethod)
- matched = False
- def password(self, pword, integer):
- self.matched = True
- return "password matched"
-
- theObj = APasswordImplementation()
- ctx = self.setupContext()
-
- D = self.postForm(ctx, theObj, "password", {"pword": ["these passwords"], "pword____2": ["don't match"], 'integer': ['Not integer']})
- def after(result):
- self.assertEquals(theObj.matched, False)
- def later(val):
- self.assertSubstring("Passwords do not match. Please reenter.", val)
- self.assertSubstring('value="Not integer"', val)
- return self.renderForms(theObj, ctx).addCallback(later)
- return D.addCallback(after)
-
- def test_2_propertyFailed(self):
- class IAProperty(formless.TypedInterface):
- prop = formless.Integer()
-
- class Impl(object):
- implements(IAProperty)
- prop = 5
-
- theObj = Impl()
- ctx = self.setupContext()
- D = self.postForm(ctx, theObj, 'prop', {'prop': ['bad']})
- def after(result):
- def later(val):
- self.assertSubstring('value="bad"', val)
- return self.renderForms(theObj, ctx).addCallback(later)
- return D.addCallback(after)
-
-
-class TestRenderPropertyGroup(Base):
- def test_1_propertyGroup(self):
- class Outer(formless.TypedInterface):
- class Inner(formless.TypedInterface):
- one = formless.Integer()
- two = formless.Integer()
-
- def buckleMyShoe():
- pass
- buckleMyShoe = formless.autocallable(buckleMyShoe)
-
- def buriedAlive():
- pass
- buriedAlive = formless.autocallable(buriedAlive)
-
- class Implementation(object):
- implements(Outer)
- one = 1
- two = 2
- buckled = False
- buried = False
- def buckleMyShoe(self):
- self.buckled = True
- def buriedAlive(self):
- self.buried = True
-
- impl = Implementation()
- ctx = self.setupContext()
-
- def later(val):
- D = self.postForm(ctx, impl, "Inner", {'one': ['Not an integer'], 'two': ['22']})
-
- def after(result):
-
- self.assertEquals(impl.one, 1)
- self.assertEquals(impl.two, 2)
- self.assertEquals(impl.buckled, False)
- self.assertEquals(impl.buried, False)
-
- def evenlater(moreval):
- self.assertSubstring("is not an integer", moreval)
- # TODO: Get default values for property groups displaying properly.
- #self.assertSubstring('value="Not an integer"', moreval)
- DD = self.postForm(ctx, impl, "Inner", {'one': ['11'], 'two': ['22']})
- def afterafter(ign):
- self.assertEquals(impl.one, 11)
- self.assertEquals(impl.two, 22)
- self.assertEquals(impl.buckled, True)
- self.assertEquals(impl.buried, True)
- return DD.addCallback(afterafter)
- return self.renderForms(impl, ctx).addCallback(evenlater)
- return D.addCallback(after)
- return self.renderForms(impl).addCallback(later)
-
-class TestRenderMethod(Base):
-
- def testDefault(self):
-
- class IFoo(formless.TypedInterface):
- def foo(abc=formless.String()):
- pass
- foo = formless.autocallable(foo)
-
- class Impl:
- implements(IFoo)
-
- def later(val):
- self.assertSubstring('value="Foo"', val)
- self.assertSubstring('name="abc"', val)
- return self.renderForms(Impl(), bindingNames=['foo']).addCallback(later)
-
-
- def testActionLabel(self):
-
- class IFoo(formless.TypedInterface):
- def foo(abc=formless.String()):
- pass
- foo = formless.autocallable(foo, action='FooFooFoo')
-
- class Impl:
- implements(IFoo)
-
- def later(val):
- self.assertSubstring('value="FooFooFoo"', val)
- self.assertSubstring('name="abc"', val)
- return self.renderForms(Impl(), bindingNames=['foo']).addCallback(later)
-
- def testOneSigMultiCallables(self):
-
- class IFoo(formless.TypedInterface):
- def sig(abc=formless.String()):
- pass
- foo = formless.autocallable(sig)
- bar = formless.autocallable(sig, action='FooFooFOo')
-
- class Impl:
- implements(IFoo)
-
- def later1(val):
- self.assertSubstring('value="Foo"', val)
- def later2(val):
- self.assertSubstring('value="FooFooFoo"', val)
- return self.renderForms(Impl(), bindingNames=['bar']).addCallback(later2)
- return self.renderForms(Impl(), bindingNames=['foo']).addCallback(later1)
- testOneSigMultiCallables.todo = 'autocallable should not set attributes directly on the callable'
-
-
-class TestCustomTyped(Base):
- def test_typedCoerceWithBinding(self):
- class MyTyped(formless.Typed):
- passed = False
- wasBoundTo = None
- def coerce(self, val, boundTo):
- self.passed = True
- self.wasBoundTo = boundTo
- return "passed"
-
- typedinst = MyTyped()
-
- class IMyInterface(formless.TypedInterface):
- def theFunc(test=typedinst):
- pass
- theFunc = formless.autocallable(theFunc)
-
- class Implementation(object):
- implements(IMyInterface)
- called = False
- def theFunc(self, test):
- self.called = True
-
- inst = Implementation()
- ctx = self.setupContext()
- D = self.postForm(ctx, inst, 'theFunc', {'test': ['a test value']})
- def after(result):
- self.assertEquals(typedinst.passed, True)
- self.assertEquals(typedinst.wasBoundTo, inst)
- self.assertEquals(inst.called, True)
- return D.addCallback(after)
-
-
-class TestUneditableProperties(Base):
- def test_uneditable(self):
- class Uneditable(formless.TypedInterface):
- aProp = formless.String(description="the description", immutable=True)
-
- class Impl(object):
- implements(Uneditable)
-
- aProp = property(lambda self: "HELLO")
-
- inst = Impl()
-
- def later(val):
- self.assertSubstring('HELLO', val)
- self.failIfSubstring('type="text"', val)
- return self.renderForms(inst).addCallback(later)
-
-
-class TestAfterValidation(Base):
- """Test post-validation rendering"""
-
- def test_property(self):
- """Test that, when validation fails, the value just entered is redisplayed"""
-
- class IThing(formless.TypedInterface):
- foo = formless.Integer()
-
- class Thing:
- implements(IThing)
- foo = 1
-
- inst = Thing()
- ctx = self.setupContext()
- D = self.postForm(ctx, inst, 'foo', {'foo': ['abc']})
- def after(result):
- def later(val):
- def morelater(noval):
- self.assertSubstring('value="abc"', val)
- return self.renderForms(inst, ctx).addCallback(morelater)
- return self.renderForms(inst)
- return D.addCallback(after)
-
-
-class TestHandAndStatus(Base):
- """Test that the method result is available as the hand, and that
- a reasonable status message string is available"""
- def test_hand(self):
- """Test that the hand and status message are available before redirecting the post
- """
- returnResult = object()
- class IMethod(formless.TypedInterface):
- def foo(): pass
- foo = formless.autocallable(foo)
-
- class Method(object):
- implements(IMethod)
- def foo(self):
- return returnResult
-
- inst = Method()
- ctx = self.setupContext()
- D = self.postForm(ctx, inst, 'foo', {})
- def after(result):
- self.assertEquals(ctx.locate(inevow.IHand), returnResult)
- self.assertEquals(ctx.locate(inevow.IStatusMessage), "'foo' success.")
- return D.addCallback(after)
-
- def test_handFactory(self):
- """Test that the hand and status message are available after redirecting the post
- """
- returnResult = object()
- status = 'horray'
- def setupRequest(r):
- r.args['_nevow_carryover_'] = ['abc']
- from nevow import rend
- c = components.Componentized()
- c.setComponent(inevow.IHand, returnResult)
- c.setComponent(inevow.IStatusMessage, status)
- rend._CARRYOVER['abc'] = c
- return r
- ctx = self.setupContext(setupRequest=setupRequest)
-
- self.assertEquals(ctx.locate(inevow.IHand), returnResult)
- self.assertEquals(ctx.locate(inevow.IStatusMessage), status)
-
-
-class TestCharsetDetectionSupport(Base):
-
- def test_property(self):
-
- class ITest(formless.TypedInterface):
- foo = formless.String()
-
- class Impl:
- implements(ITest)
-
- impl = Impl()
- ctx = self.setupContext()
- def later(val):
- self.assertIn('<input type="hidden" name="_charset_" />', val)
- self.assertIn('accept-charset="utf-8"', val)
- return self.renderForms(impl, ctx).addCallback(later)
-
-
- def test_group(self):
-
- class ITest(formless.TypedInterface):
- class Group(formless.TypedInterface):
- foo = formless.String()
-
- class Impl:
- implements(ITest)
-
- impl = Impl()
- ctx = self.setupContext()
- def later(val):
- self.assertIn('<input type="hidden" name="_charset_" />', val)
- self.assertIn('accept-charset="utf-8"', val)
- return self.renderForms(impl, ctx).addCallback(later)
-
-
- def test_method(self):
-
- class ITest(formless.TypedInterface):
- def foo(foo = formless.String()):
- pass
- foo = formless.autocallable(foo)
-
- class Impl:
- implements(ITest)
-
- impl = Impl()
- ctx = self.setupContext()
- def later(val):
- self.assertIn('<input type="hidden" name="_charset_" />', val)
- self.assertIn('accept-charset="utf-8"', val)
- return self.renderForms(impl, ctx).addCallback(later)
-
-
-class TestUnicode(Base):
-
- def test_property(self):
-
- class IThing(formless.TypedInterface):
- aString = formless.String(unicode=True)
-
- class Impl(object):
- implements(IThing)
- aString = None
-
- inst = Impl()
- ctx = self.setupContext()
- D = self.postForm(ctx, inst, 'aString', {'aString':['\xc2\xa3']})
- return D.addCallback(lambda result: self.assertEquals(inst.aString, u'\xa3'))
-
-class TestChoice(Base):
- """Test various behaviors of submitting values to a Choice Typed.
- """
-
- def test_reject_missing(self):
- # Ensure that if a Choice is not specified, the form is not submitted.
-
- self.called = []
-
- class IFormyThing(formless.TypedInterface):
- def choiceyFunc(arg = formless.Choice(["one", "two"], required=True)):
- pass
- choiceyFunc = formless.autocallable(choiceyFunc)
-
- class Impl(object):
- implements(IFormyThing)
-
- def choiceyFunc(innerSelf, arg):
- self.called.append(arg)
-
- inst = Impl()
- ctx = self.setupContext()
- D = self.postForm(ctx, inst, 'choiceyFunc', {})
- return D.addCallback(lambda result: self.assertEquals(self.called, []))
-
-
-class mg(Base):
-
- def test_leakyForms(self):
-
- class ITest(formless.TypedInterface):
- """Test that a property value on one form does not 'leak' into
- a property of the same name on another form.
- """
- foo = formless.String()
-
- def meth(foo = formless.String()):
- pass
- meth = formless.autocallable(meth)
-
- class Impl:
- implements(ITest)
- foo = 'fooFOOfoo'
-
- impl = Impl()
- ctx = self.setupContext()
- def later(val):
- self.assertEquals(val.count('fooFOOfoo'), 1)
- return self.renderForms(impl, ctx)
-
-
-# What the *hell* is this?!?
-
-#DeferredTestCases = type(Base)(
-# 'DeferredTestCases',
-# tuple([v for v in locals().values()
-# if isinstance(v, type(Base)) and issubclass(v, Base)]),
-# {'synchronousLocateConfigurable': True})
-
=== removed file 'Nevow/formless/webform.py'
--- Nevow/formless/webform.py 2006-04-14 17:23:46 +0000
+++ Nevow/formless/webform.py 1970-01-01 00:00:00 +0000
@@ -1,467 +0,0 @@
-# -*- test-case-name: formless.test.test_freeform -*-
-
-# Copyright (c) 2004 Divmod.
-# See LICENSE for details.
-
-
-from __future__ import generators
-
-import warnings
-from zope.interface import implements, Interface
-
-from twisted.python import components
-
-from nevow import inevow
-from nevow.stan import slot
-from nevow import tags
-from nevow import util
-from nevow.context import NodeNotFound
-
-from formless import iformless
-from formless.formutils import FormDefaults, FormErrors, calculatePostURL, keyToXMLID, getError
-
-
-from nevow.static import File
-
-defaultCSS = File(util.resource_filename('formless', 'freeform-default.css'), 'text/css')
-
-
-class DefaultRenderer(object):
- implements(inevow.IRenderer, iformless.ITypedRenderer)
- complexType = False
- def rend(self, context, data):
- return StringRenderer(data)
-
-defaultBindingRenderer = DefaultRenderer()
-
-
-class BaseInputRenderer(components.Adapter):
- implements(inevow.IRenderer, iformless.ITypedRenderer)
- complexType = False
- def rend(self, context, data):
- defaults = context.locate(iformless.IFormDefaults)
- value = defaults.getDefault(context.key, context)
- context.remember(data.typedValue, iformless.ITyped)
-
- if data.typedValue.getAttribute('immutable'):
- inp = tags.span(id=keyToXMLID(context.key))[value]
- else:
- ##value may be a deferred; make sure to wait on it properly before calling self.input
- ## TODO: If flattening this results in an empty string, return an empty string
- inp = tags.invisible(
- render=lambda c, value: self.input( context, tags.invisible(), data, data.name, value ),
- data=value)
-
- if data.typedValue.getAttribute('hidden') or data.typedValue.getAttribute('compact'):
- return inp
-
- context.fillSlots( 'label', data.label )
- context.fillSlots( 'name', data.name )
- context.fillSlots( 'input', inp )
- context.fillSlots( 'error', getError(context) )
- context.fillSlots( 'description', data.description )
- context.fillSlots( 'id', keyToXMLID(context.key) )
- context.fillSlots( 'value', value )
-
- return context.tag
-
- def input(self, context, slot, data, name, value):
- raise NotImplementedError, "Implement in subclass"
-
-class PasswordRenderer(BaseInputRenderer):
- def input(self, context, slot, data, name, value):
- return [
- tags.input(id=keyToXMLID(context.key), name=name, type="password", _class="freeform-input-password"),
- " Again ",
- tags.input(name="%s____2" % name, type="password", _class="freeform-input-password"),
- ]
-
-
-class PasswordEntryRenderer(BaseInputRenderer):
- def input(self, context, slot, data, name, value):
- return slot[
- tags.input(id=keyToXMLID(context.key), type='password', name=name,
- _class='freeform-input-password')]
-
-
-class StringRenderer(BaseInputRenderer):
- def input(self, context, slot, data, name, value):
- if data.typedValue.getAttribute('hidden'):
- T="hidden"
- else:
- T="text"
- return slot[
- tags.input(id=keyToXMLID(context.key), type=T, name=name, value=value,
- _class='freeform-input-%s' % T)]
-
-
-class TextRenderer(BaseInputRenderer):
- def input(self, context, slot, data, name, value):
- return slot[
- tags.textarea(id=keyToXMLID(context.key), name=name, _class="freeform-textarea", rows=8, cols=40)[
- value or '']]
-
-
-class BooleanRenderer(BaseInputRenderer):
- def input(self, context, slot, data, name, value):
- ## The only difference here is the "checked" attribute; the value is still the same because
- ## we want true to be passed to the server when the checkbox is checked and the form
- ## is posted.
- node = tags.input(id=keyToXMLID(context.key), type="checkbox", name=name, value='True', _class="freeform-input-checkbox")
- if value:
- node(checked="checked")
-
- # HTML forms are so weak. If the checkbox is not checked, no value at all will be
- # in request.args with the name data.name. So let's force the value False to always
- # be in request.args[data.name]. If the checkbox is checked, the value True will
- # be first, and we will find that.
- return slot[node, tags.input(type="hidden", name=name, value="False")]
-
-
-class FileUploadRenderer(BaseInputRenderer):
- def input(self, context, slot, data, name, value):
- return slot[tags.input(id=keyToXMLID(context.key), type="file", name=name,
- _class='freeform-input-file')]
-
-
-class ICurrentlySelectedValue(Interface):
- """The currently-selected-value for the ITypedRenderer being rendered.
- """
-
-
-csv = ICurrentlySelectedValue
-def valToKey(c, d):
- return iformless.ITyped(c).valueToKey(d)
-
-
-def isSelected(c, d):
- if csv(c) == valToKey(c, d):
- return c.tag(selected='selected')
- return c.tag
-
-
-def isChecked(c, d):
- if csv(c) == valToKey(c, d):
- return c.tag(checked='checked')
- return c.tag
-
-
-class ChoiceRenderer(BaseInputRenderer):
- default_select = tags.select(id=slot('id'), name=slot('name'), render=tags.directive('sequence'))[
- tags.option(pattern="item",
- value=valToKey,
- render=isSelected)[
- lambda c, d: iformless.ITyped(c).stringify(d)]]
-
- def input(self, context, slot, data, name, value):
- tv = data.typedValue
- choices = tv.choices
-
- if value:
- context.remember(value, csv)
- else:
- context.remember('', csv)
-
- try:
- selector = context.tag.patternGenerator( 'selector' )
- except NodeNotFound:
- selector = self.default_select
-
- return selector(data=choices)
-
-
-class RadioRenderer(ChoiceRenderer):
- default_select = tags.span(id=slot('id'), render=tags.directive('sequence'))[
- tags.div(pattern="item", _class="freeform-radio-option")[
- tags.input(type="radio", name=slot('name'), value=valToKey, render=isChecked)[
- lambda c, d: iformless.ITyped(c).stringify(d)]]]
-
-
-class ObjectRenderer(components.Adapter):
- implements(inevow.IRenderer, iformless.ITypedRenderer)
- complexType = True
- def rend(self, context, data):
- configurable = context.locate(iformless.IConfigurable)
- return getattr(configurable, data.name)
-
-class NullRenderer(components.Adapter):
- """Use a NullRenderer as the ITypedRenderer adapter when nothing should
- be included in the output.
- """
- implements(inevow.IRenderer, iformless.ITypedRenderer)
- def rend(self, context, data):
- return ''
-
-
-class GroupBindingRenderer(components.Adapter):
- implements(inevow.IRenderer)
-
- def rend(self, context, data):
- context.remember(data, iformless.IBinding)
-
- from formless import configurable as conf
-
- configurable = conf.GroupConfigurable(data.boundTo, data.typedValue.iface)
- context.remember(configurable, iformless.IConfigurable)
-
- bindingNames = configurable.getBindingNames(context)
-
- def generateBindings():
- for name in bindingNames:
- bnd = configurable.getBinding(context, name)
- renderer = iformless.IBindingRenderer(bnd, defaultBindingRenderer)
- renderer.isGrouped = True
- renderer.needsSkin = True
- yield tags.invisible(
- data=bnd,
- render=renderer,
- key=name)
-
- return getError(context), tags.form(
- id=keyToXMLID(context.key),
- enctype="multipart/form-data",
- action=calculatePostURL(context, data),
- method="post",
- **{'accept-charset':'utf-8'})[
- tags.fieldset[
- tags.legend(_class="freeform-form-label")[data.label],
- tags.input(type='hidden', name='_charset_'),
- generateBindings(),
- tags.input(type="submit")]]
-
-
-class BaseBindingRenderer(components.Adapter):
- implements(inevow.IRenderer)
-
- isGrouped = False
- needsSkin = False
- def calculateDefaultSkin(self, context):
- if self.isGrouped:
- frm = tags.invisible
- butt = ''
- fld = tags.invisible
- else:
- frm = tags.form(
- id=slot('form-id'),
- name=slot('form-id'),
- action=slot('form-action'),
- method="post",
- enctype="multipart/form-data",
- **{'accept-charset':'utf-8'}
- )
- butt = slot('form-button')
- fld = tags.fieldset[tags.input(type='hidden', name='_charset_')]
-
- ## Provide default skin since no skin was provided for us.
- context.tag.clear()[
- frm[fld[tags.legend(_class="freeform-form-label")[ slot('form-label') ],
- tags.div(_class="freeform-form-description")[slot('form-description')],
- tags.div(_class="freeform-form-error")[ slot('form-error') ],
-
- slot('form-arguments'), butt ]]]
-
- def fillForm(self, context, data):
- context.fillSlots( 'form-id', keyToXMLID(context.key) )
- context.fillSlots( 'form-action', calculatePostURL(context, data) )
- context.fillSlots( 'form-name', data.name )
- context.fillSlots( 'form-error', getError(context) )
-
-
-class PropertyBindingRenderer(BaseBindingRenderer):
- def rend(self, context, data):
- context.remember(data, iformless.IBinding)
- context.remember(data.typedValue, iformless.ITyped)
- typedRenderer = iformless.ITypedRenderer(data.typedValue, defaultBindingRenderer)
- if typedRenderer.complexType:
- return tags.invisible(data=data, render=typedRenderer)
-
- if self.needsSkin or not context.tag.children:
- self.calculateDefaultSkin(context)
-
- if self.isGrouped or data.typedValue.getAttribute('immutable'):
- subm = ''
- else:
- subm = tags.input(type="submit", name="change", value="Change")
-
- self.fillForm(context, data)
- context.fillSlots( 'form-label', '' )
- context.fillSlots( 'form-description', '' )
-
- try:
- content_pattern = context.tag.patternGenerator( 'binding' )
- except NodeNotFound:
- content_pattern = freeformDefaultContentPattern
-
- context.fillSlots(
- 'form-arguments',
- content_pattern(
- data=data, render=typedRenderer, key=data.name))
-
- context.fillSlots('form-button', subm)
-
- return context.tag
-
-
-freeformDefaultContentPattern = tags.invisible[
- tags.label(_class="freeform-label", _for=slot('id'))[ slot('label') ],
- tags.span(_class="freeform-input")[ slot('input') ],
- tags.div(_class="freeform-error")[ slot('error') ],
- tags.div(_class="freeform-description")[tags.label(_for=slot('id'))[ slot('description') ]]].freeze()
-
-
-class MethodBindingRenderer(BaseBindingRenderer):
- def rend(self, context, data):
- if data.getAttribute('invisible'):
- return ''
-
- context.remember(data, iformless.IBinding)
-
- if self.needsSkin or not context.tag.children:
- self.calculateDefaultSkin(context)
-
- self.fillForm(context, data)
- context.fillSlots( 'form-label', data.label )
- context.fillSlots( 'form-description', data.description )
- context.fillSlots( 'form-arguments', list(self.generateArguments(context, data.getArgs())))
-
- if not self.isGrouped:
- try:
- button_pattern = context.tag.onePattern( 'form-button' )
- except NodeNotFound:
- button_pattern = tags.invisible[ slot('input') ]
-
- button_pattern.fillSlots( 'input', tags.input(type='submit', value=data.action or data.label, name=data.name, class_="freeform-button") )
-
- context.fillSlots( 'form-button', button_pattern )
-
- return context.tag(key=None)
-
- def generateArguments(self, context, args):
- default_content_pattern = None
- content_pattern = None
- for argument in args:
- try:
- content_pattern = context.tag.patternGenerator( 'argument!!%s' % argument.name )
- except NodeNotFound:
- if default_content_pattern is None:
- try:
- default_content_pattern = context.tag.patternGenerator( 'argument' )
- except NodeNotFound:
- default_content_pattern = freeformDefaultContentPattern
- content_pattern = default_content_pattern
- renderer = iformless.ITypedRenderer(
- argument.typedValue, defaultBindingRenderer)
- pat = content_pattern(
- key=argument.name,
- data=argument,
- render=renderer,
- remember={iformless.ITyped: argument.typedValue})
- context.fillSlots( 'argument!!%s' % argument.name, pat )
- yield pat
-
-
-class ButtonRenderer(components.Adapter):
- implements(inevow.IRenderer)
-
- def rend(self, context, data):
- return tags.input(id=keyToXMLID(context.key), type='submit', value=data.label, name=data.name, class_="freeform-button")
-
-
-freeformDefaultForm = tags.div(_class="freeform-form").freeze()
-
-
-def renderForms(configurableKey='', bindingNames=None, bindingDefaults=None):
- """Render forms for either the named configurable, or, if no configurableKey is given,
- the main configurable. If no bindingNames are given, forms will be
- rendered for all bindings described by the configurable.
-
- @param configurableKey: The name of the configurable to render. The empty
- string indicates ctx.locate(IRenderer).
-
- @param bindingNames: The names of the bindings to render. None indicates
- all bindings.
-
- @param bindingDefaults: A dict mapping bindingName: bindingDefault. For example,
- given the TypedInterface::
-
- >>> class IMyForm(annotate.TypedInterface):
- ... def doSomething(self, name=annotate.String()):
- ... pass
- ... doSomething = annotate.autocallable(doSomething)
- ... def doNothing(self name=annotate.String()):
- ... pass
- ... doNothing = annotate.autocallable(doNothing)
- ... def doMoreThings(self name=annotate.String(), things=annotate.String()):
- ... pass
- ... doMoreThings = annotate.autocallable(doMoreThings)
-
- One might call renderForms() like this::
-
- return webform.renderForms(
- '',
- bindingDefaults={'doSomething': {'name': 'jimbo'},
- # Change 'name' default, don't change 'things'
- 'doMoreThings': {'things': 'jimbo'}
- })
-
- This would cause a form to be rendered which will call doSomething when
- submitted, and would have "jimbo" filled out as the default value for
- the name field, as well as a form which will call doMoreThings (with no
- default value filled in for 'name' but 'jimbo' filled in for 'things').
- """
-
- assert bindingNames is None or bindingDefaults is None, "Only specify bindingNames or bindingDefaults"
-
- if bindingNames is not None:
- bindingDefaults = dict.fromkeys(bindingNames, {})
-
- def formRenderer(ctx, data):
- cf = ctx.locate(iformless.IConfigurableFactory)
- return util.maybeDeferred(cf.locateConfigurable, ctx, configurableKey
- ).addCallback(_formRenderIt)
-
- def _formRenderIt(configurable):
- def _innerFormRenderIt(context, data):
- tag = context.tag
- # Remember the key for when the form post URL is generated.
- context.remember(configurableKey, iformless.IConfigurableKey)
- if configurable is None:
- warnings.warn(
- "No configurable was found which provides enough type information for freeform to be able to render forms")
- yield ''
- return
- context.remember(configurable, iformless.IConfigurable)
-
- formDefaults = iformless.IFormDefaults(context)
-
- if bindingDefaults is None:
- available = configurable.getBindingNames(context)
- else:
- available = bindingDefaults.iterkeys()
-
- def _callback(binding):
- renderer = iformless.IBindingRenderer(binding, defaultBindingRenderer)
- try:
- binding_pattern = tag.patternGenerator( 'freeform-form!!%s' % name )
- except NodeNotFound:
- try:
- binding_pattern = tag.patternGenerator( 'freeform-form' )
- except NodeNotFound:
- binding_pattern = freeformDefaultForm
-
- if binding_pattern is freeformDefaultForm:
- renderer.needsSkin = True
- return binding_pattern(data=binding, render=renderer, key=name)
-
- for name in available:
- if bindingDefaults is not None:
- defs = formDefaults.getAllDefaults(name)
- defs.update(bindingDefaults[name])
-
- d = util.maybeDeferred(configurable.getBinding, context, name)
- d.addCallback(_callback)
- yield d
-
- return _innerFormRenderIt
- return tags.invisible(render=formRenderer)
-
=== modified file 'Nevow/nevow/__init__.py'
--- Nevow/nevow/__init__.py 2008-05-20 14:44:03 +0000
+++ Nevow/nevow/__init__.py 2011-07-26 00:42:36 +0000
@@ -44,8 +44,6 @@
basic_adapters = """
-formless.annotate.Group formless.annotate.MetaTypedInterface formless.iformless.ITyped
-
nevow.accessors.DictionaryContainer __builtin__.dict nevow.inevow.IContainer
nevow.accessors.ListContainer __builtin__.list nevow.inevow.IContainer
nevow.accessors.ListContainer __builtin__.tuple nevow.inevow.IContainer
@@ -57,68 +55,16 @@
nevow.accessors.SlotAccessor nevow.stan.slot nevow.inevow.IGettable
nevow.accessors.SlotAccessor nevow.stan._PrecompiledSlot nevow.inevow.IGettable
- #
-
-formless.webform.PropertyBindingRenderer formless.annotate.Property formless.iformless.IBindingRenderer
-formless.webform.MethodBindingRenderer formless.annotate.MethodBinding formless.iformless.IBindingRenderer
-formless.webform.GroupBindingRenderer formless.annotate.GroupBinding formless.iformless.IBindingRenderer
-
- #
-
-formless.webform.StringRenderer formless.annotate.String formless.iformless.ITypedRenderer
-formless.webform.StringRenderer formless.annotate.Integer formless.iformless.ITypedRenderer
-formless.webform.StringRenderer formless.annotate.Directory formless.iformless.ITypedRenderer
-formless.webform.PasswordRenderer formless.annotate.Password formless.iformless.ITypedRenderer
-formless.webform.PasswordEntryRenderer formless.annotate.PasswordEntry formless.iformless.ITypedRenderer
-formless.webform.TextRenderer formless.annotate.Text formless.iformless.ITypedRenderer
-formless.webform.BooleanRenderer formless.annotate.Boolean formless.iformless.ITypedRenderer
-formless.webform.ChoiceRenderer formless.annotate.Choice formless.iformless.ITypedRenderer
-formless.webform.RadioRenderer formless.annotate.Radio formless.iformless.ITypedRenderer
-formless.webform.ObjectRenderer formless.annotate.Object formless.iformless.ITypedRenderer
-formless.webform.NullRenderer formless.annotate.Request formless.iformless.ITypedRenderer
-formless.webform.NullRenderer formless.annotate.Context formless.iformless.ITypedRenderer
-formless.webform.FileUploadRenderer formless.annotate.FileUpload formless.iformless.ITypedRenderer
-formless.webform.ButtonRenderer formless.annotate.Button formless.iformless.ITypedRenderer
-
- #
-
-formless.processors.ProcessGroupBinding formless.annotate.GroupBinding formless.iformless.IInputProcessor
-formless.processors.ProcessMethodBinding formless.annotate.MethodBinding formless.iformless.IInputProcessor
-formless.processors.ProcessPropertyBinding formless.annotate.Property formless.iformless.IInputProcessor
-formless.processors.ProcessTyped formless.iformless.ITyped formless.iformless.IInputProcessor
-formless.processors.ProcessPassword formless.annotate.Password formless.iformless.IInputProcessor
-formless.processors.ProcessRequest formless.annotate.Request formless.iformless.IInputProcessor
-formless.processors.ProcessContext formless.annotate.Context formless.iformless.IInputProcessor
-formless.processors.ProcessUpload formless.annotate.FileUpload formless.iformless.IInputProcessor
-
- #
-
-formless.webform.FormDefaults nevow.appserver.NevowRequest formless.iformless.IFormDefaults
-formless.webform.FormDefaults nevow.testutil.FakeRequest formless.iformless.IFormDefaults
-formless.webform.FormDefaults nevow.testutil.FakeSession formless.iformless.IFormDefaults
-formless.webform.FormDefaults twisted.web.server.Session formless.iformless.IFormDefaults
-formless.webform.FormDefaults nevow.guard.GuardSession formless.iformless.IFormDefaults
-
-formless.webform.FormErrors twisted.web.server.Session formless.iformless.IFormErrors
-formless.webform.FormErrors nevow.guard.GuardSession formless.iformless.IFormErrors
-formless.webform.FormErrors nevow.testutil.FakeSession formless.iformless.IFormErrors
-
nevow.appserver.OldResourceAdapter twisted.web.resource.IResource nevow.inevow.IResource
nevow.static.staticHTML __builtin__.str nevow.inevow.IResource
nevow.appserver.sessionFactory nevow.context.RequestContext nevow.inevow.ISession
-nevow.rend.handFactory nevow.context.RequestContext nevow.inevow.IHand
-nevow.rend.statusFactory nevow.context.RequestContext nevow.inevow.IStatusMessage
-nevow.rend.defaultsFactory nevow.context.RequestContext formless.iformless.IFormDefaults
-nevow.rend.errorsFactory nevow.context.RequestContext formless.iformless.IFormErrors
nevow.rend.originalFactory nevow.context.RequestContext nevow.inevow.IRequest
nevow.appserver.defaultExceptionHandlerFactory nevow.context.SiteContext nevow.inevow.ICanHandleException
nevow.rend.originalFactory nevow.context.PageContext nevow.inevow.IRenderer
nevow.rend.originalFactory nevow.context.PageContext nevow.inevow.IRendererFactory
-nevow.rend.originalFactory nevow.context.PageContext formless.iformless.IConfigurableFactory
-
# URL IResource adapters
nevow.url.URLRedirectAdapter nevow.url.URL nevow.inevow.IResource
nevow.url.URLRedirectAdapter nevow.url.URLOverlay nevow.inevow.IResource
=== modified file 'Nevow/nevow/rend.py'
--- Nevow/nevow/rend.py 2009-07-04 00:32:14 +0000
+++ Nevow/nevow/rend.py 2011-07-26 00:42:36 +0000
@@ -31,9 +31,6 @@
from nevow import inevow, tags, flat, util, url
from nevow.util import log
-import formless
-from formless import iformless, annotate
-
def _getPreprocessors(inst):
"""
@@ -146,224 +143,11 @@
return callable
-class FreeformChildMixin:
- """Mixin that handles locateChild for freeform segments."""
- def locateChild(self, ctx, segments):
- request = inevow.IRequest(ctx)
- ## The method or property name we are going to validate against/affect
- bindingName = None
-
- name = segments[0]
- if name.startswith('freeform_post!'):
- configurableName, bindingName = name.split('!')[1:3]
- elif name.startswith('freeform-action-post!'):
- configurableName, request.args['freeform-actee'] = name.split('!')[1:3]
- bindingName = request.args['freeform-action'][0]
- if bindingName:
- ctx.remember(self, inevow.IResource)
- ctx.remember(request, inevow.IRequest)
- cf = iformless.IConfigurableFactory(self)
- def checkC(c):
- if c is not None:
- return self.webFormPost(request, self, c, ctx, bindingName, request.args)
- return util.maybeDeferred(cf.locateConfigurable, ctx, configurableName).addCallback(checkC)
- return NotFound
-
- def child_freeform_hand(self, ctx):
- carryoverHand = inevow.IHand(ctx, None)
- if carryoverHand is not None:
- inevow.ISession(ctx).setComponent(inevow.IHand, carryoverHand)
- return carryoverHand
- return inevow.IHand(inevow.ISession(ctx), None)
-
-
-class ConfigurableMixin(object):
- """
- A sane L{IConfigurable} implementation for L{Fragment} and L{Page}.
-
- Methods starting with C{bind_} automatically expose corresponding method
- names. C{bind_*} should return an L{IBinding} (L{PropertyBinding} or
- L{MethodBinding}), or, as a shortcut for L{MethodBinding}, a C{list} of
- two-C{tuples} like this::
-
- def bind_foo(self, ctx):
- return [('argName', String()), ('anotherArg', Integer())]
-
- def foo(self, argName, anotherArg):
- assert isinstance(argName, str)
- assert isinstance(anotherArg, int)
- """
- implements(iformless.IConfigurable)
-
- def getBindingNames(self, ctx):
- """Expose bind_* methods and attributes on this class.
- """
- for name in dir(self):
- if name.startswith('bind_'):
- yield name[len('bind_'):]
-
- def getBinding(self, ctx, name):
- """Massage bind_* methods and attributes into an
- IBinding. The bind_* method or attribute can either
- already implement IBinding or be a list of twoples
- which will be massaged into a MethodBinding as
- described in the ConfigurableMixin class docstring.
- """
- def _get_binding(binding):
- if callable(binding):
- binding = util.maybeDeferred(binding, ctx)
- return binding
-
- def _convert_list(binding):
- if isinstance(binding, list):
- binding = annotate.MethodBinding(
- name, annotate.Method(arguments=[
- annotate.Argument(n, v, v.id)
- for (n, v) in binding]))
- return binding
-
- binding = util.maybeDeferred(getattr, self, 'bind_%s' % name)
- return binding.addCallback(_get_binding).addCallback(_convert_list)
-
- def getDefault(self, forBinding):
- """Get a default value for a given binding. If the
- binding is a Property, get the current value of
- that property off self. If not, simply return
- forBinding.default.
- """
- ## If it is a Property, get the value off self
- if not isinstance(forBinding, annotate.Argument):
- if hasattr(self, forBinding.name):
- return getattr(self, forBinding.name)
- return forBinding.default
-
- def postForm(self, ctx, bindingName, args):
- """Accept a form post to the given bindingName.
- The post arguments are given in args.
-
- This will invoke the IInputProcessor for the
- binding with the given name. If it succeeds, the
- property will be modified or the method will have
- been called. If it fails, a ValidateError exception
- will be raised.
- """
- def _callback(binding):
- ctx.remember(binding, iformless.IBinding)
- ctx.remember(self, iformless.IConfigurable)
- rv = iformless.IInputProcessor(binding).process(ctx, self, args)
- ctx.remember(rv, inevow.IHand)
- ctx.remember('%r success.' % bindingName, inevow.IStatusMessage)
- return rv
- return util.maybeDeferred(self.getBinding, ctx,
- bindingName).addCallback(_callback)
-
-
-class ConfigurableFactory:
- """Locates configurables by looking for methods that start with
- configurable_ and end with the name of the configurable. The method
- should take a single arg (other than self) - the current context.
- """
- implements(iformless.IConfigurableFactory)
-
- def locateConfigurable(self, context, name):
- """formless.webform.renderForms calls locateConfigurable on the IConfigurableFactory
- instance it retrieves from the context. It passes the "name" that was passed to it,
- so if renderForms() was placed in the DOM, locateConfigurable will be called with
- name = ''; if renderForms('foo') was placed in the DOM, locateConfigurable will
- be called with name = 'foo'.
-
- This default implementation of locateConfigurable looks for a configurable_* method
- corresponding to the name which was passed.
- """
- return util.maybeDeferred(getattr(self, 'configurable_%s'%name),
- context).addCallback(iformless.IConfigurable)
-
- def configurable_(self, context):
- """Configurable factory for use when self is a configurable;
- aka it implements IConfigurable or one or more TypedInterface
- subclasses. Usage:
-
- >>> class IFoo(TypedInterface):
- ... def bar(): pass
- ... bar = autocallable(bar)
- ...
- >>> class Foo(Page):
- ... implements(IFoo)
- ...
- ... def bar():
- ... print "bar called through the web!"
- ...
- ... def render_forms(self, ctx, data):
- ... return renderForms() # or renderForms('')
- ...
- ... docFactory = stan(render_forms).
- """
- if filter(lambda x: issubclass(x, annotate.TypedInterface), providedBy(self)):
- warnings.warn("[0.5] Subclassing TypedInterface to declare annotations is deprecated. Please provide bind_* methods on your Page or Fragment subclass instead.", DeprecationWarning)
- from formless import configurable
- return configurable.TypedInterfaceConfigurable(self)
- return self
-
- def configurable_original(self, ctx):
- """Configurable factory for use when self.original is a configurable;
- aka it implements IConfigurable or one or more TypedInterface
- subclasses. Usage:
-
-
- >>> class Foo(Page):
- ... def __init__(self):
- ... self.original = SomeConfigurable()
- ... def render_forms(self, ctx, data):
- ... return renderForms('original')
- ... docFactory = stan(render_forms)
- """
- return self.original
-
-_CARRYOVER = {}
-
-
-def defaultsFactory(ctx):
- co = _CARRYOVER.get(
- ctx.tag.args.get('_nevow_carryover_', [None])[0], None)
- from formless import webform
- defaults = webform.FormDefaults()
- if co is not None:
- e = iformless.IFormErrors(co, {})
- for k, v in e.items():
- defaults.getAllDefaults(k).update(v.partialForm)
- return defaults
-
-
-def errorsFactory(ctx):
- co = _CARRYOVER.get(
- ctx.tag.args.get('_nevow_carryover_', [None])[0], None)
- from formless import webform
- errs = webform.FormErrors()
- if co is not None:
- e = iformless.IFormErrors(co, {})
- for k, v in e.items():
- errs.updateErrors(k, v.errors)
- errs.setError(k, v.formErrorMessage)
- return errs
-
-
-def handFactory(ctx):
- co = _CARRYOVER.get(
- ctx.tag.args.get('_nevow_carryover_', [None])[0], None)
- return inevow.IHand(co, None)
-
-
-def statusFactory(ctx):
- co = _CARRYOVER.get(
- ctx.tag.args.get('_nevow_carryover_', [None])[0], None)
- return inevow.IStatusMessage(co, None)
-
-
def originalFactory(ctx):
return ctx.tag
-class Fragment(DataFactory, RenderFactory, MacroFactory, ConfigurableMixin):
+class Fragment(DataFactory, RenderFactory, MacroFactory):
"""
This class is deprecated because it relies on context objects
U{which are being removed from Nevow<http://divmod.org/trac/wiki/WitherContext>}.
@@ -447,7 +231,7 @@
ctx.remember(self, inevow.IData)
-class ChildLookupMixin(FreeformChildMixin):
+class ChildLookupMixin(object):
##
# IResource methods
##
@@ -492,7 +276,7 @@
if r is not None:
return r, segments[1:]
- return FreeformChildMixin.locateChild(self, ctx, segments)
+ return NotFound
def childFactory(self, ctx, name):
"""Used by locateChild to return children which are generated
@@ -512,7 +296,7 @@
self.children[name] = child
-class Page(Fragment, ConfigurableFactory, ChildLookupMixin):
+class Page(Fragment, ChildLookupMixin):
"""A page is the main Nevow resource and renders a document loaded
via the document factory (docFactory).
"""
@@ -545,9 +329,6 @@
self.rememberStuff(ctx)
def finishRequest():
- carryover = request.args.get('_nevow_carryover_', [None])[0]
- if carryover is not None and _CARRYOVER.has_key(carryover):
- del _CARRYOVER[carryover]
if self.afterRender is not None:
return util.maybeDeferred(self.afterRender,ctx)
@@ -624,77 +405,6 @@
return self
return None
- def webFormPost(self, request, res, configurable, ctx, bindingName, args):
- """Accept a web form post, either redisplaying the original form (with
- errors) if validation fails, or redirecting to the appropriate location after
- the post succeeds. This hook exists specifically for formless.
-
- New in 0.5, _nevow_carryover_ is only used if an autocallable method
- returns a result that needs to be carried over.
-
- New in 0.5, autocallables may return a nevow.url.URL or URLOverlay
- instance rather than setting IRedirectAfterPost on the request.
-
- New in 0.5, autocallables may return a Page instance to have that Page
- instance rendered at the post target URL with no redirects at all. Useful
- for multi-step wizards.
- """
- def redirectAfterPost(aspects):
- hand = aspects.get(inevow.IHand)
- refpath = None
- if hand is not None:
- if isinstance(hand, Page):
- refpath = url.here
- if 'freeform_hand' not in inevow.IRequest(ctx).prepath:
- refpath = refpath.child('freeform_hand')
- if isinstance(hand, (url.URL, url.URLOverlay)):
- refpath, hand = hand, None
-
- if refpath is None:
- redirectAfterPost = request.getComponent(iformless.IRedirectAfterPost, None)
- if redirectAfterPost is None:
- ref = request.getHeader('referer')
- if ref:
- refpath = url.URL.fromString(ref)
- else:
- refpath = url.here
- else:
- warnings.warn("[0.5] IRedirectAfterPost is deprecated. Return a URL instance from your autocallable instead.", DeprecationWarning, 2)
- ## Use the redirectAfterPost url
- ref = str(redirectAfterPost)
- refpath = url.URL.fromString(ref)
-
- if hand is not None or aspects.get(iformless.IFormErrors) is not None:
- magicCookie = '%s%s%s' % (now(),request.getClientIP(),random.random())
- refpath = refpath.replace('_nevow_carryover_', magicCookie)
- _CARRYOVER[magicCookie] = C = tpc.Componentized()
- for k, v in aspects.iteritems():
- C.setComponent(k, v)
-
- destination = flat.flatten(refpath, ctx)
- request.redirect(destination)
- from nevow import static
- return static.Data('You posted a form to %s' % bindingName, 'text/plain'), ()
-
- return util.maybeDeferred(
- configurable.postForm, ctx, bindingName, args
- ).addCallback(
- self.onPostSuccess, request, ctx, bindingName, redirectAfterPost
- ).addErrback(
- self.onPostFailure, request, ctx, bindingName, redirectAfterPost
- )
-
- def onPostSuccess(self, result, request, ctx, bindingName, redirectAfterPost):
- if result is None:
- message = "%s success." % formless.nameToLabel(bindingName)
- else:
- message = result
-
- return redirectAfterPost({inevow.IHand: result, inevow.IStatusMessage: message})
-
- def onPostFailure(self, reason, request, ctx, bindingName, redirectAfterPost):
- reason.trap(formless.ValidateError)
- return redirectAfterPost({iformless.IFormErrors: {bindingName: reason.value}})
def sequence(context, data):
=== removed file 'Nevow/nevow/test/test_passobj.py'
--- Nevow/nevow/test/test_passobj.py 2006-03-17 15:00:39 +0000
+++ Nevow/nevow/test/test_passobj.py 1970-01-01 00:00:00 +0000
@@ -1,207 +0,0 @@
-# Copyright (c) 2004 Divmod.
-# See LICENSE for details.
-
-import formless
-from zope.interface import implements
-
-class IBar(formless.TypedInterface):
- bar = formless.String()
-
-
-class Bar:
- implements(IBar)
-
- def __init__(self, bar):
- self.bar = bar
-
- def __str__(self):
- return "A Bar: %s" % self.bar
-
-
-class IFrob(formless.TypedInterface):
- integer = formless.Integer()
-
-
-class Frob:
- implements(IFrob)
-
- def __init__(self, integer):
- self.integer = integer
-
- def frobazz(self, other):
- return Frob(self.integer ** other.integer)
-
- def __str__(self):
- return "A frob of value %s" % self.integer
-
-
-class IObjectTest(formless.TypedInterface):
- def someMethod(one=formless.Object(interface=IBar), two=formless.Integer(description="an integer please")):
- """Some Method.
-
- This method takes an IBar instance.
- """
- return None
- someMethod = formless.autocallable(someMethod)
-
- def frobber(frobber=formless.Object(interface=IFrob), frobee=formless.Object(IFrob)):
- """Frobber.
-
- Takes two frobs and raises one to the power of the other.
- """
- return IFrob
- frobber = formless.autocallable(frobber)
-
- someList = formless.List()
-
-
-class ObjectTester:
- implements(IObjectTest)
-
- def __init__(self):
- self.someList = [
- Bar("boop"), Bar("bap"),
- Frob(5), Frob(9), Frob(23), Frob(1234)
- ]
-
- def someMethod(self, one, two):
- print "ONE TWO", `one`, `two`
-
- def frobber(self, frobber, frobee):
- return frobber.frobazz(frobee)
-
-
-class CompoundChecker(formless.Compound):
- def coerce(self, data):
- one, two = data
- if (one, two) != (6, 9):
- raise formless.InputError("What do you get when you multiply six by nine?")
-
-
-class IAnotherTest(formless.TypedInterface):
- def aBarMethod(abar=formless.Object(interface=IBar)):
- """A Bar Method
-
- This method takes a bar, but there are no bar instances on this page.
- You'll have to use the shelf.
- """
- return str
- aBarMethod = formless.autocallable(aBarMethod)
-
- def aFrobMethod(aFrob=formless.Object(interface=IFrob)):
- """A Frob Method
-
- This method takes a frob, but there are no frob instances on this page.
- You'll have to use the shelf.
- """
- return str
- aFrobMethod = formless.autocallable(aFrobMethod)
-
- def whatIsMyClass(anObj=formless.Object()):
- """What is my class?
-
- Pass an object and get back the class in your hand.
- """
- return formless.Object()
- whatIsMyClass = formless.autocallable(whatIsMyClass)
-
- def setBreakpoint(breakpoint=formless.String()):
- """Set a breakpoint
-
- Set a breakpoint at the given filename and line number. String passed is equivalent
- to doing b(reak) ([file:]lineno | function) in pdb.
- """
- return None
- setBreakpoint = formless.autocallable(setBreakpoint)
-
- breakpoints = formless.List()
-
- def compoundTest(
- aCompound = formless.Compound(
- [formless.String(label="firstname"), formless.String(label="lastname")],
- label="Full Name"),
- anInt = formless.Integer()):
- """Compound Test
-
- A test of a widget/controller which renders multiple fields, triggers multiple
- validators, but gathers the result into one method argument. There can
- be an additional validation step which validates that the compound data
- as a whole is valid.
- """
- return str
- compoundTest = formless.autocallable(compoundTest)
-
- def compoundChecker(
- theAnswer = CompoundChecker(
- [formless.Integer(label="six"), formless.Integer(label="nine")],
- label="The Answer",
- description="What is the meaning of life, the universe, and everything?")
- ):
- """The Answer
-
- Please type the integer six in the first box, and nine in the second.
- """
- return formless.Object(label="The Answer", interface=formless.Integer)
- compoundChecker = formless.autocallable(compoundChecker)
-
-
-class AnotherTest:
- implements(IAnotherTest)
-
- def aBarMethod(self, abar):
- return "You passed me %s" % abar
-
- def aFrobMethod(self, aFrob):
- return "You passed me %s" % aFrob
-
- def whatIsMyClass(self, anObj):
- if hasattr(anObj, '__class__'):
- return anObj.__class__
- return type(anObj)
-
- def _getDebugger(self):
- import sys, pdb
- debugInstance = sys.modules.get('debugInstance')
- if debugInstance is None:
- sys.modules['debugInstance'] = debugInstance = pdb.Pdb()
- debugInstance.reset()
- return debugInstance
-
- def setBreakpoint(self, breakpoint):
- import sys
- debugInstance = self._getDebugger()
- debugInstance.do_break(debugInstance.precmd(breakpoint))
- debugInstance.quitting = True
- sys.settrace(debugInstance.trace_dispatch)
- debugInstance.quitting = False
-
- def _currentBreakpoints(self):
- debugInstance = self._getDebugger()
- class BreakpointRemover(list):
- def remove(self, removal):
- debugInstance.breaks[removal.fn].remove(removal.ln)
- if not debugInstance.breaks[removal.fn]:
- del debugInstance.breaks[removal.fn]
- list.remove(self, removal)
- class Dummy(formless.TypedInterface): pass
- class BP:
- implements(Dummy)
- def __init__(self, fn, ln):
- self.fn=fn
- self.ln=ln
- def __str__(self):
- return "Breakpoint in file %s at line %s" % (self.fn, self.ln)
-
- breakpoints = BreakpointRemover()
- for fn in debugInstance.breaks.keys():
- for lineno in debugInstance.breaks[fn]:
- breakpoints.append(BP(fn, lineno))
- return breakpoints
- breakpoints = property(_currentBreakpoints)
-
- def compoundTest(self, aCompound, anInt):
- return "COMPOUND! %s %s" % (aCompound, anInt)
-
- def compoundChecker(self, theAnswer):
- return 42
-
=== modified file 'Nevow/nevow/test/test_rend.py'
--- Nevow/nevow/test/test_rend.py 2008-03-28 16:23:42 +0000
+++ Nevow/nevow/test/test_rend.py 2011-07-26 00:42:36 +0000
@@ -21,12 +21,6 @@
from nevow import url
from nevow import util
-import formless
-from formless import webform as freeform
-from formless import annotate
-from formless import iformless
-
-
def deferredRender(res, request=None):
if request is None:
request = testutil.FakeRequest()
@@ -504,144 +498,6 @@
ctx.remember(rend.RenderFactory(), inevow.IRendererFactory)
self.assertEquals(flat.flatten(p(data='foo', render=directive('data')), ctx), '<p>foo</p>')
-class TestConfigurableMixin(unittest.TestCase):
- def test_formRender(self):
- class FormPage(rend.Page):
- bind_test1 = [('foo', annotate.String()), ('bar', annotate.Integer())]
- bind_test2 = annotate.MethodBinding('test2', annotate.Method(
- arguments=[annotate.Argument('foo', annotate.String())]))
-
- bind_test3 = annotate.Property('test3', annotate.Integer())
-
- def bind_test4(self, ctx):
- return ([('foo', annotate.String()), ('bar', annotate.Integer())])
-
- def bind_test5(self, ctx):
- return annotate.MethodBinding('test5', annotate.Method(
- arguments=[annotate.Argument('foo', annotate.String()),
- annotate.Argument('bar', annotate.Integer())]))
-
- docFactory = loaders.stan(html[freeform.renderForms()])
- return deferredRender(FormPage())
-
- def test_formRenderDeferred(self):
- class FormPage(rend.Page):
- bind_test1 = defer.succeed([('foo', annotate.String()),
- ('bar', annotate.Integer())])
- bind_test2 = defer.succeed(annotate.MethodBinding('test2', annotate.Method(
- arguments=[annotate.Argument('foo', annotate.String())])))
-
- bind_test3 = defer.succeed(annotate.Property('test3', annotate.Integer()))
-
- def bind_test4(self, ctx):
- return defer.succeed([('foo', annotate.String()),
- ('bar', annotate.Integer())])
-
- def bind_test5(self, ctx):
- return defer.succeed(annotate.MethodBinding('test5', annotate.Method(
- arguments=[annotate.Argument('foo', annotate.String()),
- annotate.Argument('bar', annotate.Integer())])))
-
- docFactory = loaders.stan(html[freeform.renderForms()])
- return deferredRender(FormPage())
-
-
- def test_formPost(self):
- class FormPage(rend.Page):
- bind_test1 = ([('foo', annotate.Integer())])
- def test1(self, foo):
- return foo
-
- ctx = context.WovenContext()
- result = FormPage().postForm(ctx, 'test1', {'foo': ['42']})
- return result.addCallback(lambda result: self.assertEquals(result, 42))
-
- def test_formPostDeferred(self):
- class FormPage(rend.Page):
- bind_test1 = defer.succeed(([('foo', annotate.Integer())]))
- def test1(self, foo):
- return foo
-
- ctx = context.WovenContext()
- result = FormPage().postForm(ctx, 'test1', {'foo': ['42']})
- return result.addCallback(lambda result: self.assertEquals(result, 42))
-
- def test_formPostFailure(self):
- class FormPage(rend.Page):
- bind_test1 = ([('foo', annotate.Integer())])
- def test1(self, foo):
- return foo
-
- ctx = context.WovenContext()
- result = FormPage().postForm(ctx, 'test1', {'foo': ['hello, world!']})
- return self.assertFailure(result, annotate.ValidateError)
-
- def test_formPostFailureDeferred(self):
- class FormPage(rend.Page):
- bind_test1 = defer.succeed(([('foo', annotate.Integer())]))
- def test1(self, foo):
- return foo
-
- ctx = context.WovenContext()
- result = FormPage().postForm(ctx, 'test1', {'foo': ['hello, world!']})
- return self.assertFailure(result, annotate.ValidateError)
-
-class IThing(formless.TypedInterface):
- foo = formless.String()
-
-class Thing:
- implements(IThing)
-
-class TestLocateConfigurable(unittest.TestCase):
-
- def test_onSelf(self):
-
- class Page(rend.Page):
- implements(IThing)
- docFactory = loaders.stan(html[freeform.renderForms()])
-
- page = Page()
- return deferredRender(page)
-
- def test_onSelfOriginal(self):
-
- class Page(rend.Page):
- docFactory = loaders.stan(html[freeform.renderForms('original')])
-
- page = Page(Thing())
- return deferredRender(page)
-
- def test_onKeyedConfigurable(self):
-
- class Page(rend.Page):
-
- def __init__(self):
- rend.Page.__init__(self)
- self.thing = Thing()
-
- def configurable_thing(self, context):
- return self.thing
-
- docFactory = loaders.stan(html[freeform.renderForms('thing')])
-
- page = Page()
- return deferredRender(page)
-
-
-class TestDeferredDefaultValue(unittest.TestCase):
- def test_deferredProperty(self):
- class IDeferredProperty(formless.TypedInterface):
- d = formless.String()
-
- from nevow import util
- deferred = util.Deferred()
- deferred.callback('the default value')
- class Implementation(object):
- implements(IDeferredProperty)
- d = deferred
-
- return deferredRender(rend.Page(Implementation(), docFactory=loaders.stan(html[freeform.renderForms('original')]))).addCallback(
- lambda result: self.assertIn('value="the default value"', result))
class TestRenderString(unittest.TestCase):
@@ -857,46 +713,6 @@
lambda c: deferredRender(c.tag).addCallback(
lambda result: self.assertEquals(result, theString)))
- def test_freeformChildMixin_nonTrue(self):
- """Configurables that have c.__nonzero__()==False are accepted."""
- class SimpleConf(object):
- implements(iformless.IConfigurable)
- # mock mock
- def postForm(self, ctx, bindingName, args):
- return 'SimpleConf OK'
- class FormPage(rend.Page):
- addSlash = True
- def configurable_(self, ctx):
- return SimpleConf()
- page = FormPage()
-
- D = getResource(page, '/foo')
- def x1(r):
- self.failUnless(isinstance(r.tag, rend.FourOhFour))
- D.addCallback(x1)
-
- def x2(ign):
- D2 = getResource(page, '/freeform_post!!foo')
- def x3(r):
- self.failIf(isinstance(r.tag, rend.FourOhFour))
- return deferredRender(r.tag).addCallback(
- lambda result: self.assertEquals(result, 'You posted a form to foo'))
- D2.addCallback(x3)
- return D2
- D.addCallback(x2)
-
- def x4(ign):
- SimpleConf.__nonzero__ = lambda x: False
-
- D3 = getResource(page, '/freeform_post!!foo')
- def x5(r):
- self.failIf(isinstance(r.tag, rend.FourOhFour))
- return deferredRender(r.tag).addCallback(
- lambda result:
- self.assertEquals(result, 'You posted a form to foo'))
- return D3.addCallback(x5)
- D.addCallback(x4)
- return D
class TestStandardRenderers(unittest.TestCase):
=== modified file 'Nevow/nevow/testutil.py'
--- Nevow/nevow/testutil.py 2010-02-06 04:33:05 +0000
+++ Nevow/nevow/testutil.py 2011-07-26 00:42:36 +0000
@@ -20,8 +20,6 @@
from twisted.web import http
from twisted.protocols.basic import LineReceiver
-from formless import iformless
-
from nevow import inevow, context, athena, loaders, tags, appserver
from nevow.jsutil import findJavascriptInterpreter, generateTestScript
@@ -294,8 +292,6 @@
This class is named I{accumulating} for historical reasons only. You
probably want to ignore this and use L{FakeRequest} instead.
"""
- implements(iformless.IFormDefaults)
-
def __init__(self, *a, **kw):
FakeRequest.__init__(self, *a, **kw)
self.d = defer.Deferred()
Follow ups