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

# Source Code for Module Products.ZenUtils.ZenTales

     1  ###########################################################################
     2  #
     3  # This program is part of Zenoss Core, an open source monitoring platform.
     4  # Copyright (C) 2007, Zenoss Inc.
     5  #
     6  # This program is free software; you can redistribute it and/or modify it
     7  # under the terms of the GNU General Public License version 2 or (at your
     8  # option) any later version as published by the Free Software Foundation.
     9  #
    10  # For complete information please visit: http://www.zenoss.com/oss/
    11  #
    12  ###########################################################################
    13  import cgi
    14  import re
    15  import cStringIO
    16  from Products.PageTemplates.Expressions import getEngine
    17  from zope.tal.htmltalparser import HTMLTALParser
    18  from zope.tal.talgenerator import TALGenerator
    19  from zope.tales.engine import Engine
    20  from zope.tal.talinterpreter import TALInterpreter
    21  from DateTime import DateTime
    22
    23  _compiled = {}
    24
    25 -def talesEvalStr(expression, context, extra=None):
    26      return talesEval('string:%s' % expression, context, extra)
    27
    28
    29 -def talesEval(express, context, extra=None):
    30      """Perform a TALES eval on the express using context.
    31      """
    32      compiled = talesCompile(express)
    33      contextDict = { 'here':context,
    34                      'nothing':None,
    35                      'now': DateTime(),
    36                      }
    37      if isinstance(extra, dict):
    38          contextDict.update(extra)
    39      res = compiled(getEngine().getContext(contextDict))
    40      if isinstance(res, Exception):
    41          raise res
    42      return res
    43
    44 -def talesCompile(express):
    45      compiled = _compiled.get(express, None)
    46      if not compiled:
    47          _compiled[express] = compiled = getEngine().compile(express)
    48      return compiled
    49
    50  TAG = re.compile(r'(<tal[^<>]>)')
    51  TPLBLOCK = re.compile(r'\$\{(.*?)\}')
    52
    53 -def _chunk_repl(match):
    54      """
    55      Need this to escape quotes and <> in expressions
    56      """
    57      interior = cgi.escape(match.groups()[0], True)
    58      return '<tal:block content="%s"/>' % interior
    59
    60 -def talEval(expression, context, extra=None):
    61      """
    62      Perform a TAL eval on the expression.
    63      """
    64      # First, account for the possibility that it is merely TALES; if there are
    65      # no <tal> in it at all (nor the ${python:} you can do with this function),
    66      # just send it to talesEval
    67      isTales = '<tal' not in expression and '${python:' not in expression
    68      if isTales:
    69          return talesEvalStr(expression, context, extra)
    70
    71      # Next, as a convenience, replace all ${} blocks that aren't inside a <tal>
    72      # with <tal:block content="..."/> equivalent
    73      chunks = TAG.split(expression)
    74      modified = []
    75      for chunk in chunks:
    76          if chunk.startswith('<tal'):
    77              modified.append(chunk)
    78          else:
    79              modified.append(TPLBLOCK.sub(_chunk_repl, chunk))
    80      expression = ''.join(modified)
    81
    82      # Finally, compile the expression and apply context
    83      gen = TALGenerator(Engine, xml=0)
    84      parser = HTMLTALParser(gen)
    85      parser.parseString(expression)
    86      program, macros = parser.getCode()
    87      output = cStringIO.StringIO()
    88      context = Engine.getContext(context)
    89      TALInterpreter(program, macros, context, output, tal=True)()
    90      return output.getvalue()
    91