Package Products :: Package ZenUtils :: Module ZenTales |
[hide private]
[frames] | no frames]

# Source Code for Module Products.ZenUtils.ZenTales

      1  ##############################################################################
      2  #
      3  # Copyright (C) Zenoss, Inc. 2007, all rights reserved.
      4  #
      5  # This content is made available according to terms specified in
      6  # License.zenoss under the directory where your Zenoss product is installed.
      7  #
      8  ##############################################################################
      9
     10
     11  import cgi
     12  import re
     13  import cStringIO
     14  from Products.PageTemplates.Expressions import getEngine
     15  from zope.tal.htmltalparser import HTMLTALParser
     16  from zope.tal.talgenerator import TALGenerator
     17  from zope.tales.engine import Engine
     18  from zope.tal.talinterpreter import TALInterpreter
     19  from DateTime import DateTime
     20
     21 -class InvalidTalesException(Exception):
     22      pass
     23
     24
     25  _compiled = {}
     26
     27 -def talesEvalStr(expression, context, extra=None):
     28      return talesEval('string:%s' % expression, context, extra)
     29
     30
     31 -def talesEval(express, context, extra=None):
     32      """Perform a TALES eval on the express using context.
     33      """
     34      compiled = talesCompile(express)
     35      contextDict = { 'context':context,
     36                      'here':context,
     37                      'nothing':None,
     38                      'now': DateTime(),
     39                      }
     40      if isinstance(extra, dict):
     41          contextDict.update(extra)
     42      try:
     43          res = compiled(getEngine().getContext(contextDict))
     44      except Exception, e:
     45          msg = "Error when processing tales expression %s on context %s : Exception Class %s Message: %s" % (express,
     46                                                                                                              context,
     47                                                                                                              type(e), e)
     48          raise InvalidTalesException(msg)
     49      if isinstance(res, Exception):
     50          raise res
     51      return res
     52
     53 -def talesCompile(express):
     54      compiled = _compiled.get(express, None)
     55      if not compiled:
     56          _compiled[express] = compiled = getEngine().compile(express)
     57      return compiled
     58
     59  TAG = re.compile(r'(<tal[^<>]>)')
     60  TPLBLOCK = re.compile(r'\$\{(.*?)\}')
     61
     62 -def _chunk_repl(match):
     63      """
     64      Need this to escape quotes and <> in expressions
     65      """
     66      interior = cgi.escape(match.groups()[0], True)
     67      return '<tal:block content="%s"/>' % interior
     68
     69 -def talEval(expression, context, extra=None):
     70      """
     71      Perform a TAL eval on the expression.
     72      """
     73      # First, account for the possibility that it is merely TALES; if there are
     74      # no <tal> in it at all (nor the ${python:} you can do with this function),
     75      # just send it to talesEval
     76      isTales = '<tal' not in expression and '${python:' not in expression
     77      if isTales:
     78          return talesEvalStr(expression, context, extra)
     79
     80      # Next, as a convenience, replace all ${} blocks that aren't inside a <tal>
     81      # with <tal:block content="..."/> equivalent
     82      chunks = TAG.split(expression)
     83      modified = []
     84      for chunk in chunks:
     85          if chunk.startswith('<tal'):
     86              modified.append(chunk)
     87          else:
     88              modified.append(TPLBLOCK.sub(_chunk_repl, chunk))
     89      expression = ''.join(modified)
     90
     91      # Finally, compile the expression and apply context
     92      gen = TALGenerator(Engine, xml=0)
     93      parser = HTMLTALParser(gen)
     94      parser.parseString(expression)
     95      program, macros = parser.getCode()
     96      output = cStringIO.StringIO()
     97      context = Engine.getContext(context)
     98      TALInterpreter(program, macros, context, output, tal=True)()
     99      return output.getvalue()
    100