"""
Woven object collections.
THIS MODULE IS HIGHLY EXPERIMENTAL AND MAY BE DEPRECATED SOON.
"""
from __future__ import nested_scopes
__version__ = "$Revision: 1.13 $"[11:-2]
import warnings
warnings.warn("The tapestry module is deprecated. Use page instead.", DeprecationWarning, 1)
# System Imports
import sys
import os
# Twisted Imports
from twisted.internet.defer import Deferred
from twisted.web.resource import Resource, IResource
from twisted.web.static import redirectTo, addSlash, File, Data
from twisted.web.server import NOT_DONE_YET
from twisted.web import util
from twisted.python.reflect import qual
from twisted.python import components
# Sibling Imports
from twisted.web.woven.view import View
_ChildJuggler = util.DeferredResource
class ModelLoader(Resource):
"""Resource for loading models. (see loadModel)
"""
def __init__(self, parent, templateFile=None):
Resource.__init__(self)
self.parent = parent
self.templateFile = templateFile
def modelClass(self, other):
return other
def getChild(self, path, request):
d = self.loadModel(path, request)
templateFile = (self.templateFile or self.__class__.__name__+'.html')
d.addCallback(
lambda result: self.parent.makeView(self.modelClass(result),
templateFile, 1))
return util.DeferredResource(d)
def loadModelNow(self, path, request):
"""Override this rather than loadModel if your model-loading is
synchronous.
"""
raise NotImplementedError("%s.loadModelNow" % (reflect.qual(self.__class__)))
def loadModel(self, path, request):
"""Load a model, for the given path and request.
@rtype: L{Deferred}
"""
from twisted.internet.defer import execute
return execute(self.loadModelNow, path, request)
from twisted.web import microdom
from twisted.web import domhelpers
class TapestryView(View):
tapestry = None
parentCount = 0
def lookupTemplate(self, request):
fullFile = os.path.join(self.templateDirectory, self.templateFile)
document = microdom.parse(open(fullFile))
if self.tapestry:
return self.tapestry.templateMutate(document, self.parentCount)
return document
class Tapestry(Resource):
"""
I am a top-level aggregation of Woven objects: a full `site' or
`application'.
"""
viewFactory = TapestryView
def __init__(self, templateDirectory, viewFactory=None, metaTemplate=None):
"""
Create a tapestry with a specified template directory.
"""
Resource.__init__(self)
self.templateDirectory = templateDirectory
if viewFactory is not None:
self.viewFactory = viewFactory
if metaTemplate:
self.metaTemplate = microdom.parse(open(
os.path.join(templateDirectory, metaTemplate)))
else:
self.metaTemplate = None
def templateMutate(self, document, parentCount=0):
if self.metaTemplate:
newDoc = self.metaTemplate.cloneNode(1)
if parentCount:
dotdot = parentCount * '../'
for ddname in 'href', 'src', 'action':
for node in domhelpers.findElementsWithAttribute(newDoc, ddname):
node.setAttribute(ddname, dotdot + node.getAttribute(ddname))
ttl = domhelpers.findNodesNamed(newDoc, "title")[0]
ttl2 = domhelpers.findNodesNamed(document, "title")[0]
ttl.childNodes[:] = []
for n in ttl2.childNodes:
ttl.appendChild(n)
body = domhelpers.findElementsWithAttribute(newDoc, "class", "__BODY__")[0]
body2 = domhelpers.findNodesNamed(document, "body")[0]
ndx = body.parentNode.childNodes.index(body)
body.parentNode.childNodes[ndx:ndx+1] = body2.childNodes
for n in body2.childNodes:
n.parentNode = body.parentNode
f = open("garbage.html", "wb")
f.write(newDoc.toprettyxml())
return newDoc
return document
def makeView(self, model, name, parentCount=0):
v = self.viewFactory(model, name)
v.parentCount = parentCount
v.templateDirectory = self.templateDirectory
v.tapestry = self
v.importViewLibrary(self)
return v
def getSubview(self, request, node, model, viewName):
mod = sys.modules[self.__class__.__module__]
# print "I'm getting a subview", mod, viewName
# try just the name
vm = getattr(mod, viewName, None)
if vm:
return vm(model)
# try the name + a V
vn2 = "V"+viewName.capitalize()
vm = getattr(mod, vn2, None)
if vm:
return vm(model)
vm = getattr(self, 'wvfactory_'+viewName, None)
if vm:
return vm(request, node, model)
def render(self, request):
return redirectTo(addSlash(request), request)
def getChild(self, path, request):
if path == '': path = 'index'
path = path.replace(".","_")
cm = getattr(self, "wchild_"+path, None)
if cm:
p = cm(request)
if isinstance(p, Deferred):
return util.DeferredResource(p)
adapter = components.getAdapter(p, IResource, None)
if adapter is not None:
return adapter
# maybe we want direct support for ModelLoader?
# cl = getattr(self, "wload_"+path, None) #???
return Resource.getChild(self, path, request)
syntax highlighted by Code2HTML, v. 0.9.1