pytp.py :  » Web-Frameworks » Webware » Webware-1.0.2 » DocSupport » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Web Frameworks » Webware 
Webware » Webware 1.0.2 » DocSupport » pytp.py
"""pytp.py -- A very simple Python Template Processor


USAGE

pytp.py infile outfile

For use in a Python script, create a PyTP instance::

    pytp = PyTP()

Then you can process strings with the process() method,
like that::

    input = open(infile).read()
    output = pytp.process(input)
    open(outfile, 'w').write(output)

You can also pass a scope to the process() method that will
be used by the Python code in the template.

The template processor evaluates instruction of this form::

    <%...%>

The starting and ending tag can be customized by setting
the tags parameter when creating the PyTP instance.
The default tags are those used by PSP. Other templating
languages use tags like::

    ('<?py', '?>') or ('<!--python', '-->') or ('[[' , ']]')

If the directive inside the tags starts with an equals sign,
it is considered as a Python expression to be evaluated. If
if the equals sign is missing, pytp will automatically find
out whether it is a Python expression or a Python statement.

* If it is a Python expression:
  - The expression will be evaluated and processed
    recursively as follows:
    * It if is a dictionary,
      use the sorted list of items on separate lines.
    * If it is any other iterable,
      use the list of items on separate lines.
    * Otherwise,
      use the conversion of the result to a string.
  - The processed result will be inserted in the output
    instead of the processing instruction.
* If it is a block of Python statements:
  - The statements will be executed.
  - Everything that is printed to standard output during
    execution will be inserted in the output instead of
    the processing instruction.


DOWNLOAD

This script is part of Webware for Python.
You can download the latest version from the SVN repository
(http://svn.w4py.org/Webware/trunk/DocSupport/pytp.py).

Note: Similar template processors have been written by:
* Christopher A. Craig (http://www.ccraig.org/software/pyhp/)
* David McNab (http://www.freenet.org.nz/python/pyweb/docs/pyhp.html)
* Alex Martelli (http://aspn.activestate.com/ASPN/Python/Cookbook/Recipe/52305)


COPYRIGHT

Copyright (c) 2005 by Christoph Zwerschke.
Licensed under the Open Software License version 2.1.

"""

__version__ = '0.1'
__revision__ = "$Revision: 7626 $"
__date__ = "$Date: 2008-11-13 14:48:43 -0700 (Thu, 13 Nov 2008) $"


import sys, re
try:
  from cStringIO import StringIO
except ImportError:
  from StringIO import StringIO


class PyTP:
  """A very simple Python Template Processor.

  Provides only one method process().
  """

  def __init__(self, tags=None):
    """Initialize the Python template processor.

    You may define your own start and end tags here.
    """
    if tags is None:
      tags = ('<%', '%>')
    pattern = '%s(.*?)%s' % tuple(map(re.escape, tags))
    self._tags = re.compile(pattern, re.DOTALL)

  def process(self, input, scope=None):
    """Process a Python template.

    The input must be a string that will be returned
    with all tagged processing instructions expanded.

    You may also pass a variable scope for the
    processing instructions that must be a directory.

    """
    if scope is None:
      scope = {}
    stdout = sys.stdout
    output = []
    pos = 0
    while pos < len(input):
      m = self._tags.search(input, pos)
      if m is None:
        break
      pi = m.groups()[0].strip()
      isexpr = pi.startswith('=')
      if isexpr:
        pi = pi[1:].lstrip()
      try: # try to evaluate as Python expression
        out = eval(pi, scope)
        if out is None:
          out = ''
      except SyntaxError:
        if isexpr:
          line = input[:m.start()].count('\n') + 1
          self._errmsg('expression syntax', line, pi)
          raise
        out = None
      except Exception:
        line = input[:m.start()].count('\n') + 1
        self._errmsg('expression', line, pi)
        raise
      if out:
        try:
          out = self._output(out)
        except Exception:
          line = input[:m.start()].count('\n') + 1
          self._errmsg('expression output', line, pi)
          raise
      elif out is None:
        try: # try to evaluate as Python block
          tempout = StringIO()
          sys.stdout = tempout
          try:
            pi = self._adjust_block(pi)
            exec pi in scope
            out = tempout.getvalue()
          finally:
            sys.stdout = stdout
            tempout.close()
        except Exception:
          line = input[:m.start()].count('\n') + 1
          self._errmsg('statement', line, pi)
          raise
      output.append(input[pos:m.start()])
      if out:
        output.append(out)
      pos = m.end()
    output.append(input[pos:])
    return ''.join(output)

  # Auxiliary functions

  def _output(self, something):
    """Output a Python object reasonably as string."""
    output = []
    if hasattr(something, 'items'):
      items = something.items
      try:
        items.sort()
      except Exception:
        pass
      output.append(self._output(items))
    elif hasattr(something, '__iter__'):
      for s in something:
        output.append(self._output(s))
    else:
      if something is not None:
        output.append(str(something))
    while hasattr(something, 'next'):
      something = something.next
      if something is None:
        break
      output.append(self._output(something))
    return '\n'.join(output)

  def _errmsg(self, error, line, code):
    """Print an error message."""
    print 'PyTP %s error in line %d:' % (error, line)
    print code

  def _adjust_block(self, block, tab='\t'):
    """Adjust the indentation of a Python block."""
    lines = block.splitlines()
    lines = [lines[0].strip()] + [line.rstrip() for line in lines[1:]]
    ind = None # find least index
    for line in lines[1:]:
      if line != '':
        s = line.lstrip()
        if s[0] != '#':
          i = len(line) - len(s)
          if ind is None or i < ind:
            ind = i
            if i == 0:
              break
    if ind is not None or ind != 0: # remove indentation
      lines[1:] = [line[:ind].lstrip() + line[ind:]
        for line in lines[1:]]
    block = '\n'.join(lines) + '\n'
    if lines[0] and not lines[0][0] == '#':
      # the first line contains code
      try: # try to compile it
        compile(lines[0], '<string>', 'exec')
        # if it works, line does not start new block
      except SyntaxError: # unexpected EOF while parsing?
        try: # try to compile the whole block
          compile(block, '<string>', 'exec')
          # if it works, line does not start new block
        except IndentationError: # expected an indented block?
          # so try to add some indentation:
          lines2 = lines[:1] + [tab + line for line in lines[1:]]
          block2 = '\n'.join(lines2) + '\n'
          # try again to compile the whole block:
          compile(block2, '<string>', 'exec')
          block = block2 # if it works, keep the indentation
        except Exception:
          pass # leave it as it is
      except Exception:
        pass # leave it as it is
    return block


def main(args):
  try:
    infile, outfile = args
  except Exception:
    print __doc__
    sys.exit(2)
  pytp = PyTP()
  open(outfile, 'w').write(pytp.process(open(infile).read()))


if __name__ == '__main__':
  main(sys.argv[1:])
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.