Switch to using the Django template engine, since we'll
authorMagnus Hagander <magnus@hagander.net>
Mon, 3 Nov 2008 13:40:19 +0000 (13:40 +0000)
committerMagnus Hagander <magnus@hagander.net>
Mon, 3 Nov 2008 13:40:19 +0000 (13:40 +0000)
be using Django for some of the other stuff later, and it
sucks to have more than one template engine...

19 files changed:
generator.py
mako/__init__.py [deleted file]
mako/_ast_util.py [deleted file]
mako/ast.py [deleted file]
mako/cache.py [deleted file]
mako/codegen.py [deleted file]
mako/exceptions.py [deleted file]
mako/filters.py [deleted file]
mako/lexer.py [deleted file]
mako/lookup.py [deleted file]
mako/parsetree.py [deleted file]
mako/pygen.py [deleted file]
mako/pyparser.py [deleted file]
mako/runtime.py [deleted file]
mako/template.py [deleted file]
mako/util.py [deleted file]
template/base.tmpl
template/index.tmpl
template/policy.tmpl

index c3229805cf2acdec872943fd26c5ab9498c625e2..a895d2bbf20c4ec4186a2050004c1bab2f977dca 100755 (executable)
@@ -16,8 +16,9 @@ import os.path
 import sys
 import tidy
 import urllib
-from mako.template import Template
-from mako.lookup import TemplateLookup
+from django.template import Context
+from django.template.loader import get_template
+from django.conf import settings
 from HTMLParser import HTMLParser
 from planethtml import *
 
@@ -36,6 +37,9 @@ class Generator:
                self.feeds = []
                self.staticfiles = ['policy']
 
+               settings.configure(
+                       TEMPLATE_DIRS=('template',),
+               )
 
        def Generate(self):
                rss = PyRSS2Gen.RSS2(
@@ -71,10 +75,12 @@ class Generator:
                        self.UpdateStaticFile(staticfile)
 
        def WriteFromTemplate(self, templatename, outputname):
-               lookup = TemplateLookup(directories=['template'], output_encoding='utf-8', input_encoding='utf-8')
-               tmpl = lookup.get_template(templatename)
+               tmpl = get_template(templatename)
                f = open(outputname, "w")
-               f.write(tmpl.render_unicode(feeds=self.feeds, posts=self.items).encode('utf-8'))
+               f.write(tmpl.render(Context({
+                       'feeds': self.feeds,
+                       'posts': self.items,
+               })).encode('utf-8'))
                f.close()
 
        def UpdateStaticFile(self, filename):
diff --git a/mako/__init__.py b/mako/__init__.py
deleted file mode 100644 (file)
index adced7f..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# __init__.py
-# Copyright (C) 2006, 2007, 2008 Michael Bayer mike_mp@zzzcomputing.com
-#
-# This module is part of Mako and is released under
-# the MIT License: http://www.opensource.org/licenses/mit-license.php
-
diff --git a/mako/_ast_util.py b/mako/_ast_util.py
deleted file mode 100644 (file)
index a9efa2f..0000000
+++ /dev/null
@@ -1,863 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    ast
-    ~~~
-
-    The `ast` module helps Python applications to process trees of the Python
-    abstract syntax grammar.  The abstract syntax itself might change with
-    each Python release; this module helps to find out programmatically what
-    the current grammar looks like and allows modifications of it.
-
-    An abstract syntax tree can be generated by passing `ast.PyCF_ONLY_AST` as
-    a flag to the `compile()` builtin function or by using the `parse()`
-    function from this module.  The result will be a tree of objects whose
-    classes all inherit from `ast.AST`.
-
-    A modified abstract syntax tree can be compiled into a Python code object
-    using the built-in `compile()` function.
-
-    Additionally various helper functions are provided that make working with
-    the trees simpler.  The main intention of the helper functions and this
-    module in general is to provide an easy to use interface for libraries
-    that work tightly with the python syntax (template engines for example).
-
-
-    :copyright: Copyright 2008 by Armin Ronacher.
-    :license: Python License.
-"""
-import sys
-from _ast import *
-
-if sys.platform.startswith('java'):
-    import array
-
-    ast_list = array.ArrayType
-    get_symbol_key = lambda op: op
-        
-    def get_class_name(t):
-        result = t.__class__.__name__
-        if result in ("expr_contextType",
-                      "boolopType",
-                      "unaryopType",
-                      "cmpopType",
-                      "operatorType"):
-            result = str(t)
-            if result == "AugLoad":
-                result = "Load"
-            elif result == "AugStore":
-                result = "Store"
-        else:
-            result = result.split(".")[-1]
-            if result.endswith("Type"):
-                result = result[:-4]
-        return result
-
-else:
-    ast_list = list
-    get_symbol_key = type
-    get_class_name = lambda node: node.__class__.__name__
-
-
-BOOLOP_SYMBOLS = {
-    And:        'and',
-    Or:         'or'
-}
-
-BINOP_SYMBOLS = {
-    Add:        '+',
-    Sub:        '-',
-    Mult:       '*',
-    Div:        '/',
-    FloorDiv:   '//',
-    Mod:        '%',
-    LShift:     '<<',
-    RShift:     '>>',
-    BitOr:      '|',
-    BitAnd:     '&',
-    BitXor:     '^'
-}
-
-CMPOP_SYMBOLS = {
-    Eq:         '==',
-    Gt:         '>',
-    GtE:        '>=',
-    In:         'in',
-    Is:         'is',
-    IsNot:      'is not',
-    Lt:         '<',
-    LtE:        '<=',
-    NotEq:      '!=',
-    NotIn:      'not in'
-}
-
-UNARYOP_SYMBOLS = {
-    Invert:     '~',
-    Not:        'not',
-    UAdd:       '+',
-    USub:       '-'
-}
-
-ALL_SYMBOLS = {}
-ALL_SYMBOLS.update(BOOLOP_SYMBOLS)
-ALL_SYMBOLS.update(BINOP_SYMBOLS)
-ALL_SYMBOLS.update(CMPOP_SYMBOLS)
-ALL_SYMBOLS.update(UNARYOP_SYMBOLS)
-
-
-def parse(expr, filename='<unknown>', mode='exec'):
-    """Parse an expression into an AST node."""
-    return compile(expr, filename, mode, PyCF_ONLY_AST)
-
-
-def to_source(node, indent_with=' ' * 4):
-    """
-    This function can convert a node tree back into python sourcecode.  This
-    is useful for debugging purposes, especially if you're dealing with custom
-    asts not generated by python itself.
-
-    It could be that the sourcecode is evaluable when the AST itself is not
-    compilable / evaluable.  The reason for this is that the AST contains some
-    more data than regular sourcecode does, which is dropped during
-    conversion.
-
-    Each level of indentation is replaced with `indent_with`.  Per default this
-    parameter is equal to four spaces as suggested by PEP 8, but it might be
-    adjusted to match the application's styleguide.
-    """
-    generator = SourceGenerator(indent_with)
-    generator.visit(node)
-    return ''.join(generator.result)
-
-
-def dump(node):
-    """
-    A very verbose representation of the node passed.  This is useful for
-    debugging purposes.
-    """
-    def _format(node):
-        if isinstance(node, AST):
-            return '%s(%s)' % (node.__class__.__name__,
-                               ', '.join('%s=%s' % (a, _format(b))
-                                         for a, b in iter_fields(node)))
-        elif isinstance(node, ast_list):
-            return '[%s]' % ', '.join(_format(x) for x in node)
-        return repr(node)
-    if not isinstance(node, AST):
-        raise TypeError('expected AST, got %r' % node.__class__.__name__)
-    return _format(node)
-
-
-def copy_location(new_node, old_node):
-    """
-    Copy the source location hint (`lineno` and `col_offset`) from the
-    old to the new node if possible and return the new one.
-    """
-    for attr in 'lineno', 'col_offset':
-        if attr in old_node._attributes and attr in new_node._attributes \
-           and hasattr(old_node, attr):
-            setattr(new_node, attr, getattr(old_node, attr))
-    return new_node
-
-
-def fix_missing_locations(node):
-    """
-    Some nodes require a line number and the column offset.  Without that
-    information the compiler will abort the compilation.  Because it can be
-    a dull task to add appropriate line numbers and column offsets when
-    adding new nodes this function can help.  It copies the line number and
-    column offset of the parent node to the child nodes without this
-    information.
-
-    Unlike `copy_location` this works recursive and won't touch nodes that
-    already have a location information.
-    """
-    def _fix(node, lineno, col_offset):
-        if 'lineno' in node._attributes:
-            if not hasattr(node, 'lineno'):
-                node.lineno = lineno
-            else:
-                lineno = node.lineno
-        if 'col_offset' in node._attributes:
-            if not hasattr(node, 'col_offset'):
-                node.col_offset = col_offset
-            else:
-                col_offset = node.col_offset
-        for child in iter_child_nodes(node):
-            _fix(child, lineno, col_offset)
-    _fix(node, 1, 0)
-    return node
-
-
-def increment_lineno(node, n=1):
-    """
-    Increment the line numbers of all nodes by `n` if they have line number
-    attributes.  This is useful to "move code" to a different location in a
-    file.
-    """
-    for node in zip((node,), walk(node)):
-        if 'lineno' in node._attributes:
-            node.lineno = getattr(node, 'lineno', 0) + n
-
-
-def iter_fields(node):
-    """Iterate over all fields of a node, only yielding existing fields."""
-    if not hasattr(node, '_fields') or not node._fields:
-        return
-    for field in node._fields:
-        try:
-            yield field, getattr(node, field)
-        except AttributeError:
-            pass
-
-
-def get_fields(node):
-    """Like `iter_fiels` but returns a dict."""
-    return dict(iter_fields(node))
-
-
-def iter_child_nodes(node):
-    """Iterate over all child nodes or a node."""
-    for name, field in iter_fields(node):
-        if isinstance(field, AST):
-            yield field
-        elif isinstance(field, ast_list):
-            for item in field:
-                if isinstance(item, AST):
-                    yield item
-
-
-def get_child_nodes(node):
-    """Like `iter_child_nodes` but returns a list."""
-    return list(iter_child_nodes(node))
-
-
-def get_compile_mode(node):
-    """
-    Get the mode for `compile` of a given node.  If the node is not a `mod`
-    node (`Expression`, `Module` etc.) a `TypeError` is thrown.
-    """
-    if not isinstance(node, mod):
-        raise TypeError('expected mod node, got %r' % node.__class__.__name__)
-    return {
-        Expression:     'eval',
-        Interactive:    'single'
-    }.get(node.__class__, 'expr')
-
-
-def get_docstring(node):
-    """
-    Return the docstring for the given node or `None` if no docstring can be
-    found.  If the node provided does not accept docstrings a `TypeError`
-    will be raised.
-    """
-    if not isinstance(node, (FunctionDef, ClassDef, Module)):
-        raise TypeError("%r can't have docstrings" % node.__class__.__name__)
-    if node.body and isinstance(node.body[0], Str):
-        return node.body[0].s
-
-
-def walk(node):
-    """
-    Iterate over all nodes.  This is useful if you only want to modify nodes in
-    place and don't care about the context or the order the nodes are returned.
-    """
-    from collections import deque
-    todo = deque([node])
-    while todo:
-        node = todo.popleft()
-        todo.extend(iter_child_nodes(node))
-        yield node
-
-
-class NodeVisitor(object):
-    """
-    Walks the abstract syntax tree and call visitor functions for every node
-    found.  The visitor functions may return values which will be forwarded
-    by the `visit` method.
-
-    Per default the visitor functions for the nodes are ``'visit_'`` +
-    class name of the node.  So a `TryFinally` node visit function would
-    be `visit_TryFinally`.  This behavior can be changed by overriding
-    the `get_visitor` function.  If no visitor function exists for a node
-    (return value `None`) the `generic_visit` visitor is used instead.
-
-    Don't use the `NodeVisitor` if you want to apply changes to nodes during
-    traversing.  For this a special visitor exists (`NodeTransformer`) that
-    allows modifications.
-    """
-
-    def get_visitor(self, node):
-        """
-        Return the visitor function for this node or `None` if no visitor
-        exists for this node.  In that case the generic visit function is
-        used instead.
-        """
-        method = 'visit_' + get_class_name(node)
-        return getattr(self, method, None)
-
-    def visit(self, node):
-        """Visit a node."""
-        f = self.get_visitor(node)
-        if f is not None:
-            return f(node)
-        return self.generic_visit(node)
-
-    def generic_visit(self, node):
-        """Called if no explicit visitor function exists for a node."""
-        for field, value in iter_fields(node):
-            if isinstance(value, ast_list):
-                for item in value:
-                    if isinstance(item, AST):
-                        self.visit(item)
-            elif isinstance(value, AST):
-                self.visit(value)
-
-
-class NodeTransformer(NodeVisitor):
-    """
-    Walks the abstract syntax tree and allows modifications of nodes.
-
-    The `NodeTransformer` will walk the AST and use the return value of the
-    visitor functions to replace or remove the old node.  If the return
-    value of the visitor function is `None` the node will be removed
-    from the previous location otherwise it's replaced with the return
-    value.  The return value may be the original node in which case no
-    replacement takes place.
-
-    Here an example transformer that rewrites all `foo` to `data['foo']`::
-
-        class RewriteName(NodeTransformer):
-
-            def visit_Name(self, node):
-                return copy_location(Subscript(
-                    value=Name(id='data', ctx=Load()),
-                    slice=Index(value=Str(s=node.id)),
-                    ctx=node.ctx
-                ), node)
-
-    Keep in mind that if the node you're operating on has child nodes
-    you must either transform the child nodes yourself or call the generic
-    visit function for the node first.
-
-    Nodes that were part of a collection of statements (that applies to
-    all statement nodes) may also return a list of nodes rather than just
-    a single node.
-
-    Usually you use the transformer like this::
-
-        node = YourTransformer().visit(node)
-    """
-
-    def generic_visit(self, node):
-        for field, old_value in iter_fields(node):
-            old_value = getattr(node, field, None)
-            if isinstance(old_value, ast_list):
-                new_values = []
-                for value in old_value:
-                    if isinstance(value, AST):
-                        value = self.visit(value)
-                        if value is None:
-                            continue
-                        elif not isinstance(value, AST):
-                            new_values.extend(value)
-                            continue
-                    new_values.append(value)
-                old_value[:] = new_values
-            elif isinstance(old_value, AST):
-                new_node = self.visit(old_value)
-                if new_node is None:
-                    delattr(node, field)
-                else:
-                    setattr(node, field, new_node)
-        return node
-
-
-class SourceGenerator(NodeVisitor):
-    """
-    This visitor is able to transform a well formed syntax tree into python
-    sourcecode.  For more details have a look at the docstring of the
-    `node_to_source` function.
-    """
-
-    def __init__(self, indent_with):
-        self.result = []
-        self.indent_with = indent_with
-        self.indentation = 0
-        self.new_lines = 0
-
-    def write(self, x):
-        if self.new_lines:
-            if self.result:
-                self.result.append('\n' * self.new_lines)
-            self.result.append(self.indent_with * self.indentation)
-            self.new_lines = 0
-        self.result.append(x)
-
-    def newline(self, n=1):
-        self.new_lines = max(self.new_lines, n)
-
-    def body(self, statements):
-        self.new_line = True
-        self.indentation += 1
-        for stmt in statements:
-            self.visit(stmt)
-        self.indentation -= 1
-
-    def body_or_else(self, node):
-        self.body(node.body)
-        if node.orelse:
-            self.newline()
-            self.write('else:')
-            self.body(node.orelse)
-
-    def signature(self, node):
-        want_comma = []
-        def write_comma():
-            if want_comma:
-                self.write(', ')
-            else:
-                want_comma.append(True)
-
-        padding = [None] * (len(node.args) - len(node.defaults))
-        for arg, default in zip(node.args, padding + node.defaults):
-            write_comma()
-            self.visit(arg)
-            if default is not None:
-                self.write('=')
-                self.visit(default)
-        if node.vararg is not None:
-            write_comma()
-            self.write('*' + node.vararg)
-        if node.kwarg is not None:
-            write_comma()
-            self.write('**' + node.kwarg)
-
-    def decorators(self, node):
-        for decorator in node.decorator_list:
-            self.newline()
-            self.write('@')
-            self.visit(decorator)
-
-    # Statements
-
-    def visit_Assign(self, node):
-        self.newline()
-        for idx, target in enumerate(node.targets):
-            if idx:
-                self.write(', ')
-            self.visit(target)
-        self.write(' = ')
-        self.visit(node.value)
-
-    def visit_AugAssign(self, node):
-        self.newline()
-        self.visit(node.target)
-        self.write(BINOP_SYMBOLS[get_symbol_key(node.op)] + '=')
-        self.visit(node.value)
-
-    def visit_ImportFrom(self, node):
-        self.newline()
-        self.write('from %s%s import ' % ('.' * node.level, node.module))
-        for idx, item in enumerate(node.names):
-            if idx:
-                self.write(', ')
-            self.write(item)
-
-    def visit_Import(self, node):
-        self.newline()
-        for item in node.names:
-            self.write('import ')
-            self.visit(item)
-
-    def visit_Expr(self, node):
-        self.newline()
-        self.generic_visit(node)
-
-    def visit_FunctionDef(self, node):
-        self.newline(n=2)
-        self.decorators(node)
-        self.newline()
-        self.write('def %s(' % node.name)
-        self.signature(node.args)
-        self.write('):')
-        self.body(node.body)
-
-    def visit_ClassDef(self, node):
-        have_args = []
-        def paren_or_comma():
-            if have_args:
-                self.write(', ')
-            else:
-                have_args.append(True)
-                self.write('(')
-
-        self.newline(n=3)
-        self.decorators(node)
-        self.newline()
-        self.write('class %s' % node.name)
-        for base in node.bases:
-            paren_or_comma()
-            self.visit(base)
-        # XXX: the if here is used to keep this module compatible
-        #      with python 2.6.
-        if hasattr(node, 'keywords'):
-            for keyword in node.keywords:
-                paren_or_comma()
-                self.write(keyword.arg + '=')
-                self.visit(keyword.value)
-            if node.starargs is not None:
-                paren_or_comma()
-                self.write('*')
-                self.visit(node.starargs)
-            if node.kwargs is not None:
-                paren_or_comma()
-                self.write('**')
-                self.visit(node.kwargs)
-        self.write(have_args and '):' or ':')
-        self.body(node.body)
-
-    def visit_If(self, node):
-        self.newline()
-        self.write('if ')
-        self.visit(node.test)
-        self.write(':')
-        self.body(node.body)
-        while True:
-            else_ = node.orelse
-            if len(else_) == 1 and isinstance(else_[0], If):
-                node = else_[0]
-                self.newline()
-                self.write('elif ')
-                self.visit(node.test)
-                self.write(':')
-                self.body(node.body)
-            else:
-                self.newline()
-                self.write('else:')
-                self.body(else_)
-                break
-
-    def visit_For(self, node):
-        self.newline()
-        self.write('for ')
-        self.visit(node.target)
-        self.write(' in ')
-        self.visit(node.iter)
-        self.write(':')
-        self.body_or_else(node)
-
-    def visit_While(self, node):
-        self.newline()
-        self.write('while ')
-        self.visit(node.test)
-        self.write(':')
-        self.body_or_else(node)
-
-    def visit_With(self, node):
-        self.newline()
-        self.write('with ')
-        self.visit(node.context_expr)
-        if node.optional_vars is not None:
-            self.write(' as ')
-            self.visit(node.optional_vars)
-        self.write(':')
-        self.body(node.body)
-
-    def visit_Pass(self, node):
-        self.newline()
-        self.write('pass')
-
-    def visit_Print(self, node):
-        # XXX: python 2.6 only
-        self.newline()
-        self.write('print ')
-        want_comma = False
-        if node.dest is not None:
-            self.write(' >> ')
-            self.visit(node.dest)
-            want_comma = True
-        for value in node.values:
-            if want_comma:
-                self.write(', ')
-            self.visit(value)
-            want_comma = True
-        if not node.nl:
-            self.write(',')
-
-    def visit_Delete(self, node):
-        self.newline()
-        self.write('del ')
-        for idx, target in enumerate(node):
-            if idx:
-                self.write(', ')
-            self.visit(target)
-
-    def visit_TryExcept(self, node):
-        self.newline()
-        self.write('try:')
-        self.body(node.body)
-        for handler in node.handlers:
-            self.visit(handler)
-
-    def visit_TryFinally(self, node):
-        self.newline()
-        self.write('try:')
-        self.body(node.body)
-        self.newline()
-        self.write('finally:')
-        self.body(node.finalbody)
-
-    def visit_Global(self, node):
-        self.newline()
-        self.write('global ' + ', '.join(node.names))
-
-    def visit_Nonlocal(self, node):
-        self.newline()
-        self.write('nonlocal ' + ', '.join(node.names))
-
-    def visit_Return(self, node):
-        self.newline()
-        self.write('return ')
-        self.visit(node.value)
-
-    def visit_Break(self, node):
-        self.newline()
-        self.write('break')
-
-    def visit_Continue(self, node):
-        self.newline()
-        self.write('continue')
-
-    def visit_Raise(self, node):
-        # XXX: Python 2.6 / 3.0 compatibility
-        self.newline()
-        self.write('raise')
-        if hasattr(node, 'exc') and node.exc is not None:
-            self.write(' ')
-            self.visit(node.exc)
-            if node.cause is not None:
-                self.write(' from ')
-                self.visit(node.cause)
-        elif hasattr(node, 'type') and node.type is not None:
-            self.visit(node.type)
-            if node.inst is not None:
-                self.write(', ')
-                self.visit(node.inst)
-            if node.tback is not None:
-                self.write(', ')
-                self.visit(node.tback)
-
-    # Expressions
-
-    def visit_Attribute(self, node):
-        self.visit(node.value)
-        self.write('.' + node.attr)
-
-    def visit_Call(self, node):
-        want_comma = []
-        def write_comma():
-            if want_comma:
-                self.write(', ')
-            else:
-                want_comma.append(True)
-
-        self.visit(node.func)
-        self.write('(')
-        for arg in node.args:
-            write_comma()
-            self.visit(arg)
-        for keyword in node.keywords:
-            write_comma()
-            self.write(keyword.arg + '=')
-            self.visit(keyword.value)
-        if node.starargs is not None:
-            write_comma()
-            self.write('*')
-            self.visit(node.starargs)
-        if node.kwargs is not None:
-            write_comma()
-            self.write('**')
-            self.visit(node.kwargs)
-        self.write(')')
-
-    def visit_Name(self, node):
-        self.write(node.id)
-
-    def visit_Str(self, node):
-        self.write(repr(node.s))
-
-    def visit_Bytes(self, node):
-        self.write(repr(node.s))
-
-    def visit_Num(self, node):
-        self.write(repr(node.n))
-
-    def visit_Tuple(self, node):
-        self.write('(')
-        idx = -1
-        for idx, item in enumerate(node.elts):
-            if idx:
-                self.write(', ')
-            self.visit(item)
-        self.write(idx and ')' or ',)')
-
-    def sequence_visit(left, right):
-        def visit(self, node):
-            self.write(left)
-            for idx, item in enumerate(node.elts):
-                if idx:
-                    self.write(', ')
-                self.visit(item)
-            self.write(right)
-        return visit
-
-    visit_List = sequence_visit('[', ']')
-    visit_Set = sequence_visit('{', '}')
-    del sequence_visit
-
-    def visit_Dict(self, node):
-        self.write('{')
-        for idx, (key, value) in enumerate(zip(node.keys, node.values)):
-            if idx:
-                self.write(', ')
-            self.visit(key)
-            self.write(': ')
-            self.visit(value)
-        self.write('}')
-
-    def visit_BinOp(self, node):
-        self.write('(')
-        self.visit(node.left)
-        self.write(' %s ' % BINOP_SYMBOLS[get_symbol_key(node.op)])
-        self.visit(node.right)
-        self.write(')')
-
-    def visit_BoolOp(self, node):
-        self.write('(')
-        for idx, value in enumerate(node.values):
-            if idx:
-                self.write(' %s ' % BOOLOP_SYMBOLS[get_symbol_key(node.op)])
-            self.visit(value)
-        self.write(')')
-
-    def visit_Compare(self, node):
-        self.write('(')
-        self.visit(node.left)
-        for op, right in zip(node.ops, node.comparators):
-            self.write(' %s ' % CMPOP_SYMBOLS[get_symbol_key(op)])
-            self.visit(right)
-        self.write(')')
-
-    def visit_UnaryOp(self, node):
-        self.write('(')
-        op = UNARYOP_SYMBOLS[get_symbol_key(node.op)]
-        self.write(op)
-        if op == 'not':
-            self.write(' ')
-        self.visit(node.operand)
-        self.write(')')
-
-    def visit_Subscript(self, node):
-        self.visit(node.value)
-        self.write('[')
-        self.visit(node.slice)
-        self.write(']')
-
-    def visit_Slice(self, node):
-        if node.lower is not None:
-            self.visit(node.lower)
-        self.write(':')
-        if node.upper is not None:
-            self.visit(node.upper)
-        if node.step is not None:
-            self.write(':')
-            if not (isinstance(node.step, Name) and node.step.id == 'None'):
-                self.visit(node.step)
-
-    def visit_ExtSlice(self, node):
-        for idx, item in node.dims:
-            if idx:
-                self.write(', ')
-            self.visit(item)
-
-    def visit_Yield(self, node):
-        self.write('yield ')
-        self.visit(node.value)
-
-    def visit_Lambda(self, node):
-        self.write('lambda ')
-        self.signature(node.args)
-        self.write(': ')
-        self.visit(node.body)
-
-    def visit_Ellipsis(self, node):
-        self.write('Ellipsis')
-
-    def generator_visit(left, right):
-        def visit(self, node):
-            self.write(left)
-            self.visit(node.elt)
-            for comprehension in node.generators:
-                self.visit(comprehension)
-            self.write(right)
-        return visit
-
-    visit_ListComp = generator_visit('[', ']')
-    visit_GeneratorExp = generator_visit('(', ')')
-    visit_SetComp = generator_visit('{', '}')
-    del generator_visit
-
-    def visit_DictComp(self, node):
-        self.write('{')
-        self.visit(node.key)
-        self.write(': ')
-        self.visit(node.value)
-        for comprehension in node.generators:
-            self.visit(comprehension)
-        self.write('}')
-
-    def visit_IfExp(self, node):
-        self.visit(node.body)
-        self.write(' if ')
-        self.visit(node.test)
-        self.write(' else ')
-        self.visit(node.orelse)
-
-    def visit_Starred(self, node):
-        self.write('*')
-        self.visit(node.value)
-
-    def visit_Repr(self, node):
-        # XXX: python 2.6 only
-        self.write('`')
-        self.visit(node.value)
-        self.write('`')
-
-    # Helper Nodes
-
-    def visit_alias(self, node):
-        self.write(node.name)
-        if node.asname is not None:
-            self.write(' as ' + node.asname)
-
-    def visit_comprehension(self, node):
-        self.write(' for ')
-        self.visit(node.target)
-        self.write(' in ')
-        self.visit(node.iter)
-        if node.ifs:
-            for if_ in node.ifs:
-                self.write(' if ')
-                self.visit(if_)
-
-    def visit_excepthandler(self, node):
-        self.newline()
-        self.write('except')
-        if node.type is not None:
-            self.write(' ')
-            self.visit(node.type)
-            if node.name is not None:
-                self.write(' as ')
-                self.visit(node.name)
-        self.write(':')
-        self.body(node.body)
diff --git a/mako/ast.py b/mako/ast.py
deleted file mode 100644 (file)
index 6d4ef02..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-# ast.py
-# Copyright (C) 2006, 2007, 2008 Michael Bayer mike_mp@zzzcomputing.com
-#
-# This module is part of Mako and is released under
-# the MIT License: http://www.opensource.org/licenses/mit-license.php
-
-"""utilities for analyzing expressions and blocks of Python code, as well as generating Python from AST nodes"""
-
-from mako import exceptions, pyparser, util
-import re
-
-class PythonCode(object):
-    """represents information about a string containing Python code"""
-    def __init__(self, code, **exception_kwargs):
-        self.code = code
-        
-        # represents all identifiers which are assigned to at some point in the code
-        self.declared_identifiers = util.Set()
-        
-        # represents all identifiers which are referenced before their assignment, if any
-        self.undeclared_identifiers = util.Set()
-        
-        # note that an identifier can be in both the undeclared and declared lists.
-
-        # using AST to parse instead of using code.co_varnames, code.co_names has several advantages:
-        # - we can locate an identifier as "undeclared" even if its declared later in the same block of code
-        # - AST is less likely to break with version changes (for example, the behavior of co_names changed a little bit
-        # in python version 2.5)
-        if isinstance(code, basestring):
-            expr = pyparser.parse(code.lstrip(), "exec", **exception_kwargs)
-        else:
-            expr = code
-
-        f = pyparser.FindIdentifiers(self, **exception_kwargs)
-        f.visit(expr)
-
-class ArgumentList(object):
-    """parses a fragment of code as a comma-separated list of expressions"""
-    def __init__(self, code, **exception_kwargs):
-        self.codeargs = []
-        self.args = []
-        self.declared_identifiers = util.Set()
-        self.undeclared_identifiers = util.Set()
-        if isinstance(code, basestring):
-            if re.match(r"\S", code) and not re.match(r",\s*$", code):
-                # if theres text and no trailing comma, insure its parsed
-                # as a tuple by adding a trailing comma
-                code  += ","
-            expr = pyparser.parse(code, "exec", **exception_kwargs)
-        else:
-            expr = code
-
-        f = pyparser.FindTuple(self, PythonCode, **exception_kwargs)
-        f.visit(expr)
-        
-class PythonFragment(PythonCode):
-    """extends PythonCode to provide identifier lookups in partial control statements
-    
-    e.g. 
-        for x in 5:
-        elif y==9:
-        except (MyException, e):
-    etc.
-    """
-    def __init__(self, code, **exception_kwargs):
-        m = re.match(r'^(\w+)(?:\s+(.*?))?:\s*(#|$)', code.strip(), re.S)
-        if not m:
-            raise exceptions.CompileException("Fragment '%s' is not a partial control statement" % code, **exception_kwargs)
-        if m.group(3):
-            code = code[:m.start(3)]
-        (keyword, expr) = m.group(1,2)
-        if keyword in ['for','if', 'while']:
-            code = code + "pass"
-        elif keyword == 'try':
-            code = code + "pass\nexcept:pass"
-        elif keyword == 'elif' or keyword == 'else':
-            code = "if False:pass\n" + code + "pass"
-        elif keyword == 'except':
-            code = "try:pass\n" + code + "pass"
-        else:
-            raise exceptions.CompileException("Unsupported control keyword: '%s'" % keyword, **exception_kwargs)
-        super(PythonFragment, self).__init__(code, **exception_kwargs)
-        
-        
-class FunctionDecl(object):
-    """function declaration"""
-    def __init__(self, code, allow_kwargs=True, **exception_kwargs):
-        self.code = code
-        expr = pyparser.parse(code, "exec", **exception_kwargs)
-                
-        f = pyparser.ParseFunc(self, **exception_kwargs)
-        f.visit(expr)
-        if not hasattr(self, 'funcname'):
-            raise exceptions.CompileException("Code '%s' is not a function declaration" % code, **exception_kwargs)
-        if not allow_kwargs and self.kwargs:
-            raise exceptions.CompileException("'**%s' keyword argument not allowed here" % self.argnames[-1], **exception_kwargs)
-            
-    def get_argument_expressions(self, include_defaults=True):
-        """return the argument declarations of this FunctionDecl as a printable list."""
-        namedecls = []
-        defaults = [d for d in self.defaults]
-        kwargs = self.kwargs
-        varargs = self.varargs
-        argnames = [f for f in self.argnames]
-        argnames.reverse()
-        for arg in argnames:
-            default = None
-            if kwargs:
-                arg = "**" + arg
-                kwargs = False
-            elif varargs:
-                arg = "*" + arg
-                varargs = False
-            else:
-                default = len(defaults) and defaults.pop() or None
-            if include_defaults and default:
-                namedecls.insert(0, "%s=%s" % (arg, pyparser.ExpressionGenerator(default).value()))
-            else:
-                namedecls.insert(0, arg)
-        return namedecls
-
-class FunctionArgs(FunctionDecl):
-    """the argument portion of a function declaration"""
-    def __init__(self, code, **kwargs):
-        super(FunctionArgs, self).__init__("def ANON(%s):pass" % code, **kwargs)
diff --git a/mako/cache.py b/mako/cache.py
deleted file mode 100644 (file)
index 43f7317..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-from mako import exceptions
-
-try:
-    from beaker import cache
-    cache = cache.CacheManager()
-except ImportError:
-    cache = None
-
-class Cache(object):
-    def __init__(self, id, starttime):
-        self.id = id
-        self.starttime = starttime
-        self.def_regions = {}
-        
-    def put(self, key, value, **kwargs):
-        defname = kwargs.pop('defname', None)
-        expiretime = kwargs.pop('expiretime', None)
-        createfunc = kwargs.pop('createfunc', None)
-        
-        self._get_cache(defname, **kwargs).put_value(key, starttime=self.starttime, expiretime=expiretime)
-        
-    def get(self, key, **kwargs):
-        defname = kwargs.pop('defname', None)
-        expiretime = kwargs.pop('expiretime', None)
-        createfunc = kwargs.pop('createfunc', None)
-        
-        return self._get_cache(defname, **kwargs).get_value(key, starttime=self.starttime, expiretime=expiretime, createfunc=createfunc)
-        
-    def invalidate(self, key, **kwargs):
-        defname = kwargs.pop('defname', None)
-        expiretime = kwargs.pop('expiretime', None)
-        createfunc = kwargs.pop('createfunc', None)
-        
-        self._get_cache(defname, **kwargs).remove_value(key, starttime=self.starttime, expiretime=expiretime)
-    
-    def invalidate_body(self):
-        self.invalidate('render_body', defname='render_body')
-    
-    def invalidate_def(self, name):
-        self.invalidate('render_%s' % name, defname='render_%s' % name)
-        
-    def invalidate_closure(self, name):
-        self.invalidate(name, defname=name)
-    
-    def _get_cache(self, defname, type=None, **kw):
-        if not cache:
-            raise exceptions.RuntimeException("the Beaker package is required to use cache functionality.")
-        if type == 'memcached':
-            type = 'ext:memcached'
-        if not type:
-            (type, kw) = self.def_regions.get(defname, ('memory', {}))
-        else:
-            self.def_regions[defname] = (type, kw)
-        return cache.get_cache(self.id, type=type, **kw)
-        
\ No newline at end of file
diff --git a/mako/codegen.py b/mako/codegen.py
deleted file mode 100644 (file)
index 0f1be99..0000000
+++ /dev/null
@@ -1,697 +0,0 @@
-# codegen.py
-# Copyright (C) 2006, 2007, 2008 Michael Bayer mike_mp@zzzcomputing.com
-#
-# This module is part of Mako and is released under
-# the MIT License: http://www.opensource.org/licenses/mit-license.php
-
-"""provides functionality for rendering a parsetree constructing into module source code."""
-
-import time
-import re
-from mako.pygen import PythonPrinter
-from mako import util, ast, parsetree, filters
-
-MAGIC_NUMBER = 5
-
-
-def compile(node, uri, filename=None, default_filters=None, buffer_filters=None, imports=None, source_encoding=None, generate_unicode=True):
-    """generate module source code given a parsetree node, uri, and optional source filename"""
-
-    buf = util.FastEncodingBuffer(unicode=generate_unicode)
-
-    printer = PythonPrinter(buf)
-    _GenerateRenderMethod(printer, _CompileContext(uri, filename, default_filters, buffer_filters, imports, source_encoding, generate_unicode), node)
-    return buf.getvalue()
-
-class _CompileContext(object):
-    def __init__(self, uri, filename, default_filters, buffer_filters, imports, source_encoding, generate_unicode):
-        self.uri = uri
-        self.filename = filename
-        self.default_filters = default_filters
-        self.buffer_filters = buffer_filters
-        self.imports = imports
-        self.source_encoding = source_encoding
-        self.generate_unicode = generate_unicode
-        
-class _GenerateRenderMethod(object):
-    """a template visitor object which generates the full module source for a template."""
-    def __init__(self, printer, compiler, node):
-        self.printer = printer
-        self.last_source_line = -1
-        self.compiler = compiler
-        self.node = node
-        self.identifier_stack = [None]
-        
-        self.in_def = isinstance(node, parsetree.DefTag)
-
-        if self.in_def:
-            name = "render_" + node.name
-            args = node.function_decl.get_argument_expressions()
-            filtered = len(node.filter_args.args) > 0 
-            buffered = eval(node.attributes.get('buffered', 'False'))
-            cached = eval(node.attributes.get('cached', 'False'))
-            defs = None
-            pagetag = None
-        else:
-            defs = self.write_toplevel()
-            pagetag = self.compiler.pagetag
-            name = "render_body"
-            if pagetag is not None:
-                args = pagetag.body_decl.get_argument_expressions()
-                if not pagetag.body_decl.kwargs:
-                    args += ['**pageargs']
-                cached = eval(pagetag.attributes.get('cached', 'False'))
-            else:
-                args = ['**pageargs']
-                cached = False
-            buffered = filtered = False
-        if args is None:
-            args = ['context']
-        else:
-            args = [a for a in ['context'] + args]
-            
-        self.write_render_callable(pagetag or node, name, args, buffered, filtered, cached)
-        
-        if defs is not None:
-            for node in defs:
-                _GenerateRenderMethod(printer, compiler, node)
-    
-    identifiers = property(lambda self:self.identifier_stack[-1])
-    
-    def write_toplevel(self):
-        """traverse a template structure for module-level directives and generate the
-        start of module-level code."""
-        inherit = []
-        namespaces = {}
-        module_code = []
-        encoding =[None]
-
-        self.compiler.pagetag = None
-        
-        class FindTopLevel(object):
-            def visitInheritTag(s, node):
-                inherit.append(node)
-            def visitNamespaceTag(s, node):
-                namespaces[node.name] = node
-            def visitPageTag(s, node):
-                self.compiler.pagetag = node
-            def visitCode(s, node):
-                if node.ismodule:
-                    module_code.append(node)
-            
-        f = FindTopLevel()
-        for n in self.node.nodes:
-            n.accept_visitor(f)
-
-        self.compiler.namespaces = namespaces
-
-        module_ident = util.Set()
-        for n in module_code:
-            module_ident = module_ident.union(n.declared_identifiers())
-
-        module_identifiers = _Identifiers()
-        module_identifiers.declared = module_ident
-        
-        # module-level names, python code
-        if not self.compiler.generate_unicode and self.compiler.source_encoding:
-            self.printer.writeline("# -*- encoding:%s -*-" % self.compiler.source_encoding)
-            
-        self.printer.writeline("from mako import runtime, filters, cache")
-        self.printer.writeline("UNDEFINED = runtime.UNDEFINED")
-        self.printer.writeline("__M_dict_builtin = dict")
-        self.printer.writeline("__M_locals_builtin = locals")
-        self.printer.writeline("_magic_number = %s" % repr(MAGIC_NUMBER))
-        self.printer.writeline("_modified_time = %s" % repr(time.time()))
-        self.printer.writeline("_template_filename=%s" % repr(self.compiler.filename))
-        self.printer.writeline("_template_uri=%s" % repr(self.compiler.uri))
-        self.printer.writeline("_template_cache=cache.Cache(__name__, _modified_time)")
-        self.printer.writeline("_source_encoding=%s" % repr(self.compiler.source_encoding))
-        if self.compiler.imports:
-            buf = ''
-            for imp in self.compiler.imports:
-                buf += imp + "\n"
-                self.printer.writeline(imp)
-            impcode = ast.PythonCode(buf, source='', lineno=0, pos=0, filename='template defined imports')
-        else:
-            impcode = None
-        
-        main_identifiers = module_identifiers.branch(self.node)
-        module_identifiers.topleveldefs = module_identifiers.topleveldefs.union(main_identifiers.topleveldefs)
-        [module_identifiers.declared.add(x) for x in ["UNDEFINED"]]
-        if impcode:
-            [module_identifiers.declared.add(x) for x in impcode.declared_identifiers]
-            
-        self.compiler.identifiers = module_identifiers
-        self.printer.writeline("_exports = %s" % repr([n.name for n in main_identifiers.topleveldefs.values()]))
-        self.printer.write("\n\n")
-
-        if len(module_code):
-            self.write_module_code(module_code)
-
-        if len(inherit):
-            self.write_namespaces(namespaces)
-            self.write_inherit(inherit[-1])
-        elif len(namespaces):
-            self.write_namespaces(namespaces)
-
-        return main_identifiers.topleveldefs.values()
-
-    def write_render_callable(self, node, name, args, buffered, filtered, cached):
-        """write a top-level render callable.
-        
-        this could be the main render() method or that of a top-level def."""
-        self.printer.writelines(
-            "def %s(%s):" % (name, ','.join(args)),
-                "context.caller_stack._push_frame()",
-                "try:"
-        )
-        if buffered or filtered or cached:
-            self.printer.writeline("context._push_buffer()")
-        
-        self.identifier_stack.append(self.compiler.identifiers.branch(self.node))
-        if not self.in_def and '**pageargs' in args:
-            self.identifier_stack[-1].argument_declared.add('pageargs')
-
-        if not self.in_def and (len(self.identifiers.locally_assigned) > 0 or len(self.identifiers.argument_declared)>0):
-            self.printer.writeline("__M_locals = __M_dict_builtin(%s)" % ','.join(["%s=%s" % (x, x) for x in self.identifiers.argument_declared]))
-
-        self.write_variable_declares(self.identifiers, toplevel=True)
-
-        for n in self.node.nodes:
-            n.accept_visitor(self)
-
-        self.write_def_finish(self.node, buffered, filtered, cached)
-        self.printer.writeline(None)
-        self.printer.write("\n\n")
-        if cached:
-            self.write_cache_decorator(node, name, args, buffered, self.identifiers, toplevel=True)
-            
-    def write_module_code(self, module_code):
-        """write module-level template code, i.e. that which is enclosed in <%! %> tags
-        in the template."""
-        for n in module_code:
-            self.write_source_comment(n)
-            self.printer.write_indented_block(n.text)
-
-    def write_inherit(self, node):
-        """write the module-level inheritance-determination callable."""
-        self.printer.writelines(
-            "def _mako_inherit(template, context):",
-                "_mako_generate_namespaces(context)",
-                "return runtime._inherit_from(context, %s, _template_uri)" % (node.parsed_attributes['file']),
-                None
-            )
-
-    def write_namespaces(self, namespaces):
-        """write the module-level namespace-generating callable."""
-        self.printer.writelines(
-            "def _mako_get_namespace(context, name):",
-                "try:",
-                    "return context.namespaces[(__name__, name)]",
-                "except KeyError:",
-                    "_mako_generate_namespaces(context)",
-                "return context.namespaces[(__name__, name)]",
-            None,None
-            )
-        self.printer.writeline("def _mako_generate_namespaces(context):")
-        for node in namespaces.values():
-            if node.attributes.has_key('import'):
-                self.compiler.has_ns_imports = True
-            self.write_source_comment(node)
-            if len(node.nodes):
-                self.printer.writeline("def make_namespace():")
-                export = []
-                identifiers = self.compiler.identifiers.branch(node)
-                class NSDefVisitor(object):
-                    def visitDefTag(s, node):
-                        self.write_inline_def(node, identifiers, nested=False)
-                        export.append(node.name)
-                vis = NSDefVisitor()
-                for n in node.nodes:
-                    n.accept_visitor(vis)
-                self.printer.writeline("return [%s]" % (','.join(export)))
-                self.printer.writeline(None)
-                callable_name = "make_namespace()"
-            else:
-                callable_name = "None"
-            self.printer.writeline("ns = runtime.Namespace(%s, context._clean_inheritance_tokens(), templateuri=%s, callables=%s, calling_uri=_template_uri, module=%s)" % (repr(node.name), node.parsed_attributes.get('file', 'None'), callable_name, node.parsed_attributes.get('module', 'None')))
-            if eval(node.attributes.get('inheritable', "False")):
-                self.printer.writeline("context['self'].%s = ns" % (node.name))
-            self.printer.writeline("context.namespaces[(__name__, %s)] = ns" % repr(node.name))
-            self.printer.write("\n")
-        if not len(namespaces):
-            self.printer.writeline("pass")
-        self.printer.writeline(None)
-            
-    def write_variable_declares(self, identifiers, toplevel=False, limit=None):
-        """write variable declarations at the top of a function.
-        
-        the variable declarations are in the form of callable definitions for defs and/or
-        name lookup within the function's context argument.  the names declared are based on the
-        names that are referenced in the function body, which don't otherwise have any explicit
-        assignment operation.  names that are assigned within the body are assumed to be 
-        locally-scoped variables and are not separately declared.
-        
-        for def callable definitions, if the def is a top-level callable then a 
-        'stub' callable is generated which wraps the current Context into a closure.  if the def
-        is not top-level, it is fully rendered as a local closure."""
-        
-        # collection of all defs available to us in this scope
-        comp_idents = dict([(c.name, c) for c in identifiers.defs])
-        to_write = util.Set()
-        
-        # write "context.get()" for all variables we are going to need that arent in the namespace yet
-        to_write = to_write.union(identifiers.undeclared)
-        
-        # write closure functions for closures that we define right here
-        to_write = to_write.union(util.Set([c.name for c in identifiers.closuredefs.values()]))
-
-        # remove identifiers that are declared in the argument signature of the callable
-        to_write = to_write.difference(identifiers.argument_declared)
-
-        # remove identifiers that we are going to assign to.  in this way we mimic Python's behavior,
-        # i.e. assignment to a variable within a block means that variable is now a "locally declared" var,
-        # which cannot be referenced beforehand.  
-        to_write = to_write.difference(identifiers.locally_declared)
-        
-        # if a limiting set was sent, constraint to those items in that list
-        # (this is used for the caching decorator)
-        if limit is not None:
-            to_write = to_write.intersection(limit)
-        
-        if toplevel and getattr(self.compiler, 'has_ns_imports', False):
-            self.printer.writeline("_import_ns = {}")
-            self.compiler.has_imports = True
-            for ident, ns in self.compiler.namespaces.iteritems():
-                if ns.attributes.has_key('import'):
-                    self.printer.writeline("_mako_get_namespace(context, %s)._populate(_import_ns, %s)" % (repr(ident),  repr(re.split(r'\s*,\s*', ns.attributes['import']))))
-                        
-        for ident in to_write:
-            if ident in comp_idents:
-                comp = comp_idents[ident]
-                if comp.is_root():
-                    self.write_def_decl(comp, identifiers)
-                else:
-                    self.write_inline_def(comp, identifiers, nested=True)
-            elif ident in self.compiler.namespaces:
-                self.printer.writeline("%s = _mako_get_namespace(context, %s)" % (ident, repr(ident)))
-            else:
-                if getattr(self.compiler, 'has_ns_imports', False):
-                    self.printer.writeline("%s = _import_ns.get(%s, context.get(%s, UNDEFINED))" % (ident, repr(ident), repr(ident)))
-                else:
-                    self.printer.writeline("%s = context.get(%s, UNDEFINED)" % (ident, repr(ident)))
-        
-        self.printer.writeline("__M_writer = context.writer()")
-        
-    def write_source_comment(self, node):
-        """write a source comment containing the line number of the corresponding template line."""
-        if self.last_source_line != node.lineno:
-            self.printer.writeline("# SOURCE LINE %d" % node.lineno)
-            self.last_source_line = node.lineno
-
-    def write_def_decl(self, node, identifiers):
-        """write a locally-available callable referencing a top-level def"""
-        funcname = node.function_decl.funcname
-        namedecls = node.function_decl.get_argument_expressions()
-        nameargs = node.function_decl.get_argument_expressions(include_defaults=False)
-        if not self.in_def and (len(self.identifiers.locally_assigned) > 0 or len(self.identifiers.argument_declared) > 0):
-            nameargs.insert(0, 'context.locals_(__M_locals)')
-        else:
-            nameargs.insert(0, 'context')
-        self.printer.writeline("def %s(%s):" % (funcname, ",".join(namedecls)))
-        self.printer.writeline("return render_%s(%s)" % (funcname, ",".join(nameargs)))
-        self.printer.writeline(None)
-        
-    def write_inline_def(self, node, identifiers, nested):
-        """write a locally-available def callable inside an enclosing def."""
-        namedecls = node.function_decl.get_argument_expressions()
-        self.printer.writeline("def %s(%s):" % (node.name, ",".join(namedecls)))
-        filtered = len(node.filter_args.args) > 0 
-        buffered = eval(node.attributes.get('buffered', 'False'))
-        cached = eval(node.attributes.get('cached', 'False'))
-        self.printer.writelines(
-            "context.caller_stack._push_frame()",
-            "try:"
-            )
-        if buffered or filtered or cached:
-            self.printer.writelines(
-                "context._push_buffer()",
-                )
-
-        identifiers = identifiers.branch(node, nested=nested)
-
-        self.write_variable_declares(identifiers)
-        
-        self.identifier_stack.append(identifiers)
-        for n in node.nodes:
-            n.accept_visitor(self)
-        self.identifier_stack.pop()
-        
-        self.write_def_finish(node, buffered, filtered, cached)
-        self.printer.writeline(None)
-        if cached:
-            self.write_cache_decorator(node, node.name, namedecls, False, identifiers, inline=True, toplevel=False)
-            
-    def write_def_finish(self, node, buffered, filtered, cached, callstack=True):
-        """write the end section of a rendering function, either outermost or inline.
-        
-        this takes into account if the rendering function was filtered, buffered, etc.
-        and closes the corresponding try: block if any, and writes code to retrieve captured content, 
-        apply filters, send proper return value."""
-        if not buffered and not cached and not filtered:
-            self.printer.writeline("return ''")
-            if callstack:
-                self.printer.writelines(
-                    "finally:",
-                        "context.caller_stack._pop_frame()",
-                    None
-                )
-                
-        if buffered or filtered or cached:
-            if buffered or cached:
-                # in a caching scenario, don't try to get a writer
-                # from the context after popping; assume the caching
-                # implemenation might be using a context with no
-                # extra buffers
-                self.printer.writelines(
-                    "finally:",
-                        "__M_buf = context._pop_buffer()"
-                )
-            else:
-                self.printer.writelines(
-                    "finally:",
-                        "__M_buf, __M_writer = context._pop_buffer_and_writer()"
-                )
-                
-            if callstack:
-                self.printer.writeline("context.caller_stack._pop_frame()")
-                
-            s = "__M_buf.getvalue()"
-            if filtered:
-                s = self.create_filter_callable(node.filter_args.args, s, False)
-            self.printer.writeline(None)
-            if buffered and not cached:
-                s = self.create_filter_callable(self.compiler.buffer_filters, s, False)
-            if buffered or cached:
-                self.printer.writeline("return %s" % s)
-            else:
-                self.printer.writelines(
-                    "__M_writer(%s)" % s,
-                    "return ''"
-                )
-
-    def write_cache_decorator(self, node_or_pagetag, name, args, buffered, identifiers, inline=False, toplevel=False):
-        """write a post-function decorator to replace a rendering callable with a cached version of itself."""
-        self.printer.writeline("__M_%s = %s" % (name, name))
-        cachekey = node_or_pagetag.parsed_attributes.get('cache_key', repr(name))
-        cacheargs = {}
-        for arg in (('cache_type', 'type'), ('cache_dir', 'data_dir'), ('cache_timeout', 'expiretime'), ('cache_url', 'url')):
-            val = node_or_pagetag.parsed_attributes.get(arg[0], None)
-            if val is not None:
-                if arg[1] == 'expiretime':
-                    cacheargs[arg[1]] = int(eval(val))
-                else:
-                    cacheargs[arg[1]] = val
-            else:
-                if self.compiler.pagetag is not None:
-                    val = self.compiler.pagetag.parsed_attributes.get(arg[0], None)
-                    if val is not None:
-                        if arg[1] == 'expiretime':
-                            cacheargs[arg[1]] == int(eval(val))
-                        else:
-                            cacheargs[arg[1]] = val
-        
-        self.printer.writeline("def %s(%s):" % (name, ','.join(args)))
-        
-        # form "arg1, arg2, arg3=arg3, arg4=arg4", etc.
-        pass_args = [ '=' in a and "%s=%s" % ((a.split('=')[0],)*2) or a for a in args]
-
-        self.write_variable_declares(identifiers, toplevel=toplevel, limit=node_or_pagetag.undeclared_identifiers())
-        if buffered:
-            s = "context.get('local').get_cached(%s, defname=%r, %screatefunc=lambda:__M_%s(%s))" % (cachekey, name, ''.join(["%s=%s, " % (k,v) for k, v in cacheargs.iteritems()]), name, ','.join(pass_args))
-            # apply buffer_filters
-            s = self.create_filter_callable(self.compiler.buffer_filters, s, False)
-            self.printer.writelines("return " + s,None)
-        else:
-            self.printer.writelines(
-                    "__M_writer(context.get('local').get_cached(%s, defname=%r, %screatefunc=lambda:__M_%s(%s)))" % (cachekey, name, ''.join(["%s=%s, " % (k,v) for k, v in cacheargs.iteritems()]), name, ','.join(pass_args)),
-                    "return ''",
-                None
-            )
-
-    def create_filter_callable(self, args, target, is_expression):
-        """write a filter-applying expression based on the filters present in the given 
-        filter names, adjusting for the global 'default' filter aliases as needed."""
-        def locate_encode(name):
-            if re.match(r'decode\..+', name):
-                return "filters." + name
-            else:
-                return filters.DEFAULT_ESCAPES.get(name, name)
-        
-        if 'n' not in args:
-            if is_expression:
-                if self.compiler.pagetag:
-                    args = self.compiler.pagetag.filter_args.args + args
-                if self.compiler.default_filters:
-                    args = self.compiler.default_filters + args
-        for e in args:
-            # if filter given as a function, get just the identifier portion
-            if e == 'n':
-                continue
-            m = re.match(r'(.+?)(\(.*\))', e)
-            if m:
-                (ident, fargs) = m.group(1,2)
-                f = locate_encode(ident)
-                e = f + fargs
-            else:
-                x = e
-                e = locate_encode(e)
-                assert e is not None
-            target = "%s(%s)" % (e, target)
-        return target
-        
-    def visitExpression(self, node):
-        self.write_source_comment(node)
-        if len(node.escapes) or (self.compiler.pagetag is not None and len(self.compiler.pagetag.filter_args.args)) or len(self.compiler.default_filters):
-            s = self.create_filter_callable(node.escapes_code.args, "%s" % node.text, True)
-            self.printer.writeline("__M_writer(%s)" % s)
-        else:
-            self.printer.writeline("__M_writer(%s)" % node.text)
-            
-    def visitControlLine(self, node):
-        if node.isend:
-            self.printer.writeline(None)
-        else:
-            self.write_source_comment(node)
-            self.printer.writeline(node.text)
-    def visitText(self, node):
-        self.write_source_comment(node)
-        self.printer.writeline("__M_writer(%s)" % repr(node.content))
-    def visitTextTag(self, node):
-        filtered = len(node.filter_args.args) > 0
-        if filtered:
-            self.printer.writelines(
-                "__M_writer = context._push_writer()",
-                "try:",
-            )
-        for n in node.nodes:
-            n.accept_visitor(self)
-        if filtered:
-            self.printer.writelines(
-                "finally:",
-                "__M_buf, __M_writer = context._pop_buffer_and_writer()",
-                "__M_writer(%s)" % self.create_filter_callable(node.filter_args.args, "__M_buf.getvalue()", False),
-                None
-                )
-        
-    def visitCode(self, node):
-        if not node.ismodule:
-            self.write_source_comment(node)
-            self.printer.write_indented_block(node.text)
-
-            if not self.in_def and len(self.identifiers.locally_assigned) > 0:
-                # if we are the "template" def, fudge locally declared/modified variables into the "__M_locals" dictionary,
-                # which is used for def calls within the same template, to simulate "enclosing scope"
-                self.printer.writeline('__M_locals.update(__M_dict_builtin([(__M_key, __M_locals_builtin()[__M_key]) for __M_key in [%s] if __M_key in __M_locals_builtin()]))' % ','.join([repr(x) for x in node.declared_identifiers()]))
-                
-    def visitIncludeTag(self, node):
-        self.write_source_comment(node)
-        args = node.attributes.get('args')
-        if args:
-            self.printer.writeline("runtime._include_file(context, %s, _template_uri, %s)" % (node.parsed_attributes['file'], args))
-        else:
-            self.printer.writeline("runtime._include_file(context, %s, _template_uri)" % (node.parsed_attributes['file']))
-            
-    def visitNamespaceTag(self, node):
-        pass
-            
-    def visitDefTag(self, node):
-        pass
-
-    def visitCallTag(self, node):
-        self.printer.writeline("def ccall(caller):")
-        export = ['body']
-        callable_identifiers = self.identifiers.branch(node, nested=True)
-        body_identifiers = callable_identifiers.branch(node, nested=False)
-        # we want the 'caller' passed to ccall to be used for the body() function,
-        # but for other non-body() <%def>s within <%call> we want the current caller off the call stack (if any)
-        body_identifiers.add_declared('caller')
-        
-        self.identifier_stack.append(body_identifiers)
-        class DefVisitor(object):
-            def visitDefTag(s, node):
-                self.write_inline_def(node, callable_identifiers, nested=False)
-                export.append(node.name)
-                # remove defs that are within the <%call> from the "closuredefs" defined
-                # in the body, so they dont render twice
-                if node.name in body_identifiers.closuredefs:
-                    del body_identifiers.closuredefs[node.name]
-
-        vis = DefVisitor()
-        for n in node.nodes:
-            n.accept_visitor(vis)
-        self.identifier_stack.pop()
-        
-        bodyargs = node.body_decl.get_argument_expressions()    
-        self.printer.writeline("def body(%s):" % ','.join(bodyargs))
-        # TODO: figure out best way to specify buffering/nonbuffering (at call time would be better)
-        buffered = False
-        if buffered:
-            self.printer.writelines(
-                "context._push_buffer()",
-                "try:"
-            )
-        self.write_variable_declares(body_identifiers)
-        self.identifier_stack.append(body_identifiers)
-        
-        for n in node.nodes:
-            n.accept_visitor(self)
-        self.identifier_stack.pop()
-        
-        self.write_def_finish(node, buffered, False, False, callstack=False)
-        self.printer.writelines(
-            None,
-            "return [%s]" % (','.join(export)),
-            None
-        )
-
-        self.printer.writelines(
-            # get local reference to current caller, if any
-            "caller = context.caller_stack._get_caller()",
-            # push on caller for nested call
-            "context.caller_stack.nextcaller = runtime.Namespace('caller', context, callables=ccall(caller))",
-            "try:")
-        self.write_source_comment(node)
-        self.printer.writelines(
-                "__M_writer(%s)" % self.create_filter_callable([], node.attributes['expr'], True),
-            "finally:",
-                "context.caller_stack.nextcaller = None",
-            None
-        )
-
-class _Identifiers(object):
-    """tracks the status of identifier names as template code is rendered."""
-    def __init__(self, node=None, parent=None, nested=False):
-        if parent is not None:
-            # things that have already been declared in an enclosing namespace (i.e. names we can just use)
-            self.declared = util.Set(parent.declared).union([c.name for c in parent.closuredefs.values()]).union(parent.locally_declared).union(parent.argument_declared)
-            
-            # if these identifiers correspond to a "nested" scope, it means whatever the 
-            # parent identifiers had as undeclared will have been declared by that parent, 
-            # and therefore we have them in our scope.
-            if nested:
-                self.declared = self.declared.union(parent.undeclared)
-            
-            # top level defs that are available
-            self.topleveldefs = util.SetLikeDict(**parent.topleveldefs)
-        else:
-            self.declared = util.Set()
-            self.topleveldefs = util.SetLikeDict()
-        
-        # things within this level that are referenced before they are declared (e.g. assigned to)
-        self.undeclared = util.Set()
-        
-        # things that are declared locally.  some of these things could be in the "undeclared"
-        # list as well if they are referenced before declared
-        self.locally_declared = util.Set()
-    
-        # assignments made in explicit python blocks.  these will be propigated to 
-        # the context of local def calls.
-        self.locally_assigned = util.Set()
-        
-        # things that are declared in the argument signature of the def callable
-        self.argument_declared = util.Set()
-        
-        # closure defs that are defined in this level
-        self.closuredefs = util.SetLikeDict()
-        
-        self.node = node
-        
-        if node is not None:
-            node.accept_visitor(self)
-        
-    def branch(self, node, **kwargs):
-        """create a new Identifiers for a new Node, with this Identifiers as the parent."""
-        return _Identifiers(node, self, **kwargs)
-    
-    defs = property(lambda self:util.Set(self.topleveldefs.union(self.closuredefs).values()))
-    
-    def __repr__(self):
-        return "Identifiers(declared=%s, locally_declared=%s, undeclared=%s, topleveldefs=%s, closuredefs=%s, argumenetdeclared=%s)" % (repr(list(self.declared)), repr(list(self.locally_declared)), repr(list(self.undeclared)), repr([c.name for c in self.topleveldefs.values()]), repr([c.name for c in self.closuredefs.values()]), repr(self.argument_declared))
-        
-    def check_declared(self, node):
-        """update the state of this Identifiers with the undeclared and declared identifiers of the given node."""
-        for ident in node.undeclared_identifiers():
-            if ident != 'context' and ident not in self.declared.union(self.locally_declared):
-                self.undeclared.add(ident)
-        for ident in node.declared_identifiers():
-            self.locally_declared.add(ident)
-    
-    def add_declared(self, ident):
-        self.declared.add(ident)
-        if ident in self.undeclared:
-            self.undeclared.remove(ident)
-                        
-    def visitExpression(self, node):
-        self.check_declared(node)
-    def visitControlLine(self, node):
-        self.check_declared(node)
-    def visitCode(self, node):
-        if not node.ismodule:
-            self.check_declared(node)
-            self.locally_assigned = self.locally_assigned.union(node.declared_identifiers())
-    def visitDefTag(self, node):
-        if node.is_root():
-            self.topleveldefs[node.name] = node
-        elif node is not self.node:
-            self.closuredefs[node.name] = node
-        for ident in node.undeclared_identifiers():
-            if ident != 'context' and ident not in self.declared.union(self.locally_declared):
-                self.undeclared.add(ident)
-        # visit defs only one level deep
-        if node is self.node:
-            for ident in node.declared_identifiers():
-                self.argument_declared.add(ident)
-            for n in node.nodes:
-                n.accept_visitor(self)
-    def visitIncludeTag(self, node):
-        self.check_declared(node)
-    def visitPageTag(self, node):
-        for ident in node.declared_identifiers():
-            self.argument_declared.add(ident)
-        self.check_declared(node)
-                    
-    def visitCallTag(self, node):
-        if node is self.node:
-            for ident in node.undeclared_identifiers():
-                if ident != 'context' and ident not in self.declared.union(self.locally_declared):
-                    self.undeclared.add(ident)
-            for ident in node.declared_identifiers():
-                self.argument_declared.add(ident)
-            for n in node.nodes:
-                n.accept_visitor(self)
-        else:
-            for ident in node.undeclared_identifiers():
-                if ident != 'context' and ident not in self.declared.union(self.locally_declared):
-                    self.undeclared.add(ident)
-                
diff --git a/mako/exceptions.py b/mako/exceptions.py
deleted file mode 100644 (file)
index 3f4e3a7..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-# exceptions.py
-# Copyright (C) 2006, 2007, 2008 Michael Bayer mike_mp@zzzcomputing.com
-#
-# This module is part of Mako and is released under
-# the MIT License: http://www.opensource.org/licenses/mit-license.php
-
-"""exception classes"""
-
-import traceback, sys, re
-from mako import util
-
-class MakoException(Exception):
-    pass
-
-class RuntimeException(MakoException):
-    pass
-
-def _format_filepos(lineno, pos, filename):
-    if filename is None:
-        return " at line: %d char: %d" % (lineno, pos)
-    else:
-        return " in file '%s' at line: %d char: %d" % (filename, lineno, pos)     
-class CompileException(MakoException):
-    def __init__(self, message, source, lineno, pos, filename):
-        MakoException.__init__(self, message + _format_filepos(lineno, pos, filename))
-        self.lineno =lineno
-        self.pos = pos
-        self.filename = filename
-        self.source = source
-                    
-class SyntaxException(MakoException):
-    def __init__(self, message, source, lineno, pos, filename):
-        MakoException.__init__(self, message + _format_filepos(lineno, pos, filename))
-        self.lineno =lineno
-        self.pos = pos
-        self.filename = filename
-        self.source = source
-        
-class TemplateLookupException(MakoException):
-    pass
-
-class TopLevelLookupException(TemplateLookupException):
-    pass
-    
-class RichTraceback(object):
-    """pulls the current exception from the sys traceback and extracts Mako-specific 
-    template information.
-    
-    Usage:
-    
-    RichTraceback()
-    
-    Properties:
-    
-    error - the exception instance.  
-    source - source code of the file where the error occured.  if the error occured within a compiled template,
-    this is the template source.
-    lineno - line number where the error occured.  if the error occured within a compiled template, the line number
-    is adjusted to that of the template source
-    records - a list of 8-tuples containing the original python traceback elements, plus the 
-    filename, line number, source line, and full template source for the traceline mapped back to its originating source
-    template, if any for that traceline (else the fields are None).
-    reverse_records - the list of records in reverse
-    traceback - a list of 4-tuples, in the same format as a regular python traceback, with template-corresponding 
-    traceback records replacing the originals
-    reverse_traceback - the traceback list in reverse
-    """
-    def __init__(self):
-        (self.source, self.lineno) = ("", 0)
-        (t, self.error, self.records) = self._init()
-        if self.error is None:
-            self.error = t
-        if isinstance(self.error, CompileException) or isinstance(self.error, SyntaxException):
-            import mako.template
-            self.source = self.error.source
-            self.lineno = self.error.lineno
-            self._has_source = True
-        self.reverse_records = [r for r in self.records]
-        self.reverse_records.reverse()
-    def _get_reformatted_records(self, records):
-        for rec in records:
-            if rec[6] is not None:
-                yield (rec[4], rec[5], rec[2], rec[6])
-            else:
-                yield tuple(rec[0:4])
-    traceback = property(lambda self:self._get_reformatted_records(self.records), doc="""
-        return a list of 4-tuple traceback records (i.e. normal python format)
-        with template-corresponding lines remapped to the originating template
-    """)
-    reverse_traceback = property(lambda self:self._get_reformatted_records(self.reverse_records), doc="""
-        return the same data as traceback, except in reverse order
-    """)
-    def _init(self):
-        """format a traceback from sys.exc_info() into 7-item tuples, containing
-        the regular four traceback tuple items, plus the original template 
-        filename, the line number adjusted relative to the template source, and
-        code line from that line number of the template."""
-        import mako.template
-        mods = {}
-        (type, value, trcback) = sys.exc_info()
-        rawrecords = traceback.extract_tb(trcback)
-        new_trcback = []
-        for filename, lineno, function, line in rawrecords:
-            try:
-                (line_map, template_lines) = mods[filename]
-            except KeyError:
-                try:
-                    info = mako.template._get_module_info(filename)
-                    module_source = info.code
-                    template_source = info.source
-                    template_filename = info.template_filename or filename
-                except KeyError:
-                    new_trcback.append((filename, lineno, function, line, None, None, None, None))
-                    continue
-
-                template_ln = module_ln = 1
-                line_map = {}
-                for line in module_source.split("\n"):
-                    match = re.match(r'\s*# SOURCE LINE (\d+)', line)
-                    if match:
-                        template_ln = int(match.group(1))
-                    else:
-                        template_ln += 1
-                    module_ln += 1
-                    line_map[module_ln] = template_ln
-                template_lines = [line for line in template_source.split("\n")]
-                mods[filename] = (line_map, template_lines)
-
-            template_ln = line_map[lineno]
-            if template_ln <= len(template_lines):
-                template_line = template_lines[template_ln - 1]
-            else:
-                template_line = None
-            new_trcback.append((filename, lineno, function, line, template_filename, template_ln, template_line, template_source))
-        if not self.source:
-            for l in range(len(new_trcback)-1, 0, -1):
-                if new_trcback[l][5]:
-                    self.source = new_trcback[l][7]
-                    self.lineno = new_trcback[l][5]
-                    break
-            else:
-                try:
-                    # A normal .py file (not a Template)
-                    fp = open(new_trcback[-1][0])
-                    encoding = util.parse_encoding(fp)
-                    fp.seek(0)
-                    self.source = fp.read()
-                    fp.close()
-                    if encoding:
-                        self.source = self.source.decode(encoding)
-                except IOError:
-                    self.source = ''
-                self.lineno = new_trcback[-1][1]
-        return (type, value, new_trcback)
-
-                
-def text_error_template(lookup=None):
-    """provides a template that renders a stack trace in a similar format to the Python interpreter,
-    substituting source template filenames, line numbers and code for that of the originating
-    source template, as applicable."""
-    import mako.template
-    return mako.template.Template(r"""
-<%!
-    from mako.exceptions import RichTraceback
-%>\
-<%
-    tback = RichTraceback()
-%>\
-Traceback (most recent call last):
-% for (filename, lineno, function, line) in tback.traceback:
-  File "${filename}", line ${lineno}, in ${function or '?'}
-    ${line | unicode.strip}
-% endfor
-${str(tback.error.__class__.__name__)}: ${str(tback.error)}
-""")
-
-def html_error_template():
-    """provides a template that renders a stack trace in an HTML format, providing an excerpt of 
-    code as well as substituting source template filenames, line numbers and code 
-    for that of the originating source template, as applicable.
-
-    the template's default encoding_errors value is 'htmlentityreplace'. the template has
-    two options:
-
-    with the full option disabled, only a section of an HTML document is returned.
-    with the css option disabled, the default stylesheet won't be included."""
-    import mako.template
-    return mako.template.Template(r"""
-<%!
-    from mako.exceptions import RichTraceback
-%>
-<%page args="full=True, css=True"/>
-% if full:
-<html>
-<head>
-    <title>Mako Runtime Error</title>
-% endif
-% if css:
-    <style>
-        body { font-family:verdana; margin:10px 30px 10px 30px;}
-        .stacktrace { margin:5px 5px 5px 5px; }
-        .highlight { padding:0px 10px 0px 10px; background-color:#9F9FDF; }
-        .nonhighlight { padding:0px; background-color:#DFDFDF; }
-        .sample { padding:10px; margin:10px 10px 10px 10px; font-family:monospace; }
-        .sampleline { padding:0px 10px 0px 10px; }
-        .sourceline { margin:5px 5px 10px 5px; font-family:monospace;}
-        .location { font-size:80%; }
-    </style>
-% endif
-% if full:
-</head>
-<body>
-% endif
-
-<h2>Error !</h2>
-<%
-    tback = RichTraceback()
-    src = tback.source
-    line = tback.lineno
-    if src:
-        lines = src.split('\n')
-    else:
-        lines = None
-%>
-<h3>${str(tback.error.__class__.__name__)}: ${str(tback.error)}</h3>
-
-% if lines:
-    <div class="sample">
-    <div class="nonhighlight">
-% for index in range(max(0, line-4),min(len(lines), line+5)):
-    % if index + 1 == line:
-<div class="highlight">${index + 1} ${lines[index] | h}</div>
-    % else:
-<div class="sampleline">${index + 1} ${lines[index] | h}</div>
-    % endif
-% endfor
-    </div>
-    </div>
-% endif
-
-<div class="stacktrace">
-% for (filename, lineno, function, line) in tback.reverse_traceback:
-    <div class="location">${filename}, line ${lineno}:</div>
-    <div class="sourceline">${line | h}</div>
-% endfor
-</div>
-
-% if full:
-</body>
-</html>
-% endif
-""", output_encoding=sys.getdefaultencoding(), encoding_errors='htmlentityreplace')
diff --git a/mako/filters.py b/mako/filters.py
deleted file mode 100644 (file)
index f252241..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-# filters.py
-# Copyright (C) 2006, 2007, 2008 Geoffrey T. Dairiki <dairiki@dairiki.org> and Michael Bayer <mike_mp@zzzcomputing.com>
-#
-# This module is part of Mako and is released under
-# the MIT License: http://www.opensource.org/licenses/mit-license.php
-
-
-import re, cgi, urllib, htmlentitydefs, codecs
-from StringIO import StringIO
-
-xml_escapes = {
-    '&' : '&amp;',
-    '>' : '&gt;', 
-    '<' : '&lt;', 
-    '"' : '&#34;',   # also &quot; in html-only
-    "'" : '&#39;'    # also &apos; in html-only    
-}
-# XXX: &quot; is valid in HTML and XML
-#      &apos; is not valid HTML, but is valid XML
-
-def html_escape(string):
-    return cgi.escape(string, True)
-
-def xml_escape(string):
-    return re.sub(r'([&<"\'>])', lambda m: xml_escapes[m.group()], string)
-
-def url_escape(string):
-    # convert into a list of octets
-    string = string.encode("utf8")
-    return urllib.quote_plus(string)
-
-def url_unescape(string):
-    text = urllib.unquote_plus(string)
-    if not is_ascii_str(text):
-        text = text.decode("utf8")
-    return text
-
-def trim(string):
-    return string.strip()
-
-
-class Decode(object):
-    def __getattr__(self, key):
-        def decode(x):
-            if isinstance(x, unicode):
-                return x
-            elif not isinstance(x, str):
-                return unicode(str(x), encoding=key)
-            else:
-                return unicode(x, encoding=key)
-        return decode
-decode = Decode()
-        
-            
-_ASCII_re = re.compile(r'\A[\x00-\x7f]*\Z')
-
-def is_ascii_str(text):
-    return isinstance(text, str) and _ASCII_re.match(text)
-
-################################################################    
-
-class XMLEntityEscaper(object):
-    def __init__(self, codepoint2name, name2codepoint):
-        self.codepoint2entity = dict([(c, u'&%s;' % n)
-                                      for c,n in codepoint2name.iteritems()])
-        self.name2codepoint = name2codepoint
-
-    def escape_entities(self, text):
-        """Replace characters with their character entity references.
-
-        Only characters corresponding to a named entity are replaced.
-        """
-        return unicode(text).translate(self.codepoint2entity)
-
-    def __escape(self, m):
-        codepoint = ord(m.group())
-        try:
-            return self.codepoint2entity[codepoint]
-        except (KeyError, IndexError):
-            return '&#x%X;' % codepoint
-
-
-    __escapable = re.compile(r'["&<>]|[^\x00-\x7f]')
-
-    def escape(self, text):
-        """Replace characters with their character references.
-
-        Replace characters by their named entity references.
-        Non-ASCII characters, if they do not have a named entity reference,
-        are replaced by numerical character references.
-
-        The return value is guaranteed to be ASCII.
-        """
-        return self.__escapable.sub(self.__escape, unicode(text)
-                                    ).encode('ascii')
-
-    # XXX: This regexp will not match all valid XML entity names__.
-    # (It punts on details involving involving CombiningChars and Extenders.)
-    #
-    # .. __: http://www.w3.org/TR/2000/REC-xml-20001006#NT-EntityRef
-    __characterrefs = re.compile(r'''& (?:
-                                          \#(\d+)
-                                          | \#x([\da-f]+)
-                                          | ( (?!\d) [:\w] [-.:\w]+ )
-                                          ) ;''',
-                                 re.X | re.UNICODE)
-    
-    def __unescape(self, m):
-        dval, hval, name = m.groups()
-        if dval:
-            codepoint = int(dval)
-        elif hval:
-            codepoint = int(hval, 16)
-        else:
-            codepoint = self.name2codepoint.get(name, 0xfffd)
-            # U+FFFD = "REPLACEMENT CHARACTER"
-        if codepoint < 128:
-            return chr(codepoint)
-        return unichr(codepoint)
-    
-    def unescape(self, text):
-        """Unescape character references.
-
-        All character references (both entity references and numerical
-        character references) are unescaped.
-        """
-        return self.__characterrefs.sub(self.__unescape, text)
-
-
-_html_entities_escaper = XMLEntityEscaper(htmlentitydefs.codepoint2name,
-                                          htmlentitydefs.name2codepoint)
-
-html_entities_escape = _html_entities_escaper.escape_entities
-html_entities_unescape = _html_entities_escaper.unescape
-
-
-def htmlentityreplace_errors(ex):
-    """An encoding error handler.
-
-    This python `codecs`_ error handler replaces unencodable
-    characters with HTML entities, or, if no HTML entity exists for
-    the character, XML character references.
-
-    >>> u'The cost was \u20ac12.'.encode('latin1', 'htmlentityreplace')
-    'The cost was &euro;12.'
-    """
-    if isinstance(ex, UnicodeEncodeError):
-        # Handle encoding errors
-        bad_text = ex.object[ex.start:ex.end]
-        text = _html_entities_escaper.escape(bad_text)
-        return (unicode(text), ex.end)
-    raise ex
-
-codecs.register_error('htmlentityreplace', htmlentityreplace_errors)
-
-
-# TODO: options to make this dynamic per-compilation will be added in a later release
-DEFAULT_ESCAPES = {
-    'x':'filters.xml_escape',
-    'h':'filters.html_escape',
-    'u':'filters.url_escape',
-    'trim':'filters.trim',
-    'entity':'filters.html_entities_escape',
-    'unicode':'unicode',
-    'decode':'decode',
-    'str':'str',
-    'n':'n'
-}
-    
-
diff --git a/mako/lexer.py b/mako/lexer.py
deleted file mode 100644 (file)
index 785461c..0000000
+++ /dev/null
@@ -1,328 +0,0 @@
-# lexer.py
-# Copyright (C) 2006, 2007, 2008 Michael Bayer mike_mp@zzzcomputing.com
-#
-# This module is part of Mako and is released under
-# the MIT License: http://www.opensource.org/licenses/mit-license.php
-
-"""provides the Lexer class for parsing template strings into parse trees."""
-
-import re, codecs
-from mako import parsetree, exceptions
-from mako.pygen import adjust_whitespace
-
-_regexp_cache = {}
-
-class Lexer(object):
-    def __init__(self, text, filename=None, disable_unicode=False, input_encoding=None, preprocessor=None):
-        self.text = text
-        self.filename = filename
-        self.template = parsetree.TemplateNode(self.filename)
-        self.matched_lineno = 1
-        self.matched_charpos = 0
-        self.lineno = 1
-        self.match_position = 0
-        self.tag = []
-        self.control_line = []
-        self.disable_unicode = disable_unicode
-        self.encoding = input_encoding
-        if preprocessor is None:
-            self.preprocessor = []
-        elif not hasattr(preprocessor, '__iter__'):
-            self.preprocessor = [preprocessor]
-        else:
-            self.preprocessor = preprocessor
-            
-    exception_kwargs = property(lambda self:{'source':self.text, 'lineno':self.matched_lineno, 'pos':self.matched_charpos, 'filename':self.filename})
-    
-    def match(self, regexp, flags=None):
-        """match the given regular expression string and flags to the current text position.
-        
-        if a match occurs, update the current text and line position."""
-        mp = self.match_position
-        try:
-            reg = _regexp_cache[(regexp, flags)]
-        except KeyError:
-            if flags:
-                reg = re.compile(regexp, flags)
-            else:
-                reg = re.compile(regexp)
-            _regexp_cache[(regexp, flags)] = reg
-
-        match = reg.match(self.text, self.match_position)
-        if match:
-            (start, end) = match.span()
-            if end == start:
-                self.match_position = end + 1
-            else:
-                self.match_position = end
-            self.matched_lineno = self.lineno
-            lines = re.findall(r"\n", self.text[mp:self.match_position])
-            cp = mp - 1
-            while (cp >= 0 and cp<self.textlength and self.text[cp] != '\n'):
-                cp -=1
-            self.matched_charpos = mp - cp
-            self.lineno += len(lines)
-            #print "MATCHED:", match.group(0), "LINE START:", self.matched_lineno, "LINE END:", self.lineno
-        #print "MATCH:", regexp, "\n", self.text[mp : mp + 15], (match and "TRUE" or "FALSE")
-        return match
-    
-    def parse_until_text(self, *text):
-        startpos = self.match_position
-        while True:
-            match = self.match(r'#.*\n')
-            if match:
-                continue
-            match = self.match(r'(\"\"\"|\'\'\'|\"|\')')
-            if match:
-                m = self.match(r'.*?%s' % match.group(1), re.S)
-                if not m:
-                    raise exceptions.SyntaxException("Unmatched '%s'" % match.group(1), **self.exception_kwargs)
-            else:
-                match = self.match(r'(%s)' % r'|'.join(text))
-                if match:
-                    return (self.text[startpos:self.match_position-len(match.group(1))], match.group(1))
-                else:
-                    match = self.match(r".*?(?=\"|\'|#|%s)" % r'|'.join(text), re.S)
-                    if not match:
-                        raise exceptions.SyntaxException("Expected: %s" % ','.join(text), **self.exception_kwargs)
-                
-    def append_node(self, nodecls, *args, **kwargs):
-        kwargs.setdefault('source', self.text)
-        kwargs.setdefault('lineno', self.matched_lineno)
-        kwargs.setdefault('pos', self.matched_charpos)
-        kwargs['filename'] = self.filename
-        node = nodecls(*args, **kwargs)
-        if len(self.tag):
-            self.tag[-1].nodes.append(node)
-        else:
-            self.template.nodes.append(node)
-        if isinstance(node, parsetree.Tag):
-            if len(self.tag):
-                node.parent = self.tag[-1]
-            self.tag.append(node)
-        elif isinstance(node, parsetree.ControlLine):
-            if node.isend:
-                self.control_line.pop()
-            elif node.is_primary:
-                self.control_line.append(node)
-            elif len(self.control_line) and not self.control_line[-1].is_ternary(node.keyword):
-                raise exceptions.SyntaxException("Keyword '%s' not a legal ternary for keyword '%s'" % (node.keyword, self.control_line[-1].keyword), **self.exception_kwargs)
-
-    def escape_code(self, text):
-        if not self.disable_unicode and self.encoding:
-            return text.encode('ascii', 'backslashreplace')
-        else:
-            return text
-            
-    def parse(self):
-        for preproc in self.preprocessor:
-            self.text = preproc(self.text)
-        if not isinstance(self.text, unicode) and self.text.startswith(codecs.BOM_UTF8):
-            self.text = self.text[len(codecs.BOM_UTF8):]
-            parsed_encoding = 'utf-8'
-            me = self.match_encoding()
-            if me is not None and me != 'utf-8':
-                raise exceptions.CompileException("Found utf-8 BOM in file, with conflicting magic encoding comment of '%s'" % me, self.text.decode('utf-8', 'ignore'), 0, 0, self.filename)
-        else:
-            parsed_encoding = self.match_encoding()
-        if parsed_encoding:
-            self.encoding = parsed_encoding
-        if not self.disable_unicode and not isinstance(self.text, unicode):
-            if self.encoding:
-                try:
-                    self.text = self.text.decode(self.encoding)
-                except UnicodeDecodeError, e:
-                    raise exceptions.CompileException("Unicode decode operation of encoding '%s' failed" % self.encoding, self.text.decode('utf-8', 'ignore'), 0, 0, self.filename)
-            else:
-                try:
-                    self.text = self.text.decode()
-                except UnicodeDecodeError, e:
-                    raise exceptions.CompileException("Could not read template using encoding of 'ascii'.  Did you forget a magic encoding comment?", self.text.decode('utf-8', 'ignore'), 0, 0, self.filename)
-
-        self.textlength = len(self.text)
-            
-        while (True):
-            if self.match_position > self.textlength: 
-                break
-        
-            if self.match_end():
-                break
-            if self.match_expression():
-                continue
-            if self.match_control_line():
-                continue
-            if self.match_comment():
-                continue
-            if self.match_tag_start(): 
-                continue
-            if self.match_tag_end():
-                continue
-            if self.match_python_block():
-                continue
-            if self.match_text(): 
-                continue
-            
-            if self.match_position > self.textlength: 
-                break
-            raise exceptions.CompileException("assertion failed")
-            
-        if len(self.tag):
-            raise exceptions.SyntaxException("Unclosed tag: <%%%s>" % self.tag[-1].keyword, **self.exception_kwargs)
-        if len(self.control_line):
-            raise exceptions.SyntaxException("Unterminated control keyword: '%s'" % self.control_line[-1].keyword, self.text, self.control_line[-1].lineno, self.control_line[-1].pos, self.filename)
-        return self.template
-
-    def match_encoding(self):
-        match = self.match(r'#.*coding[:=]\s*([-\w.]+).*\r?\n')
-        if match:
-            return match.group(1)
-        else:
-            return None
-            
-    def match_tag_start(self):
-        match = self.match(r'''
-            \<%     # opening tag
-            
-            (\w+)   # keyword
-            
-            ((?:\s+\w+|=|".*?"|'.*?')*)  # attrname, = sign, string expression
-            
-            \s*     # more whitespace
-            
-            (/)?>   # closing
-            
-            ''', 
-            
-            re.I | re.S | re.X)
-            
-        if match:
-            (keyword, attr, isend) = (match.group(1).lower(), match.group(2), match.group(3))
-            self.keyword = keyword
-            attributes = {}
-            if attr:
-                for att in re.findall(r"\s*(\w+)\s*=\s*(?:'([^']*)'|\"([^\"]*)\")", attr):
-                    (key, val1, val2) = att
-                    text = val1 or val2
-                    text = text.replace('\r\n', '\n')
-                    attributes[key] = self.escape_code(text)
-            self.append_node(parsetree.Tag, keyword, attributes)
-            if isend:
-                self.tag.pop()
-            else:
-                if keyword == 'text':
-                    match = self.match(r'(.*?)(?=\</%text>)',  re.S)
-                    if not match:
-                        raise exceptions.SyntaxException("Unclosed tag: <%%%s>" % self.tag[-1].keyword, **self.exception_kwargs)
-                    self.append_node(parsetree.Text, match.group(1))
-                    return self.match_tag_end()
-            return True
-        else: 
-            return False
-        
-    def match_tag_end(self):
-        match = self.match(r'\</%[\t ]*(.+?)[\t ]*>')
-        if match:
-            if not len(self.tag):
-                raise exceptions.SyntaxException("Closing tag without opening tag: </%%%s>" % match.group(1), **self.exception_kwargs)
-            elif self.tag[-1].keyword != match.group(1):
-                raise exceptions.SyntaxException("Closing tag </%%%s> does not match tag: <%%%s>" % (match.group(1), self.tag[-1].keyword), **self.exception_kwargs)
-            self.tag.pop()
-            return True
-        else:
-            return False
-            
-    def match_end(self):
-        match = self.match(r'\Z', re.S)
-        if match:
-            string = match.group()
-            if string:
-                return string
-            else:
-                return True
-        else:
-            return False
-    
-    def match_text(self):
-        match = self.match(r"""
-                (.*?)         # anything, followed by:
-                (
-                 (?<=\n)(?=[ \t]*(?=%|\#\#)) # an eval or line-based comment preceded by a consumed \n and whitespace
-                 |
-                 (?=\${)   # an expression
-                 |
-                 (?=\#\*) # multiline comment
-                 |
-                 (?=</?[%&])  # a substitution or block or call start or end
-                                              # - don't consume
-                 |
-                 (\\\r?\n)         # an escaped newline  - throw away
-                 |
-                 \Z           # end of string
-                )""", re.X | re.S)
-        
-        if match:
-            text = match.group(1)
-            self.append_node(parsetree.Text, text)
-            return True
-        else:
-            return False
-    
-    def match_python_block(self):
-        match = self.match(r"<%(!)?")
-        if match:
-            (line, pos) = (self.matched_lineno, self.matched_charpos)
-            (text, end) = self.parse_until_text(r'%>')
-            text = adjust_whitespace(text) + "\n"   # the trailing newline helps compiler.parse() not complain about indentation
-            self.append_node(parsetree.Code, self.escape_code(text), match.group(1)=='!', lineno=line, pos=pos)
-            return True
-        else:
-            return False
-            
-    def match_expression(self):
-        match = self.match(r"\${")
-        if match:
-            (line, pos) = (self.matched_lineno, self.matched_charpos)
-            (text, end) = self.parse_until_text(r'\|', r'}')
-            if end == '|':
-                (escapes, end) = self.parse_until_text(r'}')
-            else:
-                escapes = ""
-            text = text.replace('\r\n', '\n')
-            self.append_node(parsetree.Expression, self.escape_code(text), escapes.strip(), lineno=line, pos=pos)
-            return True
-        else:
-            return False
-
-    def match_control_line(self):
-        match = self.match(r"(?<=^)[\t ]*(%|##)[\t ]*((?:(?:\\r?\n)|[^\r\n])*)(?:\r?\n|\Z)", re.M)
-        if match:
-            operator = match.group(1)
-            text = match.group(2)
-            if operator == '%':
-                m2 = re.match(r'(end)?(\w+)\s*(.*)', text)
-                if not m2:
-                    raise exceptions.SyntaxException("Invalid control line: '%s'" % text, **self.exception_kwargs)
-                (isend, keyword) = m2.group(1, 2)
-                isend = (isend is not None)
-                
-                if isend:
-                    if not len(self.control_line):
-                        raise exceptions.SyntaxException("No starting keyword '%s' for '%s'" % (keyword, text), **self.exception_kwargs)
-                    elif self.control_line[-1].keyword != keyword:
-                        raise exceptions.SyntaxException("Keyword '%s' doesn't match keyword '%s'" % (text, self.control_line[-1].keyword), **self.exception_kwargs)
-                self.append_node(parsetree.ControlLine, keyword, isend, self.escape_code(text))
-            else:
-                self.append_node(parsetree.Comment, text)
-            return True
-        else:
-            return False
-
-    def match_comment(self):
-        """matches the multiline version of a comment"""
-        match = self.match(r"<%doc>(.*?)</%doc>", re.S)
-        if match:
-            self.append_node(parsetree.Comment, match.group(1))
-            return True
-        else:
-            return False
-             
diff --git a/mako/lookup.py b/mako/lookup.py
deleted file mode 100644 (file)
index f720e4c..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-# lookup.py
-# Copyright (C) 2006, 2007, 2008 Michael Bayer mike_mp@zzzcomputing.com
-#
-# This module is part of Mako and is released under
-# the MIT License: http://www.opensource.org/licenses/mit-license.php
-
-import os, stat, posixpath, re
-from mako import exceptions, util
-from mako.template import Template
-
-try:
-    import threading
-except:
-    import dummy_threading as threading
-    
-class TemplateCollection(object):
-    def has_template(self, uri):
-        try:
-            self.get_template(uri)
-            return True
-        except exceptions.TemplateLookupException, e:
-            return False
-    def get_template(self, uri, relativeto=None):
-        raise NotImplementedError()
-    def filename_to_uri(self, uri, filename):
-        """convert the given filename to a uri relative to this TemplateCollection."""
-        return uri
-        
-    def adjust_uri(self, uri, filename):
-        """adjust the given uri based on the calling filename.
-        
-        when this method is called from the runtime, the 'filename' parameter 
-        is taken directly to the 'filename' attribute of the calling 
-        template.  Therefore a custom TemplateCollection subclass can place any string 
-        identifier desired in the "filename" parameter of the Template objects it constructs
-        and have them come back here."""
-        return uri
-        
-class TemplateLookup(TemplateCollection):
-    def __init__(self, directories=None, module_directory=None, filesystem_checks=True, collection_size=-1, format_exceptions=False, 
-    error_handler=None, disable_unicode=False, output_encoding=None, encoding_errors='strict', cache_type=None, cache_dir=None, cache_url=None, 
-    modulename_callable=None, default_filters=None, buffer_filters=[], imports=None, input_encoding=None, preprocessor=None):
-        if isinstance(directories, basestring):
-            directories = [directories]        
-        self.directories = [posixpath.normpath(d) for d in directories or []]
-        self.module_directory = module_directory
-        self.modulename_callable = modulename_callable
-        self.filesystem_checks = filesystem_checks
-        self.collection_size = collection_size
-        self.template_args = {'format_exceptions':format_exceptions, 'error_handler':error_handler, 'disable_unicode':disable_unicode, 'output_encoding':output_encoding, 'encoding_errors':encoding_errors, 'input_encoding':input_encoding, 'module_directory':module_directory, 'cache_type':cache_type, 'cache_dir':cache_dir or module_directory, 'cache_url':cache_url, 'default_filters':default_filters, 'buffer_filters':buffer_filters,  'imports':imports, 'preprocessor':preprocessor}
-        if collection_size == -1:
-            self.__collection = {}
-            self._uri_cache = {}
-        else:
-            self.__collection = util.LRUCache(collection_size)
-            self._uri_cache = util.LRUCache(collection_size)
-        self._mutex = threading.Lock()
-        
-    def get_template(self, uri):
-        try:
-            if self.filesystem_checks:
-                return self.__check(uri, self.__collection[uri])
-            else:
-                return self.__collection[uri]
-        except KeyError:
-            u = re.sub(r'^\/+', '', uri)
-            for dir in self.directories:
-                srcfile = posixpath.normpath(posixpath.join(dir, u))
-                if os.path.exists(srcfile):
-                    return self.__load(srcfile, uri)
-            else:
-                raise exceptions.TopLevelLookupException("Cant locate template for uri '%s'" % uri)
-
-    def adjust_uri(self, uri, relativeto):
-        """adjust the given uri based on the calling filename."""
-        
-        if uri[0] != '/':
-            if relativeto is not None:
-                return posixpath.join(posixpath.dirname(relativeto), uri)
-            else:
-                return '/' + uri
-        else:
-            return uri
-            
-    
-    def filename_to_uri(self, filename):
-        try:
-            return self._uri_cache[filename]
-        except KeyError:
-            value = self.__relativeize(filename)
-            self._uri_cache[filename] = value
-            return value
-                    
-    def __relativeize(self, filename):
-        """return the portion of a filename that is 'relative' to the directories in this lookup."""
-        filename = posixpath.normpath(filename)
-        for dir in self.directories:
-            if filename[0:len(dir)] == dir:
-                return filename[len(dir):]
-        else:
-            return None
-            
-    def __load(self, filename, uri):
-        self._mutex.acquire()
-        try:
-            try:
-                # try returning from collection one more time in case concurrent thread already loaded
-                return self.__collection[uri]
-            except KeyError:
-                pass
-            try:
-                self.__collection[uri] = Template(uri=uri, filename=posixpath.normpath(filename), lookup=self, module_filename=(self.modulename_callable is not None and self.modulename_callable(filename, uri) or None), **self.template_args)
-                return self.__collection[uri]
-            except:
-                self.__collection.pop(uri, None)
-                raise
-        finally:
-            self._mutex.release()
-            
-    def __check(self, uri, template):
-        if template.filename is None:
-            return template
-        if not os.path.exists(template.filename):
-            self.__collection.pop(uri, None)
-            raise exceptions.TemplateLookupException("Cant locate template for uri '%s'" % uri)
-        elif template.module._modified_time < os.stat(template.filename)[stat.ST_MTIME]:
-            self.__collection.pop(uri, None)
-            return self.__load(template.filename, uri)
-        else:
-            return template
-            
-    def put_string(self, uri, text):
-        self.__collection[uri] = Template(text, lookup=self, uri=uri, **self.template_args)
-    def put_template(self, uri, template):
-        self.__collection[uri] = template
-            
diff --git a/mako/parsetree.py b/mako/parsetree.py
deleted file mode 100644 (file)
index 426dc95..0000000
+++ /dev/null
@@ -1,293 +0,0 @@
-# parsetree.py
-# Copyright (C) 2006, 2007, 2008 Michael Bayer mike_mp@zzzcomputing.com
-#
-# This module is part of Mako and is released under
-# the MIT License: http://www.opensource.org/licenses/mit-license.php
-
-"""defines the parse tree components for Mako templates."""
-
-from mako import exceptions, ast, util, filters
-import re
-
-class Node(object):
-    """base class for a Node in the parse tree."""
-    def __init__(self, source, lineno, pos, filename):
-        self.source = source
-        self.lineno = lineno
-        self.pos = pos
-        self.filename = filename
-        
-    exception_kwargs = property(lambda self:{'source':self.source, 'lineno':self.lineno, 'pos':self.pos, 'filename':self.filename})
-    
-    def get_children(self):
-        return []
-    def accept_visitor(self, visitor):
-        def traverse(node):
-            for n in node.get_children():
-                n.accept_visitor(visitor)
-        method = getattr(visitor, "visit" + self.__class__.__name__, traverse)
-        method(self)
-
-class TemplateNode(Node):
-    """a 'container' node that stores the overall collection of nodes."""
-    def __init__(self, filename):
-        super(TemplateNode, self).__init__('', 0, 0, filename)
-        self.nodes = []
-        self.page_attributes = {}
-    def get_children(self):
-        return self.nodes
-    def __repr__(self):
-        return "TemplateNode(%s, %s)" % (repr(self.page_attributes), repr(self.nodes))
-        
-class ControlLine(Node):
-    """defines a control line, a line-oriented python line or end tag.
-    
-    % if foo:
-        (markup)
-    % endif
-    """
-    def __init__(self, keyword, isend, text, **kwargs):
-        super(ControlLine, self).__init__(**kwargs)
-        self.text = text
-        self.keyword = keyword
-        self.isend = isend
-        self.is_primary = keyword in ['for','if', 'while', 'try']
-        if self.isend:
-            self._declared_identifiers = []
-            self._undeclared_identifiers = []
-        else:
-            code = ast.PythonFragment(text, **self.exception_kwargs)
-            (self._declared_identifiers, self._undeclared_identifiers) = (code.declared_identifiers, code.undeclared_identifiers)
-    def declared_identifiers(self):
-        return self._declared_identifiers
-    def undeclared_identifiers(self):
-        return self._undeclared_identifiers
-    def is_ternary(self, keyword):
-        """return true if the given keyword is a ternary keyword for this ControlLine"""
-        return keyword in {
-            'if':util.Set(['else', 'elif']),
-            'try':util.Set(['except', 'finally']),
-            'for':util.Set(['else'])
-        }.get(self.keyword, [])
-    def __repr__(self):
-        return "ControlLine(%s, %s, %s, %s)" % (repr(self.keyword), repr(self.text), repr(self.isend), repr((self.lineno, self.pos)))
-
-class Text(Node):
-    """defines plain text in the template."""
-    def __init__(self, content, **kwargs):
-        super(Text, self).__init__(**kwargs)
-        self.content = content
-    def __repr__(self):
-        return "Text(%s, %s)" % (repr(self.content), repr((self.lineno, self.pos)))
-        
-class Code(Node):
-    """defines a Python code block, either inline or module level.
-    
-    inline:
-    <%
-        x = 12
-    %>
-    
-    module level:
-    <%!
-        import logger
-    %>
-    
-    """
-    def __init__(self, text, ismodule, **kwargs):
-        super(Code, self).__init__(**kwargs)
-        self.text = text
-        self.ismodule = ismodule
-        self.code = ast.PythonCode(text, **self.exception_kwargs)
-    def declared_identifiers(self):
-        return self.code.declared_identifiers
-    def undeclared_identifiers(self):
-        return self.code.undeclared_identifiers
-    def __repr__(self):
-        return "Code(%s, %s, %s)" % (repr(self.text), repr(self.ismodule), repr((self.lineno, self.pos)))
-        
-class Comment(Node):
-    """defines a comment line.
-    
-    # this is a comment
-    
-    """
-    def __init__(self, text, **kwargs):
-        super(Comment, self).__init__(**kwargs)
-        self.text = text
-    def __repr__(self):
-        return "Comment(%s, %s)" % (repr(self.text), repr((self.lineno, self.pos)))
-        
-class Expression(Node):
-    """defines an inline expression.
-    
-    ${x+y}
-    
-    """
-    def __init__(self, text, escapes, **kwargs):
-        super(Expression, self).__init__(**kwargs)
-        self.text = text
-        self.escapes = escapes
-        self.escapes_code = ast.ArgumentList(escapes, **self.exception_kwargs)
-        self.code = ast.PythonCode(text, **self.exception_kwargs)
-    def declared_identifiers(self):
-        return []
-    def undeclared_identifiers(self):
-        # TODO: make the "filter" shortcut list configurable at parse/gen time
-        return self.code.undeclared_identifiers.union(self.escapes_code.undeclared_identifiers.difference(util.Set(filters.DEFAULT_ESCAPES.keys())))
-    def __repr__(self):
-        return "Expression(%s, %s, %s)" % (repr(self.text), repr(self.escapes_code.args), repr((self.lineno, self.pos)))
-        
-class _TagMeta(type):
-    """metaclass to allow Tag to produce a subclass according to its keyword"""
-    _classmap = {}
-    def __init__(cls, clsname, bases, dict):
-        if cls.__keyword__ is not None:
-            cls._classmap[cls.__keyword__] = cls
-            super(_TagMeta, cls).__init__(clsname, bases, dict)
-    def __call__(cls, keyword, attributes, **kwargs):
-        try:
-            cls = _TagMeta._classmap[keyword]
-        except KeyError:
-            raise exceptions.CompileException("No such tag: '%s'" % keyword, source=kwargs['source'], lineno=kwargs['lineno'], pos=kwargs['pos'], filename=kwargs['filename'])
-        return type.__call__(cls, keyword, attributes, **kwargs)
-        
-class Tag(Node):
-    """abstract base class for tags.
-    
-    <%sometag/>
-    
-    <%someothertag>
-        stuff
-    </%someothertag>
-    """
-    __metaclass__ = _TagMeta
-    __keyword__ = None
-    def __init__(self, keyword, attributes, expressions, nonexpressions, required, **kwargs):
-        """construct a new Tag instance.
-        
-        this constructor not called directly, and is only called by subclasses.
-        
-        keyword - the tag keyword
-        
-        attributes - raw dictionary of attribute key/value pairs
-        
-        expressions - a util.Set of identifiers that are legal attributes, which can also contain embedded expressions
-        
-        nonexpressions - a util.Set of identifiers that are legal attributes, which cannot contain embedded expressions
-        
-        **kwargs - other arguments passed to the Node superclass (lineno, pos)"""
-        super(Tag, self).__init__(**kwargs)
-        self.keyword = keyword
-        self.attributes = attributes
-        self._parse_attributes(expressions, nonexpressions)
-        missing = [r for r in required if r not in self.parsed_attributes]
-        if len(missing):
-            raise exceptions.CompileException("Missing attribute(s): %s" % ",".join([repr(m) for m in missing]), **self.exception_kwargs)
-        self.parent = None
-        self.nodes = []
-    def is_root(self):
-        return self.parent is None
-    def get_children(self):
-        return self.nodes
-    def _parse_attributes(self, expressions, nonexpressions):
-        undeclared_identifiers = util.Set()
-        self.parsed_attributes = {}
-        for key in self.attributes:
-            if key in expressions:
-                expr = []
-                for x in re.split(r'(\${.+?})', self.attributes[key]):
-                    m = re.match(r'^\${(.+?)}$', x)
-                    if m:
-                        code = ast.PythonCode(m.group(1), **self.exception_kwargs)
-                        undeclared_identifiers = undeclared_identifiers.union(code.undeclared_identifiers)
-                        expr.append(m.group(1))
-                    else:
-                        if x:
-                            expr.append(repr(x))
-                self.parsed_attributes[key] = " + ".join(expr)
-            elif key in nonexpressions:
-                if re.search(r'${.+?}', self.attributes[key]):
-                    raise exceptions.CompileException("Attibute '%s' in tag '%s' does not allow embedded expressions"  %(key, self.keyword), **self.exception_kwargs)
-                self.parsed_attributes[key] = repr(self.attributes[key])
-            else:
-                raise exceptions.CompileException("Invalid attribute for tag '%s': '%s'" %(self.keyword, key), **self.exception_kwargs)
-        self.expression_undeclared_identifiers = undeclared_identifiers
-    def declared_identifiers(self):
-        return []
-    def undeclared_identifiers(self):
-        return self.expression_undeclared_identifiers
-    def __repr__(self):
-        return "%s(%s, %s, %s, %s)" % (self.__class__.__name__, repr(self.keyword), repr(self.attributes), repr((self.lineno, self.pos)), repr([repr(x) for x in self.nodes]))
-        
-class IncludeTag(Tag):
-    __keyword__ = 'include'
-    def __init__(self, keyword, attributes, **kwargs):
-        super(IncludeTag, self).__init__(keyword, attributes, ('file', 'import', 'args'), (), ('file',), **kwargs)
-        self.page_args = ast.PythonCode("__DUMMY(%s)" % attributes.get('args', ''), **self.exception_kwargs)
-    def declared_identifiers(self):
-        return []
-    def undeclared_identifiers(self):
-        identifiers = self.page_args.undeclared_identifiers.difference(util.Set(["__DUMMY"]))
-        return identifiers.union(super(IncludeTag, self).undeclared_identifiers())
-    
-class NamespaceTag(Tag):
-    __keyword__ = 'namespace'
-    def __init__(self, keyword, attributes, **kwargs):
-        super(NamespaceTag, self).__init__(keyword, attributes, (), ('name','inheritable','file','import','module'), (), **kwargs)
-        self.name = attributes.get('name', '__anon_%s' % hex(abs(id(self))))
-        if not 'name' in attributes and not 'import' in attributes:
-            raise exceptions.CompileException("'name' and/or 'import' attributes are required for <%namespace>", **self.exception_kwargs)
-    def declared_identifiers(self):
-        return []
-
-class TextTag(Tag):
-    __keyword__ = 'text'
-    def __init__(self, keyword, attributes, **kwargs):
-        super(TextTag, self).__init__(keyword, attributes, (), ('filter'), (), **kwargs)
-        self.filter_args = ast.ArgumentList(attributes.get('filter', ''), **self.exception_kwargs)
-        
-class DefTag(Tag):
-    __keyword__ = 'def'
-    def __init__(self, keyword, attributes, **kwargs):
-        super(DefTag, self).__init__(keyword, attributes, ('buffered', 'cached', 'cache_key', 'cache_timeout', 'cache_type', 'cache_dir', 'cache_url'), ('name','filter'), ('name',), **kwargs)
-        name = attributes['name']
-        if re.match(r'^[\w_]+$',name):
-            raise exceptions.CompileException("Missing parenthesis in %def", **self.exception_kwargs)
-        self.function_decl = ast.FunctionDecl("def " + name + ":pass", **self.exception_kwargs)
-        self.name = self.function_decl.funcname
-        self.filter_args = ast.ArgumentList(attributes.get('filter', ''), **self.exception_kwargs)
-    def declared_identifiers(self):
-        return self.function_decl.argnames
-    def undeclared_identifiers(self):
-        res = []
-        for c in self.function_decl.defaults:
-            res += list(ast.PythonCode(c, **self.exception_kwargs).undeclared_identifiers)
-        return res + list(self.filter_args.undeclared_identifiers.difference(util.Set(filters.DEFAULT_ESCAPES.keys())))
-
-class CallTag(Tag):
-    __keyword__ = 'call'
-    def __init__(self, keyword, attributes, **kwargs):
-        super(CallTag, self).__init__(keyword, attributes, ('args'), ('expr',), ('expr',), **kwargs)
-        self.code = ast.PythonCode(attributes['expr'], **self.exception_kwargs)
-        self.body_decl = ast.FunctionArgs(attributes.get('args', ''), **self.exception_kwargs)
-    def declared_identifiers(self):
-        return self.code.declared_identifiers.union(self.body_decl.argnames)
-    def undeclared_identifiers(self):
-        return self.code.undeclared_identifiers
-
-class InheritTag(Tag):
-    __keyword__ = 'inherit'
-    def __init__(self, keyword, attributes, **kwargs):
-        super(InheritTag, self).__init__(keyword, attributes, ('file',), (), ('file',), **kwargs)
-
-class PageTag(Tag):
-    __keyword__ = 'page'
-    def __init__(self, keyword, attributes, **kwargs):
-        super(PageTag, self).__init__(keyword, attributes, ('cached', 'cache_key', 'cache_timeout', 'cache_type', 'cache_dir', 'cache_url', 'args', 'expression_filter'), (), (), **kwargs)
-        self.body_decl = ast.FunctionArgs(attributes.get('args', ''), **self.exception_kwargs)
-        self.filter_args = ast.ArgumentList(attributes.get('expression_filter', ''), **self.exception_kwargs)
-    def declared_identifiers(self):
-        return self.body_decl.argnames
-        
-    
diff --git a/mako/pygen.py b/mako/pygen.py
deleted file mode 100644 (file)
index b73325f..0000000
+++ /dev/null
@@ -1,267 +0,0 @@
-# pygen.py
-# Copyright (C) 2006, 2007, 2008 Michael Bayer mike_mp@zzzcomputing.com
-#
-# This module is part of Mako and is released under
-# the MIT License: http://www.opensource.org/licenses/mit-license.php
-
-"""utilities for generating and formatting literal Python code."""
-
-import re, string
-from StringIO import StringIO
-
-class PythonPrinter(object):
-    def __init__(self, stream):
-        # indentation counter
-        self.indent = 0
-        
-        # a stack storing information about why we incremented 
-        # the indentation counter, to help us determine if we
-        # should decrement it
-        self.indent_detail = []
-        
-        # the string of whitespace multiplied by the indent
-        # counter to produce a line
-        self.indentstring = "    "
-        
-        # the stream we are writing to
-        self.stream = stream
-        
-        # a list of lines that represents a buffered "block" of code,
-        # which can be later printed relative to an indent level 
-        self.line_buffer = []
-        
-        self.in_indent_lines = False
-        
-        self._reset_multi_line_flags()
-
-    def write(self, text):
-        self.stream.write(text)
-        
-    def write_indented_block(self, block):
-        """print a line or lines of python which already contain indentation.
-        
-        The indentation of the total block of lines will be adjusted to that of
-        the current indent level.""" 
-        self.in_indent_lines = False
-        for l in re.split(r'\r?\n', block):
-            self.line_buffer.append(l)
-    
-    def writelines(self, *lines):
-        """print a series of lines of python."""
-        for line in lines:
-            self.writeline(line)
-                
-    def writeline(self, line):
-        """print a line of python, indenting it according to the current indent level.
-        
-        this also adjusts the indentation counter according to the content of the line."""
-
-        if not self.in_indent_lines:
-            self._flush_adjusted_lines()
-            self.in_indent_lines = True
-
-        decreased_indent = False
-    
-        if (line is None or 
-            re.match(r"^\s*#",line) or
-            re.match(r"^\s*$", line)
-            ):
-            hastext = False
-        else:
-            hastext = True
-
-        is_comment = line and len(line) and line[0] == '#'
-        
-        # see if this line should decrease the indentation level
-        if (not decreased_indent and 
-            not is_comment and 
-            (not hastext or self._is_unindentor(line))
-            ):
-            
-            if self.indent > 0: 
-                self.indent -=1
-                # if the indent_detail stack is empty, the user
-                # probably put extra closures - the resulting
-                # module wont compile.  
-                if len(self.indent_detail) == 0:  
-                    raise "Too many whitespace closures"
-                self.indent_detail.pop()
-        
-        if line is None:
-            return
-                
-        # write the line
-        self.stream.write(self._indent_line(line) + "\n")
-        
-        # see if this line should increase the indentation level.
-        # note that a line can both decrase (before printing) and 
-        # then increase (after printing) the indentation level.
-
-        if re.search(r":[ \t]*(?:#.*)?$", line):
-            # increment indentation count, and also
-            # keep track of what the keyword was that indented us,
-            # if it is a python compound statement keyword
-            # where we might have to look for an "unindent" keyword
-            match = re.match(r"^\s*(if|try|elif|while|for)", line)
-            if match:
-                # its a "compound" keyword, so we will check for "unindentors"
-                indentor = match.group(1)
-                self.indent +=1
-                self.indent_detail.append(indentor)
-            else:
-                indentor = None
-                # its not a "compound" keyword.  but lets also
-                # test for valid Python keywords that might be indenting us,
-                # else assume its a non-indenting line
-                m2 = re.match(r"^\s*(def|class|else|elif|except|finally)", line)
-                if m2:
-                    self.indent += 1
-                    self.indent_detail.append(indentor)
-
-    def close(self):
-        """close this printer, flushing any remaining lines."""
-        self._flush_adjusted_lines()
-    
-    def _is_unindentor(self, line):
-        """return true if the given line is an 'unindentor', relative to the last 'indent' event received."""
-                
-        # no indentation detail has been pushed on; return False
-        if len(self.indent_detail) == 0: 
-            return False
-
-        indentor = self.indent_detail[-1]
-        
-        # the last indent keyword we grabbed is not a 
-        # compound statement keyword; return False
-        if indentor is None: 
-            return False
-        
-        # if the current line doesnt have one of the "unindentor" keywords,
-        # return False
-        match = re.match(r"^\s*(else|elif|except|finally).*\:", line)
-        if not match: 
-            return False
-        
-        # whitespace matches up, we have a compound indentor,
-        # and this line has an unindentor, this
-        # is probably good enough
-        return True
-        
-        # should we decide that its not good enough, heres
-        # more stuff to check.
-        #keyword = match.group(1)
-        
-        # match the original indent keyword 
-        #for crit in [
-        #   (r'if|elif', r'else|elif'),
-        #   (r'try', r'except|finally|else'),
-        #   (r'while|for', r'else'),
-        #]:
-        #   if re.match(crit[0], indentor) and re.match(crit[1], keyword): return True
-        
-        #return False
-        
-    def _indent_line(self, line, stripspace = ''):
-        """indent the given line according to the current indent level.
-        
-        stripspace is a string of space that will be truncated from the start of the line
-        before indenting."""
-        return re.sub(r"^%s" % stripspace, self.indentstring * self.indent, line)
-
-    def _reset_multi_line_flags(self):
-        """reset the flags which would indicate we are in a backslashed or triple-quoted section."""
-        (self.backslashed, self.triplequoted) = (False, False) 
-        
-    def _in_multi_line(self, line):
-        """return true if the given line is part of a multi-line block, via backslash or triple-quote."""
-        # we are only looking for explicitly joined lines here,
-        # not implicit ones (i.e. brackets, braces etc.).  this is just
-        # to guard against the possibility of modifying the space inside 
-        # of a literal multiline string with unfortunately placed whitespace
-         
-        current_state = (self.backslashed or self.triplequoted) 
-                        
-        if re.search(r"\\$", line):
-            self.backslashed = True
-        else:
-            self.backslashed = False
-            
-        triples = len(re.findall(r"\"\"\"|\'\'\'", line))
-        if triples == 1 or triples % 2 != 0:
-            self.triplequoted = not self.triplequoted
-            
-        return current_state
-
-    def _flush_adjusted_lines(self):
-        stripspace = None
-        self._reset_multi_line_flags()
-        
-        for entry in self.line_buffer:
-            if self._in_multi_line(entry):
-                self.stream.write(entry + "\n")
-            else:
-                entry = string.expandtabs(entry)
-                if stripspace is None and re.search(r"^[ \t]*[^# \t]", entry):
-                    stripspace = re.match(r"^([ \t]*)", entry).group(1)
-                self.stream.write(self._indent_line(entry, stripspace) + "\n")
-            
-        self.line_buffer = []
-        self._reset_multi_line_flags()
-
-
-def adjust_whitespace(text):
-    """remove the left-whitespace margin of a block of Python code."""
-    state = [False, False]
-    (backslashed, triplequoted) = (0, 1)
-
-    def in_multi_line(line):
-        start_state = (state[backslashed] or state[triplequoted])
-        
-        if re.search(r"\\$", line):
-            state[backslashed] = True
-        else:
-            state[backslashed] = False
-        
-        def match(reg, t):
-            m = re.match(reg, t)
-            if m:
-                return m, t[len(m.group(0)):]
-            else:
-                return None, t
-                
-        while line:
-            if state[triplequoted]:
-                m, line = match(r"%s" % state[triplequoted], line)
-                if m:
-                    state[triplequoted] = False
-                else:
-                    m, line = match(r".*?(?=%s|$)" % state[triplequoted], line)
-            else:
-                m, line = match(r'#', line)
-                if m:
-                    return start_state
-                
-                m, line = match(r"\"\"\"|\'\'\'", line)
-                if m:
-                    state[triplequoted] = m.group(0)
-                    continue
-
-                m, line = match(r".*?(?=\"\"\"|\'\'\'|#|$)", line)
-            
-        return start_state
-
-    def _indent_line(line, stripspace = ''):
-        return re.sub(r"^%s" % stripspace, '', line)
-
-    lines = []
-    stripspace = None
-
-    for line in re.split(r'\r?\n', text):
-        if in_multi_line(line):
-            lines.append(line)
-        else:
-            line = string.expandtabs(line)
-            if stripspace is None and re.search(r"^[ \t]*[^# \t]", line):
-                stripspace = re.match(r"^([ \t]*)", line).group(1)
-            lines.append(_indent_line(line, stripspace))
-    return "\n".join(lines)
diff --git a/mako/pyparser.py b/mako/pyparser.py
deleted file mode 100644 (file)
index cc9c04e..0000000
+++ /dev/null
@@ -1,377 +0,0 @@
-# ast.py
-# Copyright (C) Mako developers
-#
-# This module is part of Mako and is released under
-# the MIT License: http://www.opensource.org/licenses/mit-license.php
-
-"""Handles parsing of Python code.
-
-Parsing to AST is done via _ast on Python > 2.5, otherwise the compiler
-module is used.
-"""
-
-import sys
-from StringIO import StringIO
-from mako import exceptions, util
-
-# words that cannot be assigned to (notably smaller than the total keys in __builtins__)
-reserved = util.Set(['True', 'False', 'None'])
-
-jython = sys.platform.startswith('java')
-
-try:
-    import _ast
-    util.restore__ast(_ast)
-    import _ast_util
-except ImportError:
-    _ast = None
-    from compiler import parse as compiler_parse
-    from compiler import visitor
-
-
-def parse(code, mode='exec', **exception_kwargs):
-    """Parse an expression into AST"""
-    try:
-        if _ast:
-            return _ast_util.parse(code, '<unknown>', mode)
-        else:
-            return compiler_parse(code, mode)
-    except Exception, e:
-        raise exceptions.SyntaxException("(%s) %s (%s)" % (e.__class__.__name__, str(e), repr(code[0:50])), **exception_kwargs)
-
-
-if _ast:
-    class FindIdentifiers(_ast_util.NodeVisitor):
-        def __init__(self, listener, **exception_kwargs):
-            self.in_function = False
-            self.in_assign_targets = False
-            self.local_ident_stack = {}
-            self.listener = listener
-            self.exception_kwargs = exception_kwargs
-        def _add_declared(self, name):
-            if not self.in_function:
-                self.listener.declared_identifiers.add(name)
-        def visit_ClassDef(self, node):
-            self._add_declared(node.name)
-        def visit_Assign(self, node):
-            # flip around the visiting of Assign so the expression gets evaluated first, 
-            # in the case of a clause like "x=x+5" (x is undeclared)
-            self.visit(node.value)
-            in_a = self.in_assign_targets
-            self.in_assign_targets = True
-            for n in node.targets:
-                self.visit(n)
-            self.in_assign_targets = in_a
-        def visit_FunctionDef(self, node):
-            self._add_declared(node.name)
-            # push function state onto stack.  dont log any
-            # more identifiers as "declared" until outside of the function,
-            # but keep logging identifiers as "undeclared".
-            # track argument names in each function header so they arent counted as "undeclared"
-            saved = {}
-            inf = self.in_function
-            self.in_function = True
-            for arg in node.args.args:
-                if arg.id in self.local_ident_stack:
-                    saved[arg.id] = True
-                else:
-                    self.local_ident_stack[arg.id] = True
-            for n in node.body:
-                self.visit(n)
-            self.in_function = inf
-            for arg in node.args.args:
-                if arg.id not in saved:
-                    del self.local_ident_stack[arg.id]
-        def visit_For(self, node):
-            # flip around visit
-            self.visit(node.iter)
-            self.visit(node.target)
-            for statement in node.body:
-                self.visit(statement)
-            for statement in node.orelse:
-                self.visit(statement)
-        def visit_Name(self, node):
-            if jython:
-                if node.ctx == _ast.Store:
-                    self._add_declared(node.id)
-            elif isinstance(node.ctx, _ast.Store):
-                self._add_declared(node.id)
-            if node.id not in reserved and node.id not in self.listener.declared_identifiers and node.id not in self.local_ident_stack:
-                self.listener.undeclared_identifiers.add(node.id)
-        def visit_Import(self, node):
-            for name in node.names:
-                if name.asname is not None:
-                    self._add_declared(name.asname)
-                else:
-                    self._add_declared(name.name.split('.')[0])
-        def visit_ImportFrom(self, node):
-            for name in node.names:
-                if name.asname is not None:
-                    self._add_declared(name.asname)
-                else:
-                    if name.name == '*':
-                        raise exceptions.CompileException("'import *' is not supported, since all identifier names must be explicitly declared.  Please use the form 'from <modulename> import <name1>, <name2>, ...' instead.", **self.exception_kwargs)
-                    self._add_declared(name.name)
-
-    class FindTuple(_ast_util.NodeVisitor):
-        def __init__(self, listener, code_factory, **exception_kwargs):
-            self.listener = listener
-            self.exception_kwargs = exception_kwargs
-            self.code_factory = code_factory
-        def visit_Tuple(self, node):
-            for n in node.elts:
-                p = self.code_factory(n, **self.exception_kwargs)
-                self.listener.codeargs.append(p)
-                self.listener.args.append(ExpressionGenerator(n).value())
-                self.listener.declared_identifiers = self.listener.declared_identifiers.union(p.declared_identifiers)
-                self.listener.undeclared_identifiers = self.listener.undeclared_identifiers.union(p.undeclared_identifiers)
-
-    class ParseFunc(_ast_util.NodeVisitor):
-        def __init__(self, listener, **exception_kwargs):
-            self.listener = listener
-            self.exception_kwargs = exception_kwargs
-        def visit_FunctionDef(self, node):
-            self.listener.funcname = node.name
-            argnames = [arg.id for arg in node.args.args]
-            if node.args.vararg:
-                argnames.append(node.args.vararg)
-            if node.args.kwarg:
-                argnames.append(node.args.kwarg)
-            self.listener.argnames = argnames
-            self.listener.defaults = node.args.defaults # ast
-            self.listener.varargs = node.args.vararg
-            self.listener.kwargs = node.args.kwarg
-
-    class ExpressionGenerator(object):
-        def __init__(self, astnode):
-            self.generator = _ast_util.SourceGenerator(' ' * 4)
-            self.generator.visit(astnode)
-        def value(self):
-            return ''.join(self.generator.result)
-else:
-    class FindIdentifiers(object):
-        def __init__(self, listener, **exception_kwargs):
-            self.in_function = False
-            self.local_ident_stack = {}
-            self.listener = listener
-            self.exception_kwargs = exception_kwargs
-        def _add_declared(self, name):
-            if not self.in_function:
-                self.listener.declared_identifiers.add(name)
-        def visitClass(self, node, *args):
-            self._add_declared(node.name)
-        def visitAssName(self, node, *args):
-            self._add_declared(node.name)
-        def visitAssign(self, node, *args):
-            # flip around the visiting of Assign so the expression gets evaluated first, 
-            # in the case of a clause like "x=x+5" (x is undeclared)
-            self.visit(node.expr, *args)
-            for n in node.nodes:
-                self.visit(n, *args)
-        def visitFunction(self,node, *args):
-            self._add_declared(node.name)
-            # push function state onto stack.  dont log any
-            # more identifiers as "declared" until outside of the function,
-            # but keep logging identifiers as "undeclared".
-            # track argument names in each function header so they arent counted as "undeclared"
-            saved = {}
-            inf = self.in_function
-            self.in_function = True
-            for arg in node.argnames:
-                if arg in self.local_ident_stack:
-                    saved[arg] = True
-                else:
-                    self.local_ident_stack[arg] = True
-            for n in node.getChildNodes():
-                self.visit(n, *args)
-            self.in_function = inf
-            for arg in node.argnames:
-                if arg not in saved:
-                    del self.local_ident_stack[arg]
-        def visitFor(self, node, *args):
-            # flip around visit
-            self.visit(node.list, *args)
-            self.visit(node.assign, *args)
-            self.visit(node.body, *args)
-        def visitName(self, node, *args):
-            if node.name not in reserved and node.name not in self.listener.declared_identifiers and node.name not in self.local_ident_stack:
-                self.listener.undeclared_identifiers.add(node.name)
-        def visitImport(self, node, *args):
-            for (mod, alias) in node.names:
-                if alias is not None:
-                    self._add_declared(alias)
-                else:
-                    self._add_declared(mod.split('.')[0])
-        def visitFrom(self, node, *args):
-            for (mod, alias) in node.names:
-                if alias is not None:
-                    self._add_declared(alias)
-                else:
-                    if mod == '*':
-                        raise exceptions.CompileException("'import *' is not supported, since all identifier names must be explicitly declared.  Please use the form 'from <modulename> import <name1>, <name2>, ...' instead.", **self.exception_kwargs)
-                    self._add_declared(mod)
-        def visit(self, expr):
-            visitor.walk(expr, self) #, walker=walker())
-
-    class FindTuple(object):
-        def __init__(self, listener, code_factory, **exception_kwargs):
-            self.listener = listener
-            self.exception_kwargs = exception_kwargs
-            self.code_factory = code_factory
-        def visitTuple(self, node, *args):
-            for n in node.nodes:
-                p = self.code_factory(n, **self.exception_kwargs)
-                self.listener.codeargs.append(p)
-                self.listener.args.append(ExpressionGenerator(n).value())
-                self.listener.declared_identifiers = self.listener.declared_identifiers.union(p.declared_identifiers)
-                self.listener.undeclared_identifiers = self.listener.undeclared_identifiers.union(p.undeclared_identifiers)
-        def visit(self, expr):
-            visitor.walk(expr, self) #, walker=walker())
-
-    class ParseFunc(object):
-        def __init__(self, listener, **exception_kwargs):
-            self.listener = listener
-            self.exception_kwargs = exception_kwargs
-        def visitFunction(self, node, *args):
-            self.listener.funcname = node.name
-            self.listener.argnames = node.argnames
-            self.listener.defaults = node.defaults
-            self.listener.varargs = node.varargs
-            self.listener.kwargs = node.kwargs
-        def visit(self, expr):
-            visitor.walk(expr, self)
-
-    class ExpressionGenerator(object):
-        """given an AST node, generates an equivalent literal Python expression."""
-        def __init__(self, astnode):
-            self.buf = StringIO()
-            visitor.walk(astnode, self) #, walker=walker())
-        def value(self):
-            return self.buf.getvalue()        
-        def operator(self, op, node, *args):
-            self.buf.write("(")
-            self.visit(node.left, *args)
-            self.buf.write(" %s " % op)
-            self.visit(node.right, *args)
-            self.buf.write(")")
-        def booleanop(self, op, node, *args):
-            self.visit(node.nodes[0])
-            for n in node.nodes[1:]:
-                self.buf.write(" " + op + " ")
-                self.visit(n, *args)
-        def visitConst(self, node, *args):
-            self.buf.write(repr(node.value))
-        def visitAssName(self, node, *args):
-            # TODO: figure out OP_ASSIGN, other OP_s
-            self.buf.write(node.name)
-        def visitName(self, node, *args):
-            self.buf.write(node.name)
-        def visitMul(self, node, *args):
-            self.operator("*", node, *args)
-        def visitAnd(self, node, *args):
-            self.booleanop("and", node, *args)
-        def visitOr(self, node, *args):
-            self.booleanop("or", node, *args)
-        def visitBitand(self, node, *args):
-            self.booleanop("&", node, *args)
-        def visitBitor(self, node, *args):
-            self.booleanop("|", node, *args)
-        def visitBitxor(self, node, *args):
-            self.booleanop("^", node, *args)
-        def visitAdd(self, node, *args):
-            self.operator("+", node, *args)
-        def visitGetattr(self, node, *args):
-            self.visit(node.expr, *args)
-            self.buf.write(".%s" % node.attrname)
-        def visitSub(self, node, *args):
-            self.operator("-", node, *args)
-        def visitNot(self, node, *args):
-            self.buf.write("not ")
-            self.visit(node.expr)
-        def visitDiv(self, node, *args):
-            self.operator("/", node, *args)
-        def visitFloorDiv(self, node, *args):
-            self.operator("//", node, *args)
-        def visitSubscript(self, node, *args):
-            self.visit(node.expr)
-            self.buf.write("[")
-            [self.visit(x) for x in node.subs]
-            self.buf.write("]")
-        def visitUnarySub(self, node, *args):
-            self.buf.write("-")
-            self.visit(node.expr)
-        def visitUnaryAdd(self, node, *args):
-            self.buf.write("-")
-            self.visit(node.expr)
-        def visitSlice(self, node, *args):
-            self.visit(node.expr)
-            self.buf.write("[")
-            if node.lower is not None:
-                self.visit(node.lower)
-            self.buf.write(":")
-            if node.upper is not None:
-                self.visit(node.upper)
-            self.buf.write("]")
-        def visitDict(self, node):
-            self.buf.write("{")
-            c = node.getChildren()
-            for i in range(0, len(c), 2):
-                self.visit(c[i])
-                self.buf.write(": ")
-                self.visit(c[i+1])
-                if i<len(c) -2:
-                    self.buf.write(", ")
-            self.buf.write("}")
-        def visitTuple(self, node):
-            self.buf.write("(")
-            c = node.getChildren()
-            for i in range(0, len(c)):
-                self.visit(c[i])
-                if i<len(c) - 1:
-                    self.buf.write(", ")
-            self.buf.write(")")
-        def visitList(self, node):
-            self.buf.write("[")
-            c = node.getChildren()
-            for i in range(0, len(c)):
-                self.visit(c[i])
-                if i<len(c) - 1:
-                    self.buf.write(", ")
-            self.buf.write("]")
-        def visitListComp(self, node):
-            self.buf.write("[")
-            self.visit(node.expr)
-            self.buf.write(" ")
-            for n in node.quals:
-                self.visit(n)
-            self.buf.write("]")
-        def visitListCompFor(self, node):
-            self.buf.write(" for ")
-            self.visit(node.assign)
-            self.buf.write(" in ")
-            self.visit(node.list)
-            for n in node.ifs:
-                self.visit(n)
-        def visitListCompIf(self, node):
-            self.buf.write(" if ")
-            self.visit(node.test)
-        def visitCompare(self, node):
-            self.visit(node.expr)
-            for tup in node.ops:
-                self.buf.write(tup[0])
-                self.visit(tup[1])
-        def visitCallFunc(self, node, *args):
-            self.visit(node.node)
-            self.buf.write("(")
-            if len(node.args):
-                self.visit(node.args[0])
-                for a in node.args[1:]:
-                    self.buf.write(", ")
-                    self.visit(a)
-            self.buf.write(")")
-
-    class walker(visitor.ASTVisitor):
-        def dispatch(self, node, *args):
-            print "Node:", str(node)
-            #print "dir:", dir(node)
-            return visitor.ASTVisitor.dispatch(self, node, *args)
diff --git a/mako/runtime.py b/mako/runtime.py
deleted file mode 100644 (file)
index a82ffb4..0000000
+++ /dev/null
@@ -1,389 +0,0 @@
-# runtime.py
-# Copyright (C) 2006, 2007, 2008 Michael Bayer mike_mp@zzzcomputing.com
-#
-# This module is part of Mako and is released under
-# the MIT License: http://www.opensource.org/licenses/mit-license.php
-
-"""provides runtime services for templates, including Context, Namespace, and various helper functions."""
-
-from mako import exceptions, util
-import inspect, sys
-import __builtin__
-
-class Context(object):
-    """provides runtime namespace, output buffer, and various callstacks for templates."""
-    def __init__(self, buffer, **data):
-        self._buffer_stack = [buffer]
-        self._data = dict(__builtin__.__dict__)
-        self._data.update(data)
-        self._kwargs = data.copy()
-        self._with_template = None
-        self.namespaces = {}
-        
-        # "capture" function which proxies to the generic "capture" function
-        self._data['capture'] = lambda x, *args, **kwargs: capture(self, x, *args, **kwargs)
-        
-        # "caller" stack used by def calls with content
-        self.caller_stack = self._data['caller'] = CallerStack()
-        
-    lookup = property(lambda self:self._with_template.lookup)
-    kwargs = property(lambda self:self._kwargs.copy())
-    
-    def push_caller(self, caller):
-        self.caller_stack.append(caller)
-        
-    def pop_caller(self):
-        del self.caller_stack[-1]
-        
-    def keys(self):
-        return self._data.keys()
-        
-    def __getitem__(self, key):
-        return self._data[key]
-
-    def _push_writer(self):
-        """push a capturing buffer onto this Context and return the new Writer function."""
-        
-        buf = util.FastEncodingBuffer()
-        self._buffer_stack.append(buf)
-        return buf.write
-
-    def _pop_buffer_and_writer(self):
-        """pop the most recent capturing buffer from this Context 
-        and return the current writer after the pop.
-        
-        """
-
-        buf = self._buffer_stack.pop()
-        return buf, self._buffer_stack[-1].write
-        
-    def _push_buffer(self):
-        """push a capturing buffer onto this Context."""
-        
-        self._push_writer()
-        
-    def _pop_buffer(self):
-        """pop the most recent capturing buffer from this Context."""
-        
-        return self._buffer_stack.pop()
-        
-    def get(self, key, default=None):
-        return self._data.get(key, default)
-        
-    def write(self, string):
-        """write a string to this Context's underlying output buffer."""
-        
-        self._buffer_stack[-1].write(string)
-        
-    def writer(self):
-        """return the current writer function"""
-
-        return self._buffer_stack[-1].write
-
-    def _copy(self):
-        c = Context.__new__(Context)
-        c._buffer_stack = self._buffer_stack
-        c._data = self._data.copy()
-        c._kwargs = self._kwargs
-        c._with_template = self._with_template
-        c.namespaces = self.namespaces
-        c.caller_stack = self.caller_stack
-        return c
-    def locals_(self, d):
-        """create a new Context with a copy of this Context's current state, updated with the given dictionary."""
-        if len(d) == 0:
-            return self
-        c = self._copy()
-        c._data.update(d)
-        return c
-    def _clean_inheritance_tokens(self):
-        """create a new copy of this Context with tokens related to inheritance state removed."""
-        c = self._copy()
-        x = c._data
-        x.pop('self', None)
-        x.pop('parent', None)
-        x.pop('next', None)
-        return c
-
-class CallerStack(list):
-    def __init__(self):
-        self.nextcaller = None
-    def __nonzero__(self):
-        return self._get_caller() and True or False
-    def _get_caller(self):
-        return self[-1]
-    def __getattr__(self, key):
-        return getattr(self._get_caller(), key)
-    def _push_frame(self):
-        self.append(self.nextcaller or None)
-        self.nextcaller = None
-    def _pop_frame(self):
-        self.nextcaller = self.pop()
-        
-        
-class Undefined(object):
-    """represents an undefined value in a template."""
-    def __str__(self):
-        raise NameError("Undefined")
-    def __nonzero__(self):
-        return False
-
-UNDEFINED = Undefined()
-
-class _NSAttr(object):
-    def __init__(self, parent):
-        self.__parent = parent
-    def __getattr__(self, key):
-        ns = self.__parent
-        while ns:
-            if hasattr(ns.module, key):
-                return getattr(ns.module, key)
-            else:
-                ns = ns.inherits
-        raise AttributeError(key)    
-    
-class Namespace(object):
-    """provides access to collections of rendering methods, which can be local, from other templates, or from imported modules"""
-    def __init__(self, name, context, module=None, template=None, templateuri=None, callables=None, inherits=None, populate_self=True, calling_uri=None):
-        self.name = name
-        if module is not None:
-            mod = __import__(module)
-            for token in module.split('.')[1:]:
-                mod = getattr(mod, token)
-            self._module = mod
-        else:
-            self._module = None
-        if templateuri is not None:
-            self.template = _lookup_template(context, templateuri, calling_uri)
-            self._templateuri = self.template.module._template_uri
-        else:
-            self.template = template
-            if self.template is not None:
-                self._templateuri = self.template.module._template_uri
-        self.context = context
-        self.inherits = inherits
-        if callables is not None:
-            self.callables = dict([(c.func_name, c) for c in callables])
-        else:
-            self.callables = None
-        if populate_self and self.template is not None:
-            (lclcallable, lclcontext) = _populate_self_namespace(context, self.template, self_ns=self)
-        
-    module = property(lambda s:s._module or s.template.module)
-    filename = property(lambda s:s._module and s._module.__file__ or s.template.filename)
-    uri = property(lambda s:s.template.uri)
-    
-    def attr(self):
-        if not hasattr(self, '_attr'):
-            self._attr = _NSAttr(self)
-        return self._attr
-    attr = property(attr)
-
-    def get_namespace(self, uri):
-        """return a namespace corresponding to the given template uri.
-        
-        if a relative uri, it is adjusted to that of the template of this namespace"""
-        key = (self, uri)
-        if self.context.namespaces.has_key(key):
-            return self.context.namespaces[key]
-        else:
-            ns = Namespace(uri, self.context._copy(), templateuri=uri, calling_uri=self._templateuri) 
-            self.context.namespaces[key] = ns
-            return ns
-    
-    def get_template(self, uri):
-        return _lookup_template(self.context, uri, self._templateuri)
-        
-    def get_cached(self, key, **kwargs):
-        if self.template:
-            if self.template.cache_dir:
-                kwargs.setdefault('data_dir', self.template.cache_dir)
-            if self.template.cache_type:
-                kwargs.setdefault('type', self.template.cache_type)
-            if self.template.cache_url:
-                kwargs.setdefault('url', self.template.cache_url)
-        return self.cache.get(key, **kwargs)
-    
-    def cache(self):
-        return self.template.cache
-    cache = property(cache)
-    
-    def include_file(self, uri, **kwargs):
-        """include a file at the given uri"""
-        _include_file(self.context, uri, self._templateuri, **kwargs)
-        
-    def _populate(self, d, l):
-        for ident in l:
-            if ident == '*':
-                for (k, v) in self._get_star():
-                    d[k] = v
-            else:
-                d[ident] = getattr(self, ident)
-    
-    def _get_star(self):
-        if self.callables:
-            for key in self.callables:
-                yield (key, self.callables[key])
-        if self.template:
-            def get(key):
-                callable_ = self.template.get_def(key).callable_
-                return lambda *args, **kwargs:callable_(self.context, *args, **kwargs)
-            for k in self.template.module._exports:
-                yield (k, get(k))
-        if self._module:
-            def get(key):
-                callable_ = getattr(self._module, key)
-                return lambda *args, **kwargs:callable_(self.context, *args, **kwargs)
-            for k in dir(self._module):
-                if k[0] != '_':
-                    yield (k, get(k))
-                            
-    def __getattr__(self, key):
-        if self.callables and key in self.callables:
-            return self.callables[key]
-
-        if self.template and self.template.has_def(key):
-            callable_ = self.template.get_def(key).callable_
-            return lambda *args, **kwargs:callable_(self.context, *args, **kwargs)
-
-        if self._module and hasattr(self._module, key):
-            callable_ = getattr(self._module, key)
-            return lambda *args, **kwargs:callable_(self.context, *args, **kwargs)
-
-        if self.inherits is not None:
-            return getattr(self.inherits, key)
-        raise exceptions.RuntimeException("Namespace '%s' has no member '%s'" % (self.name, key))
-
-def supports_caller(func):
-    """apply a caller_stack compatibility decorator to a plain Python function."""
-    def wrap_stackframe(context,  *args, **kwargs):
-        context.caller_stack._push_frame()
-        try:
-            return func(context, *args, **kwargs)
-        finally:
-            context.caller_stack._pop_frame()
-    return wrap_stackframe
-        
-def capture(context, callable_, *args, **kwargs):
-    """execute the given template def, capturing the output into a buffer."""
-    if not callable(callable_):
-        raise exceptions.RuntimeException("capture() function expects a callable as its argument (i.e. capture(func, *args, **kwargs))")
-    context._push_buffer()
-    try:
-        callable_(*args, **kwargs)
-    finally:
-        buf = context._pop_buffer()
-    return buf.getvalue()
-        
-def _include_file(context, uri, calling_uri, **kwargs):
-    """locate the template from the given uri and include it in the current output."""
-    template = _lookup_template(context, uri, calling_uri)
-    (callable_, ctx) = _populate_self_namespace(context._clean_inheritance_tokens(), template)
-    callable_(ctx, **_kwargs_for_callable(callable_, context._data, **kwargs))
-        
-def _inherit_from(context, uri, calling_uri):
-    """called by the _inherit method in template modules to set up the inheritance chain at the start
-    of a template's execution."""
-    if uri is None:
-        return None
-    template = _lookup_template(context, uri, calling_uri)
-    self_ns = context['self']
-    ih = self_ns
-    while ih.inherits is not None:
-        ih = ih.inherits
-    lclcontext = context.locals_({'next':ih})
-    ih.inherits = Namespace("self:%s" % template.uri, lclcontext, template = template, populate_self=False)
-    context._data['parent'] = lclcontext._data['local'] = ih.inherits
-    callable_ = getattr(template.module, '_mako_inherit', None)
-    if callable_ is not None:
-        ret = callable_(template, lclcontext)
-        if ret:
-            return ret
-
-    gen_ns = getattr(template.module, '_mako_generate_namespaces', None)
-    if gen_ns is not None:
-        gen_ns(context)
-    return (template.callable_, lclcontext)
-
-def _lookup_template(context, uri, relativeto):
-    lookup = context._with_template.lookup
-    if lookup is None:
-        raise exceptions.TemplateLookupException("Template '%s' has no TemplateLookup associated" % context._with_template.uri)
-    uri = lookup.adjust_uri(uri, relativeto)
-    try:
-        return lookup.get_template(uri)
-    except exceptions.TopLevelLookupException, e:
-        raise exceptions.TemplateLookupException(str(e))
-
-def _populate_self_namespace(context, template, self_ns=None):
-    if self_ns is None:
-        self_ns = Namespace('self:%s' % template.uri, context, template=template, populate_self=False)
-    context._data['self'] = context._data['local'] = self_ns
-    if hasattr(template.module, '_mako_inherit'):
-        ret = template.module._mako_inherit(template, context)
-        if ret:
-            return ret
-    return (template.callable_, context)
-
-def _render(template, callable_, args, data, as_unicode=False):
-    """create a Context and return the string output of the given template and template callable."""
-
-    if as_unicode:
-        buf = util.FastEncodingBuffer(unicode=True)
-    elif template.output_encoding:
-        buf = util.FastEncodingBuffer(unicode=as_unicode, encoding=template.output_encoding, errors=template.encoding_errors)
-    else:
-        buf = util.StringIO()
-    context = Context(buf, **data)
-    context._with_template = template
-    _render_context(template, callable_, context, *args, **_kwargs_for_callable(callable_, data))
-    return context._pop_buffer().getvalue()
-
-def _kwargs_for_callable(callable_, data, **kwargs):
-    argspec = inspect.getargspec(callable_)
-    namedargs = argspec[0] + [v for v in argspec[1:3] if v is not None]
-    for arg in namedargs:
-        if arg != 'context' and arg in data and arg not in kwargs:
-            kwargs[arg] = data[arg]
-    return kwargs
-    
-def _render_context(tmpl, callable_, context, *args, **kwargs):
-    import mako.template as template
-    # create polymorphic 'self' namespace for this template with possibly updated context
-    if not isinstance(tmpl, template.DefTemplate):
-        # if main render method, call from the base of the inheritance stack
-        (inherit, lclcontext) = _populate_self_namespace(context, tmpl)
-        _exec_template(inherit, lclcontext, args=args, kwargs=kwargs)
-    else:
-        # otherwise, call the actual rendering method specified
-        (inherit, lclcontext) = _populate_self_namespace(context, tmpl.parent)
-        _exec_template(callable_, context, args=args, kwargs=kwargs)
-        
-def _exec_template(callable_, context, args=None, kwargs=None):
-    """execute a rendering callable given the callable, a Context, and optional explicit arguments
-
-    the contextual Template will be located if it exists, and the error handling options specified
-    on that Template will be interpreted here.
-    """
-    template = context._with_template
-    if template is not None and (template.format_exceptions or template.error_handler):
-        error = None
-        try:
-            callable_(context, *args, **kwargs)
-        except Exception, e:
-            error = e
-        except:                
-            e = sys.exc_info()[0]
-            error = e
-        if error:
-            if template.error_handler:
-                result = template.error_handler(context, error)
-                if not result:
-                    raise error
-            else:
-                error_template = exceptions.html_error_template()
-                context._buffer_stack[:] = [util.FastEncodingBuffer(error_template.output_encoding, error_template.encoding_errors)]
-                context._with_template = error_template
-                error_template.render_context(context, error=error)
-    else:
-        callable_(context, *args, **kwargs)
diff --git a/mako/template.py b/mako/template.py
deleted file mode 100644 (file)
index d50eb8a..0000000
+++ /dev/null
@@ -1,274 +0,0 @@
-# template.py
-# Copyright (C) 2006, 2007, 2008 Michael Bayer mike_mp@zzzcomputing.com
-#
-# This module is part of Mako and is released under
-# the MIT License: http://www.opensource.org/licenses/mit-license.php
-
-"""provides the Template class, a facade for parsing, generating and executing template strings,
-as well as template runtime operations."""
-
-from mako.lexer import Lexer
-from mako import codegen
-from mako import runtime, util, exceptions
-import imp, os, re, shutil, stat, sys, tempfile, time, types, weakref
-
-    
-class Template(object):
-    """a compiled template"""
-    def __init__(self, text=None, filename=None, uri=None, format_exceptions=False, error_handler=None, 
-        lookup=None, output_encoding=None, encoding_errors='strict', module_directory=None, cache_type=None, 
-        cache_dir=None, cache_url=None, module_filename=None, input_encoding=None, disable_unicode=False, default_filters=None, 
-        buffer_filters=[], imports=None, preprocessor=None):
-        """construct a new Template instance using either literal template text, or a previously loaded template module
-        
-        text - textual template source, or None if a module is to be provided
-        
-        uri - the uri of this template, or some identifying string. defaults to the 
-        full filename given, or "memory:(hex id of this Template)" if no filename
-        
-        filename - filename of the source template, if any
-        
-        format_exceptions - catch exceptions and format them into an error display template
-        """
-        
-        if uri:
-            self.module_id = re.sub(r'\W', "_", uri)
-            self.uri = uri
-        elif filename:
-            self.module_id = re.sub(r'\W', "_", filename)
-            self.uri = filename
-        else:
-            self.module_id = "memory:" + hex(id(self))
-            self.uri = self.module_id
-        
-        self.input_encoding = input_encoding
-        self.output_encoding = output_encoding
-        self.encoding_errors = encoding_errors
-        self.disable_unicode = disable_unicode
-        if default_filters is None:
-            if self.disable_unicode:
-                self.default_filters = ['str']
-            else:
-                self.default_filters = ['unicode']
-        else:
-            self.default_filters = default_filters
-        self.buffer_filters = buffer_filters
-            
-        self.imports = imports
-        self.preprocessor = preprocessor
-        
-        # if plain text, compile code in memory only
-        if text is not None:
-            (code, module) = _compile_text(self, text, filename)
-            self._code = code
-            self._source = text
-            ModuleInfo(module, None, self, filename, code, text)
-        elif filename is not None:
-            # if template filename and a module directory, load
-            # a filesystem-based module file, generating if needed
-            if module_filename is not None:
-                path = module_filename
-            elif module_directory is not None:
-                u = self.uri
-                if u[0] == '/':
-                    u = u[1:]
-                path = os.path.abspath(os.path.join(module_directory.replace('/', os.path.sep), u + ".py"))
-            else:
-                path = None    
-            if path is not None:
-                util.verify_directory(os.path.dirname(path))
-                filemtime = os.stat(filename)[stat.ST_MTIME]
-                if not os.path.exists(path) or os.stat(path)[stat.ST_MTIME] < filemtime:
-                    _compile_module_file(self, file(filename).read(), filename, path)
-                module = imp.load_source(self.module_id, path, file(path))
-                del sys.modules[self.module_id]
-                if module._magic_number != codegen.MAGIC_NUMBER:
-                    _compile_module_file(self, file(filename).read(), filename, path)
-                    module = imp.load_source(self.module_id, path, file(path))
-                    del sys.modules[self.module_id]
-                ModuleInfo(module, path, self, filename, None, None)
-            else:
-                # template filename and no module directory, compile code
-                # in memory
-                (code, module) = _compile_text(self, file(filename).read(), filename)
-                self._source = None
-                self._code = code
-                ModuleInfo(module, None, self, filename, code, None)
-        else:
-            raise exceptions.RuntimeException("Template requires text or filename")
-
-        self.module = module
-        self.filename = filename
-        self.callable_ = self.module.render_body
-        self.format_exceptions = format_exceptions
-        self.error_handler = error_handler
-        self.lookup = lookup
-        self.cache_type = cache_type
-        self.cache_dir = cache_dir
-        self.cache_url = cache_url
-
-    def source(self):
-        """return the template source code for this Template."""
-        return _get_module_info_from_callable(self.callable_).source
-    source = property(source)
-    
-    def code(self):
-        """return the module source code for this Template"""
-        return _get_module_info_from_callable(self.callable_).code
-    code = property(code)
-    
-    def cache(self):
-        return self.module._template_cache
-    cache = property(cache)
-    
-    def render(self, *args, **data):
-        """render the output of this template as a string.
-        
-        if the template specifies an output encoding, the string will be encoded accordingly, else the output
-        is raw (raw output uses cStringIO and can't handle multibyte characters).
-        a Context object is created corresponding to the given data.  Arguments that are explictly
-        declared by this template's internal rendering method are also pulled from the given *args, **data 
-        members."""
-        return runtime._render(self, self.callable_, args, data)
-    
-    def render_unicode(self, *args, **data):
-        """render the output of this template as a unicode object."""
-        
-        return runtime._render(self, self.callable_, args, data, as_unicode=True)
-        
-    def render_context(self, context, *args, **kwargs):
-        """render this Template with the given context.  
-        
-        the data is written to the context's buffer."""
-        if getattr(context, '_with_template', None) is None:
-            context._with_template = self
-        runtime._render_context(self, self.callable_, context, *args, **kwargs)
-    
-    def has_def(self, name):
-        return hasattr(self.module, "render_%s" % name)
-        
-    def get_def(self, name):
-        """return a def of this template as an individual Template of its own."""
-        return DefTemplate(self, getattr(self.module, "render_%s" % name))
-    
-
-class ModuleTemplate(Template):
-    """A Template which is constructed given an existing Python module.
-    
-        e.g.::
-        
-        t = Template("this is a template")
-        f = file("mymodule.py", "w")
-        f.write(t.code)
-        f.close()
-        
-        import mymodule
-        
-        t = ModuleTemplate(mymodule)
-        print t.render()
-    
-    """
-    
-    def __init__(self, module, 
-        module_filename=None, 
-        template=None, template_filename=None, 
-        module_source=None, template_source=None,
-        output_encoding=None, encoding_errors='strict', disable_unicode=False, format_exceptions=False,
-        error_handler=None, lookup=None, cache_type=None, cache_dir=None, cache_url=None
-    ):
-        self.module_id = re.sub(r'\W', "_", module._template_uri)
-        self.uri = module._template_uri
-        self.input_encoding = module._source_encoding
-        self.output_encoding = output_encoding
-        self.encoding_errors = encoding_errors
-        self.disable_unicode = disable_unicode
-        self.module = module
-        self.filename = template_filename
-        ModuleInfo(module, module_filename, self, template_filename, module_source, template_source)
-        
-        self.callable_ = self.module.render_body
-        self.format_exceptions = format_exceptions
-        self.error_handler = error_handler
-        self.lookup = lookup
-        self.cache_type = cache_type
-        self.cache_dir = cache_dir
-        self.cache_url = cache_url
-    
-class DefTemplate(Template):
-    """a Template which represents a callable def in a parent template."""
-    def __init__(self, parent, callable_):
-        self.parent = parent
-        self.callable_ = callable_
-        self.output_encoding = parent.output_encoding
-        self.encoding_errors = parent.encoding_errors
-        self.format_exceptions = parent.format_exceptions
-        self.error_handler = parent.error_handler
-        self.lookup = parent.lookup
-
-    def get_def(self, name):
-        return self.parent.get_def(name)
-
-class ModuleInfo(object):
-    """stores information about a module currently loaded into memory,
-    provides reverse lookups of template source, module source code based on
-    a module's identifier."""
-    _modules = weakref.WeakValueDictionary()
-
-    def __init__(self, module, module_filename, template, template_filename, module_source, template_source):
-        self.module = module
-        self.module_filename = module_filename
-        self.template_filename = template_filename
-        self.module_source = module_source
-        self.template_source = template_source
-        self._modules[module.__name__] = template._mmarker = self
-        if module_filename:
-            self._modules[module_filename] = self
-    def _get_code(self):
-        if self.module_source is not None:
-            return self.module_source
-        else:
-            return file(self.module_filename).read()
-    code = property(_get_code)
-    def _get_source(self):
-        if self.template_source is not None:
-            if self.module._source_encoding and not isinstance(self.template_source, unicode):
-                return self.template_source.decode(self.module._source_encoding)
-            else:
-                return self.template_source
-        else:
-            if self.module._source_encoding:
-                return file(self.template_filename).read().decode(self.module._source_encoding)
-            else:
-                return file(self.template_filename).read()
-    source = property(_get_source)
-        
-def _compile_text(template, text, filename):
-    identifier = template.module_id
-    lexer = Lexer(text, filename, disable_unicode=template.disable_unicode, input_encoding=template.input_encoding, preprocessor=template.preprocessor)
-    node = lexer.parse()
-    source = codegen.compile(node, template.uri, filename, default_filters=template.default_filters, buffer_filters=template.buffer_filters, imports=template.imports, source_encoding=lexer.encoding, generate_unicode=not template.disable_unicode)
-    #print source
-    cid = identifier
-    if isinstance(cid, unicode):
-        cid = cid.encode()
-    module = types.ModuleType(cid)
-    code = compile(source, cid, 'exec')
-    exec code in module.__dict__, module.__dict__
-    return (source, module)
-
-def _compile_module_file(template, text, filename, outputpath):
-    identifier = template.module_id
-    lexer = Lexer(text, filename, disable_unicode=template.disable_unicode, input_encoding=template.input_encoding, preprocessor=template.preprocessor)
-    node = lexer.parse()
-    source = codegen.compile(node, template.uri, filename, default_filters=template.default_filters, buffer_filters=template.buffer_filters, imports=template.imports, source_encoding=lexer.encoding, generate_unicode=not template.disable_unicode)
-    (dest, name) = tempfile.mkstemp()
-    os.write(dest, source)
-    os.close(dest)
-    shutil.move(name, outputpath)
-
-def _get_module_info_from_callable(callable_):
-    return _get_module_info(callable_.func_globals['__name__'])
-    
-def _get_module_info(filename):
-    return ModuleInfo._modules[filename]
-        
diff --git a/mako/util.py b/mako/util.py
deleted file mode 100644 (file)
index 58a18a7..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-# util.py
-# Copyright (C) 2006, 2007, 2008 Michael Bayer mike_mp@zzzcomputing.com
-#
-# This module is part of Mako and is released under
-# the MIT License: http://www.opensource.org/licenses/mit-license.php
-
-import sys
-try:
-    Set = set
-except:
-    import sets
-    Set = sets.Set
-
-try:
-    from cStringIO import StringIO
-except:
-    from StringIO import StringIO
-
-import codecs, re, weakref, os, time
-
-try:
-    import threading
-    import thread
-except ImportError:
-    import dummy_threading as threading
-    import dummy_thread as thread
-
-if sys.platform.startswith('win') or sys.platform.startswith('java'):
-    time_func = time.clock
-else:
-    time_func = time.time 
-   
-def verify_directory(dir):
-    """create and/or verify a filesystem directory."""
-    
-    tries = 0
-    
-    while not os.path.exists(dir):
-        try:
-            tries += 1
-            os.makedirs(dir, 0750)
-        except:
-            if tries > 5:
-                raise
-
-class SetLikeDict(dict):
-    """a dictionary that has some setlike methods on it"""
-    def union(self, other):
-        """produce a 'union' of this dict and another (at the key level).
-        
-        values in the second dict take precedence over that of the first"""
-        x = SetLikeDict(**self)
-        x.update(other)
-        return x
-
-class FastEncodingBuffer(object):
-    """a very rudimentary buffer that is faster than StringIO, but doesnt crash on unicode data like cStringIO."""
-    
-    def __init__(self, encoding=None, errors='strict', unicode=False):
-        self.data = []
-        self.encoding = encoding
-        if unicode:
-            self.delim = u''
-        else:
-            self.delim = ''
-        self.unicode = unicode
-        self.errors = errors
-        self.write = self.data.append
-        
-    def getvalue(self):
-        if self.encoding:
-            return self.delim.join(self.data).encode(self.encoding, self.errors)
-        else:
-            return self.delim.join(self.data)
-
-class LRUCache(dict):
-    """A dictionary-like object that stores a limited number of items, discarding
-    lesser used items periodically.
-    
-    this is a rewrite of LRUCache from Myghty to use a periodic timestamp-based
-    paradigm so that synchronization is not really needed.  the size management 
-    is inexact.
-    """
-    
-    class _Item(object):
-        def __init__(self, key, value):
-            self.key = key
-            self.value = value
-            self.timestamp = time_func()
-        def __repr__(self):
-            return repr(self.value)
-    
-    def __init__(self, capacity, threshold=.5):
-        self.capacity = capacity
-        self.threshold = threshold
-    
-    def __getitem__(self, key):
-        item = dict.__getitem__(self, key)
-        item.timestamp = time_func()
-        return item.value
-    
-    def values(self):
-        return [i.value for i in dict.values(self)]
-    
-    def setdefault(self, key, value):
-        if key in self:
-            return self[key]
-        else:
-            self[key] = value
-            return value
-    
-    def __setitem__(self, key, value):
-        item = dict.get(self, key)
-        if item is None:
-            item = self._Item(key, value)
-            dict.__setitem__(self, key, item)
-        else:
-            item.value = value
-        self._manage_size()
-    
-    def _manage_size(self):
-        while len(self) > self.capacity + self.capacity * self.threshold:
-            bytime = dict.values(self)
-            bytime.sort(lambda a, b: cmp(b.timestamp, a.timestamp))
-            for item in bytime[self.capacity:]:
-                try:
-                    del self[item.key]
-                except KeyError:
-                    # if we couldnt find a key, most likely some other thread broke in 
-                    # on us. loop around and try again
-                    break
-
-# Regexp to match python magic encoding line
-_PYTHON_MAGIC_COMMENT_re = re.compile(
-    r'[ \t\f]* \# .* coding[=:][ \t]*([-\w.]+)',
-    re.VERBOSE)
-
-def parse_encoding(fp):
-    """Deduce the encoding of a source file from magic comment.
-
-    It does this in the same way as the `Python interpreter`__
-
-    .. __: http://docs.python.org/ref/encodings.html
-
-    The ``fp`` argument should be a seekable file object.
-    """
-    pos = fp.tell()
-    fp.seek(0)
-    try:
-        line1 = fp.readline()
-        has_bom = line1.startswith(codecs.BOM_UTF8)
-        if has_bom:
-            line1 = line1[len(codecs.BOM_UTF8):]
-
-        m = _PYTHON_MAGIC_COMMENT_re.match(line1)
-        if not m:
-            try:
-                import parser
-                parser.suite(line1)
-            except (ImportError, SyntaxError):
-                # Either it's a real syntax error, in which case the source
-                # is not valid python source, or line2 is a continuation of
-                # line1, in which case we don't want to scan line2 for a magic
-                # comment.
-                pass
-            else:
-                line2 = fp.readline()
-                m = _PYTHON_MAGIC_COMMENT_re.match(line2)
-
-        if has_bom:
-            if m:
-                raise SyntaxError, \
-                      "python refuses to compile code with both a UTF8" \
-                      " byte-order-mark and a magic encoding comment"
-            return 'utf_8'
-        elif m:
-            return m.group(1)
-        else:
-            return None
-    finally:
-        fp.seek(pos)
-
-def restore__ast(_ast):
-    """Attempt to restore the required classes to the _ast module if it
-    appears to be missing them
-    """
-    if hasattr(_ast, 'AST'):
-        return
-    _ast.PyCF_ONLY_AST = 2 << 9
-    m = compile("""\
-def foo(): pass
-class Bar(object): pass
-if False: pass
-baz = 'mako'
-1 + 2 - 3 * 4 / 5
-6 // 7 % 8 << 9 >> 10
-11 & 12 ^ 13 | 14
-15 and 16 or 17
--baz + (not +18) - ~17
-baz and 'foo' or 'bar'
-(mako is baz == baz) is not baz != mako
-mako > baz < mako >= baz <= mako
-mako in baz not in mako""", '<unknown>', 'exec', _ast.PyCF_ONLY_AST)
-    _ast.Module = type(m)
-
-    for cls in _ast.Module.__mro__:
-        if cls.__name__ == 'mod':
-            _ast.mod = cls
-        elif cls.__name__ == 'AST':
-            _ast.AST = cls
-
-    _ast.FunctionDef = type(m.body[0])
-    _ast.ClassDef = type(m.body[1])
-    _ast.If = type(m.body[2])
-
-    _ast.Name = type(m.body[3].targets[0])
-    _ast.Store = type(m.body[3].targets[0].ctx)
-    _ast.Str = type(m.body[3].value)
-
-    _ast.Sub = type(m.body[4].value.op)
-    _ast.Add = type(m.body[4].value.left.op)
-    _ast.Div = type(m.body[4].value.right.op)
-    _ast.Mult = type(m.body[4].value.right.left.op)
-
-    _ast.RShift = type(m.body[5].value.op)
-    _ast.LShift = type(m.body[5].value.left.op)
-    _ast.Mod = type(m.body[5].value.left.left.op)
-    _ast.FloorDiv = type(m.body[5].value.left.left.left.op)
-
-    _ast.BitOr = type(m.body[6].value.op)
-    _ast.BitXor = type(m.body[6].value.left.op)
-    _ast.BitAnd = type(m.body[6].value.left.left.op)
-
-    _ast.Or = type(m.body[7].value.op)
-    _ast.And = type(m.body[7].value.values[0].op)
-
-    _ast.Invert = type(m.body[8].value.right.op)
-    _ast.Not = type(m.body[8].value.left.right.op)
-    _ast.UAdd = type(m.body[8].value.left.right.operand.op)
-    _ast.USub = type(m.body[8].value.left.left.op)
-
-    _ast.Or = type(m.body[9].value.op)
-    _ast.And = type(m.body[9].value.values[0].op)
-
-    _ast.IsNot = type(m.body[10].value.ops[0])
-    _ast.NotEq = type(m.body[10].value.ops[1])
-    _ast.Is = type(m.body[10].value.left.ops[0])
-    _ast.Eq = type(m.body[10].value.left.ops[1])
-
-    _ast.Gt = type(m.body[11].value.ops[0])
-    _ast.Lt = type(m.body[11].value.ops[1])
-    _ast.GtE = type(m.body[11].value.ops[2])
-    _ast.LtE = type(m.body[11].value.ops[3])
-
-    _ast.In = type(m.body[12].value.ops[0])
-    _ast.NotIn = type(m.body[12].value.ops[1])
index 53d827686575580872eb1a82763492648ee903a8..dbaff93140cbcb38d0eef24a5bf5998f979c164c 100644 (file)
@@ -16,7 +16,7 @@
     <div class="cb"></div>
    </div> <!-- planetHeader -->
    <div id="planetMain">
-${self.body()}
+{% block content %} {% endblock %}
    </div> <!-- planetMain -->
   </div> <!-- planetWrap -->
 
index a9fbfb1156980822f6d1a4af073879b3124a66b0..3d80283ee1bcc17a1c523465fa0b0e1e683f99b0 100644 (file)
@@ -1,10 +1,11 @@
-<%inherit file="base.tmpl" />
+{% extends "base.tmpl" %}
+{% block content %}
     <div id="planetRight">
      <div class="planetRightTitle">Subscriptions</div>
      <ul>
-% for feed in feeds:
-      <li><a href="${feed.feedurl}"><img src="img/feed-icon-14x14.png" alt="RSS"/></a> <%call expr="coalescelink(feed.name, feed.blogurl)"></%call></li>
-% endfor
+{% for feed in feeds %}
+      <li><a href="{{feed.feedurl}}"><img src="img/feed-icon-14x14.png" alt="RSS"/></a> {%if feed.blogurl %}<a href="{{feed.blogurl}}">{{feed.name}}</a>{%else%}{{feed.name}}{%endif%}</li>
+{% endfor %}
      </ul>
      <div class="planetRightTitle">Feeds</div>
      <ul>
      <p><a href="policy.html">Policy</a> for being listed on Planet PostgreSQL</p>
     </div> <!-- planetRight -->
     <div id="planetLeft">
-% for post in posts:
+{% for post in posts %}
      <div class="planetPost">
-      <div class="planetPostTitle"><a href="${post.link}">${post.title}</a></div>
+      <div class="planetPostTitle"><a href="{{post.link}}">{{post.title}}</a></div>
       <div class="planetPostAuthor">
        <div class="ppa_top">&nbsp;</div>
-       <p>Posted by <%call expr="coalescelink(post.author, post.blogurl)"></%call> on <span class="date">${post.datetime}</span></p>
+       <p>Posted by {%if post.blogurl%}<a href="{{post.blogurl}}">{{post.author}}</a>{%else%}{{post.author}}{%endif%} on <span class="date">{{post.datetime}}</span></p>
        <div class="ppa_bottom">&nbsp;</div>
       </div>
-      <div class="planetPostContent">${post.contents}</div>
+      <div class="planetPostContent">{{post.contents|safe}}</div>
       <div class="cl"></div>
      </div>
-% endfor
+{% endfor %}
     </div> <!-- planetLeft -->
-<%def name="coalescelink(txt, link)">
-%if link=='':
-${txt}
-%else:
-<a href="${link}">${txt}</a>
-%endif
-</%def>
+{% endblock %}
index 5329deafe613b3512deeb67e62724c5882d93466..17c9dd3814f53bde9496188cdc409a0553f77f08 100644 (file)
@@ -1,4 +1,5 @@
-<%inherit file="base.tmpl" />
+{%extends "base.tmpl"%}
+{%block content%}
 <h1>Planet PostgreSQL policy</h1>
 <p>
 The following simple rules cover the blogs being listed on Planet PostgreSQL:
@@ -16,3 +17,4 @@ The following simple rules cover the blogs being listed on Planet PostgreSQL:
  <li>Publishing of advertising in the syndicated part of your blog is not permitted</li>
 </ul>
 <p>Violating these rules will cause your blog to be removed from Planet PostgreSQL.</p>
+{%endblock%}