| 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 |