[Subversion] / PEAK / src / peak / web / templates.py  

Diff of /PEAK/src/peak/web/templates.py

Parent Directory | Revision Log

version 1349, Tue Aug 19 18:57:03 2003 UTC version 2003, Thu Feb 3 16:19:55 2005 UTC
Line 2 
Line 2 
   
 TODO  TODO
   
  - implement interaction wrapper for "/skin", "/request", etc. data paths   - Address traversal nesting for referenced data
   
    - Dynamic attributes, independent of element?
   
    - Phase out old PWT syntax
   
  - implement sub-template support (convert doc->DOMlet in another doc)   - implement sub-template support (convert doc->DOMlet in another doc)
   
Line 20 
Line 24 
 from interfaces import *  from interfaces import *
 from xml.sax.saxutils import quoteattr, escape  from xml.sax.saxutils import quoteattr, escape
 from publish import TraversalPath  from publish import TraversalPath
   from peak.util import SOX, imports
   from places import Decorator
   from environ import traverseItem, traverseDefault
   from errors import NotFound
   
 __all__ = [  __all__ = [
     'TEMPLATE_NS', 'DOMLETS_PROPERTY', 'DOMletParser', 'TemplateDocument'      'TEMPLATE_NS', 'DOMLETS_PROPERTY', 'TemplateDocument'
 ]  ]
   
 TEMPLATE_NS = 'http://peak.telecommunity.com/DOMlets/'  TEMPLATE_NS = 'http://peak.telecommunity.com/DOMlets/'
Line 30 
Line 38 
   
 unicodeJoin = u''.join  unicodeJoin = u''.join
   
   
 def infiniter(sequence):  def infiniter(sequence):
     while 1:      while 1:
         for item in sequence:          for item in sequence:
             yield item              yield item
   
   
   class DOMletVars(Decorator):
   
       state = None
   
       def traverseTo(self, name, ctx, default=NOT_GIVEN):
           loc = traverseItem(ctx, self.state, 'item', name, name, NOT_FOUND)
           if loc is not NOT_FOUND:
               return loc
   
 class DOMletState(binding.Component):          # attribute is absent or private, fall through to underlying object
           return traverseDefault(ctx, self.ob, 'attr', name, name, default)
   
     """Execution state for a DOMlet"""  
   class DOMletMethod(object):
       """Bind an 'IDOMletRenderable' to a specific context"""
   
     protocols.advise(      protocols.advise(
         instancesProvide = [IDOMletState],          instancesProvide = [IDOMletRenderable]
     )      )
   
     write = binding.requireBinding("Unicode output stream write() method")      __slots__ = 'template','ctx'
   
   
     def findState(self, iface):  
   
         """Find nearest DOMletState implementing 'iface'"""  
   
         for c in config.iterParents(self):  
             state = adapt(c,iface,None)  
             if state is not None:  
                 return state  
   
   
   
   
       def __init__(self,ctx,template):
           self.ctx = ctx
           self.template = template
   
       def renderFor(self,ctx,state):
           return self.template.renderFor(self.ctx,state)
   
   
   
Line 70 
Line 80 
   
   
   
   class Parameters:
       """'params' object for templates"""
   
       protocols.advise( instancesProvide = [IWebTraversable] )
   
       def __init__(self,ctx,data):
           self.ctx = ctx
           self.data = data
           self.cache = {}
   
       def traverseTo(self, name, ctx, default=NOT_GIVEN):
           try:
               item = self.cache[name]
           except KeyError:
               try:
                   item = self.data[name]
               except KeyError:
                   if default is not NOT_GIVEN:
                       return default
                   raise NotFound(ctx,name,self)
               else:
                   tmpl = IDOMletRenderable(item,None)
                   if tmpl is not None:
                       item = self.cache[name] = DOMletMethod(self.ctx,tmpl)
                   else:
                       path = adapt(item,TraversalPath,None)
                       if path is not None:
                           self.data[name] = path
                           return path.traverse(self.ctx)
           return ctx.childContext(name,item)
   
   
       def beforeHTTP(self, ctx):
           return ctx
   
       def getURL(self,ctx):
           return ctx.traversedURL
   
   
   
   
 class DOMletAsWebPage(binding.Component):  class DOMletState(binding.Component):
   
     """Render a template component"""      """Execution state for a DOMlet"""
   
     protocols.advise(      protocols.advise(
         instancesProvide = [IWebPage],          instancesProvide = [IDOMletState],
         asAdapterForProtocols = [IDOMletNode],  
         factoryMethod = 'fromNode'  
     )  
   
     templateNode = binding.requireBinding("""Node to render""")  
   
     def fromNode(klass, subject, protocol):  
         return klass(templateNode = subject)  
   
     fromNode = classmethod(fromNode)  
   
     def render(self, context):  
         myOwner = context.getParentComponent()  
         data = []  
         self.templateNode.renderFor(  
             myOwner,  
             DOMletState(  
                 myOwner, write=data.append  
             )  
         )          )
         return unicodeJoin(data)  
   
   
   
   
       write = binding.Require("Unicode output stream write() method")
   
       data = binding.Make(dict)
   
       def __getitem__(self,key):
           return self.data[key]
   
       def withData(self,**kw):
           data = self.data.copy()
           data.update(kw)
           return self.__class__(self,data=data,write=self.write)
   
       def wrapContext(self,ctx):
           return DOMletVars(ob=ctx, state=self)
   
       def findState(self, iface):
   
           """Find nearest DOMletState implementing 'iface'"""
   
           for c in binding.iterParents(self):     # XXX not covered by tests!
               state = adapt(c,iface,None)
               if state is not None:
                   return state
   
   
   
 class DOMletParser(binding.Component):  
   
     """Parser that assembles a Document"""  
   
     def parser(self,d,a):  
   
         from xml.parsers.expat import ParserCreate  
         p = ParserCreate()  
   
         p.ordered_attributes = True  
         p.returns_unicode = True  
         p.specified_attributes = True  
   
         p.StartDoctypeDeclHandler = self.startDoctype  
         p.StartElementHandler = self.startElement  
         p.EndElementHandler = self.endElement  
         p.CharacterDataHandler = self.characters  
         p.StartNamespaceDeclHandler = self.startNS  
         p.EndNamespaceDeclHandler = self.endNS  
         p.CommentHandler = self.comment  
   
         # We don't use:  
         # .StartNamespaceDeclHandler  
         # .EndNamespaceDeclHandler  
         # .XmlDeclHandler(version, encoding, standalone)  
         # .ElementDeclHandler(name, model)  
         # .AttlistDeclHandler(elname, attname, type, default, required)  
         # .EndDoctypeDeclHandler()  
         # .ProcessingInstructionHandler(target, data)  
         # .UnparsedEntityDeclHandler(entityN,base,systemId,publicId,notationN)  
         # .EntityDeclHandler(  
         #      entityName, is_parameter_entity, value, base,  
         #      systemId, publicId, notationName)  
         # .NotationDeclHandler(notationName, base, systemId, publicId)  
         # .StartCdataSectionHandler()  
         # .EndCdataSectionHandler()  
         # .NotStandaloneHandler()  
         return p  
   
     parser = binding.Once(parser)  def startElement(parser,data):
   
     domlets = binding.New(list) # "nearest explicit DOMlet" stack      parent = data['previous']['pwt.content']
     stack   = binding.New(list) # "DOMlet being assembled" stack      factory = data.get('this.factory', parent.tagFactory)
     nsUri   = binding.New(dict) # URI stack for each NS prefix  
   
     myNs = binding.Once(        # prefixes that currently map to TEMPLATE_NS      data['pwt.content'] = outer = factory(parent,
         lambda self,d,a: dict(          tagName=data['name'],
             [(p,1) for (p,u) in self.nsUri.items() if u and u[-1]==TEMPLATE_NS]          attribItems=data['attributes'],
         )          domletProperty = data.get('this.domlet'),
           dataSpec  = data.get('this.data',''),
           paramName = data.get('this.is'),
       )
   
       inner = data.get('content.factory') or ('content.register' in data and parent.tagFactory)
       if inner:
           data['pwt.this'] = outer
           data['pwt.content'] = inner(outer,
               tagName='',
               attribItems=[],
               domletProperty = data.get('content.domlet'),
               dataSpec=data.get('content.data',''),
               paramName = data.get('content.is'),
     )      )
   
   
     def parseFile(self, stream, document=None):  def finishElement(parser,data):
         if document is None:      content = data['pwt.content']
             document = TemplateDocument(self.getParentComponent())      for f in data.get('content.register',()):
         self.stack.append(document)          f(content)
         self.domlets.append(document)      if 'pwt.this' in data:
         self.parser.ParseFile(stream)          this = data['pwt.this']
           this.addChild(content)
   
     def comment(self,data):  
         self.buildLiteral(u'<!--%s-->' % data)  
   
   
     def startNS(self, prefix, uri):  
         self.nsUri.setdefault(prefix,[]).append(uri)  
         if uri==TEMPLATE_NS:  
             self._delBinding('myNs')  
   
   
     def endNS(self, prefix):  
         uri = self.nsUri[prefix].pop()  
         if uri==TEMPLATE_NS:  
             self._delBinding('myNs')  
   
   
   
   
   
   
   
   
     nsStack = binding.New(list)  
   
     def pushNSinfo(self,attrs):  
   
         prefixes = []  
   
         for i in range(0,len(attrs),2):  
   
             k,v = attrs[i], attrs[i+1]  
   
             if not k.startswith('xmlns'):  
                 continue  
   
             rest = k[5:]  
             if not rest:  
                 ns = ''  
             elif rest.startswith(':'):  
                 ns = rest[1:]  
             else:              else:
                 continue          this = content
       for f in data.get('this.register',()):
             self.startNS(ns,v)          f(this)
             prefixes.append(ns)      if 'previous' in data:
           data['previous']['pwt.content'].addChild(this)
         self.nsStack.append(prefixes)      return this
   
   
     def popNSinfo(self):  
         map(self.endNS, self.nsStack.pop())  
   
   
   
   
   
   
   def negotiateDomlet(parser, data, name, value):
       data['attributes'].remove((name,value))
       if ':' in value:
           data['this.domlet'],data['this.data'] = value.split(':',1)
           domlet = data['this.domlet']
   
     def startElement(self, name, attrs):  
   
         self.pushNSinfo(attrs)  
   
         a = []  
         append = a.append  
         myNs = self.myNs or ('',)   # use unprefixed NS if no NS defined  
   
         top = self.stack[-1]  
         factory = top.tagFactory  
         domletName = dataSpec = paramName = None  
   
         for i in range(0,len(attrs),2):  
   
             k,v = attrs[i], attrs[i+1]  
   
             if ':' in k:  
                 ns, n = k.split(':',1)  
             else:              else:
                 ns, n = '', k          data['this.domlet'] = domlet = value
   
             if n=='domlet' and ns in myNs:      factory = DOMLETS_PROPERTY.of(data['previous']['pwt.content'])[domlet]
                 # XXX if domletName is not None or dataSpec is not None:      if data.setdefault('this.factory',factory) is not factory:
                 # XXX     raise ???          parser.err('More than one "domlet" or "this:" replacement defined')
                 if ':' in v:  
                     domletName, dataSpec = v.split(':',1)  
                 else:  
                     domletName, dataSpec = v, ''  
   
                 if domletName:  
                     factory = DOMLETS_PROPERTY.of(top)[domletName]  
                     factory = adapt(factory, IDOMletElementFactory)  
   
             elif n=='define' and ns in myNs:  def negotiateDefine(parser, data, name, value):
                 # XXX if paramName is not None:      data['attributes'].remove((name,value))
                 # XXX     raise ???      data['this.is'] = value
                 paramName = v      parent = data['previous']['pwt.content']
             else:      data.setdefault('this.register',[]).append(
                 append((k,v))          lambda ob: parent.addParameter(value,ob)
   
   
         element = factory(top, tagName=name, attribItems=a,  
             domletProperty = domletName or None,  
             dataSpec  = dataSpec or '',  
             paramName = paramName or None,  
             # XXX nonEmpty=False  
         )          )
   
         if paramName:  
             self.domlets[-1].addParameter(paramName,element)  
   
         if domletName:  
             # New explicit DOMlet, put it on the explicit DOMlet stack  
             self.domlets.append(element)  
         else:  
             # Push the previous "nearest enclosing explicit DOMlet"  
             self.domlets.append(self.domlets[-1])  
   
         self.stack.append(element)  
   
   
     def endElement(self, name):  
         self.domlets.pop()  
         last = self.stack.pop()  
         self.stack[-1].addChild(last)  
         self.popNSinfo()  
   
   
     def buildLiteral(self,xml):  
         top = self.stack[-1]  
         literal = top.literalFactory(top, xml=xml)  
         top.addChild(literal)  
   
   
     def characters(self, data):  
         top = self.stack[-1]  
         text = top.textFactory(top, xml=escape(data))  
         top.addChild(text)  
   
   
   
   
     def startDoctype(self, doctypeName, systemId, publicId, has_internal):  
   
         if publicId:  
             p = ' PUBLIC %s %s' % (quoteattr(publicId),quoteattr(systemId))  
         elif systemId:  
             p = ' SYSTEM %s' % quoteattr(systemId)  
         else:  
             p = ''  
   
         # we ignore internal DTD subsets; they're not useful for HTML  
         xml = u'<!DOCTYPE %s%s>\n' % (doctypeName, p)  
   
         self.buildLiteral(xml)  
   
   
   
   
   
   
   
   def negotiatorFactory(domletFactory):
       def negotiate(mode, parser, data, name, value):
           data['attributes'].remove((name,value))
           factory = data.setdefault(mode+'.factory',domletFactory)
           if factory is not domletFactory:
               parser.err('More than one "domlet" or "this:" replacement defined')
           data[mode+'.data'] = value
           data[mode+'.domlet'] = parser.splitName(name)[1]
       return negotiate
   
   def nodeIs(mode, parser, data, name, value):
       data['attributes'].remove((name,value))
       data[mode+'.is'] = value
       data.setdefault(mode+'.register',[]).append(
           lambda ob: binding.getParentComponent(ob).addParameter(value,ob)
       )
   
   
   
   def setupElement(parser,data):
   
       d = dict(data.get('attributes',()))
   
       if 'domlet' in d:
           negotiateDomlet(parser,data,'domlet',d['domlet'])
   
       if 'define' in d:
           negotiateDefine(parser,data,'define',d['define'])
   
       def text(xml):
           top = data['pwt.content']
           top.addChild(top.textFactory(top,xml=escape(xml)))
   
       def literal(xml):
           top = data['pwt.content']
           top.addChild(top.literalFactory(top,xml=xml))
   
       data['start'] = startElement
       data['finish'] = finishElement
       data['text'] = text
       data['literal'] = literal
   
   
   def setupDocument(parser,data):
       setupElement(parser,data)
       data['pwt.content'] = data['pwt_document']
   
   
   def withParam(parser,data,name,value):
       data['attributes'].remove((name,value))
       data.setdefault('content.register',[]).append(
           lambda ob: ob.addParameter(name.split(':',1)[-1],value)
       )
   
   
   
Line 378 
Line 296 
   
     xml = u''      xml = u''
   
     staticText = binding.bindTo('xml')      staticText = binding.Obtain('xml')
   
     def renderFor(self, data, state):      def renderFor(self, data, state):
         state.write(self.xml)          state.write(self.xml)
Line 415 
Line 333 
         instancesProvide = [IDOMletElement],          instancesProvide = [IDOMletElement],
     )      )
   
     children       = binding.New(list)      children       = binding.Make(list)
     params         = binding.New(dict)      params         = binding.Make(dict)
   
     tagName        = binding.requireBinding("Tag name of element")      tagName        = binding.Require("Tag name of element")
     attribItems    = binding.requireBinding("Attribute name,value pairs")      attribItems    = binding.Require("Attribute name,value pairs")
     nonEmpty       = False      nonEmpty       = False
     domletProperty = None      domletProperty = None
     dataSpec       = binding.Constant('', adaptTo=TraversalPath)      dataSpec       = binding.Make(lambda: '', adaptTo=TraversalPath)
     paramName      = None      paramName      = None
       acceptParams   = ()
       multiParams    = ()
   
     # IDOMletNode      # IDOMletNode
   
     def staticText(self, d, a):      def staticText(self):
   
         """Note: replace w/staticText = None in dynamic element subclasses"""          """Note: replace w/staticText = None in dynamic element subclasses"""
   
Line 443 
Line 363 
         else:          else:
             return self._emptyTag              return self._emptyTag
   
     staticText = binding.Once(staticText, suggestParent=False)      staticText = binding.Make(staticText, suggestParent=False)
   
   
   
   
       def optimizedChildren(self):
     def optimizedChildren(self, d, a):  
   
         """Child nodes with as many separate text nodes combined as possible"""          """Child nodes with as many separate text nodes combined as possible"""
   
Line 474 
Line 392 
         flush()          flush()
         return all          return all
   
     optimizedChildren = binding.Once(optimizedChildren)      optimizedChildren = binding.Make(optimizedChildren)
   
   
     def _traverse(self, data, state):      def _traverse(self, data, state):
           return self.dataSpec.traverse(data,state.wrapContext), state
   
   
   
         return self.dataSpec.traverse(  
             data, lambda ctx: self._wrapInteraction(ctx)  
         ), state  
   
   
   
Line 522 
Line 440 
         self.children.append(node)          self.children.append(node)
   
   
   
   
   
   
   
   
   
   
   
     def addParameter(self, name, element):      def addParameter(self, name, element):
         """Declare 'element' as part of parameter 'name'"""          """Declare 'element' as part of parameter 'name'"""
   
         self.params.setdefault(name,[]).append(element)          if not self.acceptParams:
               return self.getParentComponent().addParameter(name,element)
   
           if name not in self.acceptParams and '*' not in self.acceptParams:
               # XXX need line info
               raise SyntaxError("Unrecognized parameter: %r" % name)
   
           is_multi = (
               name in self.multiParams or
               name not in self.acceptParams and '*' in self.multiParams
           )
   
           if name in self.params:
   
               if not is_multi:
                   raise SyntaxError(
                       "Multiple definitions for parameter: %r" % name
                   )   # XXX need line info
   
               self.params[name].append(element)
   
           elif is_multi:
               self.params[name] = [element]
   
           else:
               self.params[name] = element
   
   
     # Override in subclasses  
   
     def _wrapInteraction(self,interaction):  
         # XXX This should wrap the interaction in an IWebTraversable simulator,  
         # XXX which should include access to this element's parameters as well  
         # XXX as interaction variables.  
         raise NotImplementedError  
   
   
     _emptyTag = binding.Once(  
         lambda self,d,a: self._openTag[:-1]+u' />'  
   
   
   
   
   
       # Override in subclasses
   
       _emptyTag = binding.Make(
           lambda self: self.tagName and self._openTag[:-1]+u' />' or ''
     )      )
   
     _closeTag = binding.Once(      _closeTag = binding.Make(
         lambda self,d,a: u'</%s>' % self.tagName          lambda self: self.tagName and u'</%s>' % self.tagName or ''
     )      )
   
     _openTag = binding.Once(      _openTag = binding.Make(
         lambda self,d,a: u'<%s%s>' % ( self.tagName,          lambda self: self.tagName and u'<%s%s>' % ( self.tagName,
             unicodeJoin([              unicodeJoin([
                 u' %s=%s' % (k,quoteattr(v)) for (k,v) in self.attribItems                  u' %s=%s' % (k,quoteattr(v)) for (k,v) in self.attribItems
             ])              ])
           ) or ''
         )          )
     )  
   
     tagFactory     = None # real value is set below      tagFactory     = None # real value is set below
     textFactory    = Literal      textFactory    = Literal
Line 572 
Line 525 
   
   
   
 class TemplateDocument(Element):  
   
     """Document-level template element"""  
   
   
   
   
   class TaglessElement(Element):
   
       """Element w/out tags"""
   
     _openTag = _closeTag = _emptyTag = ''      _openTag = _closeTag = _emptyTag = ''
   
     parserClass = DOMletParser  
   
     def parseFile(self, stream):  class Uses(Element):
         parser = self.parserClass(self)  
         parser.parseFile(stream,self)  
   
       """Render child elements with target data, or skip element altogether"""
   
       staticText = None
       render_if = True
   
       def renderFor(self, data, state):
           try:
               if self.dataSpec:
                   data, state = self._traverse(data, state)
           except (web.NotFound,web.NotAllowed):
               if self.render_if:
                   return
           else:
               if not self.render_if:
                   return
   
           state.write(self._openTag)
   
           for child in self.optimizedChildren:
               child.renderFor(data,state)
   
           state.write(self._closeTag)
   
   
   class Unless(Uses):
   
       """Skip child elements if target data is available"""
   
       render_if = False
   
   
   
   class TemplateDocument(TaglessElement):
   
       """Document-level template element"""
   
       protocols.advise(
           instancesProvide = [IHTTPHandler],
           classProvides = [naming.IObjectFactory],
       )
   
       acceptParams = '*',     # handle any top-level parameters
   
       def renderFor(self, ctx, state):
           if not self.fragment:
               raise TypeError("Can't be used as a fragment")
           return self.fragment.renderFor(ctx.parentContext(),state)
   
       def handle_http(self, ctx):
           name = ctx.shift()
           if name is not None:
               raise web.NotFound(ctx,name,self)   # No traversal to subobjects!
           if not self.page:
               raise web.UnsupportedMethod(ctx)    # We're not a page!
           data = []
           self.page.renderFor(
               ctx.parentContext(), DOMletState(self, write=data.append)
           )
           h = []
           if self.content_type:
               h.append(('Content-type',self.content_type))
           return '200 OK', h, [str(unicodeJoin(data))]    # XXX encoding
   
   
       def getObjectInstance(klass, context, refInfo, name, attrs=None):
           url, = refInfo.addresses
           return config.processXML(
               web.TEMPLATE_SCHEMA(context),str(url),pwt_document=klass(context),
           )
   
       getObjectInstance = classmethod(getObjectInstance)
   
   
       content_type = binding.Make(lambda self:
           str(self.params.get('content-type'))
       )
   
       def layoutDOMlet(self,d,attrName):
   
           if attrName+'-layout' in self.params:
               path = self.params[attrName+'-layout'] + ''  # ensure stringness
               if path=='/nothing':
                   return None
               elif path=='/default':
                   return super(TemplateDocument,self)
               else:
                   return Replace(self, dataSpec=path, params=self.params.copy())
   
           if attrName in self.params:
               return IDOMletRenderable(self.params[attrName])
   
           if attrName=='fragment':
               # It's okay to be a fragment by default
               return super(TemplateDocument,self)
   
       fragment = page = binding.Make(layoutDOMlet)
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   class Replace(Element):
   
       staticText = None
       acceptParams = '*',
       escaped = True
   
       def renderFor(self,data,state):
   
           if self.dataSpec:
               ctx, state = self._traverse(data, state)
   
           if self.params:
               state = state.withData(params=Parameters(data,self.params))
   
           current = ctx.current
   
           domlet = IDOMletRenderable(current,None)
           if domlet is not None:
               return domlet.renderFor(ctx,state)
   
           # XXX dyn var comp goes here
           # XXX if NOT_FOUND -> return
           # XXX if NOT_GIVEN -> render original content
   
           current = unicode(current)
           if self.escaped:
               current = escape(current)
   
           state.write(current)
   
   
   class ReplaceXML(Replace):
       escaped = False
   
   
   
Line 618 
Line 700 
     """Abstract base for elements that replace their contents"""      """Abstract base for elements that replace their contents"""
   
     staticText = None      staticText = None
     children   = optimizedChildren = binding.bindTo('contents')      children   = optimizedChildren = binding.Obtain('contents')
     contents   = binding.requireBinding("nodes to render in element body")      contents   = binding.Require("nodes to render in element body")
   
     def addChild(self, node):      def addChild(self, node):
         pass    # ignore children, only parameters count with us          pass    # ignore children, only parameters count with us
Line 627 
Line 709 
   
 class Text(ContentReplacer):  class Text(ContentReplacer):
   
     """Replace element contents w/data"""      """Replace element contents w/data (XML-quoted)"""
   
     def renderFor(self, data, state):      def renderFor(self, data, state):
   
         if self.dataSpec:          if self.dataSpec:
             data, state = self._traverse(data, state)              data, state = self._traverse(data, state)
   
         write = state.write          write = state.write
           write(self._openTag)
           write(escape(unicode(data.current)))
           write(self._closeTag)
   
   
   class XML(ContentReplacer):
   
       """Replace element contents w/data (XML structure)"""
   
       def renderFor(self, data, state):
           if self.dataSpec:
               data, state = self._traverse(data, state)
   
           write = state.write
         write(self._openTag)          write(self._openTag)
         write(unicode(data.subject))          write(unicode(data.current))
         write(self._closeTag)          write(self._closeTag)
   
   
   
   class TaglessText(Text):
   
       """Text w/out open/close tag"""
   
       _openTag = _closeTag = _emptyTag = ''
   
   
   class TaglessXML(XML):
   
       """XML w/out open/close tag"""
   
       _openTag = _closeTag = _emptyTag = ''
   
   
   class Expects(Element):
   
       """Render child elements with target data, or skip element altogether"""
   
       staticText = None
   
       dataSpec = ''   # to disable conversion to path
   
       protocol = binding.Make(
           lambda self: imports.importString(self.dataSpec),uponAssembly=True
       )
   
       def renderFor(self, data, state):
   
           data = data.clone(current=adapt(data.current,self.protocol))
   
           state.write(self._openTag)
           for child in self.optimizedChildren:
               child.renderFor(data,state)
           state.write(self._closeTag)
   
   
   
Line 665 
Line 788 
         if self.dataSpec:          if self.dataSpec:
             data, state = self._traverse(data, state)              data, state = self._traverse(data, state)
   
         url = unicode(data.absoluteURL)          url = unicode(data.url)
   
         if not self.optimizedChildren and not self.nonEmpty:          if not self.optimizedChildren and not self.nonEmpty:
             state.write(self._emptyTag % locals())              state.write(self._emptyTag % locals())
Line 689 
Line 812 
         write = state.write          write = state.write
   
         write(self._openTag)          write(self._openTag)
         write(unicode(data.absoluteURL))          write(unicode(data.url))
         write(self._closeTag)          write(self._closeTag)
   
   class TaglessURLText(URLText):
       _openTag = _closeTag = _emptyTag = ''
   
 def URLTag(parentComponent, componentName=None, domletProperty=None, **kw):  def URLTag(parentComponent, componentName=None, domletProperty=None, **kw):
   
Line 738 
Line 861 
   
 class List(ContentReplacer):  class List(ContentReplacer):
   
       acceptParams = 'listItem','header','emptyList','footer'
       multiParams = 'listItem',
   
     def renderFor(self, data, state):      def renderFor(self, data, state):
   
         if self.dataSpec:          if self.dataSpec:
             data, state = self._traverse(data, state)              data, state = self._traverse(data, state)
   
         state.write(self._openTag)          state.write(self._openTag)
   
         nextPattern = infiniter(self.params['listItem']).next          nextPattern = infiniter(self.params['listItem']).next
         allowed     = data.interaction.allows          allowed     = data.allows
         subcontext  = data.subcontext  
         ct = 0          ct = 0
   
         # XXX this should probably use an iteration location, or maybe          # XXX this should probably use an iteration location, or maybe
         # XXX put some properties in execution context for loop vars?          # XXX put some properties in execution context for loop vars?
   
         for item in data.subject:          for item in data.current:
   
             if not allowed(item):              if not allowed(item):
                 continue                  continue
   
             loc = subcontext(str(ct), item)              if not ct:
                   if 'header' in self.params:
                       self.params['header'].renderFor(data,state)
   
               loc = data.childContext(str(ct), item)
             nextPattern().renderFor(loc, state)              nextPattern().renderFor(loc, state)
             ct += 1              ct += 1
   
         if not ct:          if not ct:
             # Handle list being empty              # Handle list being empty
             for child in self.params.get('emptyList',()):              if 'emptyList' in self.params:
                 child.renderFor(data, state)                  self.params['emptyList'].renderFor(data,state)
           else:
               if 'footer' in self.params:
                   self.params['footer'].renderFor(data,state)
   
         state.write(self._closeTag)          state.write(self._closeTag)
   
   class TaglessList(List):
       _openTag = _closeTag = _emptyTag = ''
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   


Generate output suitable for use with a patch program
Legend:
Removed from v.1349  
changed lines
  Added in v.2003

cvs-admin@eby-sarna.com

Powered by ViewCVS 1.0-dev

ViewCVS and CVS Help