Merge lp:~divmod-dev/divmod.org/811792-remove-formless into lp:divmod.org
- 811792-remove-formless
- Merge into trunk
Status: | Rejected |
---|---|
Rejected by: | Tristan Seligmann |
Proposed branch: | lp:~divmod-dev/divmod.org/811792-remove-formless |
Merge into: | lp:divmod.org |
Diff against target: | 8055 lines |
To merge this branch: | bzr merge lp:~divmod-dev/divmod.org/811792-remove-formless |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Divmod-dev | Pending | ||
Review via email: mp+69186@code.launchpad.net |
Commit message
Description of the change
Jonathan Jacobs (jjacobs) wrote : | # |
Jean-Paul Calderone (exarkun) wrote : | # |
> Not everything being deleted here uses formless. I don't know how many of
> these Athena examples are still useful (most look either broken or at least
> very out of date) perhaps exarkun can weigh in on whether deleting
> Nevow/examples is okay.
Wow, all of Nevow/examples? That sounds crazy, I don't see why that would be necessary as part of the removal of formless.
- 2676. By Tristan Seligmann
-
Put the other athenademo examples back.
Tristan Seligmann (mithrandi) wrote : | # |
I was only trying to delete the examples in Nevow/examples that use formless; looks like I accidentally deleted a bit more than I needed to in the case of examples/
Zooko Wilcox-O'Hearn (zooko) wrote : | # |
I just browsed through as much of the diff as launchpad would show. It turns out I don't understand what formless is well enough to know which of the examples ought to be retained.
Unmerged revisions
- 2676. By Tristan Seligmann
-
Put the other athenademo examples back.
- 2675. By Tristan Seligmann
-
Remove formless.
Preview Diff
1 | === removed directory 'Nevow/examples/advanced_manualform' |
2 | === removed file 'Nevow/examples/advanced_manualform/__init__.py' |
3 | === removed file 'Nevow/examples/advanced_manualform/advanced_manualform.py' |
4 | --- Nevow/examples/advanced_manualform/advanced_manualform.py 2006-03-08 14:28:41 +0000 |
5 | +++ Nevow/examples/advanced_manualform/advanced_manualform.py 1970-01-01 00:00:00 +0000 |
6 | @@ -1,106 +0,0 @@ |
7 | -from time import time as now |
8 | - |
9 | -import twisted.python.components as tpc |
10 | - |
11 | -from nevow import rend, inevow, url, util, loaders, tags as t |
12 | -from nevow.rend import _CARRYOVER |
13 | -from formless import iformless |
14 | - |
15 | -# |
16 | -# This example is meant to be of some inspiration to those people |
17 | -# who need to have some inspiration to handle forms without using |
18 | -# formless. It _WILL_ raise an exception when you submit a form |
19 | -# without filling all values. This example should NOT be used as-is |
20 | -# but should be modified and enhanced to fit one's need. |
21 | -# |
22 | -# To sum up: it's just a starting point. |
23 | -# |
24 | - |
25 | -SUBMIT="_submit" |
26 | -BUTTON = 'post_btn' |
27 | - |
28 | -class WebException(Exception): pass |
29 | - |
30 | -class ManualFormMixin(rend.Page): |
31 | - def locateChild(self, ctx, segments): |
32 | - # Handle the form post |
33 | - if segments[0].startswith(SUBMIT): |
34 | - # Get a method name from the action in the form plus |
35 | - # the firt word in the button name (or simply the form action if |
36 | - # no button name is specified |
37 | - kwargs = {} |
38 | - args = inevow.IRequest(ctx).args |
39 | - bindingName = '' |
40 | - for key in args: |
41 | - if key != BUTTON: |
42 | - if args[key] != ['']: |
43 | - kwargs[key] = (args[key][0], args[key])[len(args[key])>1] |
44 | - else: |
45 | - bindingName = args[key][0] |
46 | - name_prefix = segments[0].split('!!')[1] |
47 | - if bindingName == '': name = name_prefix |
48 | - else: name = name_prefix + '_' + bindingName.split()[0].lower() |
49 | - method = getattr(self, 'form_'+name, None) |
50 | - if method is not None: |
51 | - return self.onManualPost(ctx, method, bindingName, kwargs) |
52 | - else: |
53 | - raise WebException("You should define a form_action_button method") |
54 | - return super(ManualFormMixin, self).locateChild(ctx, segments) |
55 | - |
56 | - def onManualPost(self, ctx, method, bindingName, kwargs): |
57 | - # This is copied from rend.Page.onWebFormPost |
58 | - def redirectAfterPost(aspects): |
59 | - redirectAfterPost = request.getComponent(iformless.IRedirectAfterPost, None) |
60 | - if redirectAfterPost is None: |
61 | - ref = request.getHeader('referer') or '' |
62 | - else: |
63 | - ## Use the redirectAfterPost url |
64 | - ref = str(redirectAfterPost) |
65 | - from nevow import url |
66 | - refpath = url.URL.fromString(ref) |
67 | - magicCookie = str(now()) |
68 | - refpath = refpath.replace('_nevow_carryover_', magicCookie) |
69 | - _CARRYOVER[magicCookie] = C = tpc.Componentized() |
70 | - for k, v in aspects.iteritems(): |
71 | - C.setComponent(k, v) |
72 | - request.redirect(str(refpath)) |
73 | - from nevow import static |
74 | - return static.Data('You posted a form to %s' % bindingName, 'text/plain'), () |
75 | - request = inevow.IRequest(ctx) |
76 | - return util.maybeDeferred(method, **kwargs |
77 | - ).addCallback(self.onPostSuccess, request, ctx, bindingName,redirectAfterPost |
78 | - ).addErrback(self.onPostFailure, request, ctx, bindingName,redirectAfterPost) |
79 | - |
80 | - |
81 | -class Page(ManualFormMixin, rend.Page): |
82 | - |
83 | - addSlash = True |
84 | - docFactory = loaders.stan( |
85 | - t.html[ |
86 | - t.head[ |
87 | - t.title['Advanced Manualform'] |
88 | - ], |
89 | - t.body[ |
90 | - t.p['Use the form to find out how to easily and manually handle them'], |
91 | - t.form(action=url.here.child('_submit!!post'), |
92 | - enctype="multipart/form-data", |
93 | - method='post' |
94 | - )[ |
95 | - t.input(type='text', name='what'), |
96 | - # the name attribute must be present and must be |
97 | - # post_btn for all the buttons in the form |
98 | - t.input(type='submit', value='btn1', name=BUTTON), |
99 | - t.input(type='submit', value='btn2', name=BUTTON) |
100 | - ] |
101 | - ] |
102 | - ] |
103 | - ) |
104 | - |
105 | - def form_post_btn1(self, what=None): |
106 | - # 'what' is a keyword argument, and must be the same name that you |
107 | - # give to the widget. |
108 | - print "btn1:", what |
109 | - |
110 | - def form_post_btn2(self, what=None): |
111 | - # see above for 'what'. |
112 | - print "btn2:", what |
113 | |
114 | === removed file 'Nevow/examples/athenademo/typeahead.html' |
115 | --- Nevow/examples/athenademo/typeahead.html 2006-10-06 18:48:29 +0000 |
116 | +++ Nevow/examples/athenademo/typeahead.html 1970-01-01 00:00:00 +0000 |
117 | @@ -1,103 +0,0 @@ |
118 | -<!DOCTYPE html |
119 | -PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" |
120 | -"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
121 | -<html xmlns='http://www.w3.org/1999/xhtml' |
122 | - xmlns:n='http://nevow.com/ns/nevow/0.1'> |
123 | - <!-- vi:ft=html |
124 | - --> |
125 | - <head> |
126 | - <meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /> |
127 | - <n:invisible n:render="liveglue" /> |
128 | - <title>TypeAhead Demo</title> |
129 | - <script type='text/javascript' language='javascript'> |
130 | -// <![CDATA[ |
131 | -// add events in a cross-browser way |
132 | -function xbAddEvent(obj, evType, fn, useCapture){ |
133 | - if (obj.addEventListener){ |
134 | - obj.addEventListener(evType, fn, useCapture); |
135 | - return true; |
136 | - } else if (obj.attachEvent){ |
137 | - var r = obj.attachEvent("on"+evType, fn); |
138 | - return r; |
139 | - } else { |
140 | - alert("Handler could not be attached"); |
141 | - } |
142 | -} |
143 | - |
144 | -function selectRange(ele, start, end) |
145 | -{ |
146 | - var orig = ele; |
147 | - ele = $(ele); |
148 | - if (ele == null) |
149 | - { |
150 | - alert("selectRange() can't find an element with id: " + orig + "."); |
151 | - return; |
152 | - } |
153 | - |
154 | - if (ele.setSelectionRange) |
155 | - { |
156 | - ele.setSelectionRange(start, end); |
157 | - } |
158 | - else if (ele.createTextRange) |
159 | - { |
160 | - var range = ele.createTextRange(); |
161 | - range.moveStart("character", start); |
162 | - range.moveEnd("character", end - ele.value.length); |
163 | - range.select(); |
164 | - } |
165 | - |
166 | - ele.focus(); |
167 | -}; |
168 | - |
169 | -// |
170 | -function replaceDescription(result, node) |
171 | -{ |
172 | - var animal = result[0]; var descr = result[1]; |
173 | - |
174 | - var widget = Nevow.Athena.Widget.get(node); |
175 | - var description = widget.nodeByAttribute('class', 'description'); |
176 | - description.innerHTML = descr; |
177 | - |
178 | - // fill in the text field and select the portion that was guessed |
179 | - if (animal != null) |
180 | - { |
181 | - var typehere = node; |
182 | - var current = typehere.value; |
183 | - typehere.value = animal; |
184 | - selectRange(typehere, current.length, animal.length); |
185 | - } |
186 | -} |
187 | - |
188 | -// |
189 | -function loadDescription(ev) |
190 | -{ |
191 | - // filter helpful keys like backspace |
192 | - if (ev.keyCode < 32) return; |
193 | - if (ev.keyCode >= 33 && ev.keyCode <= 46) return; |
194 | - if (ev.keyCode >= 112 && ev.keyCode <= 123) return; |
195 | - |
196 | - var typehere = ev.target; |
197 | - var typed = typehere.value; |
198 | - var d = Nevow.Athena.Widget.get(typehere).callRemote('loadDescription', typed); |
199 | - d.addCallback(replaceDescription, typehere); |
200 | -} |
201 | - |
202 | -Divmod.Base.addToCallStack(window, 'onload', function() { |
203 | - typeheres = MochiKit.DOM.getElementsByTagAndClassName('input', 'typehere'); |
204 | - for (n=0; n<typeheres.length; n++) { |
205 | - xbAddEvent(typeheres[n], 'keyup', loadDescription, 1); |
206 | - } |
207 | -}); |
208 | - |
209 | -// ]]> |
210 | - </script> |
211 | - </head> |
212 | - <body> |
213 | - <h2>Start typing an animal to see the description.</h2> |
214 | - <n:invisible n:render="typehereField" /> |
215 | - <h2>You can also type in this one. It does the same thing, independently |
216 | - of the other one.</h2> |
217 | - <n:invisible n:render="typehereField" /> |
218 | - </body> |
219 | -</html> |
220 | - |
221 | |
222 | === removed file 'Nevow/examples/athenademo/typeahead.py' |
223 | --- Nevow/examples/athenademo/typeahead.py 2006-10-06 18:48:29 +0000 |
224 | +++ Nevow/examples/athenademo/typeahead.py 1970-01-01 00:00:00 +0000 |
225 | @@ -1,82 +0,0 @@ |
226 | -# vi:ft=python |
227 | -from nevow import tags as T, rend, loaders, athena, url |
228 | -from formless import annotate, webform |
229 | -from twisted.python import util |
230 | - |
231 | -animals = {u'elf' : u'Pointy ears. Bad attitude regarding trees.', |
232 | - u'chipmunk': u'Cute. Fuzzy. Sings horribly.', |
233 | - u'chupacabra': u'It sucks goats.', |
234 | - u'ninja': u'Stealthy and invisible, and technically an animal.', |
235 | - } |
236 | - |
237 | - |
238 | -class TypeAheadPage(athena.LivePage): |
239 | - _tmpl = util.sibpath(__file__, "typeahead.html") |
240 | - docFactory = loaders.xmlfile(_tmpl) |
241 | - def render_typehereField(self, ctx, data): |
242 | - frag = TypeAheadFieldFragment() |
243 | - frag.page = self |
244 | - return frag |
245 | - |
246 | -class TypeAheadFieldFragment(athena.LiveFragment): |
247 | - docFactory = loaders.stan( |
248 | - T.span(render=T.directive('liveFragment'))[ '\n', |
249 | - T.input(type="text", _class="typehere"), '\n', |
250 | - T.h3(_class="description"), |
251 | - ]) |
252 | - |
253 | - def loadDescription(self, typed): |
254 | - if typed == u'': |
255 | - return None, u'--' |
256 | - matches = [] |
257 | - for key in animals: |
258 | - if key.startswith(typed): |
259 | - matches.append(key) |
260 | - if len(matches) == 1: |
261 | - return matches[0], animals[matches[0]] |
262 | - elif len(matches) > 1: |
263 | - return None, u"(Multiple found)" |
264 | - else: |
265 | - return None, u'--' |
266 | - athena.expose(loadDescription) |
267 | - |
268 | -class DataEntry(rend.Page): |
269 | - """Add Animal""" |
270 | - addSlash = 1 |
271 | - |
272 | - docFactory = loaders.stan( |
273 | - T.html[T.body[T.h1[ |
274 | - "First, a Setup Form."], |
275 | - T.h2["Enter some animals as data. Click 'Done' to test looking up these animals."], |
276 | - T.h3["The neat stuff happens when you hit 'Done'."], |
277 | - webform.renderForms(), |
278 | - T.ol(data=T.directive("animals"), render=rend.sequence)[ |
279 | - T.li(pattern="item", render=T.directive("string")), |
280 | - ], |
281 | - T.h1[T.a(href=url.here.child('typeahead'))["Done"]], |
282 | - ] |
283 | - ] |
284 | - ) |
285 | - def bind_animals(self, ctx, ): |
286 | - """Add Animal""" |
287 | - return annotate.MethodBinding( |
288 | - 'animals', |
289 | - annotate.Method(arguments= |
290 | - [annotate.Argument('animal', annotate.String()), |
291 | - annotate.Argument('description', annotate.Text())]), |
292 | - action="Add Animal", |
293 | - ) |
294 | - |
295 | - def animals(self, animal, description): |
296 | - """Add Animal""" |
297 | - if not (animal and description): |
298 | - return |
299 | - animals[animal.decode('utf-8')] = description.decode('utf-8') |
300 | - return url.here |
301 | - |
302 | - def data_animals(self, ctx, data): |
303 | - return animals.keys() |
304 | - |
305 | - def child_typeahead(self, ctx): |
306 | - return TypeAheadPage(None, None) |
307 | - |
308 | |
309 | === removed directory 'Nevow/examples/blogengine' |
310 | === removed file 'Nevow/examples/blogengine/atom.xml' |
311 | --- Nevow/examples/blogengine/atom.xml 2005-10-14 17:36:24 +0000 |
312 | +++ Nevow/examples/blogengine/atom.xml 1970-01-01 00:00:00 +0000 |
313 | @@ -1,22 +0,0 @@ |
314 | -<?xml version="1.0"?> |
315 | -<feed version="0.3" xmlns="http://purl.org/atom/ns#" xml:lang="en" xmlns:n="http://nevow.com/ns/nevow/0.1"> |
316 | - <title mode="escaped">Subbacultcha</title> |
317 | - <link rel="alternate" type="text/html" href="http://localhost:8080" /> |
318 | - <tagline mode="escaped">Subbacultcha atom</tagline> |
319 | - <modified n:data="getFirstPost" n:render="modified">Page modified</modified> |
320 | - <id>tag:localhost,2004:/</id> |
321 | - <n:invisible n:data="get_posts" n:render="sequence"> |
322 | - <entry n:pattern="item" n:render="post"> |
323 | - <title mode="escaped"><n:slot name="title">Entry Title</n:slot></title> |
324 | - <link rel="alternate" type="text/html" href="#"> |
325 | - <n:attr name="href"> <n:slot name="link" /> </n:attr> |
326 | - </link> |
327 | - <id>tag:localhost,2004:/<n:slot name="id">id</n:slot></id> |
328 | - <issued><n:slot name="created">Date created</n:slot></issued> |
329 | - <modified><n:slot name="modified">Date modified</n:slot></modified> |
330 | - <author> |
331 | - <name><n:slot name="author">Author</n:slot></name> |
332 | - </author> |
333 | - <content type="text/plain" mode="escaped"><n:slot name="content">Content</n:slot></content> |
334 | - </entry> |
335 | </n:invisible> |
336 | -</feed> |
337 | \ No newline at end of file |
338 | |
339 | === removed file 'Nevow/examples/blogengine/axiomstore.py' |
340 | --- Nevow/examples/blogengine/axiomstore.py 2006-04-14 17:23:46 +0000 |
341 | +++ Nevow/examples/blogengine/axiomstore.py 1970-01-01 00:00:00 +0000 |
342 | @@ -1,76 +0,0 @@ |
343 | -from iblogengine import IBlog |
344 | -from zope.interface import implements |
345 | -from axiom import item, store, attributes, sequence |
346 | -from epsilon.extime import Time |
347 | - |
348 | -class Post(item.Item): |
349 | - typeName = "BlogenginePost" |
350 | - schemaVersion = 1 |
351 | - |
352 | - id = attributes.integer(indexed=True, allowNone=False) |
353 | - created = attributes.timestamp(indexed=True) |
354 | - modified = attributes.timestamp(indexed=True) |
355 | - title = attributes.text(indexed=True, allowNone=False) |
356 | - author = attributes.text(indexed=True, allowNone=False) |
357 | - category = attributes.text(indexed=True) |
358 | - content = attributes.text(indexed=True) |
359 | - |
360 | - def __init__(self, **kw): |
361 | - now = Time() |
362 | - kw.update({'created':now, |
363 | - 'modified':now}) |
364 | - super(Post, self).__init__(**kw) |
365 | - |
366 | - def setModified(self): |
367 | - self.modified = Time() |
368 | - |
369 | -class Blog(item.Item, item.InstallableMixin): |
370 | - implements(IBlog) |
371 | - |
372 | - typeName = "BlogengineBlog" |
373 | - schemaVersion = 1 |
374 | - |
375 | - posts = attributes.reference() |
376 | - next_id = attributes.integer(default=0) |
377 | - |
378 | - def __init__(self, **kw): |
379 | - super(Blog, self).__init__(**kw) |
380 | - self.posts = sequence.List(store=self.store) |
381 | - post = Post(store=self.store, |
382 | - id=self.getNextId(), |
383 | - author=u'mike', |
384 | - title=u'FIRST POST!!!!', |
385 | - category=u'Test', |
386 | - content=u'I guess it worked.') |
387 | - self.addNewPost(post) |
388 | - |
389 | - def installOn(self, other): |
390 | - super(Blog, self).installOn(other) |
391 | - other.powerUp(self, IBlog) |
392 | - |
393 | - def addNewPost(self, post): |
394 | - # Why even let posts manage their own ids? Oh well. |
395 | - assert post.id == self.next_id,\ |
396 | - "Bad post ID; is %r, should be %r" % (post.id, self.next_id) |
397 | - self.posts.append(post) |
398 | - self.next_id += 1 |
399 | - |
400 | - def getPosts(self, how_many = None): |
401 | - """Return the latest 'how_many' posts, in reverse database order. |
402 | - |
403 | - XXX Really, it should be based on modtime. Which is broken. |
404 | - """ |
405 | - if how_many is None or how_many > self.next_id: |
406 | - how_many = self.next_id |
407 | - return (self.getOne(self.next_id-id-1) for id in range(how_many)) |
408 | - |
409 | - def getOne(self, id): |
410 | - return self.posts[id] |
411 | - |
412 | - def getNextId(self): |
413 | - return self.next_id |
414 | - |
415 | -def initialize(storename): |
416 | - s = store.Store(storename) |
417 | - s.findOrCreate(Blog).installOn(s) |
418 | - return s |
419 | |
420 | === removed file 'Nevow/examples/blogengine/blogengine.tac' |
421 | --- Nevow/examples/blogengine/blogengine.tac 2006-01-21 22:53:11 +0000 |
422 | +++ Nevow/examples/blogengine/blogengine.tac 1970-01-01 00:00:00 +0000 |
423 | @@ -1,12 +0,0 @@ |
424 | -from twisted.application import service, strports |
425 | -from nevow import appserver |
426 | - |
427 | -import frontend, axiomstore as store, iblogengine |
428 | -from smtpserver import BlogSMTPFactory |
429 | - |
430 | -application = service.Application('blogengine') |
431 | -db = store.initialize('db.axiom') |
432 | -site = appserver.NevowSite(resource = frontend.UI()) |
433 | -site.remember(db, iblogengine.IStore) |
434 | -strports.service("8080", site).setServiceParent(application) |
435 | -strports.service("2500", BlogSMTPFactory(db)).setServiceParent(application) |
436 | |
437 | === removed file 'Nevow/examples/blogengine/email_client.py' |
438 | --- Nevow/examples/blogengine/email_client.py 2005-10-14 17:36:24 +0000 |
439 | +++ Nevow/examples/blogengine/email_client.py 1970-01-01 00:00:00 +0000 |
440 | @@ -1,16 +0,0 @@ |
441 | -import sys, smtplib |
442 | - |
443 | -fromaddr = raw_input("From: ") |
444 | -toaddrs = raw_input("To: ").split(',') |
445 | -print "Enter message, end with ^D:" |
446 | -msg = '' |
447 | -while 1: |
448 | - line = sys.stdin.readline() |
449 | - if not line: |
450 | - break |
451 | - msg = msg + line |
452 | - |
453 | -# The actual mail send |
454 | -server = smtplib.SMTP('localhost', 2500) |
455 | -server.sendmail(fromaddr, toaddrs, msg) |
456 | -server.quit() |
457 | |
458 | === removed file 'Nevow/examples/blogengine/frontend.py' |
459 | --- Nevow/examples/blogengine/frontend.py 2006-04-14 17:23:46 +0000 |
460 | +++ Nevow/examples/blogengine/frontend.py 1970-01-01 00:00:00 +0000 |
461 | @@ -1,241 +0,0 @@ |
462 | -from time import time as now |
463 | -from zope.interface import implements, Interface |
464 | - |
465 | -from twisted.web import xmlrpc |
466 | -from twisted.python.components import registerAdapter |
467 | - |
468 | -from nevow import rend, loaders, url, static |
469 | -from nevow import tags as t, inevow |
470 | -from formless import annotate, iformless, webform |
471 | - |
472 | -from axiomstore import Post |
473 | -from iblogengine import IStore, IBlog |
474 | - |
475 | -def pptime(tt): |
476 | - return tt.asHumanly()+" UTC" |
477 | -def atompptime(tt): |
478 | - return tt.asISO8601TimeAndDate() |
479 | -class ITimer(Interface): |
480 | - pass |
481 | - |
482 | -##################################### |
483 | -categories = ['Programming', 'Test', 'Sport', 'People', 'Python', |
484 | - 'Databases', 'bench', 'woo', 'Friends'] |
485 | - |
486 | -class IInsert(annotate.TypedInterface): |
487 | - def insert( |
488 | - ctx = annotate.Context(), |
489 | - title = annotate.String(strip=True, required=True, \ |
490 | - requiredFailMessage="Title must be provided", tabindex='1'), |
491 | - author = annotate.String(strip=True, default="Anonymous", tabindex='2'), |
492 | - id = annotate.String(hidden=True), |
493 | - category = annotate.Choice(categories, tabindex='3'), |
494 | - content = annotate.Text(required=True, \ |
495 | - requiredFailMessage="Posts with no content are not allowed", tabindex='4'), |
496 | - ): |
497 | - pass |
498 | - insert = annotate.autocallable(insert) |
499 | - |
500 | -##################################### |
501 | -class BaseUI(rend.Page): |
502 | - addSlash = True |
503 | - def renderHTTP(self, ctx): |
504 | - return IStore(ctx).transact(rend.Page.renderHTTP, self, ctx) |
505 | - |
506 | - def locateChild(self, ctx, segments): |
507 | - return IStore(ctx).transact(rend.Page.locateChild, self, ctx, segments) |
508 | - |
509 | -############################# |
510 | -class UI(BaseUI): |
511 | - |
512 | - docFactory = loaders.xmlfile ('ui.html') |
513 | - child_styles = static.File('styles') |
514 | - child_images = static.File('images') |
515 | - child_webform_css = webform.defaultCSS |
516 | - |
517 | - def render_starttimer(self, ctx, data): |
518 | - ctx.remember(now(), ITimer) |
519 | - return ctx.tag |
520 | - |
521 | - def render_stoptimer(self, ctx, data): |
522 | - start = ITimer(ctx) |
523 | - return ctx.tag['%s' % (now()-start)] |
524 | - |
525 | - def render_needForms(self, ctx, data): |
526 | - action = ctx.arg('action', 'view') |
527 | - if action == 'edit': |
528 | - form = inevow.IQ(ctx).onePattern('frm') |
529 | - return ctx.tag[form] |
530 | - return ctx.tag.clear() |
531 | - |
532 | - def data_getEntries(self, ctx, data): |
533 | - num = ctx.arg('num', '60') |
534 | - return IBlog(IStore(ctx)).getPosts(int(num)) |
535 | - |
536 | - def render_entries(self, ctx, data): |
537 | - ctx.tag.fillSlots('modification', pptime(data.modified)) |
538 | - ctx.tag.fillSlots('category', data.category) |
539 | - ctx.tag.fillSlots('author', data.author) |
540 | - ctx.tag.fillSlots('title', data.title) |
541 | - ctx.tag.fillSlots('content', data.content) |
542 | - ctx.tag.fillSlots('permaLink', url.root.child('%s' % (data.id))) |
543 | - return ctx.tag |
544 | - |
545 | - def render_insert(self, ctx, data): |
546 | - return ctx.tag |
547 | - |
548 | - def render_editer(self, ctx, data): |
549 | - ctx.tag.fillSlots('editPost', url.root.child('%s' % (data.id) |
550 | - ).add('action','edit')) |
551 | - return ctx.tag |
552 | - |
553 | - def render_insert(self, ctx, data): |
554 | - ctx.tag.fillSlots('insert', url.root.child('insertEntry')) |
555 | - return ctx.tag |
556 | - |
557 | - def child_insertEntry(self, ctx): |
558 | - return NewEntry() |
559 | - |
560 | - def childFactory(self, ctx, segment): |
561 | - id = segment.isdigit() and segment or '-1' |
562 | - if int(id) >= 0: |
563 | - return IBlog(IStore(ctx)).getOne(int(id)) |
564 | - elif segment == 'rpc2': |
565 | - return BlogRPC(IStore(ctx)) |
566 | - elif segment == 'atom.xml': |
567 | - return Atom() |
568 | - |
569 | - def child_thx(self, ctx): |
570 | - return Thx() |
571 | - |
572 | -################################## |
573 | -class NewEntry(BaseUI): |
574 | - implements(IInsert) |
575 | - |
576 | - docFactory = loaders.stan( |
577 | - t.html[ |
578 | - t.head[ |
579 | - t.title['Insertion form'], |
580 | - t.link(rel='stylesheet', type='text/css', href=url.root.child('webform_css')), |
581 | - ], |
582 | - t.body[ |
583 | - t.h1['Insertion'], |
584 | - t.invisible(render=t.directive("forms")) |
585 | - ] |
586 | - ]) |
587 | - def render_forms(self, ctx, data): |
588 | - d = iformless.IFormDefaults(ctx).getAllDefaults('insert') |
589 | - d['author'] = 'Anonymous' |
590 | - d['id'] = IBlog(IStore(ctx)).getNextId() |
591 | - return webform.renderForms() |
592 | - |
593 | - def insert(self, ctx, id, title, author, category, content): |
594 | - newPost = Post(store=IStore(ctx), |
595 | - id=int(id), |
596 | - author=unicode(author), |
597 | - title=unicode(title), |
598 | - category=unicode(category), |
599 | - content=unicode(content)) |
600 | - IBlog(IStore(ctx)).addNewPost(newPost) |
601 | - inevow.IRequest(ctx).setComponent(iformless.IRedirectAfterPost, '/thx') |
602 | - |
603 | -##################################### |
604 | -class Thx(rend.Page): |
605 | - docFactory = loaders.stan( |
606 | - t.html[ |
607 | - t.body[ |
608 | - t.h1['Succeeded'], |
609 | - t.a(href=url.root)["Back to main"] |
610 | - ] |
611 | - ]) |
612 | - |
613 | -#################################### |
614 | -class Entry(UI): |
615 | - implements(IInsert) |
616 | - def data_getEntries(self, ctx, data): |
617 | - return [data] |
618 | - |
619 | - def render_forms(self, ctx, data): |
620 | - d = iformless.IFormDefaults(ctx).getAllDefaults('insert') |
621 | - d['author'] = self.original.author |
622 | - d['category'] = self.original.category |
623 | - d['title'] = self.original.title |
624 | - d['content'] = self.original.content |
625 | - d['id'] = self.original.id |
626 | - return webform.renderForms() |
627 | - |
628 | - def insert(self, ctx, id, title, author, category, content): |
629 | - self.original.author = unicode(author) |
630 | - self.original.title = unicode(title) |
631 | - self.original.category = unicode(category) |
632 | - self.original.content = unicode(content) |
633 | - inevow.IRequest(ctx).setComponent(iformless.IRedirectAfterPost, '/thx') |
634 | - |
635 | -##################################### |
636 | -class Atom(BaseUI): |
637 | - docFactory = loaders.xmlfile('atom.xml') |
638 | - |
639 | - def beforeRender(self, ctx): |
640 | - inevow.IRequest(ctx).setHeader("Content-Type", "application/application+xml; charset=UTF-8") |
641 | - |
642 | - def data_getFirstPost(self, ctx, data): |
643 | - for post in IBlog(IStore(ctx)).getPosts(1): |
644 | - return post |
645 | - |
646 | - def render_modified(self, ctx, data): |
647 | - return ctx.tag.clear()[atompptime(data.modified)] |
648 | - |
649 | - def data_get_posts(self, ctx, data): |
650 | - return IBlog(IStore(ctx)).getPosts(15) |
651 | - |
652 | - def render_post(self, ctx, data): |
653 | - #id = data.poolToUID[IBlog(IStore(ctx)).postsPool] |
654 | - # mkp: ...I don't know what that means or what it's for. |
655 | - ctx.tag.fillSlots('title', data.title) |
656 | - ctx.tag.fillSlots('link', url.root.child(data.id)) |
657 | - ctx.tag.fillSlots('id', data.id) |
658 | - ctx.tag.fillSlots('created', atompptime(data.created)) |
659 | - ctx.tag.fillSlots('modified', atompptime(data.modified)) |
660 | - ctx.tag.fillSlots('author', data.author) |
661 | - ctx.tag.fillSlots('content', data.content) |
662 | - return ctx.tag |
663 | - |
664 | -##################################### |
665 | -from axiom.item import transacted |
666 | -class BlogRPC(xmlrpc.XMLRPC): |
667 | - """Publishes stuff""" |
668 | - |
669 | - def __init__(self, store): |
670 | - xmlrpc.XMLRPC.__init__(self) |
671 | - self.store = store |
672 | - |
673 | - def xmlrpc_publish(self, author, title, category, content): |
674 | - newid = IBlog(self.store).getNextId() |
675 | - newPost = Post(store=self.store, |
676 | - id=newid, |
677 | - author=unicode(author), |
678 | - title=unicode(title), |
679 | - category=unicode(category), |
680 | - content=unicode(content)) |
681 | - IBlog(self.store).addNewPost(newPost) |
682 | - return 'Successfully added post number %s' % newid |
683 | - xmlrpc_publish = transacted(xmlrpc_publish) |
684 | - |
685 | - def xmlrpc_edit(self, id, author, title, category, content): |
686 | - post = IBlog(self.store).getOne(id) |
687 | - post.author = author |
688 | - post.title = title |
689 | - post.category = category |
690 | - post.content = content |
691 | - post.setModified() |
692 | - return 'Successfully modified post number %s' % id |
693 | - xmlrpc_edit = transacted(xmlrpc_edit) |
694 | - |
695 | - def xmlrpc_entries(self, count): |
696 | - return [(entry.id, entry.author, entry.category, entry.title, entry.content) \ |
697 | - for entry in IBlog(self.store).getPosts(count)] |
698 | - |
699 | - xmlrpc_entries = transacted(xmlrpc_entries) |
700 | - |
701 | -registerAdapter(Entry, Post, inevow.IResource) |
702 | - |
703 | |
704 | === removed file 'Nevow/examples/blogengine/iblogengine.py' |
705 | --- Nevow/examples/blogengine/iblogengine.py 2006-03-17 15:00:39 +0000 |
706 | +++ Nevow/examples/blogengine/iblogengine.py 1970-01-01 00:00:00 +0000 |
707 | @@ -1,17 +0,0 @@ |
708 | -from zope.interface import Interface |
709 | - |
710 | -class IStore(Interface): |
711 | - """ Interface used to remember the store in the site object """ |
712 | - |
713 | -class IBlog(Interface): |
714 | - """ Represents the Blog Powerup in the Store """ |
715 | - def addNewPost(post): |
716 | - """ Add the user provided post instance to the blog """ |
717 | - def getPosts(how_many = None): |
718 | - """ Get the last X posts, if how_many is not specified, gets all of them """ |
719 | - |
720 | - def getOne(id): |
721 | - """ Get the post with the corresponding id from the store """ |
722 | - |
723 | - def getNextId(): |
724 | - """ Get the next free id in the store """ |
725 | |
726 | === removed directory 'Nevow/examples/blogengine/images' |
727 | === removed file 'Nevow/examples/blogengine/images/bg-header2.jpg' |
728 | 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 |
729 | === removed file 'Nevow/examples/blogengine/images/blank.gif' |
730 | 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 |
731 | === removed file 'Nevow/examples/blogengine/images/geek-bullet.gif' |
732 | 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 |
733 | === removed file 'Nevow/examples/blogengine/images/here-bullet.gif' |
734 | 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 |
735 | === removed file 'Nevow/examples/blogengine/images/home-bullet.gif' |
736 | 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 |
737 | === removed file 'Nevow/examples/blogengine/images/top.gif' |
738 | 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 |
739 | === removed file 'Nevow/examples/blogengine/smtpserver.py' |
740 | --- Nevow/examples/blogengine/smtpserver.py 2006-01-21 22:53:11 +0000 |
741 | +++ Nevow/examples/blogengine/smtpserver.py 1970-01-01 00:00:00 +0000 |
742 | @@ -1,148 +0,0 @@ |
743 | - |
744 | -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. |
745 | -# See LICENSE for details. |
746 | - |
747 | -""" |
748 | -A toy email server. |
749 | -""" |
750 | -from zope.interface import implements |
751 | - |
752 | -from twisted.internet import defer |
753 | -from twisted.mail import smtp |
754 | - |
755 | -from axiom.item import transacted |
756 | - |
757 | -from axiomstore import Post |
758 | -from iblogengine import IBlog |
759 | - |
760 | - |
761 | -# You need to set this to your real SMTP_HOST |
762 | -SMTP_HOST = 'localhost' |
763 | -FROM = 'user@localhost' |
764 | - |
765 | -__doc__ = """ |
766 | -This is the mail message format to post something via mail, no special |
767 | -order is required, but all those fields must be present: |
768 | -====== |
769 | -[Id: ID] |
770 | -Author: AUTHOR_NAME |
771 | -Category: CATEGORY_NAME |
772 | -Title: TITLE |
773 | -Content: CONTENT |
774 | -""" |
775 | - |
776 | -class BlogMessageDelivery: |
777 | - implements(smtp.IMessageDelivery) |
778 | - def __init__(self, store): |
779 | - self.store = store |
780 | - |
781 | - def receivedHeader(self, helo, origin, recipients): |
782 | - return recipients |
783 | - |
784 | - def validateFrom(self, helo, origin): |
785 | - # All addresses are accepted |
786 | - return origin |
787 | - |
788 | - def validateTo(self, user): |
789 | - # Only messages directed to the "console" user are accepted. |
790 | - if user.dest.local == "blog": |
791 | - return lambda: BlogMessage(self.store) |
792 | - raise smtp.SMTPBadRcpt(user) |
793 | - |
794 | -class BlogMessage: |
795 | - implements(smtp.IMessage) |
796 | - |
797 | - def __init__(self, store): |
798 | - self.lines = [] |
799 | - self.store = store |
800 | - |
801 | - def lineReceived(self, line): |
802 | - self.lines.append(line) |
803 | - |
804 | - def eomReceived(self): |
805 | - post = {} |
806 | - isContent = False |
807 | - ctnt_buff = [] |
808 | - recipients = self.lines[0] |
809 | - addrs = [] |
810 | - |
811 | - for recipient in recipients: |
812 | - if '@' not in recipient.orig.addrstr: |
813 | - # Avoid answering to bounches |
814 | - if not recipient.orig.addrstr == '<>': |
815 | - addrs.append(recipient.orig.addrstr[:-1]+'@'+recipient.orig.domain+'>') |
816 | - else: |
817 | - # Avoid answering to bounches |
818 | - if not recipient.orig.addrstr == '<#@[]>': |
819 | - addrs.append(recipient.orig.addrstr) |
820 | - |
821 | - for line in self.lines[1:]: |
822 | - if not isContent: |
823 | - try: |
824 | - field, value = line.split(':', 1) |
825 | - except ValueError: |
826 | - continue |
827 | - if field.lower() != 'content': |
828 | - post[field.lower()] = value.strip() |
829 | - else: |
830 | - isContent = True |
831 | - ctnt_buff.append(value.strip()) |
832 | - else: |
833 | - ctnt_buff.append(line.strip()) |
834 | - post['content'] = '\n'.join(ctnt_buff) |
835 | - |
836 | - for header in 'content author category title'.split(): |
837 | - if not post.has_key(header): |
838 | - self.lines = [] |
839 | - return defer.fail(None) |
840 | - if post.has_key('id'): |
841 | - oldpost = IBlog(self.store).getOne(int(post['id'])) |
842 | - oldpost.author = unicode(post['author']) |
843 | - oldpost.title = unicode(post['title']) |
844 | - oldpost.category = unicode(post['category']) |
845 | - oldpost.content = unicode(post['content']) |
846 | - oldpost.setModified() |
847 | - action = 'modified' |
848 | - id = post['id'] |
849 | - else: |
850 | - newid = IBlog(self.store).getNextId() |
851 | - newPost = Post(store=self.store, |
852 | - id=newid, |
853 | - author=unicode(post['author']), |
854 | - title=unicode(post['title']), |
855 | - category=unicode(post['category']), |
856 | - content=unicode(post['content'])) |
857 | - IBlog(self.store).addNewPost(newPost) |
858 | - action = 'added' |
859 | - id = newid |
860 | - self.lines = [] |
861 | - msg = """From: <%s> |
862 | -Subject: Successfull Post |
863 | - |
864 | -Post number %s successfully %s |
865 | -""" % (FROM, id, action) |
866 | - return self.sendNotify(addrs, msg) |
867 | - eomReceived = transacted(eomReceived) |
868 | - |
869 | - def toLog(self, what): |
870 | - print what |
871 | - |
872 | - def sendNotify(self, to_addr, msg): |
873 | - d = smtp.sendmail(SMTP_HOST, FROM, to_addr, msg) |
874 | - d.addCallback(self.toLog) |
875 | - d.addErrback(self.toLog) |
876 | - return d |
877 | - |
878 | - def connectionLost(self): |
879 | - # There was an error, throw away the stored lines |
880 | - self.lines = None |
881 | - |
882 | -class BlogSMTPFactory(smtp.SMTPFactory): |
883 | - def __init__(self, store, *a, **kw): |
884 | - smtp.SMTPFactory.__init__(self, *a, **kw) |
885 | - self.delivery = BlogMessageDelivery(store) |
886 | - |
887 | - def buildProtocol(self, addr): |
888 | - p = smtp.SMTPFactory.buildProtocol(self, addr) |
889 | - p.delivery = self.delivery |
890 | - return p |
891 | |
892 | === removed directory 'Nevow/examples/blogengine/styles' |
893 | === removed file 'Nevow/examples/blogengine/styles/form.css' |
894 | --- Nevow/examples/blogengine/styles/form.css 2005-10-14 17:36:24 +0000 |
895 | +++ Nevow/examples/blogengine/styles/form.css 1970-01-01 00:00:00 +0000 |
896 | @@ -1,78 +0,0 @@ |
897 | -form { |
898 | - margin: 0; |
899 | -} |
900 | - |
901 | -/* |
902 | -form div { |
903 | - margin-top: 10px; |
904 | -} |
905 | -*/ |
906 | - |
907 | -form .field { |
908 | - margin-top: 10px; |
909 | -} |
910 | - |
911 | -fieldset { |
912 | - margin: 0; |
913 | - margin-top: 10px; |
914 | - |
915 | -/*border: 1px solid red;*/ |
916 | - border-style: none; |
917 | - padding: 0; |
918 | -} |
919 | - |
920 | - |
921 | -label { |
922 | - display: block; |
923 | - margin-bottom: 2px; |
924 | -} |
925 | - |
926 | -label span { |
927 | - font-size: 85%; |
928 | - color: #666; |
929 | -} |
930 | - |
931 | -input, textarea { |
932 | - /* f a t font to ease input */ |
933 | - font: bold 12px/100% "Lucida Console", Curier, monospace; |
934 | - color: #444; |
935 | - |
936 | - padding: 4px 2px; |
937 | - border: 1px solid #ccc; |
938 | - |
939 | - margin: 0; |
940 | -} |
941 | - |
942 | -input:focus, textarea:focus { |
943 | - border-color: #6cc; |
944 | -} |
945 | - |
946 | - |
947 | -input.btn { |
948 | - margin: 0; |
949 | - margin-right: 2px; /* space between the next button */ |
950 | - |
951 | - padding: 2px 4px; |
952 | - |
953 | - color: #333; |
954 | - background: #6cc; |
955 | - |
956 | - /* raised 3d look */ |
957 | - border-top: 2px solid #ccc; |
958 | - border-left: 2px solid #ccc; |
959 | - border-bottom: 2px solid #444; |
960 | - border-right: 2px solid #444; |
961 | - |
962 | - font-family: Verdana, Helvetica, sans-serif; |
963 | - line-height: 150%; |
964 | - |
965 | - font-size: xx-small; /* fake value for IE4/5.x */ |
966 | - voice-family: "\"}\""; |
967 | - voice-family: inherit; |
968 | - font-size: x-small; /* real inteded value for text size */ |
969 | -} |
970 | - |
971 | -blah { |
972 | - /* fake rule for IE */ |
973 | -} |
974 | - |
975 | |
976 | === removed file 'Nevow/examples/blogengine/styles/site.css' |
977 | --- Nevow/examples/blogengine/styles/site.css 2005-10-14 17:36:24 +0000 |
978 | +++ Nevow/examples/blogengine/styles/site.css 1970-01-01 00:00:00 +0000 |
979 | @@ -1,482 +0,0 @@ |
980 | -@import url("typo.css"); |
981 | -@import url("form.css"); |
982 | - |
983 | -/* |
984 | -------------------------------------------------- |
985 | -Theme by Andrea Peltrin (http://www.deelan.com) |
986 | -------------------------------------------------- |
987 | -*/ |
988 | - |
989 | - |
990 | -/* basic elements */ |
991 | -/*---------------------------------------------------*/ |
992 | - |
993 | -body, html { |
994 | - margin: 0; |
995 | - padding: 0; |
996 | -} |
997 | - |
998 | - |
999 | -body { |
1000 | - color: #222; |
1001 | - |
1002 | - margin: 0; |
1003 | -/* background: #903 url("images/background.gif"); */ |
1004 | - background: #fafafa; |
1005 | -} |
1006 | - |
1007 | -body, p, li, td, th, dd, dt, h1, h2, h3, h4, h5, h6 /* help browser to not forget */ |
1008 | -{ |
1009 | - font-family: verdana, geneva, arial, sans-serif; |
1010 | -/* line-height: 200%;*/ |
1011 | - |
1012 | - font-size: x-small; /* IE5 */ |
1013 | - voice-family: "\"}\""; |
1014 | - voice-family: inherit; |
1015 | - font-size: small; |
1016 | -} |
1017 | - |
1018 | -html>body { |
1019 | - font-size: small; |
1020 | -} |
1021 | - |
1022 | - |
1023 | -a img { |
1024 | - border-style: none; |
1025 | -} |
1026 | - |
1027 | -/* main contents */ |
1028 | - |
1029 | -#main { |
1030 | - /*border: 1px solid red; */ /* debug */ |
1031 | - /*border-top: none;*/ |
1032 | - |
1033 | - |
1034 | - |
1035 | - margin: 0 auto; |
1036 | - padding: 0; |
1037 | - |
1038 | - position: absolute; |
1039 | - |
1040 | - top: 30px; |
1041 | - left: 50%; |
1042 | - margin-left: -380px; |
1043 | - |
1044 | - width: 760px; |
1045 | -} |
1046 | - |
1047 | -/* header */ |
1048 | - |
1049 | -#header { |
1050 | - background: #069 url("/images/bg-header2.jpg") top right no-repeat; |
1051 | - |
1052 | - height: 235px; |
1053 | - border: 1px solid #ccc; |
1054 | -} |
1055 | - |
1056 | - |
1057 | -#header h1 { |
1058 | - margin: 0; |
1059 | - margin-top: 140px; |
1060 | - /*margin-right: 280px;*/ |
1061 | - |
1062 | - padding: 0; |
1063 | - padding-left:30px; |
1064 | - |
1065 | - |
1066 | - font: bold italic 52px/100% georgia, times, serif; |
1067 | - color: #fff; |
1068 | -} |
1069 | - |
1070 | -#header p { |
1071 | - margin: 0; |
1072 | - /*margin-left: 280px;*/ /* == #header h1 */ |
1073 | - |
1074 | - padding: 0; |
1075 | - padding-left:30px; |
1076 | - |
1077 | - |
1078 | - text-transform: lowercase; |
1079 | - font: bold 18px/100% verdana, arial, sans-serif; |
1080 | - |
1081 | - color: #fff; |
1082 | -} |
1083 | - |
1084 | - |
1085 | -/*---------------------------------------------------*/ |
1086 | - |
1087 | -#content{ |
1088 | - padding: 35px; |
1089 | - margin: 0; |
1090 | - |
1091 | - /*border: 1px solid red; */ /* debug */ |
1092 | - margin-right: 245px; |
1093 | - |
1094 | -} |
1095 | - |
1096 | -#content p { |
1097 | - /* border: 1px solid red; */ /* debug */ |
1098 | -/* text-align: justify;*/ |
1099 | - line-height: 160%; |
1100 | - |
1101 | - margin: 1em 0; |
1102 | - padding: 0; |
1103 | -} |
1104 | - |
1105 | -#content ul, #content ol, #content dl, #content blockquote { |
1106 | - line-height: 160%; |
1107 | -} |
1108 | - |
1109 | - |
1110 | -#content dd { |
1111 | - margin: 0; |
1112 | - margin-bottom: 10px; |
1113 | -} |
1114 | - |
1115 | - |
1116 | -/* funky titles */ |
1117 | -#content h2 { |
1118 | - |
1119 | -/* font: bold italic 24px/100% georgia, times, serif;*/ |
1120 | - font: bold 18px/100% verdana, arial, sans-serif; |
1121 | - |
1122 | - color: #069; |
1123 | - |
1124 | - margin: 0; |
1125 | - margin-bottom: 4px; /* space up for datetime */ |
1126 | - |
1127 | - text-transform: lowercase; |
1128 | -/* font-variant: small-caps;*/ |
1129 | - |
1130 | -} |
1131 | - |
1132 | -#content p.dtm { |
1133 | - |
1134 | - margin: 0; |
1135 | - margin-bottom: 1em; |
1136 | - |
1137 | - font-size: 80%; |
1138 | - |
1139 | - text-transform: uppercase; |
1140 | -} |
1141 | - |
1142 | - |
1143 | -div.entry { |
1144 | - |
1145 | -} |
1146 | - |
1147 | - |
1148 | -#content hr { |
1149 | - visibility: hidden; |
1150 | - |
1151 | |
1152 | - |
1153 | |
1154 | - padding: 0; |
1155 | |
1156 | - margin: 2.5em auto; |
1157 | |
1158 | - |
1159 | |
1160 | - |
1161 | |
1162 | -} |
1163 | - |
1164 | - |
1165 | - |
1166 | -/* ...and finally we place the list of links */ |
1167 | - |
1168 | -#sidebar{ |
1169 | - float: right; |
1170 | - |
1171 | -/* border: 1px solid #069;*/ |
1172 | - |
1173 | - margin: 0; |
1174 | - padding: 35px; |
1175 | - |
1176 | - width: 250px; |
1177 | - voice-family: "\"}\""; |
1178 | - voice-family: inherit; |
1179 | - width: 180px; |
1180 | -} |
1181 | - |
1182 | -#main>#sidebar { |
1183 | - width: 180px; |
1184 | -} |
1185 | - |
1186 | - |
1187 | -#sidebar ul { |
1188 | - list-style: none; |
1189 | - |
1190 | - margin: 0; |
1191 | - margin-bottom: 25px; |
1192 | - |
1193 | - padding: 0; |
1194 | -} |
1195 | - |
1196 | - |
1197 | -#sidebar ul li { |
1198 | - line-height: 150%; |
1199 | - |
1200 | - margin: 0; |
1201 | - padding: 5px 0; |
1202 | -} |
1203 | - |
1204 | - |
1205 | -#sidebar ul#nav li { |
1206 | - line-height: 160%; /* restore global value */ |
1207 | - |
1208 | - border-style: none; |
1209 | - background: none; |
1210 | - |
1211 | - margin-bottom: 10px; |
1212 | - padding: 5px 0 5px 22px; /* space for arrow gfx */ |
1213 | - |
1214 | - border-top: 1px solid #ccc; |
1215 | - border-bottom: 1px solid #ccc; |
1216 | - |
1217 | - text-transform: lowercase; |
1218 | -} |
1219 | - |
1220 | - |
1221 | -/* funky titles */ |
1222 | -#sidebar h3 { |
1223 | - color: #069; |
1224 | - |
1225 | - margin: 0; |
1226 | - margin-bottom: 15px; |
1227 | - |
1228 | - padding: 0; |
1229 | - |
1230 | - |
1231 | -} |
1232 | - |
1233 | - |
1234 | -/* styles for in-line images/photos */ |
1235 | -/*---------------------------------------------------*/ |
1236 | -#content .image img { |
1237 | - display: block; |
1238 | - border: 1px solid #444; |
1239 | -} |
1240 | - |
1241 | -#content .image { |
1242 | - margin: 1em auto; /* == #content p*/ |
1243 | - |
1244 | - width: 360px; |
1245 | - position: relative; |
1246 | -} |
1247 | - |
1248 | -#content .image span { |
1249 | - position: absolute; |
1250 | - |
1251 | - background: #069; |
1252 | - color: #fff; |
1253 | - |
1254 | - padding: 4px 4px; |
1255 | - |
1256 | - bottom: 10px; |
1257 | - left: 10px; |
1258 | - |
1259 | - z-index: 1; |
1260 | - |
1261 | - /* verdana looks better than arial if font is small */ |
1262 | - font-family: verdana, arial, helvetica, sans-serif; |
1263 | - |
1264 | - /* @@ fix IE5 here */ |
1265 | - font-size: x-small; |
1266 | -} |
1267 | - |
1268 | -/* hyperlink */ |
1269 | -/*---------------------------------------------------*/ |
1270 | - |
1271 | -a:link, a:visited, a:hover, a:active { |
1272 | - color: #099; |
1273 | - |
1274 | - text-decoration: none; |
1275 | - border-bottom: 1px solid #099; |
1276 | -} |
1277 | - |
1278 | -a:visited { |
1279 | - color: #444; |
1280 | - border-bottom-color: #444; |
1281 | -} |
1282 | - |
1283 | -a:hover { |
1284 | - color: #903; |
1285 | - /*border-bottom: 1px solid #903;*/ |
1286 | - border-bottom: none; |
1287 | -} |
1288 | - |
1289 | - |
1290 | -#footer { |
1291 | - margin: 0; |
1292 | - margin-top: 20px; |
1293 | - padding: 15px 0; |
1294 | - |
1295 | -/* background: #903;*/ |
1296 | - |
1297 | - clear: both; /* float reset */ |
1298 | - text-align: center; |
1299 | - |
1300 | - |
1301 | - border-top: 1px solid #ccc; |
1302 | - |
1303 | - font-size: 85%; |
1304 | -} |
1305 | - |
1306 | - |
1307 | - |
1308 | -/* utilities */ |
1309 | -/*---------------------------------------------------*/ |
1310 | - |
1311 | -.cut {clear: both; height: 1px;} |
1312 | -.hidden {display: none;} |
1313 | - |
1314 | -/*---------------------------------------------------*/ |
1315 | - |
1316 | -ul#breadcrumb { |
1317 | - list-style: none; |
1318 | - |
1319 | - /* reset both on Mozilla and IE */ |
1320 | - padding: 0; |
1321 | - |
1322 | - margin: 0; |
1323 | - margin-bottom: 35px; |
1324 | -} |
1325 | - |
1326 | -ul#breadcrumb li { |
1327 | - display: inline; |
1328 | - margin-right: 5px; |
1329 | - |
1330 | - /*text-transform: lowercase;*/ |
1331 | -} |
1332 | - |
1333 | -ul#breadcrumb li:last-child { |
1334 | - font-weight: bold; |
1335 | -} |
1336 | - |
1337 | -/* |
1338 | -#searchBtn { |
1339 | - margin-left: 5px; |
1340 | -} |
1341 | - |
1342 | - |
1343 | -*/ |
1344 | -/* -------------------------------------------------- */ |
1345 | - |
1346 | -.photo { |
1347 | - |
1348 | - float: left; |
1349 | - |
1350 | - margin: 5px 0; |
1351 | - margin-right: 10px; |
1352 | - |
1353 | - padding: 0; |
1354 | -} |
1355 | - |
1356 | -.photo a:link, .photo a:visited { |
1357 | - border: 1px solid #0099CC; |
1358 | - |
1359 | - display: block; |
1360 | -} |
1361 | - |
1362 | -.photo a:link:hover, .photo a:visited:hover { |
1363 | - border: 1px solid #903; |
1364 | -} |
1365 | - |
1366 | -.photo img { |
1367 | - display: block; |
1368 | - |
1369 | - margin:0; |
1370 | - |
1371 | - padding: 5px; |
1372 | - background: #fff; |
1373 | -} |
1374 | - |
1375 | - |
1376 | - |
1377 | -.transport { |
1378 | - |
1379 | - |
1380 | - width: auto; |
1381 | - |
1382 | - /*border: 2px solid #069;*/ |
1383 | - text-align: center; |
1384 | - |
1385 | - padding: 5px 0; |
1386 | -} |
1387 | - |
1388 | - |
1389 | - |
1390 | -#alert { |
1391 | - background: #069; |
1392 | - color: white; |
1393 | - |
1394 | - font-weight: bold; |
1395 | - |
1396 | - margin-bottom: 20px; |
1397 | -} |
1398 | - |
1399 | - |
1400 | - |
1401 | -#alert ul { |
1402 | - list-style: none; |
1403 | - |
1404 | - padding: 0; |
1405 | - margin: 0; |
1406 | -} |
1407 | - |
1408 | - |
1409 | -#alert ul li { |
1410 | - margin: 5px 10px; |
1411 | -} |
1412 | - |
1413 | - |
1414 | -/* @@ fix, it's ugly looking */ |
1415 | -.comment:target { |
1416 | - border: 1px solid #099; |
1417 | - |
1418 | -} |
1419 | - |
1420 | - |
1421 | - |
1422 | - |
1423 | - |
1424 | -#moblog{ |
1425 | - text-align: center; |
1426 | - background: #ddd; |
1427 | - border: 1px solid #999999; |
1428 | - padding: 5px; |
1429 | -} |
1430 | - |
1431 | - |
1432 | - |
1433 | -#moblog { |
1434 | - margin: 5px 0; |
1435 | - padding: 10px; |
1436 | - |
1437 | -} |
1438 | - |
1439 | -#moblog a:link, #moblog a:visited { |
1440 | - border: 1px solid #0099CC; |
1441 | - |
1442 | - display: block; |
1443 | - width: 85px; |
1444 | - |
1445 | - margin: 5px auto; |
1446 | -} |
1447 | - |
1448 | -#moblog a:link:hover, #moblog a:visited:hover { |
1449 | - border: 1px solid #903; |
1450 | -} |
1451 | - |
1452 | -#moblog img { |
1453 | - display: block; |
1454 | - |
1455 | - margin:0; |
1456 | - padding: 5px; |
1457 | - |
1458 | - background: #fff; |
1459 | -} |
1460 | - |
1461 | - |
1462 | -#moblog p { |
1463 | - padding: 0; |
1464 | - margin: 0; |
1465 | - |
1466 | - text-align: center; |
1467 | -} |
1468 | |
1469 | === removed file 'Nevow/examples/blogengine/styles/typo.css' |
1470 | --- Nevow/examples/blogengine/styles/typo.css 2005-10-14 17:36:24 +0000 |
1471 | +++ Nevow/examples/blogengine/styles/typo.css 1970-01-01 00:00:00 +0000 |
1472 | @@ -1,103 +0,0 @@ |
1473 | -/* -------------------- |
1474 | -definition list |
1475 | ----------------------*/ |
1476 | - |
1477 | -dl { |
1478 | - |
1479 | -} |
1480 | - |
1481 | -dd { |
1482 | - margin-left: 1em; |
1483 | -} |
1484 | - |
1485 | -dt { |
1486 | - |
1487 | -} |
1488 | - |
1489 | -/* -------------------- |
1490 | -phrase elements |
1491 | ----------------------*/ |
1492 | - |
1493 | -abbr, acronym |
1494 | -{ |
1495 | - cursor: help; |
1496 | - border-bottom: dotted 1px; |
1497 | -} |
1498 | - |
1499 | - |
1500 | -ins, del |
1501 | -{ |
1502 | - |
1503 | -} |
1504 | - |
1505 | -ins |
1506 | -{ |
1507 | - text-decoration: none; /* some UAs reder as underlined, hence reset */ |
1508 | -} |
1509 | - |
1510 | -ins:before |
1511 | -{ |
1512 | - /* content: '[' */ |
1513 | -} |
1514 | - |
1515 | -ins:after |
1516 | -{ |
1517 | - /* content: ']' */ |
1518 | -} |
1519 | - |
1520 | - |
1521 | -/* -------------------- |
1522 | -block/inline quotations, |
1523 | -check: http://diveintomark.org/archives/2002/05/04/the_q_tag.html |
1524 | ----------------------*/ |
1525 | - |
1526 | -blockquote { |
1527 | - border-left: 4px double #6cc; |
1528 | - |
1529 | - padding: 0; |
1530 | - padding-left: 10px; |
1531 | - |
1532 | - margin: 0.5em 5%; |
1533 | -} |
1534 | - |
1535 | -cite, q { |
1536 | - font-style: italic; |
1537 | -} |
1538 | - |
1539 | -p>q, li>q, p>cite, li>cite { /* reset for mozilla, opera */ |
1540 | - font-style: normal; |
1541 | -} |
1542 | - |
1543 | -cite, q { |
1544 | - quotes: '\201C' '\201D' '\2018' '\2019'; /* quote and quote within quote */ |
1545 | -} |
1546 | - |
1547 | -cite:before, q:before { |
1548 | - content: open-quote; |
1549 | -} |
1550 | - |
1551 | -cite:after, q:after { |
1552 | - content: close-quote; |
1553 | -} |
1554 | - |
1555 | - |
1556 | -/* -------------------- |
1557 | -geeks' markup codes |
1558 | ----------------------*/ |
1559 | - |
1560 | -pre, code { |
1561 | - font-size: 100%; /* reset size for IE */ |
1562 | -} |
1563 | - |
1564 | - |
1565 | -#content>pre { |
1566 | - width: auto; /* reset value for moz, opera */ |
1567 | -} |
1568 | - |
1569 | - |
1570 | - |
1571 | -/* mostly used to indicate markup/language keywords*/ |
1572 | -code { |
1573 | - color: #6cc; |
1574 | - font-weight: bold; |
1575 | -} |
1576 | |
1577 | === removed file 'Nevow/examples/blogengine/ui.html' |
1578 | --- Nevow/examples/blogengine/ui.html 2005-10-14 17:36:24 +0000 |
1579 | +++ Nevow/examples/blogengine/ui.html 1970-01-01 00:00:00 +0000 |
1580 | @@ -1,79 +0,0 @@ |
1581 | -<?xml version="1.0" encoding="UTF-8"?> |
1582 | -<!DOCTYPE html |
1583 | - PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" |
1584 | - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
1585 | - |
1586 | -<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"> |
1587 | - |
1588 | - <head> |
1589 | - <title>Subbacultcha</title> |
1590 | - <style type="text/css">@import url('/styles/site.css');</style> |
1591 | - <style type="text/css">@import url('/webform_css');</style> |
1592 | - </head> |
1593 | - |
1594 | - <body> |
1595 | - |
1596 | - <div id="main"> |
1597 | - |
1598 | - <div id="header"> |
1599 | - <h1>Subbacultcha</h1> |
1600 | - <p>not offending anyone</p> |
1601 | - </div> |
1602 | - |
1603 | - <div id="sidebar"> |
1604 | - <ul id="nav"> |
1605 | - <li><a id="a_home" href="/">Home</a></li> |
1606 | - <!-- <li><a id="a_archives" title="" href="#">Archives</a></li> --> |
1607 | - <li nevow:render="insert"><a href="#"> |
1608 | - <nevow:attr name="href"><nevow:slot name="insert" /></nevow:attr> |
1609 | - Insert a new entry |
1610 | - </a> |
1611 | - </li> |
1612 | - </ul> |
1613 | - </div> |
1614 | - |
1615 | - <div id="content"> |
1616 | - <div nevow:data="getEntries" nevow:render="sequence"> |
1617 | - |
1618 | - <div nevow:pattern="item" nevow:render="entries"> |
1619 | - <h2><nevow:slot name="title" /></h2> |
1620 | - |
1621 | - <!-- <p><nevow:slot name="modification"></nevow:slot></p> --> |
1622 | - |
1623 | - <p><nevow:slot name="content"></nevow:slot></p> |
1624 | - <p> |
1625 | - <a href="#"> |
1626 | - <nevow:attr name="href"><nevow:slot name="permaLink" /></nevow:attr> |
1627 | - PermaLink |
1628 | - </a> |
1629 | - • |
1630 | - <nevow:invisible nevow:render="editer"> |
1631 | - <a href="#"> |
1632 | - <nevow:attr name="href"><nevow:slot name="editPost" /></nevow:attr> |
1633 | - Edit |
1634 | - </a> |
1635 | - </nevow:invisible> |
1636 | - </p> |
1637 | - |
1638 | - <p>Posted by <nevow:slot name="author"></nevow:slot> on <nevow:slot name="modification" />, filed under <nevow:slot name="category" /></p> |
1639 | - </div> |
1640 | - |
1641 | - </div> |
1642 | - |
1643 | - <!-- /content --> |
1644 | - <nevow:invisible nevow:render="needForms"> |
1645 | - <p>Edit Entry</p> |
1646 | - <div nevow:pattern="frm" nevow:render="forms" /> |
1647 | - </nevow:invisible> |
1648 | - </div> |
1649 | - |
1650 | - <div id="footer"> |
1651 | - <p>Served in <span nevow:render="stoptimer" /></p> |
1652 | - <p>CSS by Andrea 'deelan' Peltrin, <a href="http://www.deelan.com/">website</a></p> |
1653 | - </div> |
1654 | - |
1655 | - <!-- /main --> |
1656 | - </div> |
1657 | - </body> |
1658 | -</html> |
1659 | - |
1660 | |
1661 | === modified file 'Nevow/examples/children/children.py' |
1662 | --- Nevow/examples/children/children.py 2005-10-14 17:36:24 +0000 |
1663 | +++ Nevow/examples/children/children.py 2011-07-27 23:02:31 +0000 |
1664 | @@ -82,10 +82,6 @@ |
1665 | """ |
1666 | |
1667 | # Let parent class have a go first |
1668 | - # WARNING: This 3 lines work well until you use formless in this page |
1669 | - # because formless will make locateChild return only one return value |
1670 | - # (a deferred) on which you should add a callback that accepts a resource and |
1671 | - # an empty tuple that represents no remaining segments. |
1672 | child, remainingSegments = rend.Page.locateChild(self, ctx, segments) |
1673 | if child: |
1674 | return child, remainingSegments |
1675 | |
1676 | === removed directory 'Nevow/examples/customform' |
1677 | === removed file 'Nevow/examples/customform/__init__.py' |
1678 | === removed file 'Nevow/examples/customform/customform.py' |
1679 | --- Nevow/examples/customform/customform.py 2006-03-17 15:00:39 +0000 |
1680 | +++ Nevow/examples/customform/customform.py 1970-01-01 00:00:00 +0000 |
1681 | @@ -1,159 +0,0 @@ |
1682 | -################################################################################# |
1683 | -# Example of using patterns to change the appearance of a webform. |
1684 | - |
1685 | -#from twisted.application import internet, service |
1686 | -#from twisted.web import static |
1687 | - |
1688 | -from zope.interface import implements |
1689 | - |
1690 | -from nevow import rend |
1691 | -from nevow import url |
1692 | -from nevow import loaders |
1693 | -from nevow import tags as T |
1694 | - |
1695 | -from formless import annotate |
1696 | -from formless import webform |
1697 | - |
1698 | - |
1699 | -################################################################################# |
1700 | -# This beasty defines how I want the form to look. It's a table (eek!). |
1701 | -# webform looks for patterns to use when rendering parts of the form and fills |
1702 | -# slots with key information. |
1703 | -# |
1704 | -# Key patterns are: |
1705 | -# freeform-form -- the form itself, mostly just the structure |
1706 | -# argument -- the pattern to use for arguments when nothing better |
1707 | -# is found |
1708 | -# argument!!fo -- the pattern to use for the 'fo' argument |
1709 | -# |
1710 | -# Inside the patterns the following slots are filled: |
1711 | -# freeform-form: |
1712 | -# form-action -- action attribute, where the form will be posted |
1713 | -# form-id -- id of the form |
1714 | -# form-name -- name of the form |
1715 | -# form-label -- form label, extracted from the docstring |
1716 | -# form-description -- description, also extracted from the docstring |
1717 | -# form-error -- "global" error |
1718 | -# form-arguments -- insertion point for the arguments' HTML |
1719 | -# argument: |
1720 | -# label -- label |
1721 | -# input -- the form element (input, textarea, etc) |
1722 | -# error -- error message (if any) |
1723 | -# description -- description of argument |
1724 | -# |
1725 | -# Note that you do not have to provide slots for all of the above. For |
1726 | -# instance, you may not want to display the descriptions. |
1727 | -# |
1728 | -# Chances are that this block of text would be in a disk template or |
1729 | -# perhaps defined using stan in a taglib module. |
1730 | - |
1731 | - |
1732 | -FORM_LAYOUT = loaders.xmlstr( |
1733 | - """<?xml version="1.0"?> |
1734 | - <form xmlns:n="http://nevow.com/ns/nevow/0.1" n:pattern="freeform-form"> |
1735 | - |
1736 | - <!-- Replace/fill the form attributes --> |
1737 | - <n:attr name="action"><n:slot name="form-action"/></n:attr> |
1738 | - <n:attr name="id"><n:slot name="form-id"/></n:attr> |
1739 | - <n:attr name="name"><n:slot name="form-name"/></n:attr> |
1740 | - |
1741 | - <!-- General form information --> |
1742 | - <p><strong><n:slot name="form-label"/></strong></p> |
1743 | - <p><em><n:slot name="form-description"/></em></p> |
1744 | - <p><strong><em><n:slot name="form-error"/></em></strong></p> |
1745 | - |
1746 | - <!-- Start of the form layout table --> |
1747 | - <table style="background: #eee; border: 1px solid #bbb; padding: 1em;" > |
1748 | - <!-- Mark location arguments will be added --> |
1749 | - <n:slot name="form-arguments"/> |
1750 | - <!-- General argument layout pattern --> |
1751 | - <n:invisible n:pattern="argument" n:render="remove"> |
1752 | - <tr> |
1753 | - <th><n:slot name="label"/>:</th> |
1754 | - <td><n:slot name="input"/><span class="freeform-error"><n:slot name="error"/></span></td> |
1755 | - </tr> |
1756 | - <tr> |
1757 | - <th></th> |
1758 | - <td><n:slot name="description"/></td> |
1759 | - </tr> |
1760 | - </n:invisible> |
1761 | - <!-- Argument layout, just for fum --> |
1762 | - <n:invisible n:pattern="argument!!fo" n:render="remove"> |
1763 | - <tr> |
1764 | - <th><n:slot name="label"/>:</th> |
1765 | - <td> |
1766 | - <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> |
1767 | - <span class="freeform-error"><n:slot name="error"/></span></td> |
1768 | - </tr> |
1769 | - <tr> |
1770 | - <th></th> |
1771 | - <td><n:slot name="description"/></td> |
1772 | - </tr> |
1773 | - </n:invisible> |
1774 | - <!-- Button row --> |
1775 | - <tr> |
1776 | - <td colspan="2"> |
1777 | - <n:slot name="form-button"/> |
1778 | - </td> |
1779 | - </tr> |
1780 | - </table> |
1781 | - </form> |
1782 | - """).load() |
1783 | - |
1784 | - |
1785 | -################################################################################# |
1786 | -# ISomething and Page are just something to test the form rendering on. |
1787 | - |
1788 | -class ISomething(annotate.TypedInterface): |
1789 | - |
1790 | - def doSomething( |
1791 | - ctx = annotate.Context(), |
1792 | - fee = annotate.String(required=True, description="Wee!"), |
1793 | - fi = annotate.Integer(description="Tra-la-la"), |
1794 | - fo = annotate.Text(), |
1795 | - fum = annotate.String(), |
1796 | - ): |
1797 | - """Do Something Really Exciting |
1798 | - |
1799 | - Normally you would put a useful description of the interface here but, |
1800 | - since the inteface is useless anyway, I cannot think of anything |
1801 | - useful to say about it. Although ... did I mention it is useless?""" |
1802 | - doSomething = annotate.autocallable(doSomething) |
1803 | - |
1804 | - |
1805 | -class Root(rend.Page): |
1806 | - """Render a custom and normal form for an ISomething. |
1807 | - """ |
1808 | - implements(ISomething) |
1809 | - addSlash = True |
1810 | - |
1811 | - child_webform_css = webform.defaultCSS |
1812 | - |
1813 | - def render_normalForm(self, ctx, data): |
1814 | - return webform.renderForms() |
1815 | - |
1816 | - def render_customForm(self, ctx, data): |
1817 | - return webform.renderForms()[FORM_LAYOUT] |
1818 | - |
1819 | - def doSomething(self, ctx, **kwargs): |
1820 | - print '***** doSomething called with:', kwargs |
1821 | - |
1822 | - docFactory = loaders.stan( |
1823 | - T.html[ |
1824 | - T.head[ |
1825 | - T.title['Example :: Custom Form Layout'], |
1826 | - T.link(rel='stylesheet', type='text/css', href=url.here.child("webform_css")), |
1827 | - ], |
1828 | - T.body[ |
1829 | - T.h1['Custom'], |
1830 | - render_customForm, |
1831 | - T.h1['Default'], |
1832 | - render_normalForm, |
1833 | - ] |
1834 | - ] |
1835 | - ) |
1836 | - |
1837 | - |
1838 | -#application = service.Application('hellostan') |
1839 | -#webServer = internet.TCPServer(8080, appserver.NevowSite(Root())) |
1840 | -#webServer.setServiceParent(application) |
1841 | |
1842 | === removed directory 'Nevow/examples/db' |
1843 | === removed file 'Nevow/examples/db/__init__.py' |
1844 | === removed file 'Nevow/examples/db/db.py' |
1845 | --- Nevow/examples/db/db.py 2006-04-14 17:23:46 +0000 |
1846 | +++ Nevow/examples/db/db.py 1970-01-01 00:00:00 +0000 |
1847 | @@ -1,132 +0,0 @@ |
1848 | - |
1849 | -from zope.interface import implements |
1850 | - |
1851 | -from nevow import inevow |
1852 | -from nevow import loaders |
1853 | -from nevow import rend |
1854 | -from nevow import tags |
1855 | -from nevow.url import here |
1856 | - |
1857 | -from formless import annotate |
1858 | -from formless import webform |
1859 | - |
1860 | - |
1861 | -whole = [(1, 'one'), (2, 'two'), (3, 'buckle'), (4, 'my'), (5, 'shoe')] |
1862 | - |
1863 | - |
1864 | -def doQuery(q, *args): |
1865 | - """Pretend like we have a database and we are accessing it through this hypothetical interface. |
1866 | - Ignore this. Use dbapi or adbapi instead, and build a real sql table. I hope that's obvious. |
1867 | - """ |
1868 | - matchid = 'select * from foo where id =' |
1869 | - setsql = 'update foo set subject = ' |
1870 | - insertsql = 'insert into foo values' |
1871 | - if q == 'select * from foo': |
1872 | - return whole |
1873 | - elif q.startswith(matchid): |
1874 | - theId = args[0] |
1875 | - for dbid, subj in whole: |
1876 | - if dbid == theId: |
1877 | - return [(dbid, subj)] |
1878 | - raise KeyError, theId |
1879 | - elif q.startswith(setsql): |
1880 | - newsubj, theId = args |
1881 | - for index, (dbid, subj) in enumerate(whole): |
1882 | - if dbid == theId: |
1883 | - whole[index] = (dbid, newsubj) |
1884 | - elif q.startswith(insertsql): |
1885 | - max = whole[-1][0] |
1886 | - subject, = args |
1887 | - whole.append((max + 1, subject)) |
1888 | - |
1889 | - |
1890 | -class IAddItem(annotate.TypedInterface): |
1891 | - def addItem(newSubject=annotate.String()): |
1892 | - pass |
1893 | - addItem = annotate.autocallable(addItem) |
1894 | - |
1895 | - |
1896 | -class DBBrowser(rend.Page): |
1897 | - implements(IAddItem) |
1898 | - addSlash = True |
1899 | - |
1900 | - def addItem(self, newSubject): |
1901 | - doQuery('insert into foo values subject = "%s"', newSubject) |
1902 | - |
1903 | - def data_queryDatabase(self, context, data): |
1904 | - return doQuery('select * from foo') |
1905 | - |
1906 | - def render_row(self, context, data): |
1907 | - theId, theSubj = data |
1908 | - return context.tag[ # put our anchor in the li provided by the template |
1909 | - tags.a(href=theId)[ theSubj ] |
1910 | - ] |
1911 | - |
1912 | - docFactory = loaders.stan( |
1913 | - tags.html[ |
1914 | - tags.body[ |
1915 | - tags.h1["Welcome, user"], |
1916 | - tags.ul(data=tags.directive("queryDatabase"), render=tags.directive("sequence"))[ |
1917 | - tags.li(pattern="item", render=render_row) |
1918 | - ], |
1919 | - webform.renderForms() |
1920 | - ] |
1921 | - ] |
1922 | - ) |
1923 | - |
1924 | - def childFactory(self, ctx, name): |
1925 | - """Since we created anchor tags linking to children of this resource |
1926 | - directly by id, when the anchor is clicked, childFactory will be called |
1927 | - with the appropriate id as the name argument.""" |
1928 | - try: |
1929 | - ## Pass the id of the database item we want to be rendered on this page |
1930 | - ## to the DBItem constructor. This integer will be used as the default data |
1931 | - ## for this page. |
1932 | - return DBItem(int(name)) |
1933 | - except ValueError: |
1934 | - pass |
1935 | - ## returning None results in a 404 |
1936 | - |
1937 | - |
1938 | -class IItemWithSubject(annotate.TypedInterface): |
1939 | - def setSubject(newSubject=annotate.String(label="Change Subject")): |
1940 | - pass |
1941 | - setSubject = annotate.autocallable(setSubject) |
1942 | - |
1943 | - |
1944 | -class DBItem(rend.Page): |
1945 | - implements(IItemWithSubject) |
1946 | - addSlash=True |
1947 | - |
1948 | - def setSubject(self, newSubject): |
1949 | - ## Self.original is the data that was passed to the DBItem constructor above; the id of this record |
1950 | - doQuery('update foo set subject = "%s" where id = %s', newSubject, self.original) |
1951 | - |
1952 | - def render_viewSelector(self, context, data): |
1953 | - args = inevow.IRequest(context).args |
1954 | - view = args.get('view', ['view'])[0] |
1955 | - if view == 'view': |
1956 | - selector = "View | ", tags.a(href=here.add('view','edit'))[ "Edit" ] |
1957 | - editor = '' |
1958 | - else: |
1959 | - selector = tags.a(href=here.add('view','view'))["View"], " | Edit" |
1960 | - editor = context.onePattern('edit')() # get one copy of the edit pattern |
1961 | - viewer = context.onePattern('view')() # get one copy of the view pattern |
1962 | - return selector, viewer, editor |
1963 | - |
1964 | - def render_itemDetail(self, context, data): |
1965 | - theId, theSubject = doQuery('select * from foo where id = %s', self.original)[0] |
1966 | - return tags.h2["Object ", theId], tags.span["Subject: ", theSubject] |
1967 | - |
1968 | - docFactory = loaders.stan( |
1969 | - tags.html[ |
1970 | - tags.body[ |
1971 | - tags.p[tags.a(href=here.parent())["Up"]], |
1972 | - tags.div(render=render_viewSelector)[ |
1973 | - tags.p(pattern="edit")[webform.renderForms()], |
1974 | - tags.p(pattern="view")[render_itemDetail] |
1975 | - ] |
1976 | - ] |
1977 | - ] |
1978 | - ) |
1979 | - |
1980 | |
1981 | === modified file 'Nevow/examples/examples.tac' |
1982 | --- Nevow/examples/examples.tac 2009-07-06 12:22:09 +0000 |
1983 | +++ Nevow/examples/examples.tac 2011-07-27 23:02:31 +0000 |
1984 | @@ -22,22 +22,15 @@ |
1985 | import sys |
1986 | |
1987 | try: |
1988 | - from advanced_manualform import advanced_manualform |
1989 | - from customform import customform |
1990 | from disktemplates import disktemplates |
1991 | from disktemplates import disktemplates_stan |
1992 | from simple import simple |
1993 | from simple import simplehtml |
1994 | - from tree import tree |
1995 | - from formpost import formpost2 |
1996 | - from formpost import formpost |
1997 | from children import children |
1998 | from children import childrenhtml |
1999 | from table import tablehtml |
2000 | from irenderer import irenderer |
2001 | from irenderer import simple_irenderer |
2002 | - from formbuilder import formbuilder |
2003 | - from db import db |
2004 | from hello import hellohtml |
2005 | from hello import hellostan |
2006 | from canvas import canvas |
2007 | @@ -58,11 +51,10 @@ |
2008 | from cal import cal |
2009 | from tabbed import tabbed |
2010 | from progress import progress |
2011 | - from tests import testformless, testexamples |
2012 | + from tests import testexamples |
2013 | from nevow import livetest |
2014 | |
2015 | from athenademo import calculator |
2016 | - from athenademo import typeahead |
2017 | from athenademo import widgets |
2018 | from athenademo import benchmark |
2019 | except ImportError, e: |
2020 | @@ -127,21 +119,15 @@ |
2021 | child_sources.contentTypes = {} |
2022 | child_cssfile = static.File('index.css') |
2023 | children = dict( |
2024 | - customform=customform.Root(), |
2025 | disktemplates=disktemplates.Mine(), |
2026 | disktemplates_stan=disktemplates_stan.Mine(), |
2027 | simple=simple.Simple(), |
2028 | simplehtml=simplehtml.Simple(), |
2029 | - tree=tree.Tree('base', 'base'), |
2030 | - formpost2=formpost2.FormPage(formpost2.Implementation()), |
2031 | - formpost=formpost.FormPage(), |
2032 | children=children.RootPage(), |
2033 | childrenhtml=childrenhtml.RootPage(), |
2034 | tablehtml=tablehtml.Table(), |
2035 | irenderer=irenderer.Page(), |
2036 | simple_irenderer=simple_irenderer.Page(), |
2037 | - formbuilder=formbuilder.FormBuilder(), |
2038 | - db=db.DBBrowser(), |
2039 | hellohtml=hellohtml.Page(), |
2040 | hellostan=hellostan.Page(), |
2041 | canvas=canvas.createResource(), |
2042 | @@ -149,7 +135,6 @@ |
2043 | guarded=guarded.createResource(), |
2044 | guarded2=guarded2.createResource(), |
2045 | xul_nevow=xul_nevow.createResource(), |
2046 | - advanced_manualform=advanced_manualform.Page(), |
2047 | liveanimal=liveanimal.createResource(), |
2048 | http_auth=http_auth.AuthorizationRequired(), |
2049 | most_basic=most_basic.root, |
2050 | @@ -165,12 +150,8 @@ |
2051 | tests=testexamples.createResource(), |
2052 | livetests=testexamples.createLiveSuite(), |
2053 | testtests=livetest.createResource(), |
2054 | - testformless=testformless.NameWizard(), |
2055 | - formless_redirector=testformless.Redirector(), |
2056 | - formless_tests=testformless.formless_tests, |
2057 | fragments=fragments.Root(), |
2058 | macros=macros.Root(), |
2059 | - typeahead=typeahead.DataEntry(), |
2060 | ) |
2061 | |
2062 | def child_calculator(self, ctx): |
2063 | |
2064 | === removed directory 'Nevow/examples/formbuilder' |
2065 | === removed file 'Nevow/examples/formbuilder/__init__.py' |
2066 | === removed file 'Nevow/examples/formbuilder/formbuilder.py' |
2067 | --- Nevow/examples/formbuilder/formbuilder.py 2006-04-14 17:23:46 +0000 |
2068 | +++ Nevow/examples/formbuilder/formbuilder.py 1970-01-01 00:00:00 +0000 |
2069 | @@ -1,98 +0,0 @@ |
2070 | -## formbuilder |
2071 | - |
2072 | -from zope.interface import implements |
2073 | - |
2074 | -from nevow import rend |
2075 | -from nevow import loaders |
2076 | -from nevow import tags as T |
2077 | -from nevow import util |
2078 | - |
2079 | -from formless import annotate |
2080 | -from formless import webform |
2081 | -from formless import configurable |
2082 | - |
2083 | -from twisted.python import reflect |
2084 | - |
2085 | - |
2086 | -class BuilderCore(configurable.Configurable): |
2087 | - def __init__(self): |
2088 | - configurable.Configurable.__init__(self, None) |
2089 | - self.formElements = [] |
2090 | - |
2091 | - def getBindingNames(self, ctx): |
2092 | - return ['form'] |
2093 | - |
2094 | - def bind_form(self, ctx): |
2095 | - return annotate.MethodBinding( |
2096 | - 'action', |
2097 | - annotate.Method(arguments=self.formElements)) |
2098 | - |
2099 | - def action(self, **kw): |
2100 | - print "ACTION!", kw |
2101 | - |
2102 | - def addElement(self, name, type): |
2103 | - self.formElements.append( |
2104 | - annotate.Argument(name, type())) |
2105 | - |
2106 | - |
2107 | -allTypes = [annotate.String, annotate.Text, annotate.Integer, annotate.Real, annotate.Password] |
2108 | -typeChoice = annotate.Choice(choices=allTypes, valueToKey=reflect.qual, keyToValue=reflect.namedAny, stringify=lambda x: x.__name__) |
2109 | - |
2110 | - |
2111 | -class IFormBuilder(annotate.TypedInterface): |
2112 | - def addElement(name=annotate.String(required=True), type=typeChoice): |
2113 | - """Add Element |
2114 | - |
2115 | - Add an element to this form. |
2116 | - """ |
2117 | - pass |
2118 | - addElement = annotate.autocallable(addElement) |
2119 | - |
2120 | - def clearForm(): |
2121 | - """Clear Form |
2122 | - |
2123 | - Clear this form. |
2124 | - """ |
2125 | - clearForm = annotate.autocallable(clearForm) |
2126 | - |
2127 | - |
2128 | -class FormBuilder(rend.Page): |
2129 | - implements(IFormBuilder) |
2130 | - addSlash = True |
2131 | - |
2132 | - def __init__(self): |
2133 | - rend.Page.__init__(self) |
2134 | - self.clearForm() |
2135 | - |
2136 | - def configurable_formBuilder(self, ctx): |
2137 | - return configurable.TypedInterfaceConfigurable(self) |
2138 | - |
2139 | - def configurable_dynamicForm(self, ctx): |
2140 | - return self.builderCore |
2141 | - |
2142 | - def addElement(self, name, type): |
2143 | - self.builderCore.addElement(name, type) |
2144 | - |
2145 | - def clearForm(self): |
2146 | - self.builderCore = BuilderCore() |
2147 | - |
2148 | - docFactory = loaders.stan(T.html[ |
2149 | - T.head[ |
2150 | - T.title["Form builder!"]], |
2151 | - T.style(type="text/css")[ |
2152 | - open(util.resource_filename('formless', 'freeform-default.css')).read()], |
2153 | - T.body[ |
2154 | - T.h1["Welcome to form builder"], |
2155 | - webform.renderForms('formBuilder'), |
2156 | - T.h2["Here is your form:"], |
2157 | - webform.renderForms('dynamicForm')]]) |
2158 | - |
2159 | - |
2160 | -## Startup glue |
2161 | -from nevow import appserver |
2162 | -from twisted.application import service |
2163 | -from twisted.application import internet |
2164 | - |
2165 | -application = service.Application('formbuilder') |
2166 | -internet.TCPServer(8080, appserver.NevowSite(FormBuilder())).setServiceParent(application) |
2167 | - |
2168 | |
2169 | === removed directory 'Nevow/examples/formpost' |
2170 | === removed file 'Nevow/examples/formpost/__init__.py' |
2171 | === removed file 'Nevow/examples/formpost/formpost.py' |
2172 | --- Nevow/examples/formpost/formpost.py 2005-10-14 17:36:24 +0000 |
2173 | +++ Nevow/examples/formpost/formpost.py 1970-01-01 00:00:00 +0000 |
2174 | @@ -1,41 +0,0 @@ |
2175 | -# -*- python -*- |
2176 | - |
2177 | -from zope.interface import implements |
2178 | - |
2179 | -from nevow import loaders |
2180 | -from nevow import rend |
2181 | -from nevow import tags |
2182 | -from nevow import url |
2183 | - |
2184 | -from formless import annotate |
2185 | -from formless import webform |
2186 | - |
2187 | -class IMyForm(annotate.TypedInterface): |
2188 | - foo = annotate.Integer() |
2189 | - |
2190 | - |
2191 | -class FormPage(rend.Page): |
2192 | - implements(IMyForm) |
2193 | - |
2194 | - addSlash = True |
2195 | - |
2196 | - child_webform_css = webform.defaultCSS |
2197 | - |
2198 | - # We need this to implement IMyForm |
2199 | - foo = 5 |
2200 | - |
2201 | - docFactory = loaders.stan( |
2202 | - tags.html[ |
2203 | - tags.head[ |
2204 | - tags.link(rel='stylesheet', type='text/css', href=url.here.child('webform_css')), |
2205 | - ], |
2206 | - tags.body[ |
2207 | - "Hello! Here is a form:", |
2208 | - |
2209 | - # We want to render the "default" configurable. |
2210 | - # This is located in Page.configurable_() and is going to be |
2211 | - # 'self' (which, as you see above, implements IMyForm). |
2212 | - webform.renderForms(), |
2213 | - ], |
2214 | - ], |
2215 | - ) |
2216 | |
2217 | === removed file 'Nevow/examples/formpost/formpost2.py' |
2218 | --- Nevow/examples/formpost/formpost2.py 2006-03-22 18:03:26 +0000 |
2219 | +++ Nevow/examples/formpost/formpost2.py 1970-01-01 00:00:00 +0000 |
2220 | @@ -1,83 +0,0 @@ |
2221 | -# -*- python -*- |
2222 | - |
2223 | -from zope.interface import implements |
2224 | - |
2225 | -from nevow import loaders |
2226 | -from nevow import rend |
2227 | -from nevow import tags |
2228 | -from nevow import inevow |
2229 | -from nevow import url |
2230 | - |
2231 | -from formless import annotate |
2232 | -from formless import webform |
2233 | - |
2234 | -from twisted.internet import defer |
2235 | - |
2236 | - |
2237 | -#oldChoicesWay = annotate.Choice(choicesAttribute='theChoices') # Doing this gives you a DeprecationWarning now |
2238 | - |
2239 | -# If you still want to use an attribute or method of some other object, you should use a function as shown below, |
2240 | -# but look up IResource(ctx) or IConfigurable(ctx), whichever is more appropriate. |
2241 | -newChoicesWay = annotate.Choice(lambda c, d: range(30)) |
2242 | -deferChoicesWay = annotate.Choice(lambda c, d: defer.succeed(['abcd', 'efgh', 'ijkl'])) |
2243 | -radioChoices = annotate.Radio(["Old", "Tyme", "Radio"]) |
2244 | - |
2245 | -## An example of using custom valueToKey and keyToValue functions to serialize/deserialize items |
2246 | -values = {0: dict(name="Zero", stuff=1234), 1: dict(name="One", stuff=1234), 2: dict(name="Two", stuff=2345435)} |
2247 | -customValueToKey = annotate.Choice( |
2248 | - [0, 1, 2], # Perhaps these are primary keys in a database |
2249 | - stringify=lambda x: values[x]['name'], # Do a database lookup to render a nice label in the ui |
2250 | - valueToKey=str, # Convert the primary key to a value suitable for sending across the web |
2251 | - keyToValue=lambda x: values[int(x)]) # Do a database lookup to get the actual value to pass to the binding |
2252 | - |
2253 | - |
2254 | -class IMyForm(annotate.TypedInterface): |
2255 | - foo = annotate.Integer() |
2256 | - |
2257 | - def bar(baz=annotate.Integer(), |
2258 | - slam=newChoicesWay, ham=deferChoicesWay, radio=radioChoices, custom=customValueToKey): |
2259 | - pass |
2260 | - bar = annotate.autocallable(bar) |
2261 | - |
2262 | - |
2263 | -class Implementation(object): |
2264 | - implements(IMyForm) |
2265 | - |
2266 | - foo = 5 |
2267 | - |
2268 | - def bar(self, baz, slam, ham, radio, custom): |
2269 | - return "You called bar! %s %s %s %s %r" % (baz, slam, ham, radio, custom) |
2270 | - |
2271 | - theChoices = [1, 2, 3] |
2272 | - |
2273 | - |
2274 | -class FormPage(rend.Page): |
2275 | - |
2276 | - addSlash = True |
2277 | - |
2278 | - child_webform_css = webform.defaultCSS |
2279 | - |
2280 | - def render_hand(self, ctx, data): |
2281 | - hand = inevow.IHand(ctx, None) |
2282 | - if hand is not None: |
2283 | - return ctx.tag[hand] |
2284 | - return '' |
2285 | - |
2286 | - docFactory = loaders.stan( |
2287 | - tags.html[ |
2288 | - tags.head[ |
2289 | - tags.link(rel='stylesheet', type='text/css', href=url.here.child('webform_css')), |
2290 | - ], |
2291 | - tags.body[ |
2292 | - tags.h3(render=render_hand, style="color: red; font-size: xx-large"), |
2293 | - "Hello! Here is a form:", |
2294 | - |
2295 | - # We want to render forms defined by the Implementation instance. |
2296 | - # When we pass the Implementation instance to FormPage below, |
2297 | - # rend.Page sets it as the .original attribute. To tell webform to render |
2298 | - # forms described by this object, we use the configurable name "original". |
2299 | - webform.renderForms('original'), |
2300 | - ], |
2301 | - ], |
2302 | - ) |
2303 | - |
2304 | |
2305 | === removed directory 'Nevow/examples/image_uploader' |
2306 | === removed file 'Nevow/examples/image_uploader/images.py' |
2307 | --- Nevow/examples/image_uploader/images.py 2006-01-22 00:10:42 +0000 |
2308 | +++ Nevow/examples/image_uploader/images.py 1970-01-01 00:00:00 +0000 |
2309 | @@ -1,35 +0,0 @@ |
2310 | -from zope.interface import implements, Interface |
2311 | - |
2312 | -from axiom import store, item |
2313 | -from axiom.attributes import text, bytes |
2314 | - |
2315 | -class IImages(Interface): |
2316 | - pass |
2317 | - |
2318 | -class Image(item.Item): |
2319 | - title = text() |
2320 | - author = text() |
2321 | - image = bytes() |
2322 | - hash = text() |
2323 | - |
2324 | -class Application(item.Item, item.InstallableMixin): |
2325 | - implements(IImages) |
2326 | - |
2327 | - name = text() |
2328 | - |
2329 | - def installOn(self, other): |
2330 | - super(Application, self).installOn(other) |
2331 | - other.powerUp(self, IImages) |
2332 | - |
2333 | - def getImages(self, how_many=None): |
2334 | - return self.store.query(Image, limit=how_many, sort=Image.storeID.descending) |
2335 | - |
2336 | - def getOne(self, hash): |
2337 | - return self.store.findUnique(Image, Image.hash==hash) |
2338 | - |
2339 | -def initialize(): |
2340 | - s = store.Store('imagination.axiom') |
2341 | - images = IImages(s, None) |
2342 | - if not images: |
2343 | - Application(store=s, name=u'Imagination').installOn(s) |
2344 | - return s |
2345 | |
2346 | === removed file 'Nevow/examples/image_uploader/imagination.py' |
2347 | --- Nevow/examples/image_uploader/imagination.py 2006-03-17 15:00:39 +0000 |
2348 | +++ Nevow/examples/image_uploader/imagination.py 1970-01-01 00:00:00 +0000 |
2349 | @@ -1,85 +0,0 @@ |
2350 | -from zope.interface import implements |
2351 | - |
2352 | -from nevow import loaders, rend, tags as t, static, url |
2353 | -from formless import webform, annotate |
2354 | - |
2355 | -from images import Image, IImages |
2356 | - |
2357 | -import random |
2358 | -from string import ascii_letters as alpha # ohhh... |
2359 | - |
2360 | -alphaDigit = alpha + '0123456789' |
2361 | - |
2362 | -def label(length=None): |
2363 | - """ |
2364 | - Return one of 183,123,959,522,816 possible labels. |
2365 | - """ |
2366 | - |
2367 | - first = random.choice(alpha) |
2368 | - rest = [random.choice(alphaDigit) for i in xrange(length or 7)] |
2369 | - newLabel = first + ''.join(rest) |
2370 | - return newLabel |
2371 | - |
2372 | -class IInsert(annotate.TypedInterface): |
2373 | - def insert(ctx = annotate.Context(), |
2374 | - title = annotate.String(), |
2375 | - author = annotate.String(), |
2376 | - image = annotate.FileUpload(required=True, |
2377 | - requiredFailMessage="Must upload something") |
2378 | - ): |
2379 | - """ Insert a new image """ |
2380 | - insert = annotate.autocallable(insert, action="New Image") |
2381 | - |
2382 | -class TransactionalPage(rend.Page): |
2383 | - adaptsToStore = False |
2384 | - def __init__(self, store, *args, **kwargs): |
2385 | - super(TransactionalPage, self).__init__(*args, **kwargs) |
2386 | - self.store = store |
2387 | - |
2388 | - def locateChild(self, ctx, segments): |
2389 | - return self.store.transact(super(TransactionalPage, self).locateChild, ctx, segments) |
2390 | - |
2391 | - def renderHTTP(self, ctx): |
2392 | - return self.store.transact(super(TransactionalPage, self).renderHTTP, ctx) |
2393 | - |
2394 | - |
2395 | -class Root(TransactionalPage): |
2396 | - child_webform_css = webform.defaultCSS |
2397 | - implements(IInsert) |
2398 | - |
2399 | - docFactory = loaders.stan( |
2400 | - t.html[ |
2401 | - t.head[ |
2402 | - t.title['Imagination'], |
2403 | - t.link(rel='stylesheet', type='text/css', href=url.root.child('webform_css')) |
2404 | - ], |
2405 | - t.body[ |
2406 | - webform.renderForms(), |
2407 | - t.ul(render=t.directive("sequence"), |
2408 | - data=t.directive("images"))[ |
2409 | - t.li(pattern="item", render=t.directive("image")), |
2410 | - t.li(pattern="empty")["No images yet"] |
2411 | - ] |
2412 | - ] |
2413 | - ] |
2414 | - ) |
2415 | - |
2416 | - def data_images(self, ctx, data): |
2417 | - return IImages(self.store).getImages(15) |
2418 | - |
2419 | - def render_image(self, ctx, data): |
2420 | - return t.a(href=url.root.child('fs').child(data.hash))[data.title] |
2421 | - |
2422 | - def insert(self, ctx, title, author, image): |
2423 | - img = Image(store=self.store, |
2424 | - image=image.value, |
2425 | - title=title.decode('utf-8'), |
2426 | - author=author.decode('utf-8'), |
2427 | - hash=label().decode('utf-8')) |
2428 | - |
2429 | - def locateChild(self, ctx, segments): |
2430 | - if segments[0] == 'fs': |
2431 | - data = IImages(self.store).getOne(segments[1].decode('utf-8')) |
2432 | - return static.Data(data.image, 'image/jpeg'), () |
2433 | - return super(Root, self).locateChild(ctx, segments) |
2434 | - |
2435 | |
2436 | === removed file 'Nevow/examples/image_uploader/imagination.tac' |
2437 | --- Nevow/examples/image_uploader/imagination.tac 2006-01-22 00:10:42 +0000 |
2438 | +++ Nevow/examples/image_uploader/imagination.tac 1970-01-01 00:00:00 +0000 |
2439 | @@ -1,9 +0,0 @@ |
2440 | -from twisted.application import service, strports |
2441 | -from nevow import appserver |
2442 | - |
2443 | -import imagination, images |
2444 | - |
2445 | -application = service.Application('image_uploader') |
2446 | -db = images.initialize() |
2447 | -site = appserver.NevowSite(resource = imagination.Root(db)) |
2448 | -strports.service("8080", site).setServiceParent(application) |
2449 | |
2450 | === modified file 'Nevow/examples/index.html' |
2451 | --- Nevow/examples/index.html 2009-07-06 12:22:09 +0000 |
2452 | +++ Nevow/examples/index.html 2011-07-27 23:02:31 +0000 |
2453 | @@ -69,17 +69,11 @@ |
2454 | <ol> |
2455 | <li><a href="/tests/">Run basic tests</a></li> |
2456 | |
2457 | - <li><a href="/formless_tests/">Run formless tests</a></li> |
2458 | - |
2459 | <li><a href="/livetests/">Run livepage example tests</a></li> |
2460 | |
2461 | <li><a href="/testtests/tests/">Test test harness</a></li> |
2462 | </ol> |
2463 | |
2464 | - <p>Athena also has <a href="/athenatest/">some tests</a>, although |
2465 | - there is not yet a fancy test runner like the one demonstrated |
2466 | - above.</p> |
2467 | - |
2468 | <h1 id="examples">Examples Listing</h1> |
2469 | |
2470 | <ol> |
2471 | @@ -427,122 +421,6 @@ |
2472 | </li> |
2473 | |
2474 | <li> |
2475 | - <span>Advanced manual form example</span> |
2476 | - |
2477 | - <div class="source"> |
2478 | - <table border="0" cellpadding="0" cellspacing="0" width= |
2479 | - "100%"> |
2480 | - <tbody> |
2481 | - <tr> |
2482 | - <td>Stan Source</td> |
2483 | - |
2484 | - <td width="100%"><a href= |
2485 | - "sources/advanced_manualform/advanced_manualform.py"> |
2486 | - advanced_manualform.py</a></td> |
2487 | - </tr> |
2488 | - </tbody> |
2489 | - </table>Live example: <a href= |
2490 | - "advanced_manualform/">form</a> |
2491 | - </div> |
2492 | - </li> |
2493 | - |
2494 | - <li> |
2495 | - <span>Formless example</span> |
2496 | - |
2497 | - <div class="source"> |
2498 | - <table border="0" cellpadding="0" cellspacing="0" width= |
2499 | - "100%"> |
2500 | - <tbody> |
2501 | - <tr> |
2502 | - <td>Stan Source</td> |
2503 | - |
2504 | - <td width="100%"><a href= |
2505 | - "sources/formpost/formpost.py">formpost.py</a></td> |
2506 | - </tr> |
2507 | - </tbody> |
2508 | - </table>Live example: <a href="formpost/">formpost</a> |
2509 | - </div> |
2510 | - </li> |
2511 | - |
2512 | - <li> |
2513 | - <span>Another formless example, but a little bit more |
2514 | - complex</span> |
2515 | - |
2516 | - <div class="source"> |
2517 | - <table border="0" cellpadding="0" cellspacing="0" width= |
2518 | - "100%"> |
2519 | - <tbody> |
2520 | - <tr> |
2521 | - <td>Stan Source</td> |
2522 | - |
2523 | - <td width="100%"><a href= |
2524 | - "sources/formpost/formpost2.py">formpost2.py</a></td> |
2525 | - </tr> |
2526 | - </tbody> |
2527 | - </table>Live example: <a href="formpost2/">formpost2</a> |
2528 | - </div> |
2529 | - </li> |
2530 | - |
2531 | - <li> |
2532 | - <span><b>[0.5]</b>Using formless to create multi-step |
2533 | - wizards by returning Page instances from |
2534 | - autocallables</span> |
2535 | - |
2536 | - <div class="source"> |
2537 | - <table border="0" cellpadding="0" cellspacing="0" width= |
2538 | - "100%"> |
2539 | - <tbody> |
2540 | - <tr> |
2541 | - <td>Stan Source</td> |
2542 | - |
2543 | - <td width="100%"><a href= |
2544 | - "sources/tests/testformless.py">tests/testformless.py</a></td> |
2545 | - </tr> |
2546 | - </tbody> |
2547 | - </table>Live example: <a href= |
2548 | - "testformless">testformless</a> |
2549 | - </div> |
2550 | - </li> |
2551 | - |
2552 | - <li> |
2553 | - <span><b>[0.5]</b>Using formless, return a URL instance |
2554 | - from an autocallable to redirect to it</span> |
2555 | - |
2556 | - <div class="source"> |
2557 | - <table border="0" cellpadding="0" cellspacing="0" width= |
2558 | - "100%"> |
2559 | - <tbody> |
2560 | - <tr> |
2561 | - <td>Stan Source</td> |
2562 | - |
2563 | - <td width="100%"><a href= |
2564 | - "sources/tests/testformless.py">tests/testformless.py</a></td> |
2565 | - </tr> |
2566 | - </tbody> |
2567 | - </table>Live example: <a href= |
2568 | - "formless_redirector">formless_redirector</a> |
2569 | - </div> |
2570 | - </li> |
2571 | - |
2572 | - <li> |
2573 | - <span>Example of interacting with a database</span> |
2574 | - |
2575 | - <div class="source"> |
2576 | - <table border="0" cellpadding="0" cellspacing="0" width= |
2577 | - "100%"> |
2578 | - <tbody> |
2579 | - <tr> |
2580 | - <td>Stan Source:</td> |
2581 | - |
2582 | - <td width="100%"><a href= |
2583 | - "sources/db/db.py">db.py</a></td> |
2584 | - </tr> |
2585 | - </tbody> |
2586 | - </table>Live examples: <a href="db/">db</a> |
2587 | - </div> |
2588 | - </li> |
2589 | - |
2590 | - <li> |
2591 | <span>An example of using HTTP Basic Auth for simple |
2592 | authentication</span> |
2593 | |
2594 | @@ -637,25 +515,6 @@ |
2595 | </li> |
2596 | |
2597 | <li> |
2598 | - <span>Dynamically build your forms</span> |
2599 | - |
2600 | - <div class="source"> |
2601 | - <table border="0" cellpadding="0" cellspacing="0" width= |
2602 | - "100%"> |
2603 | - <tbody> |
2604 | - <tr> |
2605 | - <td>Stan Source</td> |
2606 | - |
2607 | - <td width="100%"><a href= |
2608 | - "sources/formbuilder/formbuilder.py">formbuilder.py</a></td> |
2609 | - </tr> |
2610 | - </tbody> |
2611 | - </table>Live example: <a href= |
2612 | - "formbuilder/">formbuilder</a> |
2613 | - </div> |
2614 | - </li> |
2615 | - |
2616 | - <li> |
2617 | <span>Adapting an object to the IRenderer interface in |
2618 | order to make it render itself</span> |
2619 | |
2620 | @@ -695,24 +554,6 @@ |
2621 | </li> |
2622 | |
2623 | <li> |
2624 | - <span>Handling and building a Tree structure dynamically on |
2625 | - yor site</span> |
2626 | - |
2627 | - <div class="source"> |
2628 | - <table border="0" cellpadding="0" cellspacing="0"> |
2629 | - <tbody> |
2630 | - <tr> |
2631 | - <td>Stan Source</td> |
2632 | - |
2633 | - <td width="100%"><a href= |
2634 | - "sources/tree/tree.py">tree.py</a></td> |
2635 | - </tr> |
2636 | - </tbody> |
2637 | - </table>Live example: <a href="tree/">tree</a> |
2638 | - </div> |
2639 | - </li> |
2640 | - |
2641 | - <li> |
2642 | <span>Simple example of text localisation</span> |
2643 | |
2644 | <div class="source"> |
2645 | @@ -961,22 +802,6 @@ |
2646 | </li> |
2647 | |
2648 | <li> |
2649 | - <span>Pastebin example with nevow</span> |
2650 | - |
2651 | - <div class="source"> |
2652 | - Source: <a href="sources/pastebin">pastebin</a> |
2653 | - </div> |
2654 | - </li> |
2655 | - |
2656 | - <li> |
2657 | - <span>Blog engine</span> |
2658 | - |
2659 | - <div class="source"> |
2660 | - Source: <a href="sources/blogengine">blogengine</a> |
2661 | - </div> |
2662 | - </li> |
2663 | - |
2664 | - <li> |
2665 | <span>Link storage webservice (uses Twisted's |
2666 | XML-RPC)</span> |
2667 | |
2668 | @@ -984,23 +809,6 @@ |
2669 | Source: <a href="sources/postit">postit</a> |
2670 | </div> |
2671 | </li> |
2672 | - |
2673 | - <li> |
2674 | - <span>Todo list with rails like file structure (requires |
2675 | - pgasync 1.3b and postgres)</span> |
2676 | - |
2677 | - <div class="source"> |
2678 | - Source: <a href="sources/todo">todo</a> |
2679 | - </div> |
2680 | - </li> |
2681 | - |
2682 | - <li> |
2683 | - <span>Image uploader that uses axiom</span> |
2684 | - |
2685 | - <div class="source"> |
2686 | - Source: <a href="sources/image_uploader">imagination</a> |
2687 | - </div> |
2688 | - </li> |
2689 | </ul> |
2690 | </div> |
2691 | </body> |
2692 | |
2693 | === removed directory 'Nevow/examples/pastebin' |
2694 | === removed file 'Nevow/examples/pastebin/TODO' |
2695 | --- Nevow/examples/pastebin/TODO 2005-10-14 17:36:24 +0000 |
2696 | +++ Nevow/examples/pastebin/TODO 1970-01-01 00:00:00 +0000 |
2697 | @@ -1,11 +0,0 @@ |
2698 | -Syntax highlighting: Python, HTML, diff etc |
2699 | -Coloured diff view |
2700 | -Cookie to save author |
2701 | -UI - move menu etc to right |
2702 | -View | Edit when viewing latest revision |
2703 | -Line numbers |
2704 | -Wrap the syntax highlighted bit. |
2705 | - |
2706 | -Syntax highligh options: |
2707 | -t.p.htmlizer, enscript, webcpp, SilverCity |
2708 | -copy source code highlight code from viewcvs |
2709 | |
2710 | === removed directory 'Nevow/examples/pastebin/data' |
2711 | === removed directory 'Nevow/examples/pastebin/pastebin' |
2712 | === removed file 'Nevow/examples/pastebin/pastebin.tac' |
2713 | --- Nevow/examples/pastebin/pastebin.tac 2005-10-14 17:36:24 +0000 |
2714 | +++ Nevow/examples/pastebin/pastebin.tac 1970-01-01 00:00:00 +0000 |
2715 | @@ -1,25 +0,0 @@ |
2716 | -from twisted.application import strports |
2717 | -from twisted.application import service |
2718 | - |
2719 | -from twisted.web import static |
2720 | - |
2721 | -from nevow import appserver |
2722 | -from nevow import vhost |
2723 | - |
2724 | -from pastebin import interfaces |
2725 | -from pastebin.service import FSPasteBinService |
2726 | -from pastebin.web import pages |
2727 | - |
2728 | - |
2729 | -application = service.Application('pastebin') |
2730 | - |
2731 | -pastebin = FSPasteBinService('data') |
2732 | -pastebin.setServiceParent(application) |
2733 | - |
2734 | -appResource = pages.RootPage(pastebin) |
2735 | -appResource.putChild('robots.txt', static.File('static/robots.txt')) |
2736 | -vResource = vhost.VHostMonsterResource() |
2737 | -appResource.putChild('vhost', vResource) |
2738 | - |
2739 | - |
2740 | -strports.service("8080", appserver.NevowSite(appResource)).setServiceParent(application) |
2741 | |
2742 | === removed file 'Nevow/examples/pastebin/pastebin/__init__.py' |
2743 | === removed file 'Nevow/examples/pastebin/pastebin/interfaces.py' |
2744 | --- Nevow/examples/pastebin/pastebin/interfaces.py 2006-03-08 14:28:41 +0000 |
2745 | +++ Nevow/examples/pastebin/pastebin/interfaces.py 1970-01-01 00:00:00 +0000 |
2746 | @@ -1,18 +0,0 @@ |
2747 | -from zope.interface import Interface |
2748 | - |
2749 | -class IPasteBin(Interface): |
2750 | - |
2751 | - def getListOfPastings(limit=None): |
2752 | - """ |
2753 | - (oid, author, time) tuples |
2754 | - """ |
2755 | - pass |
2756 | - |
2757 | - def getPasting(oid): |
2758 | - pass |
2759 | - |
2760 | - def addPasting(author, text): |
2761 | - pass |
2762 | - |
2763 | - def updatePasting(oid, author, text): |
2764 | - pass |
2765 | |
2766 | === removed file 'Nevow/examples/pastebin/pastebin/pasting.py' |
2767 | --- Nevow/examples/pastebin/pastebin/pasting.py 2006-03-08 14:28:41 +0000 |
2768 | +++ Nevow/examples/pastebin/pastebin/pasting.py 1970-01-01 00:00:00 +0000 |
2769 | @@ -1,25 +0,0 @@ |
2770 | -from zope.interface import Interface |
2771 | - |
2772 | - |
2773 | -class IPasting(Interface): |
2774 | - |
2775 | - def getLatestVersion(): |
2776 | - """Return the latest version""" |
2777 | - |
2778 | - def getVersion(version): |
2779 | - """Get a specific version""" |
2780 | - |
2781 | - def getHistory(): |
2782 | - """Get the history of the pasting as a list of (version, author, time) tuples.""" |
2783 | - |
2784 | - |
2785 | -class IVersion(Interface): |
2786 | - |
2787 | - def getAuthor(): |
2788 | - pass |
2789 | - |
2790 | - def getText(): |
2791 | - pass |
2792 | - |
2793 | - def getTime(): |
2794 | - pass |
2795 | |
2796 | === removed file 'Nevow/examples/pastebin/pastebin/service.py' |
2797 | --- Nevow/examples/pastebin/pastebin/service.py 2005-10-14 17:36:24 +0000 |
2798 | +++ Nevow/examples/pastebin/pastebin/service.py 1970-01-01 00:00:00 +0000 |
2799 | @@ -1,120 +0,0 @@ |
2800 | -import cPickle as pickle |
2801 | -import os.path |
2802 | -import time |
2803 | -from zope.interface import implements |
2804 | - |
2805 | -from twisted.application import service |
2806 | -from twisted.python import log |
2807 | - |
2808 | -from pastebin import interfaces |
2809 | -from pastebin import pasting |
2810 | - |
2811 | - |
2812 | -class Record(object): |
2813 | - |
2814 | - def __init__(self, oid, author, time): |
2815 | - self.oid = oid |
2816 | - self.author = author |
2817 | - self.time = time |
2818 | - self.version = 0 |
2819 | - |
2820 | - |
2821 | -class FSPasteBinService(service.Service): |
2822 | - |
2823 | - implements(interfaces.IPasteBin) |
2824 | - |
2825 | - def __init__(self, storageDir): |
2826 | - self._dir = storageDir |
2827 | - |
2828 | - def getListOfPastings(self, limit=None): |
2829 | - if limit is None: |
2830 | - limited = self._index |
2831 | - else: |
2832 | - limited = self._index[0:limit] |
2833 | - return [(r.oid, r.author, r.time) for r in limited] |
2834 | - |
2835 | - def _makeFilename(self, name): |
2836 | - return os.path.join(self._dir, name) |
2837 | - |
2838 | - def _loadPastingData(self, oid): |
2839 | - f = file(self._makeFilename(str(oid)), 'rb') |
2840 | - return pickle.load(f) |
2841 | - |
2842 | - def _savePastingData(self, oid, data): |
2843 | - f = file(self._makeFilename(str(oid)), 'wb') |
2844 | - pickle.dump(data, f, pickle.HIGHEST_PROTOCOL) |
2845 | - |
2846 | - def getPasting(self, oid): |
2847 | - data = self._loadPastingData(oid) |
2848 | - return Pasting(data) |
2849 | - |
2850 | - def addPasting(self, author, text): |
2851 | - oid = self._nextOid |
2852 | - now = time.gmtime() |
2853 | - data = [{'author':author, 'time':now, 'text':text}] |
2854 | - self._savePastingData(oid, data) |
2855 | - self._index.insert(0, Record(oid, author, now)) |
2856 | - self._nextOid += 1 |
2857 | - return oid |
2858 | - |
2859 | - def updatePasting(self, oid, author, text): |
2860 | - now = time.gmtime() |
2861 | - data = self._loadPastingData(oid) |
2862 | - data.append({'author':author, 'time':now, 'text':text}) |
2863 | - self._savePastingData(oid, data) |
2864 | - for i, r in enumerate(self._index): |
2865 | - if r.oid == oid: |
2866 | - r.time = now |
2867 | - self._index.insert(0,self._index.pop(i)) |
2868 | - |
2869 | - def startService(self): |
2870 | - log.msg('Loading index') |
2871 | - try: |
2872 | - f = file(self._makeFilename('index'), 'rb') |
2873 | - d = pickle.load(f) |
2874 | - self._index = d['index'] |
2875 | - self._nextOid = d['nextOid'] |
2876 | - except IOError: |
2877 | - self._index = [] |
2878 | - self._nextOid = 1 |
2879 | - |
2880 | - def stopService(self): |
2881 | - log.msg('Storing index') |
2882 | - d = {'index':self._index, 'nextOid':self._nextOid} |
2883 | - f = file(self._makeFilename('index'), 'wb') |
2884 | - pickle.dump(d, f, pickle.HIGHEST_PROTOCOL) |
2885 | - |
2886 | -class Pasting(object): |
2887 | - |
2888 | - implements(pasting.IPasting) |
2889 | - |
2890 | - def __init__(self, data): |
2891 | - self._data = data |
2892 | - |
2893 | - def getLatestVersion(self): |
2894 | - return self.getVersion(-1) |
2895 | - |
2896 | - def getVersion(self, version): |
2897 | - return Version(self._data[version]) |
2898 | - |
2899 | - def getHistory(self): |
2900 | - history = [(i,d['author'],d['time']) for i,d in enumerate(self._data)] |
2901 | - history.reverse() |
2902 | - return history |
2903 | - |
2904 | - |
2905 | -class Version: |
2906 | - |
2907 | - implements(pasting.IVersion) |
2908 | - |
2909 | - def __init__(self, data): |
2910 | - self._data = data |
2911 | - |
2912 | - def getAuthor(self): |
2913 | - return self._data['author'] |
2914 | - |
2915 | - def getText(self): |
2916 | - return self._data['text'] |
2917 | - |
2918 | - def getTime(self): |
2919 | - return self._data['time'] |
2920 | |
2921 | === removed directory 'Nevow/examples/pastebin/pastebin/web' |
2922 | === removed file 'Nevow/examples/pastebin/pastebin/web/__init__.py' |
2923 | === removed file 'Nevow/examples/pastebin/pastebin/web/pages.py' |
2924 | --- Nevow/examples/pastebin/pastebin/web/pages.py 2006-04-14 17:23:46 +0000 |
2925 | +++ Nevow/examples/pastebin/pastebin/web/pages.py 1970-01-01 00:00:00 +0000 |
2926 | @@ -1,212 +0,0 @@ |
2927 | -from cStringIO import StringIO |
2928 | -import time |
2929 | -from zope.interface import implements |
2930 | - |
2931 | -from twisted.python import htmlizer |
2932 | -from twisted.web import static |
2933 | - |
2934 | -from nevow import loaders |
2935 | -from nevow import rend |
2936 | -from nevow import tags |
2937 | -from nevow import url |
2938 | - |
2939 | -from formless import annotate |
2940 | -from formless import iformless |
2941 | -from formless import webform |
2942 | - |
2943 | -ANONYMOUS = 'anonymous' |
2944 | - |
2945 | - |
2946 | -## |
2947 | -# Text colourisers (aka syntax highlighting) |
2948 | -## |
2949 | - |
2950 | -def _python_colouriser(text): |
2951 | - out = StringIO() |
2952 | - try: |
2953 | - htmlizer.filter(StringIO(text), out) |
2954 | - except AttributeError: |
2955 | - out = StringIO("""Starting after Nevow 0.4.1 Twisted |
2956 | -2.0 is a required dependency. Please install it""") |
2957 | - return out.getvalue() |
2958 | - |
2959 | -_colourisers = { |
2960 | - 'python': _python_colouriser |
2961 | - } |
2962 | - |
2963 | - |
2964 | -## |
2965 | -# Formless |
2966 | -## |
2967 | - |
2968 | -class IAddPasting(annotate.TypedInterface): |
2969 | - def addPasting( |
2970 | - request=annotate.Request(), |
2971 | - author=annotate.String(strip=True), |
2972 | - text=annotate.Text(strip=True, required=True)): |
2973 | - pass |
2974 | - addPasting = annotate.autocallable(addPasting) |
2975 | - |
2976 | - |
2977 | -class IEditPasting(annotate.TypedInterface): |
2978 | - def editPasting( |
2979 | - request=annotate.Request(), |
2980 | - postedBy=annotate.String(immutable=1), |
2981 | - author=annotate.String(strip=True), |
2982 | - text=annotate.Text(strip=True, required=True)): |
2983 | - pass |
2984 | - editPasting = annotate.autocallable(editPasting) |
2985 | - |
2986 | - |
2987 | -## |
2988 | -# "Standard" renderers |
2989 | -## |
2990 | - |
2991 | -def render_time(theTime): |
2992 | - def _(context, data): |
2993 | - return time.strftime('%Y-%m-%d %H:%M:%S %Z', theTime) |
2994 | - return _ |
2995 | - |
2996 | -def render_pastingText(text): |
2997 | - def _(context, data): |
2998 | - colouriser = _colourisers.get('python') |
2999 | - if colouriser: |
3000 | - return tags.xml(colouriser(text)) |
3001 | - return tags.pre[tags.xml(text)] |
3002 | - return _ |
3003 | - |
3004 | -def render_pasting(version): |
3005 | - def _(context, data): |
3006 | - context.fillSlots('author', version.getAuthor() or ANONYMOUS) |
3007 | - time = context.fillSlots('time', render_time(version.getTime())) |
3008 | - text = context.fillSlots('text', render_pastingText(version.getText())) |
3009 | - return context.tag |
3010 | - return _ |
3011 | - |
3012 | - |
3013 | -class BasePage(rend.Page): |
3014 | - |
3015 | - docFactory = loaders.htmlfile(templateDir='templates', template='site.html') |
3016 | - |
3017 | - child_css = static.File('static/css') |
3018 | - child_images = static.File('static/images') |
3019 | - |
3020 | - def data_pastings(self, context, data): |
3021 | - return self.pastebin.getListOfPastings(20) |
3022 | - |
3023 | - def render_pasting(self, context, data): |
3024 | - oid, author, time = data |
3025 | - context.tag.fillSlots('url', url.root.child(str(oid))) |
3026 | - context.tag.fillSlots('id', oid) |
3027 | - context.tag.fillSlots('author', author or ANONYMOUS) |
3028 | - return context.tag |
3029 | - |
3030 | - def render_content(self, context, data): |
3031 | - tag = context.tag.clear() |
3032 | - tag[loaders.htmlfile(templateDir='templates', template=self.contentTemplateFile)] |
3033 | - return tag |
3034 | - |
3035 | - |
3036 | -class RootPage(BasePage): |
3037 | - implements(IAddPasting) |
3038 | - |
3039 | - addSlash = True |
3040 | - |
3041 | - def __init__(self, pastebin): |
3042 | - BasePage.__init__(self) |
3043 | - self.pastebin = pastebin |
3044 | - |
3045 | - def locateChild(self, context, segments): |
3046 | - try: |
3047 | - return Pasting(self.pastebin, int(segments[0])), segments[1:] |
3048 | - except ValueError: |
3049 | - pass |
3050 | - return BasePage.locateChild(self, context, segments) |
3051 | - |
3052 | - def render_content(self, context, data): |
3053 | - tag = context.tag.clear() |
3054 | - return tag[webform.renderForms()] |
3055 | - |
3056 | - def addPasting(self, request, author, text): |
3057 | - oid = self.pastebin.addPasting(author, text) |
3058 | - request.setComponent(iformless.IRedirectAfterPost, '/'+str(oid)) |
3059 | - |
3060 | - |
3061 | -class Pasting(BasePage): |
3062 | - |
3063 | - implements(IEditPasting) |
3064 | - contentTemplateFile = 'pasting.html' |
3065 | - |
3066 | - def __init__(self, pastebin, pastingOid, version=-1): |
3067 | - BasePage.__init__(self) |
3068 | - self.pastebin = pastebin |
3069 | - self.pastingOid = pastingOid |
3070 | - self.version = version |
3071 | - self.pasting = self.pastebin.getPasting(self.pastingOid) |
3072 | - |
3073 | - def locateChild(self, context, segments): |
3074 | - try: |
3075 | - return Pasting(self.pastebin, self.pastingOid, int(segments[0])), segments[1:] |
3076 | - except: |
3077 | - pass |
3078 | - return BasePage.locateChild(self, context, segments) |
3079 | - |
3080 | - def data_history(self, context, data): |
3081 | - return self.pasting.getHistory() |
3082 | - |
3083 | - def render_aPasting(self, context, data): |
3084 | - return render_pasting(self.pasting.getVersion(self.version)) |
3085 | - |
3086 | - def render_form(self, context, data): |
3087 | - if self.version != -1: |
3088 | - return '' |
3089 | - version = self.pasting.getVersion(self.version) |
3090 | - formDefaults = context.locate(iformless.IFormDefaults) |
3091 | - formDefaults.setDefault('editPasting.text', version.getText()) |
3092 | - formDefaults.setDefault('editPasting.postedBy', version.getAuthor()) |
3093 | - return webform.renderForms() |
3094 | - |
3095 | - def render_version(self, context, data): |
3096 | - version, author, theTime = data |
3097 | - if self.version == -1: |
3098 | - u = url.here.child |
3099 | - else: |
3100 | - u = url.here.sibling |
3101 | - context.tag.fillSlots('url', u(version)) |
3102 | - context.tag.fillSlots('time', render_time(theTime)) |
3103 | - context.tag.fillSlots('author', author or ANONYMOUS) |
3104 | -## context.fillSlots('link', a(href=[u(version)])[ |
3105 | -## render_time(theTime), ' (',author or ANONYMOUS,')' |
3106 | -## ]) |
3107 | - return context.tag |
3108 | - |
3109 | - def editPasting(self, request, postedBy, author, text): |
3110 | - self.pastebin.updatePasting(self.pastingOid, author, text) |
3111 | - request.setComponent(iformless.IRedirectAfterPost, '/%s'%self.pastingOid) |
3112 | - |
3113 | - |
3114 | -class Version(BasePage): |
3115 | - |
3116 | - contentTemplateFile = "pasting.html" |
3117 | - |
3118 | - child_ = rend.FourOhFour() |
3119 | - |
3120 | - def __init__(self, pastebin, pasting, version): |
3121 | - BasePage.__init__(self) |
3122 | - self.pastebin = pastebin |
3123 | - self.pasting = pasting |
3124 | - self.version = version |
3125 | - |
3126 | - def data_history(self, context, data): |
3127 | - return self.pasting.getHistory() |
3128 | - |
3129 | - def render_aPasting(self, context, data): |
3130 | - return render_pasting(self.pasting.getVersion(self.version)) |
3131 | - |
3132 | - def render_version(self, context, data): |
3133 | - version, author, theTime = data |
3134 | - context.fillSlots('link', tags.a(href=[url.here.sibling(str(version))])[ |
3135 | - render_time(theTime), ' (',author,')' |
3136 | - ]) |
3137 | - return context.tag |
3138 | - |
3139 | |
3140 | === removed directory 'Nevow/examples/pastebin/static' |
3141 | === removed directory 'Nevow/examples/pastebin/static/css' |
3142 | === removed file 'Nevow/examples/pastebin/static/css/default.css' |
3143 | --- Nevow/examples/pastebin/static/css/default.css 2005-10-14 17:36:24 +0000 |
3144 | +++ Nevow/examples/pastebin/static/css/default.css 1970-01-01 00:00:00 +0000 |
3145 | @@ -1,100 +0,0 @@ |
3146 | -body |
3147 | -{ |
3148 | - margin: 0; |
3149 | - padding: 1em 1em; |
3150 | - color: #330033; |
3151 | - font-size: 10pt; |
3152 | -} |
3153 | - |
3154 | -a |
3155 | -{ |
3156 | - color: inherit; |
3157 | -} |
3158 | - |
3159 | -a:visited |
3160 | -{ |
3161 | - color: #996699; |
3162 | -} |
3163 | - |
3164 | -#header |
3165 | -{ |
3166 | - border-bottom: 1px solid #cccc99; |
3167 | -} |
3168 | - |
3169 | -#header h1 |
3170 | -{ |
3171 | - padding: 0; |
3172 | - margin: 0; |
3173 | - color: #cccc66; |
3174 | -} |
3175 | - |
3176 | -#footer |
3177 | -{ |
3178 | - padding: 0.1em 0.5em; |
3179 | - margin-top: 1em; |
3180 | - clear: both; |
3181 | - border-top: 1px solid #cccc99; |
3182 | - font-size: 77%; |
3183 | - color: #666699; |
3184 | -} |
3185 | - |
3186 | -#content-container |
3187 | -{ |
3188 | - margin: 2em 0.5em; |
3189 | -} |
3190 | - |
3191 | -#nav |
3192 | -{ |
3193 | - position: relative; |
3194 | - float: left; |
3195 | - width: 10em; |
3196 | -} |
3197 | - |
3198 | -#menu, #pastings |
3199 | -{ |
3200 | - list-style: url(/images/pasting.gif); |
3201 | - padding: 0 0 0 18px; |
3202 | - margin-top: 0; |
3203 | -} |
3204 | - |
3205 | -#content |
3206 | -{ |
3207 | - margin-left: 10em; |
3208 | -} |
3209 | - |
3210 | -div.pastingText |
3211 | -{ |
3212 | - padding: 0.5em; |
3213 | - background-color: #fafafa; |
3214 | - color: #333; |
3215 | - border: 1px solid #ccc; |
3216 | - overflow: auto; |
3217 | -} |
3218 | - |
3219 | -div.pastingText pre |
3220 | -{ |
3221 | - margin: 0; |
3222 | -} |
3223 | - |
3224 | -.revision-history |
3225 | -{ |
3226 | - font-size: 86%; |
3227 | -} |
3228 | - |
3229 | -.view-menu |
3230 | -{ |
3231 | - list-style: none; |
3232 | - margin: 1em 0; |
3233 | - padding: 0; |
3234 | -} |
3235 | - |
3236 | -.view-menu li |
3237 | -{ |
3238 | - display: inline; |
3239 | - margin-right: 1em; |
3240 | -} |
3241 | - |
3242 | -.view-menu li a |
3243 | -{ |
3244 | - color: inherit; |
3245 | -} |
3246 | |
3247 | === removed file 'Nevow/examples/pastebin/static/css/freeform.css' |
3248 | --- Nevow/examples/pastebin/static/css/freeform.css 2005-10-14 17:36:24 +0000 |
3249 | +++ Nevow/examples/pastebin/static/css/freeform.css 1970-01-01 00:00:00 +0000 |
3250 | @@ -1,27 +0,0 @@ |
3251 | - |
3252 | -.freeform-typed { clear: both; } |
3253 | -.freeform-property-binding { clear: both; border: 1px solid blue; padding: 0.5em; width: auto } |
3254 | -.freeform-method-binding { clear: both; border: 1px solid black; padding: 0.5em; width: auto } |
3255 | -.freeform-argument-binding { clear: both; border: 1px solid blue; padding: 0.5em; width: auto } |
3256 | -.freeform-binding-content { border-top: 1px dashed #bdedfe; margin-top: 0.5em; padding-top: 0.5em } |
3257 | -.freeform-label { float: left; width: 200px; } |
3258 | -.freeform-input { float: left; width: 200px; } |
3259 | -.freeform-error { color: red; } |
3260 | -.freeform-description { clear: both; border-bottom: 1px dashed #bdedfe; margin-bottom: 0.5em; padding-bottom: 0.5em } |
3261 | -.freeform-list-item { clear: both; width: auto } |
3262 | -.freeform-form-label { color: #666666 } |
3263 | - |
3264 | -.freeform-textarea { width: 5in; height: 3in } |
3265 | - |
3266 | -.freeform-success { padding: 0.5em; border: 1px dashed green; } |
3267 | -.freeform-failure { padding: 0.5em; color: red; border: 1px dashed red; } |
3268 | - |
3269 | -.freeform-list { border: 1px dashed #cdcdcd; } |
3270 | -.freeform-dictionary { border: 1px dashed #dedede; } |
3271 | -.freeform-action-group { margin: 0px } |
3272 | -.freeform-action { color: green } |
3273 | -.freeform-action-selection { background-color: red; height: 1em; width: 1em; } |
3274 | - |
3275 | -.freeform-group-binding { border: 1px dashed #efabab } |
3276 | -.freeform-grouped-property-binding {} |
3277 | -.freeform-grouped-method-binding {} |
3278 | |
3279 | === removed file 'Nevow/examples/pastebin/static/css/python.css' |
3280 | --- Nevow/examples/pastebin/static/css/python.css 2005-10-14 17:36:24 +0000 |
3281 | +++ Nevow/examples/pastebin/static/css/python.css 1970-01-01 00:00:00 +0000 |
3282 | @@ -1,32 +0,0 @@ |
3283 | -.py-src-comment |
3284 | -{ |
3285 | - color: #1111CC |
3286 | -} |
3287 | - |
3288 | -.py-src-keyword |
3289 | -{ |
3290 | - color: #3333CC; |
3291 | - font-weight: bold; |
3292 | -} |
3293 | - |
3294 | -.py-src-parameter |
3295 | -{ |
3296 | - color: #000066; |
3297 | - font-weight: bold; |
3298 | -} |
3299 | - |
3300 | -.py-src-identifier |
3301 | -{ |
3302 | - color: #CC0000 |
3303 | -} |
3304 | - |
3305 | -.py-src-string |
3306 | -{ |
3307 | - |
3308 | - color: #115511 |
3309 | -} |
3310 | - |
3311 | -.py-src-endmarker |
3312 | -{ |
3313 | - display: block; /* IE hack; prevents following line from being sucked into the py-listing box. */ |
3314 | -} |
3315 | |
3316 | === removed file 'Nevow/examples/pastebin/static/css/standard.css' |
3317 | --- Nevow/examples/pastebin/static/css/standard.css 2005-10-14 17:36:24 +0000 |
3318 | +++ Nevow/examples/pastebin/static/css/standard.css 1970-01-01 00:00:00 +0000 |
3319 | @@ -1,25 +0,0 @@ |
3320 | -body |
3321 | -{ |
3322 | - font-family: Verdana, Geneva, "Bitstream Vera Sans", Helvetica; |
3323 | - /* font-family: Georgia, "Bitstream Vera Serif", "New York", Palatino; */ |
3324 | - font-size: 103%; |
3325 | -} |
3326 | - |
3327 | -th, td /* Needed for NN4 as its tables do not inherit styles */ |
3328 | -{ |
3329 | - font-family: Verdana, Geneva, "Bitstream Vera Sans", Helvetica; |
3330 | - /* font-family: Georgia, "Bitstream Vera Serif", "New York", Palatino; */ |
3331 | - font-size: 103%; |
3332 | -} |
3333 | - |
3334 | -/* Headers */ |
3335 | -h1 { font-size: 160%; } |
3336 | -h2 { font-size: 130%; } |
3337 | -h3 { font-size: 116%; } |
3338 | - |
3339 | - |
3340 | -/* Standard sizes */ |
3341 | -.normal-size { font-size: 103%; } |
3342 | -.small { font-size: 88%; } |
3343 | -.smaller { font-size: 77%; } |
3344 | -.smallest { font-size: 68%; } |
3345 | |
3346 | === removed directory 'Nevow/examples/pastebin/static/images' |
3347 | === removed file 'Nevow/examples/pastebin/static/images/pasting.gif' |
3348 | 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 |
3349 | === removed file 'Nevow/examples/pastebin/static/robots.txt' |
3350 | --- Nevow/examples/pastebin/static/robots.txt 2005-10-14 17:36:24 +0000 |
3351 | +++ Nevow/examples/pastebin/static/robots.txt 1970-01-01 00:00:00 +0000 |
3352 | @@ -1,2 +0,0 @@ |
3353 | -User-agent: * |
3354 | -Disallow: / |
3355 | |
3356 | === removed directory 'Nevow/examples/pastebin/templates' |
3357 | === removed file 'Nevow/examples/pastebin/templates/pasting.html' |
3358 | --- Nevow/examples/pastebin/templates/pasting.html 2005-10-14 17:36:24 +0000 |
3359 | +++ Nevow/examples/pastebin/templates/pasting.html 1970-01-01 00:00:00 +0000 |
3360 | @@ -1,14 +0,0 @@ |
3361 | -<div nevow:render="aPasting"> |
3362 | - |
3363 | - <p>Pasted by <nevow:slot name="author">author</nevow:slot> at <nevow:slot name="time">time</nevow:slot>.</p> |
3364 | - <div class="pastingText"><nevow:slot name="text">Pasting goes here</nevow:slot></div> |
3365 | - <div class="revision-history"> |
3366 | - <p>Revision history:</p> |
3367 | - <ul nevow:render="sequence" nevow:data="history"> |
3368 | - <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> |
3369 | - </ul> |
3370 | - </div> |
3371 | - |
3372 | - <form nevow:render="form"/> |
3373 | - |
3374 | -</div> |
3375 | |
3376 | === removed file 'Nevow/examples/pastebin/templates/site.html' |
3377 | --- Nevow/examples/pastebin/templates/site.html 2005-10-14 17:36:24 +0000 |
3378 | +++ Nevow/examples/pastebin/templates/site.html 1970-01-01 00:00:00 +0000 |
3379 | @@ -1,50 +0,0 @@ |
3380 | -<?xml version="1.0"?> |
3381 | - |
3382 | -<html xmlns="http://www.w3.org/1999/xhtml"> |
3383 | - |
3384 | - <head> |
3385 | - <title>Twisted Pastebin</title> |
3386 | - <link rel="stylesheet" type="text/css" href="/css/standard.css"/> |
3387 | - <link rel="stylesheet" type="text/css" href="/css/default.css"/> |
3388 | - <link rel="stylesheet" type="text/css" href="/css/freeform.css"/> |
3389 | - <link rel="stylesheet" type="text/css" href="/css/python.css"/> |
3390 | - </head> |
3391 | - |
3392 | - <body> |
3393 | - |
3394 | - <div id="header"> |
3395 | - <h1>Twisted Pastebin</h1> |
3396 | - </div> |
3397 | - |
3398 | - <div id="content-container"> |
3399 | - |
3400 | - <div id="nav"> |
3401 | - |
3402 | - Menu: |
3403 | - <ul id="menu"> |
3404 | - <li><a href="/">Add pasting</a></li> |
3405 | - </ul> |
3406 | - |
3407 | - Recent pastings: |
3408 | - <ul id="pastings" nevow:data="pastings" nevow:render="sequence"> |
3409 | - <li nevow:pattern="empty"><em>none</em></li> |
3410 | - <li nevow:pattern="item" nevow:render="pasting"> |
3411 | - <a href="#"><nevow:attr name="href"><nevow:slot name="url"/></nevow:attr><nevow:slot name="id" /> (<nevow:slot name="author"/>)</a> |
3412 | - </li> |
3413 | - </ul> |
3414 | - |
3415 | - </div> |
3416 | - |
3417 | - <div id="content" nevow:render="content"> |
3418 | - </div> |
3419 | - |
3420 | - </div> |
3421 | - |
3422 | - <div id="footer"> |
3423 | - Powered by <a href="http://www.twistedmatrix.com/">Twisted</a> and |
3424 | - <a href="http://divmod.org/users/wiki.twistd/nevow/moin.cgi">Nevow</a>. |
3425 | - </div> |
3426 | - |
3427 | - </body> |
3428 | - |
3429 | -</html> |
3430 | |
3431 | === removed file 'Nevow/examples/tests/testformless.py' |
3432 | --- Nevow/examples/tests/testformless.py 2006-04-14 17:23:46 +0000 |
3433 | +++ Nevow/examples/tests/testformless.py 1970-01-01 00:00:00 +0000 |
3434 | @@ -1,105 +0,0 @@ |
3435 | - |
3436 | -from twisted.internet import defer |
3437 | - |
3438 | -from formless import annotate, webform |
3439 | - |
3440 | -from nevow import rend, loaders, tags, livetest, url, livepage |
3441 | - |
3442 | - |
3443 | -"""WWWWizard functionality! |
3444 | -""" |
3445 | - |
3446 | - |
3447 | -test_suite = [ |
3448 | - ('visit', '/formpost/', ''), |
3449 | - ('value', 'foo-foo', '5'), |
3450 | - ('post', 'foo', {'foo-foo': 'asdf'}), |
3451 | - ('assert', livetest.xpath('//form[@id="foo"]//div[@class="freeform-form-error"]'), "'asdf' is not an integer."), |
3452 | - ## Check to make sure we repopulate the user's input with the erronious input |
3453 | - ('value', 'foo-foo', 'asdf'), |
3454 | - ('post', 'foo', {'foo-foo': '10'}), |
3455 | - ('value', 'foo-foo', '10'), |
3456 | - ] |
3457 | - |
3458 | - |
3459 | -test_suite += [ |
3460 | - ('visit', '/formpost2/', ''), |
3461 | - ('post', 'bar', {'bar-baz': '5', 'bar-slam': '5', 'bar-ham': 'efgh', 'bar-custom': '1'}), |
3462 | - ## XXX TODO: Can't post a radio button, so there is "None" below |
3463 | - ('assert', livetest.xpath('//h3'), "You called bar! 5 5 efgh None {'stuff': 1234, 'name': 'One'}") |
3464 | -] |
3465 | - |
3466 | -test_suite += [ |
3467 | - ('visit', '/testformless', ''), |
3468 | - ('post', 'name', {'name-name': 'Fred'}), |
3469 | - ('post', 'quest', {'quest-quest': 'Find the Grail'}), |
3470 | - ('post', 'speed', {'speed-speed': '123'}), |
3471 | - ('assert', 'body', "Thanks for taking our survey! You said: 'Fred' 'Find the Grail' 123")] |
3472 | - |
3473 | - |
3474 | -class NameWizard(rend.Page): |
3475 | - docFactory = loaders.stan(tags.html[tags.h1["What is your name"], webform.renderForms()]) |
3476 | - |
3477 | - def bind_name(self, ctx): |
3478 | - return [('name', annotate.String())] |
3479 | - |
3480 | - def name(self, name): |
3481 | - return QuestWizard(name) |
3482 | - |
3483 | - |
3484 | -class QuestWizard(rend.Page): |
3485 | - docFactory = loaders.stan(tags.html[tags.h1["What is your quest"], webform.renderForms()]) |
3486 | - |
3487 | - def bind_quest(self, ctx): |
3488 | - return [('quest', annotate.Choice(['Find the Grail', 'Get laid', 'Earn twenty bucks', 'Destroy the sun']))] |
3489 | - |
3490 | - def quest(self, quest): |
3491 | - return FinalWizard((self.original, quest)) |
3492 | - |
3493 | - |
3494 | -class FinalWizard(rend.Page): |
3495 | - docFactory = loaders.stan(tags.html[tags.h1["What is the airspeed velocity of an unladen swallow"], webform.renderForms()]) |
3496 | - |
3497 | - def bind_speed(self, ctx): |
3498 | - return [('speed', annotate.Integer())] |
3499 | - |
3500 | - def speed(self, speed): |
3501 | - return rend.Page( |
3502 | - docFactory=loaders.stan( |
3503 | - tags.html[ |
3504 | - tags.body(id='body')[ |
3505 | - "Thanks for taking our survey! You said: %r %r %r" % ( |
3506 | - self.original[0], self.original[1], speed)]])) |
3507 | - |
3508 | - |
3509 | -def checkLocation(client): |
3510 | - d = defer.Deferred() |
3511 | - def gotResult(ctx, location): |
3512 | - from urlparse import urlparse |
3513 | - if urlparse(location)[2] == '/': |
3514 | - d.callback(None) |
3515 | - else: |
3516 | - d.errback(None) |
3517 | - client.send(client.transient(gotResult, livepage.js.testFrameNode.contentDocument.location)) |
3518 | - return d |
3519 | - |
3520 | - |
3521 | -test_suite += [ |
3522 | - ('visit', '/formless_redirector', ''), |
3523 | - ('post', 'goHome', {}), |
3524 | - ('call', checkLocation, ())] |
3525 | - |
3526 | - |
3527 | -class Redirector(rend.Page): |
3528 | - docFactory = loaders.stan(tags.html[tags.body[webform.renderForms()]]) |
3529 | - |
3530 | - def bind_goHome(self, ctx): |
3531 | - return [] |
3532 | - |
3533 | - def goHome(self): |
3534 | - return url.root |
3535 | - |
3536 | - |
3537 | -formless_tests = livetest.Tester(test_suite) |
3538 | - |
3539 | - |
3540 | |
3541 | === removed directory 'Nevow/examples/todo' |
3542 | === removed file 'Nevow/examples/todo/controller.py' |
3543 | --- Nevow/examples/todo/controller.py 2006-03-17 15:00:39 +0000 |
3544 | +++ Nevow/examples/todo/controller.py 1970-01-01 00:00:00 +0000 |
3545 | @@ -1,83 +0,0 @@ |
3546 | -from zope.interface import implements |
3547 | - |
3548 | -from nevow import rend, loaders, tags as t |
3549 | -from formless import annotate, webform |
3550 | -from time import time as now |
3551 | -import itodo |
3552 | - |
3553 | -class ITodo(annotate.TypedInterface): |
3554 | - def insert(ctx=annotate.Context(), |
3555 | - description=annotate.String(required=True, |
3556 | - requiredFailMessage="Description Missing") |
3557 | - ): |
3558 | - pass |
3559 | - insert = annotate.autocallable(insert, action="New Todo") |
3560 | - def delete(ctx=annotate.Context(), id=annotate.Integer()): |
3561 | - pass |
3562 | - delete = annotate.autocallable(delete, invisible=True) |
3563 | - def update(ctx=annotate.Context(), |
3564 | - id=annotate.Integer(), |
3565 | - oldstate=annotate.Integer()): |
3566 | - pass |
3567 | - update = annotate.autocallable(update, invisible=True) |
3568 | - |
3569 | -class Root(rend.Page): |
3570 | - implements(ITodo) |
3571 | - |
3572 | - child_css = webform.defaultCSS |
3573 | - |
3574 | - docFactory = loaders.stan( |
3575 | - t.html(render=t.directive("time"))[ |
3576 | - t.head[ |
3577 | - t.title['todo'], |
3578 | - t.style(type="text/css")[".done { color: #dddddd; }"], |
3579 | - t.style(type="text/css")["@import url(/css);"] |
3580 | - ], |
3581 | - t.body[ |
3582 | - webform.renderForms(), |
3583 | - t.ul(data=t.directive("findAll"), |
3584 | - render=t.directive("sequence"))[ |
3585 | - t.li(pattern="item",render=t.directive('todo')), |
3586 | - t.li(pattern="empty",render=t.directive('empty')), |
3587 | - ], |
3588 | - t.p(render=t.directive("end")) |
3589 | - ] |
3590 | - ] |
3591 | - ) |
3592 | - |
3593 | - def insert(self, ctx, description): |
3594 | - return itodo.ITodos(ctx).add(description, 0) |
3595 | - |
3596 | - def delete(self, ctx, id): |
3597 | - return itodo.ITodos(ctx).delete(id) |
3598 | - |
3599 | - def update(self, ctx, id, oldstate): |
3600 | - newstate = [1, 0][oldstate] |
3601 | - return itodo.ITodos(ctx).update(id, newstate) |
3602 | - |
3603 | - def data_findAll(self, ctx, data): |
3604 | - return itodo.ITodos(ctx).findAll() |
3605 | - |
3606 | - def render_todo(self, ctx, data): |
3607 | - deluri = "freeform_post!!delete?id="+str(data[0]) |
3608 | - updateuri = "freeform_post!!update?id="+str(data[0])+"&oldstate="+str(data[2]) |
3609 | - state = [" Done", " To Do"][int(data[2])==0] |
3610 | - tag = ctx.tag |
3611 | - if data[2]: |
3612 | - tag = ctx.tag(_class="done") |
3613 | - return tag[data[1]+" - ", |
3614 | - t.a(href=deluri)["Delete"], " / ", |
3615 | - t.a(href=updateuri)[("Mark Done", "Mark Undone")[data[2]]], |
3616 | - state] |
3617 | - |
3618 | - def render_empty(self, ctx, data): |
3619 | - return ctx.tag["No Todos"] |
3620 | - |
3621 | - def render_time(self, ctx, data): |
3622 | - ctx.remember(now(), itodo.ITimer) |
3623 | - return ctx.tag |
3624 | - |
3625 | - def render_end(self, ctx, data): |
3626 | - return ctx.tag["%.3f"%(now()-itodo.ITimer(ctx))] |
3627 | - |
3628 | -root = Root() |
3629 | |
3630 | === removed file 'Nevow/examples/todo/database.sql' |
3631 | --- Nevow/examples/todo/database.sql 2005-10-14 17:36:24 +0000 |
3632 | +++ Nevow/examples/todo/database.sql 1970-01-01 00:00:00 +0000 |
3633 | @@ -1,5 +0,0 @@ |
3634 | -CREATE TABLE todos ( |
3635 | - id serial primary key, |
3636 | - description varchar(100) not null, |
3637 | - done int not null |
3638 | -) |
3639 | \ No newline at end of file |
3640 | |
3641 | === removed file 'Nevow/examples/todo/dispatcher.py' |
3642 | --- Nevow/examples/todo/dispatcher.py 2005-10-14 17:36:24 +0000 |
3643 | +++ Nevow/examples/todo/dispatcher.py 1970-01-01 00:00:00 +0000 |
3644 | @@ -1,13 +0,0 @@ |
3645 | -from nevow import rend |
3646 | -import itodo |
3647 | -import controller |
3648 | - |
3649 | -# All this is only useful to dynamically update the web page code |
3650 | -# without restarting the server each time. As you can see below, you can |
3651 | -# disable this by putting a false value in the Env object. |
3652 | - |
3653 | -class Dispatch(rend.Page): |
3654 | - def locateChild(self, ctx, segments): |
3655 | - if itodo.IEnv(ctx).development: |
3656 | - reload(controller) |
3657 | - return controller.root.locateChild(ctx,segments) |
3658 | |
3659 | === removed file 'Nevow/examples/todo/environment.py' |
3660 | --- Nevow/examples/todo/environment.py 2005-10-14 17:36:24 +0000 |
3661 | +++ Nevow/examples/todo/environment.py 1970-01-01 00:00:00 +0000 |
3662 | @@ -1,8 +0,0 @@ |
3663 | -class Env(object): |
3664 | - user='test' |
3665 | - password='test' |
3666 | - port=5432 |
3667 | - host='localhost' |
3668 | - dbname='todo' |
3669 | - development=False |
3670 | -env = Env() |
3671 | |
3672 | === removed file 'Nevow/examples/todo/itodo.py' |
3673 | --- Nevow/examples/todo/itodo.py 2006-03-08 14:28:41 +0000 |
3674 | +++ Nevow/examples/todo/itodo.py 1970-01-01 00:00:00 +0000 |
3675 | @@ -1,16 +0,0 @@ |
3676 | -from zope.interface import Interface |
3677 | - |
3678 | -class ITimer(Interface): |
3679 | - """ """ |
3680 | - |
3681 | -class IEnv(Interface): |
3682 | - """ """ |
3683 | - |
3684 | -class ITodos(Interface): |
3685 | - """ """ |
3686 | - def add(description, done): |
3687 | - pass |
3688 | - def delete(id): |
3689 | - pass |
3690 | - def edit(id, description, done): |
3691 | - pass |
3692 | |
3693 | === removed file 'Nevow/examples/todo/store.py' |
3694 | --- Nevow/examples/todo/store.py 2005-10-14 17:36:24 +0000 |
3695 | +++ Nevow/examples/todo/store.py 1970-01-01 00:00:00 +0000 |
3696 | @@ -1,29 +0,0 @@ |
3697 | -from zope.interface import implements |
3698 | -import pgasync |
3699 | -import itodo |
3700 | - |
3701 | -class Todos(object): |
3702 | - implements(itodo.ITodos) |
3703 | - def __init__(self, dbname, user, password, host): |
3704 | - self.original = pgasync.ConnectionPool("pgasync", dbname=dbname, |
3705 | - user=user, password=password, host=host) |
3706 | - |
3707 | - def add(self, description, done): |
3708 | - query = "INSERT INTO todos (description, done) VALUES (%(description)s,%(done)s)" |
3709 | - args = dict(description=description, done=done) |
3710 | - return self.original.runOperation(query, args) |
3711 | - |
3712 | - def delete(self, id): |
3713 | - query="DELETE FROM todos WHERE id=%(id)s" |
3714 | - args = dict(id=id) |
3715 | - return self.original.runOperation(query, args) |
3716 | - |
3717 | - def update(self, id, state): |
3718 | - query = "UPDATE todos SET done=%(done)s WHERE id=%(id)s" |
3719 | - args = dict(id=id, done=state) |
3720 | - return self.original.runOperation(query, args) |
3721 | - |
3722 | - def findAll(self): |
3723 | - query = "SELECT * FROM todos" |
3724 | - return self.original.runQuery(query) |
3725 | - |
3726 | |
3727 | === removed file 'Nevow/examples/todo/todo.tac' |
3728 | --- Nevow/examples/todo/todo.tac 2005-10-14 17:36:24 +0000 |
3729 | +++ Nevow/examples/todo/todo.tac 1970-01-01 00:00:00 +0000 |
3730 | @@ -1,18 +0,0 @@ |
3731 | -from twisted.application import service, strports |
3732 | -from nevow import appserver |
3733 | - |
3734 | -from environment import env as e |
3735 | -import store |
3736 | -import dispatcher |
3737 | -import itodo |
3738 | - |
3739 | -application = service.Application('todo') |
3740 | -db = store.Todos(e.dbname, e.user, e.password, e.host) |
3741 | -disp = dispatcher.Dispatch() |
3742 | - |
3743 | -site = appserver.NevowSite(resource=disp) |
3744 | -site.remember(db, itodo.ITodos) |
3745 | -site.remember(e, itodo.IEnv) |
3746 | - |
3747 | -webserver = strports.service("tcp:8080", site) |
3748 | -webserver.setServiceParent(application) |
3749 | |
3750 | === removed directory 'Nevow/examples/tree' |
3751 | === removed file 'Nevow/examples/tree/__init__.py' |
3752 | === removed file 'Nevow/examples/tree/tree.py' |
3753 | --- Nevow/examples/tree/tree.py 2006-03-17 15:00:39 +0000 |
3754 | +++ Nevow/examples/tree/tree.py 1970-01-01 00:00:00 +0000 |
3755 | @@ -1,73 +0,0 @@ |
3756 | -from zope.interface import implements |
3757 | - |
3758 | -from twisted.python.components import registerAdapter |
3759 | - |
3760 | -from nevow import loaders, rend, inevow, tags as T |
3761 | -from formless import annotate, webform |
3762 | - |
3763 | -class Tree(dict): |
3764 | - def __init__(self, name, description, *children): |
3765 | - self.name = name |
3766 | - self.description = description |
3767 | - for child in children: |
3768 | - self.add(child) |
3769 | - def add(self, child): |
3770 | - self[child.name] = child |
3771 | - def __nonzero__(self): |
3772 | - return True |
3773 | - |
3774 | -class ITreeEdit(annotate.TypedInterface): |
3775 | - def setDescription(description=annotate.String()): |
3776 | - pass |
3777 | - setDescription = annotate.autocallable(setDescription) |
3778 | - def deleteChild(name=annotate.String(required=True)): |
3779 | - pass |
3780 | - deleteChild = annotate.autocallable(deleteChild, invisible=True) |
3781 | - def addChild(name=annotate.String(required=True), |
3782 | - description=annotate.String()): |
3783 | - pass |
3784 | - addChild = annotate.autocallable(addChild) |
3785 | - |
3786 | -class TreeRenderer(rend.Page): |
3787 | - implements(ITreeEdit) |
3788 | - addSlash = True |
3789 | - docFactory = loaders.htmlstr(""" |
3790 | -<html> |
3791 | -<head><title>Tree Editor</title></head> |
3792 | -<body><h1><span nevow:data="description" |
3793 | - nevow:render="string">Tree Description</span></h1> |
3794 | -<span nevow:render="descriptionForm"/> |
3795 | -<ol nevow:data="children" nevow:render="sequence"> |
3796 | -<li nevow:pattern="item"><span nevow:render="childLink"/> |
3797 | -<span nevow:render="childDel"/> |
3798 | -</li> |
3799 | -</ol> |
3800 | -<a href="..">Up</a> |
3801 | -</body> |
3802 | -</html> |
3803 | - """) |
3804 | - def setDescription(self, description): |
3805 | - self.original.description = description |
3806 | - def addChild(self, name, description): |
3807 | - self.original.add(Tree(name, description)) |
3808 | - def deleteChild(self, name): |
3809 | - del self.original[name] |
3810 | - def data_description(self, context, data): |
3811 | - return self.original.description |
3812 | - def data_children(self, context, data): |
3813 | - return self.original.items() |
3814 | - def render_childLink(self, context, data): |
3815 | - return T.a(href='subtree_%s/'%data[0])[data[1].description] |
3816 | - def childFactory(self, ctx, name): |
3817 | - if name.startswith('subtree_'): |
3818 | - return self.original[name[len('subtree_'):]] |
3819 | - def render_descriptionForm(self, context, data): |
3820 | - return webform.renderForms() |
3821 | - def render_childDel(self, context, (name, _)): |
3822 | - ret = T.form(action="./freeform_post!!deleteChild", |
3823 | - enctype="multipart/form-data", method="POST")[ |
3824 | - T.input(type="hidden", name="name", value=name), |
3825 | - T.input(type="submit", value="Delete")] |
3826 | - return ret |
3827 | - |
3828 | -registerAdapter(TreeRenderer, Tree, inevow.IResource) |
3829 | |
3830 | === removed directory 'Nevow/formless' |
3831 | === removed file 'Nevow/formless/__init__.py' |
3832 | --- Nevow/formless/__init__.py 2005-10-14 17:36:24 +0000 |
3833 | +++ Nevow/formless/__init__.py 1970-01-01 00:00:00 +0000 |
3834 | @@ -1,10 +0,0 @@ |
3835 | -# Copyright (c) 2004 Divmod. |
3836 | -# See LICENSE for details. |
3837 | - |
3838 | -# FIXME: remove next two lines after fixing compyCompat to have lazy importing. |
3839 | -# or else moving formless' adapter registration here. |
3840 | -import nevow |
3841 | -del nevow |
3842 | - |
3843 | -from formless.annotate import * |
3844 | -from formless.processors import process |
3845 | |
3846 | === removed file 'Nevow/formless/annotate.py' |
3847 | --- Nevow/formless/annotate.py 2010-02-06 04:33:05 +0000 |
3848 | +++ Nevow/formless/annotate.py 1970-01-01 00:00:00 +0000 |
3849 | @@ -1,852 +0,0 @@ |
3850 | -# -*- test-case-name: formless.test -*- |
3851 | -# Copyright (c) 2004 Divmod. |
3852 | -# See LICENSE for details. |
3853 | - |
3854 | - |
3855 | -"""And the earth was without form, and void; and darkness was upon the face of the deep. |
3856 | -""" |
3857 | - |
3858 | -import os |
3859 | -import sys |
3860 | -import inspect |
3861 | -import warnings |
3862 | -from zope.interface import implements |
3863 | -from zope.interface.interface import InterfaceClass, Attribute |
3864 | - |
3865 | -from nevow import util |
3866 | - |
3867 | - |
3868 | -from formless import iformless |
3869 | - |
3870 | - |
3871 | -class count(object): |
3872 | - def __init__(self): |
3873 | - self.id = 0 |
3874 | - def next(self): |
3875 | - self.id += 1 |
3876 | - return self.id |
3877 | - |
3878 | -nextId = count().next |
3879 | - |
3880 | - |
3881 | -class InputError(Exception): |
3882 | - """A Typed instance was unable to coerce from a string to the |
3883 | - appropriate type. |
3884 | - """ |
3885 | - def __init__(self, reason): |
3886 | - self.reason = reason |
3887 | - |
3888 | - def __str__(self): |
3889 | - return self.reason |
3890 | - |
3891 | - |
3892 | -class ValidateError(Exception): |
3893 | - """A Binding instance was unable to coerce all it's arguments from a |
3894 | - dictionary of lists of strings to the appropriate types. |
3895 | - |
3896 | - One use of this is to raise from an autocallable if an input is invalid. |
3897 | - For example, a password is incorrect. |
3898 | - |
3899 | - errors must be a dictionary mapping argument names to error messages |
3900 | - to display next to the arguments on the form. |
3901 | - |
3902 | - formErrorMessage is a string to display at the top of the form, not tied to |
3903 | - any specific argument on the form. |
3904 | - |
3905 | - partialForm is a dict mapping argument name to argument value, allowing |
3906 | - you to have the form save values that were already entered in the form. |
3907 | - """ |
3908 | - def __init__(self, errors, formErrorMessage=None, partialForm=None): |
3909 | - self.errors = errors |
3910 | - self.formErrorMessage = formErrorMessage |
3911 | - if partialForm is None: |
3912 | - self.partialForm = {} |
3913 | - else: |
3914 | - self.partialForm = partialForm |
3915 | - |
3916 | - def __str__(self): |
3917 | - return self.formErrorMessage |
3918 | - |
3919 | - |
3920 | - |
3921 | -class Typed(Attribute): |
3922 | - """A typed value. Subclasses of Typed are constructed inside of |
3923 | - TypedInterface class definitions to describe the types of properties, |
3924 | - the parameter types to method calls, and method return types. |
3925 | - |
3926 | - @ivar label: The short label which will describe this |
3927 | - parameter/proerties purpose to the user. |
3928 | - |
3929 | - @ivar description: A long description which further describes the |
3930 | - sort of input the user is expected to provide. |
3931 | - |
3932 | - @ivar default: A default value that may be used as an initial |
3933 | - value in the form. |
3934 | - |
3935 | - @ivar required: Whether the user is required to provide a value |
3936 | - |
3937 | - @ivar null: The value which will be produced if required is False |
3938 | - and the user does not provide a value |
3939 | - |
3940 | - @ivar unicode: Iff true, try to determine the character encoding |
3941 | - of the data from the browser and pass unicode strings to |
3942 | - coerce. |
3943 | - """ |
3944 | - implements(iformless.ITyped) |
3945 | - |
3946 | - complexType = False |
3947 | - strip = False |
3948 | - label = None |
3949 | - description = None |
3950 | - default = '' |
3951 | - required = False |
3952 | - requiredFailMessage = 'Please enter a value' |
3953 | - null = None |
3954 | - unicode = False |
3955 | - |
3956 | - __name__ = '' |
3957 | - |
3958 | - def __init__( |
3959 | - self, |
3960 | - label=None, |
3961 | - description=None, |
3962 | - default=None, |
3963 | - required=None, |
3964 | - requiredFailMessage=None, |
3965 | - null=None, |
3966 | - unicode=None, |
3967 | - **attributes): |
3968 | - |
3969 | - self.id = nextId() |
3970 | - if label is not None: |
3971 | - self.label = label |
3972 | - if description is not None: |
3973 | - self.description = description |
3974 | - if default is not None: |
3975 | - self.default = default |
3976 | - if required is not None: |
3977 | - self.required = required |
3978 | - if requiredFailMessage is not None: |
3979 | - self.requiredFailMessage = requiredFailMessage |
3980 | - if null is not None: |
3981 | - self.null = null |
3982 | - if unicode is not None: |
3983 | - self.unicode = unicode |
3984 | - self.attributes = attributes |
3985 | - |
3986 | - def getAttribute(self, name, default=None): |
3987 | - return self.attributes.get(name, default) |
3988 | - |
3989 | - def coerce(self, val, configurable): |
3990 | - raise NotImplementedError, "Implement in %s" % util.qual(self.__class__) |
3991 | - |
3992 | - |
3993 | -####################################### |
3994 | -## External API; your code will create instances of these objects |
3995 | -####################################### |
3996 | - |
3997 | -class String(Typed): |
3998 | - """A string that is expected to be reasonably short and contain no |
3999 | - newlines or tabs. |
4000 | - |
4001 | - strip: remove leading and trailing whitespace. |
4002 | - """ |
4003 | - |
4004 | - requiredFailMessage = 'Please enter a string.' |
4005 | - # iff true, return the stripped value. |
4006 | - strip = False |
4007 | - |
4008 | - def __init__(self, *args, **kwargs): |
4009 | - try: |
4010 | - self.strip = kwargs['strip'] |
4011 | - del kwargs['strip'] |
4012 | - except KeyError: |
4013 | - pass |
4014 | - Typed.__init__(self, *args, **kwargs) |
4015 | - |
4016 | - def coerce(self, val, configurable): |
4017 | - if self.strip: |
4018 | - val = val.strip() |
4019 | - return val |
4020 | - |
4021 | - |
4022 | -class Text(String): |
4023 | - """A string that is likely to be of a significant length and |
4024 | - probably contain newlines and tabs. |
4025 | - """ |
4026 | - |
4027 | - |
4028 | -class Password(String): |
4029 | - """Password is used when asking a user for a new password. The renderer |
4030 | - user interface will possibly ask for the password multiple times to |
4031 | - ensure it has been entered correctly. Typical use would be for |
4032 | - registration of a new user.""" |
4033 | - requiredFailMessage = 'Please enter a password.' |
4034 | - |
4035 | - |
4036 | -class PasswordEntry(String): |
4037 | - """PasswordEntry is used to ask for an existing password. Typical use |
4038 | - would be for login to an existing account.""" |
4039 | - requiredFailMessage = 'Please enter a password.' |
4040 | - |
4041 | - |
4042 | -class FileUpload(Typed): |
4043 | - requiredFailMessage = 'Please enter a file name.' |
4044 | - |
4045 | - def coerce(self, val, configurable): |
4046 | - return val.filename |
4047 | - |
4048 | - |
4049 | -class Integer(Typed): |
4050 | - |
4051 | - requiredFailMessage = 'Please enter an integer.' |
4052 | - |
4053 | - def coerce(self, val, configurable): |
4054 | - if val is None: |
4055 | - return None |
4056 | - try: |
4057 | - return int(val) |
4058 | - except ValueError: |
4059 | - if sys.version_info < (2,3): # Long/Int aren't integrated |
4060 | - try: |
4061 | - return long(val) |
4062 | - except ValueError: |
4063 | - raise InputError("'%s' is not an integer." % val) |
4064 | - |
4065 | - raise InputError("'%s' is not an integer." % val) |
4066 | - |
4067 | - |
4068 | -class Real(Typed): |
4069 | - |
4070 | - requiredFailMessage = 'Please enter a real number.' |
4071 | - |
4072 | - def coerce(self, val, configurable): |
4073 | - # TODO: This shouldn't be required; check. |
4074 | - # val should never be None, but always a string. |
4075 | - if val is None: |
4076 | - return None |
4077 | - try: |
4078 | - return float(val) |
4079 | - except ValueError: |
4080 | - raise InputError("'%s' is not a real number." % val) |
4081 | - |
4082 | - |
4083 | -class Boolean(Typed): |
4084 | - def coerce(self, val, configurable): |
4085 | - if val == 'False': |
4086 | - return False |
4087 | - elif val == 'True': |
4088 | - return True |
4089 | - raise InputError("'%s' is not a boolean" % val) |
4090 | - |
4091 | - |
4092 | -class FixedDigitInteger(Integer): |
4093 | - |
4094 | - def __init__(self, digits = 1, *args, **kw): |
4095 | - Integer.__init__(self, *args, **kw) |
4096 | - self.digits = digits |
4097 | - self.requiredFailMessage = \ |
4098 | - 'Please enter a %d digit integer.' % self.digits |
4099 | - |
4100 | - def coerce(self, val, configurable): |
4101 | - v = Integer.coerce(self, val, configurable) |
4102 | - if len(str(v)) != self.digits: |
4103 | - raise InputError("Number must be %s digits." % self.digits) |
4104 | - return v |
4105 | - |
4106 | - |
4107 | -class Directory(Typed): |
4108 | - |
4109 | - requiredFailMessage = 'Please enter a directory name.' |
4110 | - |
4111 | - def coerce(self, val, configurable): |
4112 | - # TODO: This shouldn't be required; check. |
4113 | - # val should never be None, but always a string. |
4114 | - if val is None: |
4115 | - return None |
4116 | - if not os.path.exists(val): |
4117 | - raise InputError("The directory '%s' does not exist." % val) |
4118 | - return val |
4119 | - |
4120 | - |
4121 | -class Choice(Typed): |
4122 | - """Allow the user to pick from a list of "choices", presented in a drop-down |
4123 | - menu. The elements of the list will be rendered by calling the function |
4124 | - passed to stringify, which is by default "str". |
4125 | - """ |
4126 | - |
4127 | - requiredFailMessage = 'Please choose an option.' |
4128 | - |
4129 | - def __init__(self, choices=None, choicesAttribute=None, stringify=str, |
4130 | - valueToKey=str, keyToValue=None, keyAndConfigurableToValue=None, |
4131 | - *args, **kw): |
4132 | - """ |
4133 | - Create a Choice. |
4134 | - |
4135 | - @param choices: an object adaptable to IGettable for an iterator (such |
4136 | - as a function which takes (ctx, data) and returns a list, a list |
4137 | - itself, a tuple, a generator...) |
4138 | - |
4139 | - @param stringify: a pretty-printer. a function which takes an object |
4140 | - in the list of choices and returns a label for it. |
4141 | - |
4142 | - @param valueToKey: a function which converts an object in the list of |
4143 | - choices to a string that can be sent to a client. |
4144 | - |
4145 | - @param keyToValue: a 1-argument convenience version of |
4146 | - keyAndConfigurableToValue |
4147 | - |
4148 | - @param keyAndConfigurableToValue: a 2-argument function which takes a string such as |
4149 | - one returned from valueToKey and a configurable, and returns an object |
4150 | - such as one from the list of choices. |
4151 | - """ |
4152 | - |
4153 | - Typed.__init__(self, *args, **kw) |
4154 | - self.choices = choices |
4155 | - if choicesAttribute: |
4156 | - self.choicesAttribute = choicesAttribute |
4157 | - if getattr(self, 'choicesAttribute', None): |
4158 | - warnings.warn( |
4159 | - "Choice.choicesAttribute is deprecated. Please pass a function to choices instead.", |
4160 | - DeprecationWarning, |
4161 | - stacklevel=2) |
4162 | - def findTheChoices(ctx, data): |
4163 | - return getattr(iformless.IConfigurable(ctx).original, self.choicesAttribute) |
4164 | - self.choices = findTheChoices |
4165 | - |
4166 | - self.stringify = stringify |
4167 | - self.valueToKey=valueToKey |
4168 | - |
4169 | - if keyAndConfigurableToValue is not None: |
4170 | - assert keyToValue is None, 'This should be *obvious*' |
4171 | - self.keyAndConfigurableToValue = keyAndConfigurableToValue |
4172 | - elif keyToValue is not None: |
4173 | - self.keyAndConfigurableToValue = lambda x,y: keyToValue(x) |
4174 | - else: |
4175 | - self.keyAndConfigurableToValue = lambda x,y: str(x) |
4176 | - |
4177 | - |
4178 | - def coerce(self, val, configurable): |
4179 | - """Coerce a value with the help of an object, which is the object |
4180 | - we are configuring. |
4181 | - """ |
4182 | - return self.keyAndConfigurableToValue(val, configurable) |
4183 | - |
4184 | - |
4185 | -class Radio(Choice): |
4186 | - """Type influencing presentation! horray! |
4187 | - |
4188 | - Show the user radio button choices instead of a picklist. |
4189 | - """ |
4190 | - |
4191 | - |
4192 | -class Any(object): |
4193 | - """Marker which indicates any object type. |
4194 | - """ |
4195 | - |
4196 | - |
4197 | -class Object(Typed): |
4198 | - complexType = True |
4199 | - def __init__(self, interface=Any, *args, **kw): |
4200 | - Typed.__init__(self, *args, **kw) |
4201 | - self.iface = interface |
4202 | - |
4203 | - def __repr__(self): |
4204 | - if self.iface is not None: |
4205 | - return "%s(interface=%s)" % (self.__class__.__name__, util.qual(self.iface)) |
4206 | - return "%s(None)" % (self.__class__.__name__,) |
4207 | - |
4208 | - |
4209 | - |
4210 | -class List(Object): |
4211 | - implements(iformless.IActionableType) |
4212 | - |
4213 | - complexType = True |
4214 | - def __init__(self, actions=None, header='', footer='', separator='', *args, **kw): |
4215 | - """Actions is a list of action methods which may be invoked on one |
4216 | - or more of the elements of this list. Action methods are defined |
4217 | - on a TypedInterface and declare that they take one parameter |
4218 | - of type List. They do not declare themselves to be autocallable |
4219 | - in the traditional manner. Instead, they are passed in the actions |
4220 | - list of a list Property to declare that the action may be taken on |
4221 | - one or more of the list elements. |
4222 | - """ |
4223 | - if actions is None: |
4224 | - actions = [] |
4225 | - self.actions = actions |
4226 | - self.header = header |
4227 | - self.footer = footer |
4228 | - self.separator = separator |
4229 | - Object.__init__(self, *args, **kw) |
4230 | - |
4231 | - def coerce(self, data, configurable): |
4232 | - return data |
4233 | - |
4234 | - def __repr__(self): |
4235 | - if self.iface is not None: |
4236 | - return "%s(interface=%s)" % (self.__class__.__name__, util.qual(self.iface)) |
4237 | - return self.__class__.__name__ + "()" |
4238 | - |
4239 | - def attachActionBindings(self, possibleActions): |
4240 | - ## Go through and replace self.actions, which is a list of method |
4241 | - ## references, with the MethodBinding instance which holds |
4242 | - ## metadata about this function. |
4243 | - act = self.actions |
4244 | - for method, binding in possibleActions: |
4245 | - if method in act: |
4246 | - act[act.index(method)] = binding |
4247 | - |
4248 | - def getActionBindings(self): |
4249 | - return self.actions |
4250 | - |
4251 | -class Dictionary(List): |
4252 | - pass |
4253 | - |
4254 | - |
4255 | -class Table(Object): |
4256 | - pass |
4257 | - |
4258 | - |
4259 | -class Request(Typed): |
4260 | - """Marker that indicates that an autocallable should be passed the |
4261 | - request when called. Including a Request arg will not affect the |
4262 | - appearance of the rendered form. |
4263 | - |
4264 | - >>> def doSomething(request=formless.Request(), name=formless.String()): |
4265 | - ... pass |
4266 | - >>> doSomething = formless.autocallable(doSomething) |
4267 | - """ |
4268 | - complexType = True ## Don't use the regular form |
4269 | - |
4270 | - |
4271 | -class Context(Typed): |
4272 | - """Marker that indicates that an autocallable should be passed the |
4273 | - context when called. Including a Context arg will not affect the |
4274 | - appearance of the rendered form. |
4275 | - |
4276 | - >>> def doSomething(context=formless.Context(), name=formless.String()): |
4277 | - ... pass |
4278 | - >>> doSomething = formless.autocallable(doSomething) |
4279 | - """ |
4280 | - complexType = True ## Don't use the regular form |
4281 | - |
4282 | - |
4283 | -class Button(Typed): |
4284 | - def coerce(self, data, configurable): |
4285 | - return data |
4286 | - |
4287 | - |
4288 | -class Compound(Typed): |
4289 | - complexType = True |
4290 | - def __init__(self, elements=None, *args, **kw): |
4291 | - assert elements, "What is the sound of a Compound type with no elements?" |
4292 | - self.elements = elements |
4293 | - Typed.__init__(self, *args, **kw) |
4294 | - |
4295 | - def __len__(self): |
4296 | - return len(self.elements) |
4297 | - |
4298 | - def coerce(self, data, configurable): |
4299 | - return data |
4300 | - |
4301 | - |
4302 | -class Method(Typed): |
4303 | - def __init__(self, returnValue=None, arguments=(), *args, **kw): |
4304 | - Typed.__init__(self, *args, **kw) |
4305 | - self.returnValue = returnValue |
4306 | - self.arguments = arguments |
4307 | - |
4308 | - |
4309 | -class Group(Object): |
4310 | - pass |
4311 | - |
4312 | - |
4313 | -def autocallable(method, action=None, visible=False, **kw): |
4314 | - """Describe a method in a TypedInterface as being callable through the |
4315 | - UI. The "action" paramter will be used to label the action button, or the |
4316 | - user interface element which performs the method call. |
4317 | - |
4318 | - Use this like a method adapter around a method in a TypedInterface: |
4319 | - |
4320 | - >>> class IFoo(TypedInterface): |
4321 | - ... def doSomething(): |
4322 | - ... '''Do Something |
4323 | - ... |
4324 | - ... Do some action bla bla''' |
4325 | - ... return None |
4326 | - ... doSomething = autocallable(doSomething, action="Do it!!") |
4327 | - """ |
4328 | - method.autocallable = True |
4329 | - method.id = nextId() |
4330 | - method.action = action |
4331 | - method.attributes = kw |
4332 | - return method |
4333 | - |
4334 | - |
4335 | -####################################### |
4336 | -## Internal API; formless uses these objects to keep track of |
4337 | -## what names are bound to what types |
4338 | -####################################### |
4339 | - |
4340 | - |
4341 | -class Binding(object): |
4342 | - """Bindings bind a Typed instance to a name. When TypedInterface is subclassed, |
4343 | - the metaclass looks through the dict looking for all properties and methods. |
4344 | - |
4345 | - If a properties is a Typed instance, a Property Binding is constructed, passing |
4346 | - the name of the binding and the Typed instance. |
4347 | - |
4348 | - If a method has been wrapped with the "autocallable" function adapter, |
4349 | - a Method Binding is constructed, passing the name of the binding and the |
4350 | - Typed instance. Then, getargspec is called. For each keyword argument |
4351 | - in the method definition, an Argument is constructed, passing the name |
4352 | - of the keyword argument as the binding name, and the value of the |
4353 | - keyword argument, a Typed instance, as the binding typeValue. |
4354 | - |
4355 | - One more thing. When an autocallable method is found, it is called with |
4356 | - None as the self argument. The return value is passed the Method |
4357 | - Binding when it is constructed to keep track of what the method is |
4358 | - supposed to return. |
4359 | - """ |
4360 | - implements(iformless.IBinding) |
4361 | - |
4362 | - label = None |
4363 | - description = '' |
4364 | - |
4365 | - def __init__(self, name, typedValue, id=0): |
4366 | - self.id = id |
4367 | - self.name = name |
4368 | - self.typedValue = iformless.ITyped(typedValue) |
4369 | - |
4370 | - # pull these out to remove one level of indirection... |
4371 | - if typedValue.description is not None: |
4372 | - self.description = typedValue.description |
4373 | - if typedValue.label is not None: |
4374 | - self.label = typedValue.label |
4375 | - if self.label is None: |
4376 | - self.label = nameToLabel(name) |
4377 | - self.default = typedValue.default |
4378 | - self.complexType = typedValue.complexType |
4379 | - |
4380 | - def __repr__(self): |
4381 | - return "<%s %s=%s at 0x%x>" % (self.__class__.__name__, self.name, self.typedValue.__class__.__name__, id(self)) |
4382 | - |
4383 | - def getArgs(self): |
4384 | - """Return a *copy* of this Binding. |
4385 | - """ |
4386 | - return (Binding(self.name, self.original, self.id), ) |
4387 | - |
4388 | - def getViewName(self): |
4389 | - return self.original.__class__.__name__.lower() |
4390 | - |
4391 | - def configure(self, boundTo, results): |
4392 | - raise NotImplementedError, "Implement in %s" % util.qual(self.__class__) |
4393 | - |
4394 | - def coerce(self, val, configurable): |
4395 | - if hasattr(self.original, 'coerce'): |
4396 | - return self.original.coerce(val) |
4397 | - return val |
4398 | - |
4399 | -class Argument(Binding): |
4400 | - pass |
4401 | - |
4402 | - |
4403 | -class Property(Binding): |
4404 | - action = 'Change' |
4405 | - def configure(self, boundTo, results): |
4406 | - ## set the property! |
4407 | - setattr(boundTo, self.name, results[self.name]) |
4408 | - |
4409 | - |
4410 | -class MethodBinding(Binding): |
4411 | - typedValue = None |
4412 | - def __init__(self, name, typeValue, id=0, action="Call", attributes = {}): |
4413 | - Binding.__init__(self, name, typeValue, id) |
4414 | - self.action = action |
4415 | - self.arguments = typeValue.arguments |
4416 | - self.returnValue = typeValue.returnValue |
4417 | - self.attributes = attributes |
4418 | - |
4419 | - def getAttribute(self, name): |
4420 | - return self.attributes.get(name, None) |
4421 | - |
4422 | - def configure(self, boundTo, results): |
4423 | - bound = getattr(boundTo, self.name) |
4424 | - return bound(**results) |
4425 | - |
4426 | - def getArgs(self): |
4427 | - """Make sure each form post gets a unique copy of the argument list which it can use to keep |
4428 | - track of values given in partially-filled forms |
4429 | - """ |
4430 | - return self.typedValue.arguments[:] |
4431 | - |
4432 | - |
4433 | -class ElementBinding(Binding): |
4434 | - """An ElementBinding binds a key to an element of a container. |
4435 | - For example, ElementBinding('0', Object()) indicates the 0th element |
4436 | - of a container of Objects. When this ElementBinding is bound to |
4437 | - the list [1, 2, 3], resolving the binding will result in the 0th element, |
4438 | - the object 1. |
4439 | - """ |
4440 | - pass |
4441 | - |
4442 | - |
4443 | -class GroupBinding(Binding): |
4444 | - """A GroupBinding is a way of naming a group of other Bindings. |
4445 | - The typedValue of a GroupBinding should be a Configurable. |
4446 | - The Bindings returned from this Configurable (usually a TypedInterface) |
4447 | - will be rendered such that all fields must/may be filled out, and all |
4448 | - fields will be changed at once upon form submission. |
4449 | - """ |
4450 | - def __init__(self, name, typedValue, id=0): |
4451 | - """Hack to prevent adaption to ITyped while the adapters are still |
4452 | - being registered, because we know that the typedValue should be |
4453 | - a Group when we are constructing a GroupBinding. |
4454 | - """ |
4455 | - self.id = id |
4456 | - self.name = name |
4457 | - self.typedValue = Group(typedValue) |
4458 | - |
4459 | - # pull these out to remove one level of indirection... |
4460 | - self.description = typedValue.description |
4461 | - if typedValue.label: |
4462 | - self.label = typedValue.label |
4463 | - else: |
4464 | - self.label = nameToLabel(name) |
4465 | - self.default = typedValue.default |
4466 | - self.complexType = typedValue.complexType |
4467 | - |
4468 | - def configure(self, boundTo, group): |
4469 | - print "CONFIGURING GROUP BINDING", boundTo, group |
4470 | - |
4471 | - |
4472 | -def _sorter(x, y): |
4473 | - return cmp(x.id, y.id) |
4474 | - |
4475 | - |
4476 | -class _Marker(object): |
4477 | - pass |
4478 | - |
4479 | - |
4480 | -def caps(c): |
4481 | - return c.upper() == c |
4482 | - |
4483 | - |
4484 | -def nameToLabel(mname): |
4485 | - labelList = [] |
4486 | - word = '' |
4487 | - lastWasUpper = False |
4488 | - for letter in mname: |
4489 | - if caps(letter) == lastWasUpper: |
4490 | - # Continuing a word. |
4491 | - word += letter |
4492 | - else: |
4493 | - # breaking a word OR beginning a word |
4494 | - if lastWasUpper: |
4495 | - # could be either |
4496 | - if len(word) == 1: |
4497 | - # keep going |
4498 | - word += letter |
4499 | - else: |
4500 | - # acronym |
4501 | - # we're processing the lowercase letter after the acronym-then-capital |
4502 | - lastWord = word[:-1] |
4503 | - firstLetter = word[-1] |
4504 | - labelList.append(lastWord) |
4505 | - word = firstLetter + letter |
4506 | - else: |
4507 | - # definitely breaking: lower to upper |
4508 | - labelList.append(word) |
4509 | - word = letter |
4510 | - lastWasUpper = caps(letter) |
4511 | - if labelList: |
4512 | - labelList[0] = labelList[0].capitalize() |
4513 | - else: |
4514 | - return mname.capitalize() |
4515 | - labelList.append(word) |
4516 | - return ' '.join(labelList) |
4517 | - |
4518 | - |
4519 | -def labelAndDescriptionFromDocstring(docstring): |
4520 | - if docstring is None: |
4521 | - docstring = '' |
4522 | - docs = filter(lambda x: x, [x.strip() for x in docstring.split('\n')]) |
4523 | - if len(docs) > 1: |
4524 | - return docs[0], '\n'.join(docs[1:]) |
4525 | - else: |
4526 | - return None, '\n'.join(docs) |
4527 | - |
4528 | - |
4529 | -_typedInterfaceMetadata = {} |
4530 | - |
4531 | - |
4532 | -class MetaTypedInterface(InterfaceClass): |
4533 | - """The metaclass for TypedInterface. When TypedInterface is subclassed, |
4534 | - this metaclass' __new__ method is invoked. The Typed Binding introspection |
4535 | - described in the Binding docstring occurs, and when it is all done, there will |
4536 | - be three attributes on the TypedInterface class: |
4537 | - |
4538 | - - __methods__: An ordered list of all the MethodBinding instances |
4539 | - produced by introspecting all autocallable methods on this |
4540 | - TypedInterface |
4541 | - |
4542 | - - __properties__: An ordered list of all the Property Binding |
4543 | - instances produced by introspecting all properties which have |
4544 | - Typed values on this TypedInterface |
4545 | - |
4546 | - - __spec__: An ordered list of all methods and properties |
4547 | - |
4548 | - These lists are sorted in the order that the methods and properties appear |
4549 | - in the TypedInterface definition. |
4550 | - |
4551 | - For example: |
4552 | - |
4553 | - >>> class Foo(TypedInterface): |
4554 | - ... bar = String() |
4555 | - ... baz = Integer() |
4556 | - ... |
4557 | - ... def frotz(): pass |
4558 | - ... frotz = autocallable(frotz) |
4559 | - ... |
4560 | - ... xyzzy = Float() |
4561 | - ... |
4562 | - ... def blam(): pass |
4563 | - ... blam = autocallable(blam) |
4564 | - |
4565 | - Once the metaclass __new__ is done, the Foo class instance will have three |
4566 | - properties, __methods__, __properties__, and __spec__, |
4567 | - """ |
4568 | - __methods__ = property(lambda self: _typedInterfaceMetadata[self, '__methods__']) |
4569 | - __id__ = property(lambda self: _typedInterfaceMetadata[self, '__id__']) |
4570 | - __properties__ = property(lambda self: _typedInterfaceMetadata[self, '__properties__']) |
4571 | - __spec__ = property(lambda self: _typedInterfaceMetadata[self, '__spec__']) |
4572 | - name = property(lambda self: _typedInterfaceMetadata[self, 'name']) |
4573 | - label = property(lambda self: _typedInterfaceMetadata[self, 'label']) |
4574 | - description = property(lambda self: _typedInterfaceMetadata[self, 'description']) |
4575 | - default = property(lambda self: _typedInterfaceMetadata.get((self, 'default'), 'DEFAULT')) |
4576 | - complexType = property(lambda self: _typedInterfaceMetadata.get((self, 'complexType'), True)) |
4577 | - |
4578 | - def __new__(cls, name, bases, dct): |
4579 | - rv = cls = InterfaceClass.__new__(cls) |
4580 | - _typedInterfaceMetadata[cls, '__id__'] = nextId() |
4581 | - _typedInterfaceMetadata[cls, '__methods__'] = methods = [] |
4582 | - _typedInterfaceMetadata[cls, '__properties__'] = properties = [] |
4583 | - possibleActions = [] |
4584 | - actionAttachers = [] |
4585 | - for key, value in dct.items(): |
4586 | - if key[0] == '_': continue |
4587 | - |
4588 | - if isinstance(value, MetaTypedInterface): |
4589 | - ## A Nested TypedInterface indicates a GroupBinding |
4590 | - properties.append(GroupBinding(key, value, value.__id__)) |
4591 | - |
4592 | - ## zope.interface doesn't like these |
4593 | - del dct[key] |
4594 | - setattr(cls, key, value) |
4595 | - elif callable(value): |
4596 | - names, _, _, typeList = inspect.getargspec(value) |
4597 | - |
4598 | - _testCallArgs = () |
4599 | - |
4600 | - if typeList is None: |
4601 | - typeList = [] |
4602 | - |
4603 | - if len(names) == len(typeList) + 1: |
4604 | - warnings.warn( |
4605 | - "TypeInterface method declarations should not have a 'self' parameter", |
4606 | - DeprecationWarning, |
4607 | - stacklevel=2) |
4608 | - del names[0] |
4609 | - _testCallArgs = (_Marker,) |
4610 | - |
4611 | - if len(names) != len(typeList): |
4612 | - ## Allow non-autocallable methods in the interface; ignore them |
4613 | - continue |
4614 | - |
4615 | - argumentTypes = [ |
4616 | - Argument(n, argtype, argtype.id) for n, argtype in zip(names[-len(typeList):], typeList) |
4617 | - ] |
4618 | - |
4619 | - result = value(*_testCallArgs) |
4620 | - |
4621 | - label = None |
4622 | - description = None |
4623 | - if getattr(value, 'autocallable', None): |
4624 | - # autocallables have attributes that can set label and description |
4625 | - label = value.attributes.get('label', None) |
4626 | - description = value.attributes.get('description', None) |
4627 | - |
4628 | - adapted = iformless.ITyped(result, None) |
4629 | - if adapted is None: |
4630 | - adapted = Object(result) |
4631 | - |
4632 | - # ITyped has label and description we can use |
4633 | - if label is None: |
4634 | - label = adapted.label |
4635 | - if description is None: |
4636 | - description = adapted.description |
4637 | - |
4638 | - defaultLabel, defaultDescription = labelAndDescriptionFromDocstring(value.__doc__) |
4639 | - if defaultLabel is None: |
4640 | - # docstring had no label, try the action if it is an autocallable |
4641 | - if getattr(value, 'autocallable', None): |
4642 | - if label is None and value.action is not None: |
4643 | - # no explicit label, but autocallable has action we can use |
4644 | - defaultLabel = value.action |
4645 | - |
4646 | - if defaultLabel is None: |
4647 | - # final fallback: use the function name as label |
4648 | - defaultLabel = nameToLabel(key) |
4649 | - |
4650 | - if label is None: |
4651 | - label = defaultLabel |
4652 | - if description is None: |
4653 | - description = defaultDescription |
4654 | - |
4655 | - theMethod = Method( |
4656 | - adapted, argumentTypes, label=label, description=description |
4657 | - ) |
4658 | - |
4659 | - if getattr(value, 'autocallable', None): |
4660 | - methods.append( |
4661 | - MethodBinding( |
4662 | - key, theMethod, value.id, value.action, value.attributes)) |
4663 | - else: |
4664 | - possibleActions.append((value, MethodBinding(key, theMethod))) |
4665 | - else: |
4666 | - if not value.label: |
4667 | - value.label = nameToLabel(key) |
4668 | - if iformless.IActionableType.providedBy(value): |
4669 | - actionAttachers.append(value) |
4670 | - properties.append( |
4671 | - Property(key, value, value.id) |
4672 | - ) |
4673 | - for attacher in actionAttachers: |
4674 | - attacher.attachActionBindings(possibleActions) |
4675 | - methods.sort(_sorter) |
4676 | - properties.sort(_sorter) |
4677 | - _typedInterfaceMetadata[cls, '__spec__'] = spec = methods + properties |
4678 | - spec.sort(_sorter) |
4679 | - _typedInterfaceMetadata[cls, 'name'] = name |
4680 | - |
4681 | - # because attributes "label" and "description" would become Properties, |
4682 | - # check for ones with an underscore prefix. |
4683 | - _typedInterfaceMetadata[cls, 'label'] = dct.get('_label', None) |
4684 | - _typedInterfaceMetadata[cls, 'description'] = dct.get('_description', None) |
4685 | - defaultLabel, defaultDescription = labelAndDescriptionFromDocstring(dct.get('__doc__')) |
4686 | - if defaultLabel is None: |
4687 | - defaultLabel = nameToLabel(name) |
4688 | - if _typedInterfaceMetadata[cls, 'label'] is None: |
4689 | - _typedInterfaceMetadata[cls, 'label'] = defaultLabel |
4690 | - if _typedInterfaceMetadata[cls, 'description'] is None: |
4691 | - _typedInterfaceMetadata[cls, 'description'] = defaultDescription |
4692 | - |
4693 | - return rv |
4694 | - |
4695 | - |
4696 | -####################################### |
4697 | -## External API; subclass this to create a TypedInterface |
4698 | -####################################### |
4699 | - |
4700 | -TypedInterface = MetaTypedInterface('TypedInterface', (InterfaceClass('TypedInterface'), ), {}) |
4701 | - |
4702 | |
4703 | === removed file 'Nevow/formless/configurable.py' |
4704 | --- Nevow/formless/configurable.py 2006-03-17 15:00:39 +0000 |
4705 | +++ Nevow/formless/configurable.py 1970-01-01 00:00:00 +0000 |
4706 | @@ -1,173 +0,0 @@ |
4707 | -# Copyright (c) 2004 Divmod. |
4708 | -# See LICENSE for details. |
4709 | - |
4710 | -from zope.interface import implements, providedBy |
4711 | - |
4712 | -from formless.iformless import IConfigurable, IActionableType, IBinding |
4713 | -from formless.annotate import Argument, ElementBinding, GroupBinding, Object, TypedInterface |
4714 | - |
4715 | -from nevow import inevow |
4716 | -from nevow.context import WovenContext |
4717 | - |
4718 | -class Configurable(object): |
4719 | - implements(IConfigurable) |
4720 | - |
4721 | - bindingDict = None |
4722 | - |
4723 | - def __init__(self, original): |
4724 | - self.original = original |
4725 | - self.boundTo = self |
4726 | - |
4727 | - def getBindingNames(self, context): |
4728 | - ## Todo: remove this getattr |
4729 | - ifs = providedBy(getattr(self, 'boundTo', self)) |
4730 | - ifs = [ |
4731 | - x for x in ifs if x is not IConfigurable and x is not TypedInterface |
4732 | - ] |
4733 | - bindingNames = [] |
4734 | - self.bindingDict = bindingDict = {} |
4735 | - for interface in ifs: |
4736 | - ## TypedInterfaces have a __spec__ attribute which is a list of all Typed properties and |
4737 | - ## autocallable methods |
4738 | - for binding in getattr(interface, '__spec__', []): |
4739 | - bindingDict[binding.name] = binding |
4740 | - if binding.name not in bindingNames: |
4741 | - bindingNames.append(binding.name) |
4742 | - if IActionableType.providedBy(binding.typedValue): |
4743 | - acts = binding.typedValue.actions |
4744 | - if acts is None: |
4745 | - acts = [] |
4746 | - for action in acts: |
4747 | - bindingDict[action.name] = action |
4748 | - return bindingNames |
4749 | - |
4750 | - def getDefault(self, forBinding): |
4751 | - ## TODO: Clean this up, it's a mess |
4752 | - if not isinstance(forBinding, Argument): |
4753 | - name = forBinding.name |
4754 | - if hasattr(self, name): |
4755 | - return getattr(self, name) |
4756 | - ## Todo: Only do this in ConfigurableAdapter instead of Configurable |
4757 | - if hasattr(self.boundTo, name): |
4758 | - return getattr(self.boundTo, name) |
4759 | - if self.original is not self.boundTo and hasattr(self.original, name): |
4760 | - return getattr(self.original, name) |
4761 | - return forBinding.default |
4762 | - |
4763 | - def getBinding(self, context, name): |
4764 | - if self.bindingDict is None: |
4765 | - self.getBindingNames(context) |
4766 | - if self.bindingDict is None: |
4767 | - self.bindingDict = {} |
4768 | - binding = getattr(self, 'bind_%s' % name, getattr(self.boundTo, 'bind_%s' % name, None)) |
4769 | - if binding is not None: |
4770 | - binding = binding(context) |
4771 | - else: |
4772 | - try: |
4773 | - binding = self.bindingDict[name] |
4774 | - except KeyError: |
4775 | - raise RuntimeError, "%s is not an exposed binding on object %s." % (name, self.boundTo) |
4776 | - binding.boundTo = self.boundTo |
4777 | - return binding |
4778 | - |
4779 | - def postForm(self, ctx, bindingName, args): |
4780 | - """Accept a form post to the given bindingName. The bindingName |
4781 | - can be dotted to indicate an attribute of this Configurable, eg |
4782 | - addresses.0.changeEmail. The post arguments are given in args. |
4783 | - Return a Resource which will be rendered in response. |
4784 | - """ |
4785 | - from formless import iformless |
4786 | - from nevow.tags import invisible |
4787 | - request = ctx.locate(inevow.IRequest) |
4788 | - pathSegs = bindingName.split('.') |
4789 | - configurable = self |
4790 | - |
4791 | - cf = ctx.locate(iformless.IConfigurableFactory) |
4792 | - ## Get the first binding |
4793 | - firstSeg = pathSegs.pop(0) |
4794 | - binding = configurable.getBinding(ctx, firstSeg) |
4795 | - ctx.remember(binding, IBinding) |
4796 | - ctx.remember(configurable, IConfigurable) |
4797 | - ## I don't think this works right now, it needs to be fixed. |
4798 | - ## Most cases it won't be triggered, because we're just traversing a |
4799 | - ## single binding name |
4800 | - for seg in pathSegs: |
4801 | - assert 1 == 0, "Sorry, this doesn't work right now" |
4802 | - binding = configurable.getBinding(ctx, seg) |
4803 | - child = self.boundTo |
4804 | - if not isinstance(binding, GroupBinding): |
4805 | - accessor = inevow.IContainer(configurable.boundTo, None) |
4806 | - if accessor is None: |
4807 | - child = getattr(configurable.boundTo, binding.name) |
4808 | - else: |
4809 | - child = accessor.child(ctx, binding.name) |
4810 | - ## If it's a groupbinding, we don't do anything at all for this path segment |
4811 | - |
4812 | - ## This won't work right now. We need to push the previous configurable |
4813 | - ## as the configurableFactory somehow and ask that for hte next binding |
4814 | - ## we also need to support deferreds coming back from locateConfigurable |
4815 | - assert 'black' is 'white', "Deferred support is pending" |
4816 | - configurable = cf.locateConfigurable(ctx, child) |
4817 | - ctx = WovenContext(ctx, invisible(key=seg)) |
4818 | - ctx.remember(binding, IBinding) |
4819 | - ctx.remember(configurable, IConfigurable) |
4820 | - |
4821 | - bindingProcessor = iformless.IInputProcessor(binding) |
4822 | - rv = bindingProcessor.process(ctx, binding.boundTo, args) |
4823 | - ctx.remember(rv, inevow.IHand) |
4824 | - ctx.remember('%r success.' % bindingName, inevow.IStatusMessage) |
4825 | - return rv |
4826 | - |
4827 | - def summary(self): |
4828 | - return "An instance of %s" % self.__class__.__name__ |
4829 | - |
4830 | - postLocation = None |
4831 | - |
4832 | -class NotFoundConfigurable(Configurable): |
4833 | - def getBinding(self, context, name): |
4834 | - raise RuntimeError, self.original |
4835 | - |
4836 | - |
4837 | -class TypedInterfaceConfigurable(Configurable): |
4838 | - def __init__(self, original): |
4839 | - self.original = original |
4840 | - self.boundTo = original |
4841 | - |
4842 | - def summary(self): |
4843 | - return "An instance of %s" % self.original.__class__.__name__ |
4844 | - |
4845 | - def __repr__(self): |
4846 | - return "TypedInterfaceConfigurable(%r)" % self.original |
4847 | - |
4848 | - |
4849 | -class ListConfigurable(TypedInterfaceConfigurable): |
4850 | - def getBinding(self, context, name): |
4851 | - eb = ElementBinding(name, Object()) |
4852 | - eb.boundTo = self.original |
4853 | - return eb |
4854 | - |
4855 | - |
4856 | -class GroupConfigurable(TypedInterfaceConfigurable): |
4857 | - def __init__(self, original, groupInterface): |
4858 | - TypedInterfaceConfigurable.__init__(self, original) |
4859 | - self.groupInterface = groupInterface |
4860 | - |
4861 | - bindingDict = None |
4862 | - |
4863 | - def getBindingNames(self, context): |
4864 | - bindingNames = [] |
4865 | - self.bindingDict = bindingDict = {} |
4866 | - interface = self.groupInterface |
4867 | - for binding in getattr(interface, '__spec__', []): |
4868 | - bindingDict[binding.name] = binding |
4869 | - if binding.name not in bindingNames: |
4870 | - bindingNames.append(binding.name) |
4871 | - if IActionableType.providedBy(binding.typedValue): |
4872 | - acts = binding.typedValue.actions |
4873 | - if acts is None: |
4874 | - acts = [] |
4875 | - for action in acts: |
4876 | - bindingDict[action.name] = action |
4877 | - return bindingNames |
4878 | - |
4879 | - |
4880 | |
4881 | === removed file 'Nevow/formless/formutils.py' |
4882 | --- Nevow/formless/formutils.py 2006-04-14 17:23:46 +0000 |
4883 | +++ Nevow/formless/formutils.py 1970-01-01 00:00:00 +0000 |
4884 | @@ -1,143 +0,0 @@ |
4885 | -# Copyright (c) 2004 Divmod. |
4886 | -# See LICENSE for details. |
4887 | - |
4888 | -from __future__ import generators |
4889 | - |
4890 | -from zope.interface import implements |
4891 | - |
4892 | -from twisted.python import components |
4893 | - |
4894 | -from nevow import inevow |
4895 | -from nevow import tags |
4896 | - |
4897 | -from formless import iformless |
4898 | - |
4899 | - |
4900 | -try: |
4901 | - enumerate = enumerate |
4902 | -except: |
4903 | - def enumerate(collection): |
4904 | - i = 0 |
4905 | - it = iter(collection) |
4906 | - while 1: |
4907 | - yield (i, it.next()) |
4908 | - i += 1 |
4909 | - |
4910 | - |
4911 | -class PrefixerDict(dict): |
4912 | - def __init__(self, prefix, errors): |
4913 | - if prefix is None: prefix = '' |
4914 | - self.prefix = prefix |
4915 | - self.errors = errors |
4916 | - dict.__init__(self) |
4917 | - |
4918 | - def __setitem__(self, key, value): |
4919 | - if key is None: |
4920 | - key = '' |
4921 | - if key == '': |
4922 | - pfxkey = self.prefix |
4923 | - else: |
4924 | - pfxkey = '.'.join((self.prefix, key)) |
4925 | - self.errors[pfxkey] = value |
4926 | - |
4927 | - def __getitem__(self, key): |
4928 | - if key == '': |
4929 | - pfxkey = self.prefix |
4930 | - else: |
4931 | - pfxkey = '.'.join((self.prefix, key)) |
4932 | - return self.errors[pfxkey] |
4933 | - |
4934 | - def update(self, other): |
4935 | - for key, value in other.items(): |
4936 | - self[key] = value |
4937 | - |
4938 | - |
4939 | -class FormDefaults(components.Adapter): |
4940 | - def __init__(self): |
4941 | - self.defaults = {} |
4942 | - |
4943 | - def setDefault(self, key, value, context=None): |
4944 | - self.defaults[key] = value |
4945 | - |
4946 | - def getDefault(self, key, context=None): |
4947 | - #print "getting default for key", key, self.defaults |
4948 | - # 1) Check on the request |
4949 | - current = self.defaults.get(key, None) |
4950 | - if current is None: |
4951 | - # 2) Check on the session |
4952 | - if context is not None: |
4953 | - sessionDefaults = context.locate(iformless.IFormDefaults) |
4954 | - if sessionDefaults is not self: |
4955 | - current = sessionDefaults.getDefault(key) |
4956 | - if current is not None: |
4957 | - return current |
4958 | - # 3) Ask the Binding instance for the default values |
4959 | - try: |
4960 | - configurable = context.locate(iformless.IConfigurable) |
4961 | - except KeyError: |
4962 | - return '' |
4963 | - return configurable.getDefault(context.locate(inevow.IData)) |
4964 | - return current |
4965 | - |
4966 | - def getAllDefaults(self, key): |
4967 | - return PrefixerDict(key, self.defaults) |
4968 | - |
4969 | - def clearAll(self): |
4970 | - self.defaults = {} |
4971 | - |
4972 | - |
4973 | -class FormErrors(components.Adapter): |
4974 | - """An object which keeps track of which forms have which errors |
4975 | - """ |
4976 | - implements(iformless.IFormErrors) |
4977 | - def __init__(self): |
4978 | - self.errors = {} |
4979 | - |
4980 | - def setError(self, errorKey, error): |
4981 | - self.errors[errorKey] = error |
4982 | - |
4983 | - def getError(self, errorKey): |
4984 | - #print "get error", errorKey, self.__dict__ |
4985 | - return self.errors.get(errorKey) |
4986 | - |
4987 | - def getAllErrors(self, formName): |
4988 | - return PrefixerDict(formName, self.errors) |
4989 | - |
4990 | - def updateErrors(self, formName, errors): |
4991 | - PrefixerDict(formName, self.errors).update(errors) |
4992 | - |
4993 | - def clearErrors(self, formName): |
4994 | - for key in self.errors.keys(): |
4995 | - if key.startswith(formName): |
4996 | - del self.errors[key] |
4997 | - |
4998 | - def clearAll(self): |
4999 | - self.errors = {} |
5000 | - |
Not everything being deleted here uses formless. I don't know how many of these Athena examples are still useful (most look either broken or at least very out of date) perhaps exarkun can weigh in on whether deleting Nevow/examples is okay.