| Index: third_party/twisted_8_1/twisted/web/woven/controller.py
|
| diff --git a/third_party/twisted_8_1/twisted/web/woven/controller.py b/third_party/twisted_8_1/twisted/web/woven/controller.py
|
| deleted file mode 100644
|
| index a7aca0c5d369bb6fd7bb3ba34ddb5a1f473b3eab..0000000000000000000000000000000000000000
|
| --- a/third_party/twisted_8_1/twisted/web/woven/controller.py
|
| +++ /dev/null
|
| @@ -1,436 +0,0 @@
|
| -# -*- test-case-name: twisted.web.test.test_woven -*-
|
| -#
|
| -# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
|
| -# See LICENSE for details.
|
| -
|
| -
|
| -from __future__ import nested_scopes
|
| -
|
| -__version__ = "$Revision: 1.67 $"[11:-2]
|
| -
|
| -import os
|
| -import cgi
|
| -import types
|
| -
|
| -from twisted.python import log
|
| -from twisted.python import components
|
| -from twisted.python import failure
|
| -from zope.interface import implements
|
| -from twisted.web import resource, server, static
|
| -from twisted.web.woven import interfaces, utils
|
| -from twisted.web import woven
|
| -from twisted.web import microdom
|
| -from twisted.web.static import redirectTo, addSlash
|
| -
|
| -import warnings
|
| -from time import time as now
|
| -
|
| -def controllerFactory(controllerClass):
|
| - return lambda request, node, model: controllerClass(model)
|
| -
|
| -def controllerMethod(controllerClass):
|
| - return lambda self, request, node, model: controllerClass(model)
|
| -
|
| -
|
| -class Controller(resource.Resource):
|
| - """
|
| - A Controller which handles to events from the user. Such events
|
| - are `web request', `form submit', etc.
|
| -
|
| - I should be the IResource implementor for your Models (and
|
| - L{registerControllerForModel} makes this so).
|
| - """
|
| -
|
| - implements(interfaces.IController)
|
| - setupStacks = 1
|
| - addSlash = 1 # Should this controller add a slash to the url automatically?
|
| - controllerLibraries = []
|
| - viewFactory = None
|
| - templateDirectory = ""
|
| - def __init__(self, m, inputhandlers=None, view=None, controllers=None, templateDirectory = None):
|
| - #self.start = now()
|
| - resource.Resource.__init__(self)
|
| - self.model = m
|
| - # It's the responsibility of the calling code to make sure setView is
|
| - # called on this controller before it's rendered.
|
| - self.view = None
|
| - self.subcontrollers = []
|
| - if self.setupStacks:
|
| - self.setupControllerStack()
|
| - if inputhandlers is None and controllers is None:
|
| - self._inputhandlers = []
|
| - elif inputhandlers:
|
| - print "The inputhandlers arg is deprecated, please use controllers instead"
|
| - self._inputhandlers = inputhandlers
|
| - else:
|
| - self._inputhandlers = controllers
|
| - if templateDirectory is not None:
|
| - self.templateDirectory = templateDirectory
|
| - self._valid = {}
|
| - self._invalid = {}
|
| - self._process = {}
|
| - self._parent = None
|
| -
|
| - def setupControllerStack(self):
|
| - self.controllerStack = utils.Stack([])
|
| - from twisted.web.woven import input
|
| - if input not in self.controllerLibraries:
|
| - self.controllerLibraries.append(input)
|
| - for library in self.controllerLibraries:
|
| - self.importControllerLibrary(library)
|
| - self.controllerStack.push(self)
|
| -
|
| - def importControllerLibrary(self, namespace):
|
| - if not hasattr(namespace, 'getSubcontroller'):
|
| - namespace.getSubcontroller = utils.createGetFunction(namespace)
|
| - self.controllerStack.push(namespace)
|
| -
|
| - def getSubcontroller(self, request, node, model, controllerName):
|
| - controller = None
|
| - cm = getattr(self, 'wcfactory_' +
|
| - controllerName, None)
|
| - if cm is None:
|
| - cm = getattr(self, 'factory_' +
|
| - controllerName, None)
|
| - if cm is not None:
|
| - warnings.warn("factory_ methods are deprecated; please use "
|
| - "wcfactory_ instead", DeprecationWarning)
|
| - if cm:
|
| - if cm.func_code.co_argcount == 1 and not type(cm) == types.LambdaType:
|
| - warnings.warn("A Controller Factory takes "
|
| - "(request, node, model) "
|
| - "now instead of (model)", DeprecationWarning)
|
| - controller = controllerFactory(model)
|
| - else:
|
| - controller = cm(request, node, model)
|
| - return controller
|
| -
|
| - def setSubcontrollerFactory(self, name, factory, setup=None):
|
| - setattr(self, "wcfactory_" + name, lambda request, node, m:
|
| - factory(m))
|
| -
|
| - def setView(self, view):
|
| - self.view = view
|
| -
|
| - def setNode(self, node):
|
| - self.node = node
|
| -
|
| - def setUp(self, request, *args):
|
| - """
|
| - @type request: L{twisted.web.server.Request}
|
| - """
|
| - pass
|
| -
|
| - def getChild(self, name, request):
|
| - """
|
| - Look for a factory method to create the object to handle the
|
| - next segment of the URL. If a wchild_* method is found, it will
|
| - be called to produce the Resource object to handle the next
|
| - segment of the path. If a wchild_* method is not found,
|
| - getDynamicChild will be called with the name and request.
|
| -
|
| - @param name: The name of the child being requested.
|
| - @type name: string
|
| - @param request: The HTTP request being handled.
|
| - @type request: L{twisted.web.server.Request}
|
| - """
|
| - if not name:
|
| - method = "index"
|
| - else:
|
| - method = name.replace('.', '_')
|
| - f = getattr(self, "wchild_%s" % method, None)
|
| - if f:
|
| - return f(request)
|
| - else:
|
| - child = self.getDynamicChild(name, request)
|
| - if child is None:
|
| - return resource.Resource.getChild(self, name, request)
|
| - else:
|
| - return child
|
| -
|
| - def getDynamicChild(self, name, request):
|
| - """
|
| - This method is called when getChild cannot find a matching wchild_*
|
| - method in the Controller. Override me if you wish to have dynamic
|
| - handling of child pages. Should return a Resource if appropriate.
|
| - Return None to indicate no resource found.
|
| -
|
| - @param name: The name of the child being requested.
|
| - @type name: string
|
| - @param request: The HTTP request being handled.
|
| - @type request: L{twisted.web.server.Request}
|
| - """
|
| - pass
|
| -
|
| - def wchild_index(self, request):
|
| - """By default, we return ourself as the index.
|
| - Override this to provide different behavior
|
| - for a URL that ends in a slash.
|
| - """
|
| - self.addSlash = 0
|
| - return self
|
| -
|
| - def render(self, request):
|
| - """
|
| - Trigger any inputhandlers that were passed in to this Page,
|
| - then delegate to the View for traversing the DOM. Finally,
|
| - call gatheredControllers to deal with any InputHandlers that
|
| - were constructed from any controller= tags in the
|
| - DOM. gatheredControllers will render the page to the browser
|
| - when it is done.
|
| - """
|
| - if self.addSlash and request.uri.split('?')[0][-1] != '/':
|
| - return redirectTo(addSlash(request), request)
|
| - # Handle any inputhandlers that were passed in to the controller first
|
| - for ih in self._inputhandlers:
|
| - ih._parent = self
|
| - ih.handle(request)
|
| - self._inputhandlers = []
|
| - for key, value in self._valid.items():
|
| - key.commit(request, None, value)
|
| - self._valid = {}
|
| - return self.renderView(request)
|
| -
|
| - def makeView(self, model, templateFile=None, parentCount=0):
|
| - if self.viewFactory is None:
|
| - self.viewFactory = self.__class__
|
| - v = self.viewFactory(model, templateFile=templateFile, templateDirectory=self.templateDirectory)
|
| - v.parentCount = parentCount
|
| - v.tapestry = self
|
| - v.importViewLibrary(self)
|
| - return v
|
| -
|
| - def renderView(self, request):
|
| - if self.view is None:
|
| - if self.viewFactory is not None:
|
| - self.setView(self.makeView(self.model, None))
|
| - else:
|
| - self.setView(interfaces.IView(self.model, None))
|
| - self.view.setController(self)
|
| - return self.view.render(request, doneCallback=self.gatheredControllers)
|
| -
|
| - def gatheredControllers(self, v, d, request):
|
| - process = {}
|
| - request.args = {}
|
| - for key, value in self._valid.items():
|
| - key.commit(request, None, value)
|
| - process[key.submodel] = value
|
| - self.process(request, **process)
|
| - #log.msg("Sending page!")
|
| - self.pageRenderComplete(request)
|
| - utils.doSendPage(v, d, request)
|
| - #v.unlinkViews()
|
| -
|
| - #print "Page time: ", now() - self.start
|
| - #return view.View.render(self, request, block=0)
|
| -
|
| - def aggregateValid(self, request, input, data):
|
| - self._valid[input] = data
|
| -
|
| - def aggregateInvalid(self, request, input, data):
|
| - self._invalid[input] = data
|
| -
|
| - def process(self, request, **kwargs):
|
| - if kwargs:
|
| - log.msg("Processing results: ", kwargs)
|
| -
|
| - def setSubmodel(self, submodel):
|
| - self.submodel = submodel
|
| -
|
| - def handle(self, request):
|
| - """
|
| - By default, we don't do anything
|
| - """
|
| - pass
|
| -
|
| - def exit(self, request):
|
| - """We are done handling the node to which this controller was attached.
|
| - """
|
| - pass
|
| -
|
| - def domChanged(self, request, widget, node):
|
| - parent = getattr(self, '_parent', None)
|
| - if parent is not None:
|
| - parent.domChanged(request, widget, node)
|
| -
|
| - def pageRenderComplete(self, request):
|
| - """Override this to recieve notification when the view rendering
|
| - process is complete.
|
| - """
|
| - pass
|
| -
|
| -WOVEN_PATH = os.path.split(woven.__file__)[0]
|
| -
|
| -class LiveController(Controller):
|
| - """A Controller that encapsulates logic that makes it possible for this
|
| - page to be "Live". A live page can have it's content updated after the
|
| - page has been sent to the browser, and can translate client-side
|
| - javascript events into server-side events.
|
| - """
|
| - pageSession = None
|
| - def render(self, request):
|
| - """First, check to see if this request is attempting to hook up the
|
| - output conduit. If so, do it. Otherwise, unlink the current session's
|
| - View from the MVC notification infrastructure, then render the page
|
| - normally.
|
| - """
|
| - # Check to see if we're hooking up an output conduit
|
| - sess = request.getSession(interfaces.IWovenLivePage)
|
| - #print "REQUEST.ARGS", request.args
|
| - if request.args.has_key('woven_hookupOutputConduitToThisFrame'):
|
| - sess.hookupOutputConduit(request)
|
| - return server.NOT_DONE_YET
|
| - if request.args.has_key('woven_clientSideEventName'):
|
| - try:
|
| - request.d = microdom.parseString('<xml/>', caseInsensitive=0, preserveCase=0)
|
| - eventName = request.args['woven_clientSideEventName'][0]
|
| - eventTarget = request.args['woven_clientSideEventTarget'][0]
|
| - eventArgs = request.args.get('woven_clientSideEventArguments', [])
|
| - #print "EVENT", eventName, eventTarget, eventArgs
|
| - return self.clientToServerEvent(request, eventName, eventTarget, eventArgs)
|
| - except:
|
| - fail = failure.Failure()
|
| - self.view.renderFailure(fail, request)
|
| - return server.NOT_DONE_YET
|
| -
|
| - # Unlink the current page in this user's session from MVC notifications
|
| - page = sess.getCurrentPage()
|
| - #request.currentId = getattr(sess, 'currentId', 0)
|
| - if page is not None:
|
| - page.view.unlinkViews()
|
| - sess.setCurrentPage(None)
|
| - #print "PAGE SESSION IS NONE"
|
| - self.pageSession = None
|
| - return Controller.render(self, request)
|
| -
|
| - def clientToServerEvent(self, request, eventName, eventTarget, eventArgs):
|
| - """The client sent an asynchronous event to the server.
|
| - Locate the View object targeted by this event and attempt
|
| - to call onEvent on it.
|
| - """
|
| - sess = request.getSession(interfaces.IWovenLivePage)
|
| - self.view = sess.getCurrentPage().view
|
| - #request.d = self.view.d
|
| - print "clientToServerEvent", eventTarget
|
| - target = self.view.subviews[eventTarget]
|
| - print "target, parent", target, target.parent
|
| - #target.parent = self.view
|
| - #target.controller._parent = self
|
| -
|
| - ## From the time we call onEvent until it returns, we want all
|
| - ## calls to IWovenLivePage.sendScript to be appended to this
|
| - ## list so we can spit them out in the response, immediately
|
| - ## below.
|
| - scriptOutput = []
|
| - orig = sess.sendScript
|
| - sess.sendScript = scriptOutput.append
|
| - target.onEvent(request, eventName, *eventArgs)
|
| - sess.sendScript = orig
|
| -
|
| - scriptOutput.append('parent.woven_clientToServerEventComplete()')
|
| -
|
| - #print "GATHERED JS", scriptOutput
|
| -
|
| - return '''<html>
|
| -<body>
|
| - <script language="javascript">
|
| - %s
|
| - </script>
|
| - %s event sent to %s (%s) with arguments %s.
|
| -</body>
|
| -</html>''' % ('\n'.join(scriptOutput), eventName, cgi.escape(str(target)), eventTarget, eventArgs)
|
| -
|
| - def gatheredControllers(self, v, d, request):
|
| - Controller.gatheredControllers(self, v, d, request)
|
| - sess = request.getSession(interfaces.IWovenLivePage)
|
| - self.pageSession = sess
|
| - sess.setCurrentPage(self)
|
| - sess.currentId = request.currentId
|
| -
|
| - def domChanged(self, request, widget, node):
|
| - sess = request.getSession(interfaces.IWovenLivePage)
|
| - print "domchanged"
|
| - if sess is not None:
|
| - if not hasattr(node, 'getAttribute'):
|
| - return
|
| - page = sess.getCurrentPage()
|
| - if page is None:
|
| - return
|
| - nodeId = node.getAttribute('id')
|
| - #logger.warn("DOM for %r is changing to %s", nodeId, node.toprettyxml())
|
| - nodeXML = node.toxml()
|
| - nodeXML = nodeXML.replace("\\", "\\\\")
|
| - nodeXML = nodeXML.replace("'", "\\'")
|
| - nodeXML = nodeXML.replace('"', '\\"')
|
| - nodeXML = nodeXML.replace('\n', '\\n')
|
| - nodeXML = nodeXML.replace('\r', ' ')
|
| - nodeXML = nodeXML.replace('\b', ' ')
|
| - nodeXML = nodeXML.replace('\t', ' ')
|
| - nodeXML = nodeXML.replace('\000', ' ')
|
| - nodeXML = nodeXML.replace('\v', ' ')
|
| - nodeXML = nodeXML.replace('\f', ' ')
|
| -
|
| - js = "parent.woven_replaceElement('%s', '%s')" % (nodeId, nodeXML)
|
| - #for key in widget.subviews.keys():
|
| - # view.subviews[key].unlinkViews()
|
| - oldNode = page.view.subviews[nodeId]
|
| - for id, subview in oldNode.subviews.items():
|
| - subview.unlinkViews()
|
| - topSubviews = page.view.subviews
|
| - #print "Widgetid, subviews", id(widget), widget.subviews
|
| - if widget.subviews:
|
| - def recurseSubviews(w):
|
| - #print "w.subviews", w.subviews
|
| - topSubviews.update(w.subviews)
|
| - for id, sv in w.subviews.items():
|
| - recurseSubviews(sv)
|
| - #print "recursing"
|
| - recurseSubviews(widget)
|
| - #page.view.subviews.update(widget.subviews)
|
| - sess.sendScript(js)
|
| -
|
| - def wchild_WebConduit2_js(self, request):
|
| - #print "returning js file"
|
| - h = request.getHeader("user-agent")
|
| - if h.count("MSIE"):
|
| - fl = "WebConduit2_msie.js"
|
| - else:
|
| - fl = "WebConduit2_mozilla.js"
|
| -
|
| - return static.File(os.path.join(WOVEN_PATH, fl))
|
| -
|
| - def wchild_FlashConduit_swf(self, request):
|
| - #print "returning flash file"
|
| - h = request.getHeader("user-agent")
|
| - if h.count("MSIE"):
|
| - fl = "FlashConduit.swf"
|
| - else:
|
| - fl = "FlashConduit.swf"
|
| - return static.File(os.path.join(WOVEN_PATH, fl))
|
| -
|
| - def wchild_input_html(self, request):
|
| - return BlankPage()
|
| -
|
| -
|
| -class BlankPage(resource.Resource):
|
| - def render(self, request):
|
| - return "<html>This space intentionally left blank</html>"
|
| -
|
| -
|
| -WController = Controller
|
| -
|
| -def registerControllerForModel(controller, model):
|
| - """
|
| - Registers `controller' as an adapter of `model' for IController, and
|
| - optionally registers it for IResource, if it implements it.
|
| -
|
| - @param controller: A class that implements L{interfaces.IController}, usually a
|
| - L{Controller} subclass. Optionally it can implement
|
| - L{resource.IResource}.
|
| - @param model: Any class, but probably a L{twisted.web.woven.model.Model}
|
| - subclass.
|
| - """
|
| - components.registerAdapter(controller, model, interfaces.IController)
|
| - if resource.IResource.implementedBy(controller):
|
| - components.registerAdapter(controller, model, resource.IResource)
|
| -
|
|
|