OLD | NEW |
| (Empty) |
1 # -*- test-case-name: twisted.web.test.test_woven -*- | |
2 # | |
3 # Copyright (c) 2001-2004 Twisted Matrix Laboratories. | |
4 # See LICENSE for details. | |
5 | |
6 | |
7 from __future__ import nested_scopes | |
8 | |
9 __version__ = "$Revision: 1.91 $"[11:-2] | |
10 | |
11 # Sibling imports | |
12 import interfaces | |
13 import utils | |
14 import controller | |
15 from utils import doSendPage | |
16 import model | |
17 | |
18 # Twisted imports | |
19 from twisted.internet import defer | |
20 from twisted.python import components | |
21 from twisted.python import log | |
22 from twisted.web import resource, microdom, html, error | |
23 from twisted.web.server import NOT_DONE_YET | |
24 from zope.interface import implements | |
25 | |
26 try: | |
27 import cPickle as pickle | |
28 except ImportError: | |
29 import pickle | |
30 | |
31 import os | |
32 import sys | |
33 import stat | |
34 import warnings | |
35 import types | |
36 | |
37 | |
38 def peek(stack): | |
39 if stack is None: | |
40 return None | |
41 it = None | |
42 while it is None and stack is not None: | |
43 it, stack = stack | |
44 return it | |
45 | |
46 | |
47 def poke(stack, new): | |
48 it, stack = stack | |
49 return (new, stack) | |
50 | |
51 | |
52 def filterStack(stack): | |
53 returnVal = [] | |
54 while stack is not None: | |
55 it, stack = stack | |
56 if it is not None: | |
57 returnVal.append(it) | |
58 return returnVal | |
59 | |
60 | |
61 def viewFactory(viewClass): | |
62 return lambda request, node, model: viewClass(model) | |
63 | |
64 def viewMethod(viewClass): | |
65 return lambda self, request, node, model: viewClass(model) | |
66 | |
67 | |
68 templateCache = {} | |
69 | |
70 | |
71 class View: | |
72 implements(resource.IResource, interfaces.IView) | |
73 # wvfactory_xxx method signature: request, node, model; returns Widget | |
74 # wvupdate_xxx method signature: request, widget, data; mutates widget | |
75 # based on data (not necessarily an IModel; | |
76 # has been unwrapped at this point) | |
77 | |
78 wantsAllNotifications = 0 | |
79 templateFile = '' | |
80 templateDirectory = '' | |
81 template = '' | |
82 | |
83 isLeaf = 1 | |
84 | |
85 def getChild(self, path, request): | |
86 return error.NoResource("No such child resource.") | |
87 | |
88 def getChildWithDefault(self, path, request): | |
89 return self.getChild(path, request) | |
90 | |
91 viewLibraries = [] | |
92 setupStacks = 1 | |
93 livePage = 0 | |
94 doneCallback = None | |
95 templateNode = None | |
96 def __init__(self, m, templateFile=None, templateDirectory=None, template=No
ne, controller=None, doneCallback=None, modelStack=None, viewStack=None, control
lerStack=None): | |
97 """ | |
98 A view must be told what its model is, and may be told what its | |
99 controller is, but can also look up its controller if none specified. | |
100 """ | |
101 if not interfaces.IModel.providedBy(m): | |
102 m = model.adaptToIModel(m, None, None) | |
103 self.model = self.mainModel = m | |
104 # It's the responsibility of the calling code to make sure | |
105 # setController is called on this view before it's rendered. | |
106 self.controller = None | |
107 self.subviews = {} | |
108 if self.setupStacks: | |
109 self.modelStack = None | |
110 self.viewStack = None | |
111 self.controllerStack = None | |
112 if doneCallback is None and self.doneCallback is None: | |
113 self.doneCallback = doSendPage | |
114 else: | |
115 print "DoneCallback", doneCallback | |
116 self.doneCallback = doneCallback | |
117 if template is not None: | |
118 self.template = template | |
119 if templateFile is not None: | |
120 self.templateFile = templateFile | |
121 if templateDirectory is not None: | |
122 self.templateDirectory = templateDirectory | |
123 | |
124 self.outstandingCallbacks = 0 | |
125 self.outstandingNodes = [] | |
126 self.failed = 0 | |
127 self.setupMethods = [] | |
128 | |
129 def setupAllStacks(self): | |
130 self.modelStack = (self.model, None) | |
131 self.controllerStack = (self.controller, (input, None)) | |
132 self.setupViewStack() | |
133 | |
134 def setUp(self, request, d): | |
135 pass | |
136 | |
137 def setupViewStack(self): | |
138 self.viewStack = None | |
139 if widgets not in self.viewLibraries: | |
140 self.viewLibraries.append(widgets) | |
141 for library in self.viewLibraries: | |
142 if not hasattr(library, 'getSubview'): | |
143 library.getSubview = utils.createGetFunction(library) | |
144 self.viewStack = (library, self.viewStack) | |
145 self.viewStack = (self, self.viewStack) | |
146 | |
147 def importViewLibrary(self, namespace): | |
148 self.viewLibraries.append(namespace) | |
149 return self | |
150 | |
151 def render(self, request, doneCallback=None): | |
152 if not getattr(request, 'currentId', 0): | |
153 request.currentId = 0 | |
154 request.currentPage = self | |
155 if self.controller is None: | |
156 self.controller = controller.Controller(self.model) | |
157 if doneCallback is not None: | |
158 self.doneCallback = doneCallback | |
159 else: | |
160 self.doneCallback = doSendPage | |
161 self.setupAllStacks() | |
162 template = self.getTemplate(request) | |
163 if template: | |
164 self.d = microdom.parseString(template, caseInsensitive=0, preserveC
ase=0) | |
165 else: | |
166 if not self.templateFile: | |
167 raise AttributeError, "%s does not define self.templateFile to o
perate on" % self.__class__ | |
168 self.d = self.lookupTemplate(request) | |
169 request.d = self.d | |
170 self.handleDocument(request, self.d) | |
171 return NOT_DONE_YET | |
172 | |
173 def getTemplate(self, request): | |
174 """ | |
175 Override this if you want to have your subclass look up its template | |
176 using a different method. | |
177 """ | |
178 return self.template | |
179 | |
180 def lookupTemplate(self, request): | |
181 """ | |
182 Use acquisition to look up the template named by self.templateFile, | |
183 located anywhere above this object in the heirarchy, and use it | |
184 as the template. The first time the template is used it is cached | |
185 for speed. | |
186 """ | |
187 if self.template: | |
188 return microdom.parseString(self.template, caseInsensitive=0, preser
veCase=0) | |
189 if not self.templateDirectory: | |
190 mod = sys.modules[self.__module__] | |
191 if hasattr(mod, '__file__'): | |
192 self.templateDirectory = os.path.split(mod.__file__)[0] | |
193 # First see if templateDirectory + templateFile is a file | |
194 templatePath = os.path.join(self.templateDirectory, self.templateFile) | |
195 if not os.path.exists(templatePath): | |
196 raise RuntimeError, "The template %r was not found." % templatePath | |
197 # Check to see if there is an already parsed copy of it | |
198 mtime = os.path.getmtime(templatePath) | |
199 cachedTemplate = templateCache.get(templatePath, None) | |
200 compiledTemplate = None | |
201 | |
202 if cachedTemplate is not None: | |
203 if cachedTemplate[0] == mtime: | |
204 compiledTemplate = templateCache[templatePath][1].cloneNode(deep
=1) | |
205 | |
206 if compiledTemplate is None: | |
207 compiledTemplate = microdom.parse(templatePath, caseInsensitive=0, p
reserveCase=0) | |
208 templateCache[templatePath] = (mtime, compiledTemplate.cloneNode(dee
p=1)) | |
209 return compiledTemplate | |
210 | |
211 def handleDocument(self, request, document): | |
212 """Handle the root node, and send the page if there are no | |
213 outstanding callbacks when it returns. | |
214 """ | |
215 try: | |
216 request.d = document | |
217 self.setUp(request, document) | |
218 # Don't let outstandingCallbacks get to 0 until the | |
219 # entire tree has been recursed | |
220 # If you don't do this, and any callback has already | |
221 # completed by the time the dispatchResultCallback | |
222 # is added in dispachResult, then sendPage will be | |
223 # called prematurely within dispatchResultCallback | |
224 # resulting in much gnashing of teeth. | |
225 self.outstandingNodes = document.childNodes[:] + [1] | |
226 self.outstandingNodes.reverse() | |
227 | |
228 self.outstandingCallbacks += 1 | |
229 self.handleOutstanding(request) | |
230 self.outstandingCallbacks -= 1 | |
231 if not self.outstandingCallbacks: | |
232 return self.sendPage(request) | |
233 except: | |
234 self.renderFailure(None, request) | |
235 | |
236 def handleOutstanding(self, request): | |
237 while self.outstandingNodes: | |
238 node = self.outstandingNodes.pop() | |
239 if node is 1: | |
240 self.modelStack = self.modelStack[1] | |
241 self.viewStack = self.viewStack[1] | |
242 if self.controllerStack is not None: | |
243 controller, self.controllerStack = self.controllerStack | |
244 if controller is not None: | |
245 controller.exit(request) | |
246 attrs = getattr(node, 'attributes', None) | |
247 if (attrs is not None and | |
248 (attrs.get('model') or attrs.get('view') or attrs.get('controller'))
): | |
249 self.outstandingNodes.append(1) | |
250 self.handleNode(request, node) | |
251 else: | |
252 if attrs is not None and (attrs.get('view') or attrs.get('contro
ller')): | |
253 self.outstandingNodes.append(node) | |
254 if hasattr(node, 'childNodes') and node.childNodes: | |
255 self.recurseChildren(request, node) | |
256 | |
257 def recurseChildren(self, request, node): | |
258 """If this node has children, handle them. | |
259 """ | |
260 new = node.childNodes[:] | |
261 new.reverse() | |
262 self.outstandingNodes.extend(new) | |
263 | |
264 def dispatchResult(self, request, node, result): | |
265 """Check a given result from handling a node and look up a NodeMutator | |
266 adapter which will convert the result into a node and insert it | |
267 into the DOM tree. Return the new node. | |
268 """ | |
269 if not isinstance(result, defer.Deferred): | |
270 if node.parentNode is not None: | |
271 node.parentNode.replaceChild(result, node) | |
272 else: | |
273 raise RuntimeError, "We're dying here, please report this immedi
ately" | |
274 else: | |
275 self.outstandingCallbacks += 1 | |
276 result.addCallback(self.dispatchResultCallback, request, node) | |
277 result.addErrback(self.renderFailure, request) | |
278 # Got to wait until the callback comes in | |
279 return result | |
280 | |
281 def modelChanged(self, changed): | |
282 """Rerender this view, because our model has changed. | |
283 """ | |
284 # arg. this needs to go away. | |
285 request = changed.get('request', None) | |
286 oldNode = self.node | |
287 #import pdb; pdb.set_trace() | |
288 newNode = self.generate(request, oldNode) | |
289 returnNode = self.dispatchResult(request, oldNode, newNode) | |
290 self.handleNewNode(request, returnNode) | |
291 self.handleOutstanding(request) | |
292 self.controller.domChanged(request, self, returnNode) | |
293 | |
294 def generate(self, request, node): | |
295 """Allow a view to be used like a widget. Will look up the template | |
296 file and return it in place of the incoming node. | |
297 """ | |
298 newNode = self.lookupTemplate(request).childNodes[0] | |
299 newNode.setAttribute('id', 'woven_id_%s' % id(self)) | |
300 self.node = newNode | |
301 return newNode | |
302 | |
303 def setController(self, controller): | |
304 self.controller = controller | |
305 self.controllerStack = (controller, self.controllerStack) | |
306 | |
307 def setNode(self, node): | |
308 if self.templateNode == None: | |
309 self.templateNode = node | |
310 self.node = node | |
311 | |
312 def setSubmodel(self, name): | |
313 self.submodel = name | |
314 | |
315 def getNodeModel(self, request, node, submodel): | |
316 """ | |
317 Get the model object associated with this node. If this node has a | |
318 model= attribute, call getSubmodel on the current model object. | |
319 If not, return the top of the model stack. | |
320 """ | |
321 parent = None | |
322 if submodel: | |
323 if submodel == '.': | |
324 m = peek(self.modelStack) | |
325 else: | |
326 modelStack = self.modelStack | |
327 while modelStack is not None: | |
328 parent, modelStack = modelStack | |
329 if parent is None: | |
330 continue | |
331 m = parent.lookupSubmodel(request, submodel) | |
332 if m is not None: | |
333 #print "model", m | |
334 break | |
335 else: | |
336 raise Exception("Node had a model=%s " | |
337 "attribute, but the submodel was not " | |
338 "found in %s." % (submodel, | |
339 filterStack(self.modelStack))) | |
340 else: | |
341 m = None | |
342 self.modelStack = (m, self.modelStack) | |
343 if m is not None: | |
344 # print "M NAME", m.name | |
345 # if parent is not m: | |
346 # m.parent = parent | |
347 # if not getattr(m, 'name', None): | |
348 # m.name = submodel | |
349 return m | |
350 #print `submodel`, self.getTopOfModelStack() | |
351 if submodel: | |
352 return peek(self.modelStack) | |
353 return None | |
354 | |
355 def getNodeController(self, request, node, submodel, model): | |
356 """ | |
357 Get a controller object to handle this node. If the node has no | |
358 controller= attribute, first check to see if there is an IController | |
359 adapter for our model. | |
360 """ | |
361 controllerName = node.attributes.get('controller') | |
362 controller = None | |
363 | |
364 if model is None: | |
365 model = peek(self.modelStack) | |
366 | |
367 # Look up a controller factory. | |
368 if controllerName: | |
369 #if not node.hasAttribute('name'): | |
370 # warnings.warn("POTENTIAL ERROR: %s had a controller, but not a
" | |
371 # "'name' attribute." % node) | |
372 controllerStack = self.controllerStack | |
373 while controllerStack is not None: | |
374 namespace, controllerStack = controllerStack | |
375 if namespace is None: | |
376 continue | |
377 controller = namespace.getSubcontroller(request, node, model, co
ntrollerName) | |
378 if controller is not None: | |
379 break | |
380 else: | |
381 raise NotImplementedError("You specified controller name %s on " | |
382 "a node, but no wcfactory_%s method " | |
383 "was found in %s." % (controllerName, | |
384 controllerName, | |
385 filterStack(self.controllerStack) | |
386 )) | |
387 elif node.attributes.get("model"): | |
388 # If no "controller" attribute was specified on the node, see if | |
389 # there is a IController adapter registerred for the model. | |
390 controller = interfaces.IController( | |
391 model, | |
392 None) | |
393 | |
394 return controller | |
395 | |
396 | |
397 def getSubview(self, request, node, model, viewName): | |
398 """Get a sub-view from me. | |
399 | |
400 @returns: L{widgets.Widget} | |
401 """ | |
402 view = None | |
403 vm = getattr(self, 'wvfactory_' + viewName, None) | |
404 if vm is None: | |
405 vm = getattr(self, 'factory_' + viewName, None) | |
406 if vm is not None: | |
407 warnings.warn("factory_ methods are deprecated; please use " | |
408 "wvfactory_ instead", DeprecationWarning) | |
409 if vm: | |
410 if vm.func_code.co_argcount == 3 and not type(vm) == types.LambdaTyp
e: | |
411 warnings.warn("wvfactory_ methods take (request, node, " | |
412 "model) instead of (request, node) now. \n" | |
413 "Please instantiate your widgets with a " | |
414 "reference to model instead of self.model", | |
415 DeprecationWarning) | |
416 self.model = model | |
417 view = vm(request, node) | |
418 self.model = self.mainModel | |
419 else: | |
420 view = vm(request, node, model) | |
421 | |
422 setupMethod = getattr(self, 'wvupdate_' + viewName, None) | |
423 if setupMethod: | |
424 if view is None: | |
425 view = widgets.Widget(model) | |
426 view.setupMethods.append(setupMethod) | |
427 return view | |
428 | |
429 | |
430 def getNodeView(self, request, node, submodel, model): | |
431 view = None | |
432 viewName = node.attributes.get('view') | |
433 | |
434 if model is None: | |
435 model = peek(self.modelStack) | |
436 | |
437 # Look up a view factory. | |
438 if viewName: | |
439 viewStack = self.viewStack | |
440 while viewStack is not None: | |
441 namespace, viewStack = viewStack | |
442 if namespace is None: | |
443 continue | |
444 try: | |
445 view = namespace.getSubview(request, node, model, viewName) | |
446 except AttributeError: | |
447 # Was that from something in the viewStack that didn't | |
448 # have a getSubview? | |
449 if not hasattr(namespace, "getSubview"): | |
450 log.msg("Warning: There is no getSubview on %r" % | |
451 (namespace,)) | |
452 continue | |
453 else: | |
454 # No, something else is really broken. | |
455 raise | |
456 if view is not None: | |
457 break | |
458 else: | |
459 raise NotImplementedError( | |
460 "You specified view name %s on a node %s, but no " | |
461 "wvfactory_%s method was found in %s. (Or maybe they were " | |
462 "found but they returned None.)" % ( | |
463 viewName, node, viewName, | |
464 filterStack(self.viewStack))) | |
465 elif node.attributes.get("model"): | |
466 # If no "view" attribute was specified on the node, see if there | |
467 # is a IView adapter registerred for the model. | |
468 # First, see if the model is Componentized. | |
469 if isinstance(model, components.Componentized): | |
470 view = model.getAdapter(interfaces.IView) | |
471 if not view and hasattr(model, '__class__'): | |
472 view = interfaces.IView(model, None) | |
473 | |
474 return view | |
475 | |
476 def handleNode(self, request, node): | |
477 submodelName = node.attributes.get('model') | |
478 if submodelName is None: | |
479 submodelName = "" | |
480 model = self.getNodeModel(request, node, submodelName) | |
481 view = self.getNodeView(request, node, submodelName, model) | |
482 controller = self.getNodeController(request, node, submodelName, model) | |
483 if view or controller: | |
484 if model is None: | |
485 model = peek(self.modelStack) | |
486 if not view or not isinstance(view, View): | |
487 view = widgets.DefaultWidget(model) | |
488 | |
489 if not controller: | |
490 controller = input.DefaultHandler(model) | |
491 | |
492 prevView, stack = self.viewStack | |
493 while isinstance(prevView, widgets.DefaultWidget) and stack is not N
one: | |
494 prevView, stack = stack | |
495 if prevView is None: | |
496 prevMod = None | |
497 else: | |
498 prevMod = prevView.model | |
499 if model is not prevMod and not isinstance(view, widgets.DefaultWidg
et): | |
500 model.addView(view) | |
501 submodelList = [x.name for x in filterStack(self.modelStack) if x.na
me] | |
502 submodelList.reverse() | |
503 submodelName = '/'.join(submodelList) | |
504 if not getattr(view, 'submodel', None): | |
505 view.submodel = submodelName | |
506 | |
507 theId = node.attributes.get("id") | |
508 if self.livePage and not theId: | |
509 theId = "woven_id_%d" % id(view) | |
510 view.setupMethods.append(utils.createSetIdFunction(theId)) | |
511 view.outgoingId = theId | |
512 #print "SET AN ID", theId | |
513 self.subviews[theId] = view | |
514 view.parent = peek(self.viewStack) | |
515 view.parent.subviews[theId] = view | |
516 # If a Widget was constructed directly with a model that so far | |
517 # is not in modelspace, we should put it on the stack so other | |
518 # Widgets below this one can find it. | |
519 if view.model is not peek(self.modelStack): | |
520 self.modelStack = poke(self.modelStack, view.model) | |
521 | |
522 cParent = peek(self.controllerStack) | |
523 if controller._parent is None or cParent != controller: | |
524 controller._parent = cParent | |
525 | |
526 self.controllerStack = (controller, self.controllerStack) | |
527 self.viewStack = (view, self.viewStack) | |
528 | |
529 view.viewStack = self.viewStack | |
530 view.controllerStack = self.controllerStack | |
531 view.modelStack = self.modelStack | |
532 | |
533 view.setController(controller) | |
534 view.setNode(node) | |
535 | |
536 if not getattr(controller, 'submodel', None): | |
537 controller.setSubmodel(submodelName) | |
538 | |
539 controller.setView(view) | |
540 controller.setNode(node) | |
541 | |
542 controllerResult = controller.handle(request) | |
543 if controllerResult is not None: | |
544 ## It's a deferred | |
545 controller | |
546 self.outstandingCallbacks += 1 | |
547 controllerResult.addCallback( | |
548 self.handleControllerResults, | |
549 request, | |
550 node, | |
551 controller, | |
552 view) | |
553 controllerResult.addErrback(self.renderFailure, request) | |
554 else: | |
555 viewResult = view.generate(request, node) | |
556 returnNode = self.dispatchResult(request, node, viewResult) | |
557 self.handleNewNode(request, returnNode) | |
558 else: | |
559 self.controllerStack = (controller, self.controllerStack) | |
560 self.viewStack = (view, self.viewStack) | |
561 | |
562 def handleControllerResults(self, | |
563 controllerResult, request, node, controller, view): | |
564 """Handle a deferred from a controller. | |
565 """ | |
566 self.outstandingCallbacks -= 1 | |
567 if isinstance(controllerResult, defer.Deferred): | |
568 self.outstandingCallbacks += 1 | |
569 controllerResult.addCallback( | |
570 self.handleControllerResults, | |
571 request, | |
572 node, | |
573 controller, | |
574 view) | |
575 controllerResult.addErrback(self.renderFailure, request) | |
576 else: | |
577 viewResult = view.generate(request, node) | |
578 returnNode = self.dispatchResult(request, node, viewResult) | |
579 self.handleNewNode(request, returnNode) | |
580 return controllerResult | |
581 | |
582 def handleNewNode(self, request, returnNode): | |
583 if not isinstance(returnNode, defer.Deferred): | |
584 self.recurseChildren(request, returnNode) | |
585 else: | |
586 # TODO: Need to handle deferreds here? | |
587 pass | |
588 | |
589 def sendPage(self, request): | |
590 """ | |
591 Check to see if handlers recorded any errors before sending the page | |
592 """ | |
593 self.doneCallback(self, self.d, request) | |
594 | |
595 def setSubviewFactory(self, name, factory, setup=None, *args, **kwargs): | |
596 setattr(self, "wvfactory_" + name, lambda request, node, m: | |
597 factory(m, *args, **kwargs)) | |
598 if setup: | |
599 setattr(self, "wvupdate_" + name, setup) | |
600 | |
601 def __setitem__(self, key, value): | |
602 pass | |
603 | |
604 def unlinkViews(self): | |
605 #print "unlinking views" | |
606 self.model.removeView(self) | |
607 for key, value in self.subviews.items(): | |
608 value.unlinkViews() | |
609 # value.model.removeView(value) | |
610 | |
611 def dispatchResultCallback(self, result, request, node): | |
612 """Deal with a callback from a deferred, checking to see if it is | |
613 ok to send the page yet or not. | |
614 """ | |
615 self.outstandingCallbacks -= 1 | |
616 #node = self.dispatchResult(request, node, result) | |
617 #self.recurseChildren(request, node) | |
618 if not self.outstandingCallbacks: | |
619 self.sendPage(request) | |
620 return result | |
621 | |
622 def renderFailure(self, failure, request): | |
623 try: | |
624 xml = request.d.toprettyxml() | |
625 except: | |
626 xml = "" | |
627 # if not hasattr(request, 'channel'): | |
628 # log.msg("The request got away from me before I could render an err
or page.") | |
629 # log.err(failure) | |
630 # return failure | |
631 if not self.failed: | |
632 self.failed = 1 | |
633 if failure: | |
634 request.write("<html><head><title>%s: %s</title></head><body>\n"
% (html.escape(str(failure.type)), html.escape(str(failure.value)))) | |
635 else: | |
636 request.write("<html><head><title>Failure!</title></head><body>\
n") | |
637 utils.renderFailure(failure, request) | |
638 request.write("<h3>Here is the partially processed DOM:</h3>") | |
639 request.write("\n<pre>\n") | |
640 request.write(html.escape(xml)) | |
641 request.write("\n</pre>\n") | |
642 request.write("</body></html>") | |
643 request.finish() | |
644 return failure | |
645 | |
646 class LiveView(View): | |
647 livePage = 1 | |
648 def wvfactory_webConduitGlue(self, request, node, m): | |
649 if request.getHeader("user-agent").count("MSIE"): | |
650 return View(m, templateFile="FlashConduitGlue.html") | |
651 else: | |
652 return View(m, templateFile="WebConduitGlue.html") | |
653 | |
654 def wvupdate_woven_flashConduitSessionView(self, request, wid, mod): | |
655 #print "updating flash thingie" | |
656 uid = request.getSession().uid | |
657 n = wid.templateNode | |
658 if n.attributes.has_key('src'): | |
659 n.attributes['src'] = n.attributes.get('src') + '?twisted_session='
+ str(uid) | |
660 else: | |
661 n.attributes['value'] = n.attributes.get('value') + '?twisted_sessio
n=' + str(uid) | |
662 #print wid.templateNode.toxml() | |
663 | |
664 | |
665 #backwards compatibility | |
666 WView = View | |
667 | |
668 | |
669 def registerViewForModel(view, model): | |
670 """ | |
671 Registers `view' as an adapter of `model' for L{interfaces.IView}. | |
672 """ | |
673 components.registerAdapter(view, model, interfaces.IView) | |
674 # adapter = resource.IResource(model, None) | |
675 # if adapter is None and resource.IResource.providedBy(view): | |
676 # components.registerAdapter(view, model, resource.IResource) | |
677 | |
678 | |
679 | |
680 #sibling imports:: | |
681 | |
682 # If no widget/handler was found in the container controller or view, these | |
683 # modules will be searched. | |
684 | |
685 import input | |
686 import widgets | |
687 | |
OLD | NEW |