| OLD | NEW |
| (Empty) |
| 1 | |
| 2 """ | |
| 3 Woven object collections. | |
| 4 | |
| 5 THIS MODULE IS HIGHLY EXPERIMENTAL AND MAY BE DEPRECATED SOON. | |
| 6 """ | |
| 7 | |
| 8 from __future__ import nested_scopes | |
| 9 | |
| 10 __version__ = "$Revision: 1.13 $"[11:-2] | |
| 11 | |
| 12 | |
| 13 import warnings | |
| 14 warnings.warn("The tapestry module is deprecated. Use page instead.", Deprecatio
nWarning, 1) | |
| 15 | |
| 16 # System Imports | |
| 17 import sys | |
| 18 import os | |
| 19 | |
| 20 # Twisted Imports | |
| 21 | |
| 22 from twisted.internet.defer import Deferred | |
| 23 | |
| 24 from twisted.web.resource import Resource, IResource | |
| 25 from twisted.web.static import redirectTo, addSlash, File, Data | |
| 26 from twisted.web.server import NOT_DONE_YET | |
| 27 from twisted.web import util | |
| 28 | |
| 29 from twisted.python.reflect import qual | |
| 30 | |
| 31 # Sibling Imports | |
| 32 from twisted.web.woven.view import View | |
| 33 | |
| 34 _ChildJuggler = util.DeferredResource | |
| 35 | |
| 36 class ModelLoader(Resource): | |
| 37 """Resource for loading models. (see loadModel) | |
| 38 """ | |
| 39 def __init__(self, parent, templateFile=None): | |
| 40 Resource.__init__(self) | |
| 41 self.parent = parent | |
| 42 self.templateFile = templateFile | |
| 43 | |
| 44 def modelClass(self, other): | |
| 45 return other | |
| 46 | |
| 47 def getChild(self, path, request): | |
| 48 d = self.loadModel(path, request) | |
| 49 templateFile = (self.templateFile or self.__class__.__name__+'.html') | |
| 50 d.addCallback( | |
| 51 lambda result: self.parent.makeView(self.modelClass(result), | |
| 52 templateFile, 1)) | |
| 53 return util.DeferredResource(d) | |
| 54 | |
| 55 def loadModelNow(self, path, request): | |
| 56 """Override this rather than loadModel if your model-loading is | |
| 57 synchronous. | |
| 58 """ | |
| 59 raise NotImplementedError("%s.loadModelNow" % (reflect.qual(self.__class
__))) | |
| 60 | |
| 61 def loadModel(self, path, request): | |
| 62 """Load a model, for the given path and request. | |
| 63 | |
| 64 @rtype: L{Deferred} | |
| 65 """ | |
| 66 from twisted.internet.defer import execute | |
| 67 return execute(self.loadModelNow, path, request) | |
| 68 | |
| 69 | |
| 70 from twisted.web import microdom | |
| 71 from twisted.web import domhelpers | |
| 72 | |
| 73 class TapestryView(View): | |
| 74 tapestry = None | |
| 75 parentCount = 0 | |
| 76 def lookupTemplate(self, request): | |
| 77 fullFile = os.path.join(self.templateDirectory, self.templateFile) | |
| 78 document = microdom.parse(open(fullFile)) | |
| 79 if self.tapestry: | |
| 80 return self.tapestry.templateMutate(document, self.parentCount) | |
| 81 return document | |
| 82 | |
| 83 class Tapestry(Resource): | |
| 84 """ | |
| 85 I am a top-level aggregation of Woven objects: a full `site' or | |
| 86 `application'. | |
| 87 """ | |
| 88 viewFactory = TapestryView | |
| 89 def __init__(self, templateDirectory, viewFactory=None, metaTemplate=None): | |
| 90 """ | |
| 91 Create a tapestry with a specified template directory. | |
| 92 """ | |
| 93 Resource.__init__(self) | |
| 94 self.templateDirectory = templateDirectory | |
| 95 if viewFactory is not None: | |
| 96 self.viewFactory = viewFactory | |
| 97 if metaTemplate: | |
| 98 self.metaTemplate = microdom.parse(open( | |
| 99 os.path.join(templateDirectory, metaTemplate))) | |
| 100 else: | |
| 101 self.metaTemplate = None | |
| 102 | |
| 103 def templateMutate(self, document, parentCount=0): | |
| 104 if self.metaTemplate: | |
| 105 newDoc = self.metaTemplate.cloneNode(1) | |
| 106 if parentCount: | |
| 107 dotdot = parentCount * '../' | |
| 108 for ddname in 'href', 'src', 'action': | |
| 109 for node in domhelpers.findElementsWithAttribute(newDoc, ddn
ame): | |
| 110 node.setAttribute(ddname, dotdot + node.getAttribute(ddn
ame)) | |
| 111 ttl = domhelpers.findNodesNamed(newDoc, "title")[0] | |
| 112 ttl2 = domhelpers.findNodesNamed(document, "title")[0] | |
| 113 ttl.childNodes[:] = [] | |
| 114 for n in ttl2.childNodes: | |
| 115 ttl.appendChild(n) | |
| 116 body = domhelpers.findElementsWithAttribute(newDoc, "class", "__BODY
__")[0] | |
| 117 body2 = domhelpers.findNodesNamed(document, "body")[0] | |
| 118 ndx = body.parentNode.childNodes.index(body) | |
| 119 body.parentNode.childNodes[ndx:ndx+1] = body2.childNodes | |
| 120 for n in body2.childNodes: | |
| 121 n.parentNode = body.parentNode | |
| 122 f = open("garbage.html", "wb") | |
| 123 f.write(newDoc.toprettyxml()) | |
| 124 return newDoc | |
| 125 return document | |
| 126 | |
| 127 def makeView(self, model, name, parentCount=0): | |
| 128 v = self.viewFactory(model, name) | |
| 129 v.parentCount = parentCount | |
| 130 v.templateDirectory = self.templateDirectory | |
| 131 v.tapestry = self | |
| 132 v.importViewLibrary(self) | |
| 133 return v | |
| 134 | |
| 135 def getSubview(self, request, node, model, viewName): | |
| 136 mod = sys.modules[self.__class__.__module__] | |
| 137 # print "I'm getting a subview", mod, viewName | |
| 138 | |
| 139 # try just the name | |
| 140 vm = getattr(mod, viewName, None) | |
| 141 if vm: | |
| 142 return vm(model) | |
| 143 | |
| 144 # try the name + a V | |
| 145 vn2 = "V"+viewName.capitalize() | |
| 146 vm = getattr(mod, vn2, None) | |
| 147 if vm: | |
| 148 return vm(model) | |
| 149 | |
| 150 vm = getattr(self, 'wvfactory_'+viewName, None) | |
| 151 if vm: | |
| 152 return vm(request, node, model) | |
| 153 | |
| 154 def render(self, request): | |
| 155 return redirectTo(addSlash(request), request) | |
| 156 | |
| 157 def getChild(self, path, request): | |
| 158 if path == '': path = 'index' | |
| 159 path = path.replace(".","_") | |
| 160 cm = getattr(self, "wchild_"+path, None) | |
| 161 if cm: | |
| 162 p = cm(request) | |
| 163 if isinstance(p, Deferred): | |
| 164 return util.DeferredResource(p) | |
| 165 adapter = IResource(p, None) | |
| 166 if adapter is not None: | |
| 167 return adapter | |
| 168 # maybe we want direct support for ModelLoader? | |
| 169 # cl = getattr(self, "wload_"+path, None) #??? | |
| 170 return Resource.getChild(self, path, request) | |
| OLD | NEW |