aboutsummaryrefslogtreecommitdiffstats
path: root/lib/mako
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-02-05 00:15:54 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2010-02-05 00:15:54 +0000
commit1575e1e4e117cf127ddeade810c3dccafe1f218b (patch)
tree4b66991b170127051dd3c250f1a0c03943477832 /lib/mako
parent86411ebded5f62970eaa2b119a215a71212cb492 (diff)
downloadexternal_python_mako-1575e1e4e117cf127ddeade810c3dccafe1f218b.tar.gz
external_python_mako-1575e1e4e117cf127ddeade810c3dccafe1f218b.tar.bz2
external_python_mako-1575e1e4e117cf127ddeade810c3dccafe1f218b.zip
move lib/mako to mako
Diffstat (limited to 'lib/mako')
-rw-r--r--lib/mako/__init__.py9
-rw-r--r--lib/mako/_ast_util.py834
-rw-r--r--lib/mako/ast.py125
-rw-r--r--lib/mako/cache.py55
-rw-r--r--lib/mako/codegen.py765
-rw-r--r--lib/mako/exceptions.py283
-rw-r--r--lib/mako/ext/__init__.py0
-rw-r--r--lib/mako/ext/autohandler.py57
-rw-r--r--lib/mako/ext/babelplugin.py123
-rw-r--r--lib/mako/ext/preprocessors.py20
-rw-r--r--lib/mako/ext/pygmentplugin.py101
-rw-r--r--lib/mako/ext/turbogears.py50
-rw-r--r--lib/mako/filters.py170
-rw-r--r--lib/mako/lexer.py328
-rw-r--r--lib/mako/lookup.py202
-rw-r--r--lib/mako/parsetree.py422
-rw-r--r--lib/mako/pygen.py267
-rw-r--r--lib/mako/pyparser.py371
-rw-r--r--lib/mako/runtime.py419
-rw-r--r--lib/mako/template.py392
-rw-r--r--lib/mako/util.py274
21 files changed, 0 insertions, 5267 deletions
diff --git a/lib/mako/__init__.py b/lib/mako/__init__.py
deleted file mode 100644
index 6a30418..0000000
--- a/lib/mako/__init__.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# __init__.py
-# Copyright (C) 2006, 2007, 2008, 2009, 2010 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
-
-
-__version__ = '0.2.5'
-
diff --git a/lib/mako/_ast_util.py b/lib/mako/_ast_util.py
deleted file mode 100644
index 6ff4ab9..0000000
--- a/lib/mako/_ast_util.py
+++ /dev/null
@@ -1,834 +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.
-"""
-from _ast import *
-
-
-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, 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."""
- # CPython 2.5 compat
- 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, 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_' + node.__class__.__name__
- 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, 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, 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[type(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[type(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[type(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[type(op)])
- self.visit(right)
- self.write(')')
-
- def visit_UnaryOp(self, node):
- self.write('(')
- op = UNARYOP_SYMBOLS[type(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/lib/mako/ast.py b/lib/mako/ast.py
deleted file mode 100644
index 3b9f3ed..0000000
--- a/lib/mako/ast.py
+++ /dev/null
@@ -1,125 +0,0 @@
-# ast.py
-# Copyright (C) 2006, 2007, 2008, 2009, 2010 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/lib/mako/cache.py b/lib/mako/cache.py
deleted file mode 100644
index 43f7317..0000000
--- a/lib/mako/cache.py
+++ /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/lib/mako/codegen.py b/lib/mako/codegen.py
deleted file mode 100644
index b3074f0..0000000
--- a/lib/mako/codegen.py
+++ /dev/null
@@ -1,765 +0,0 @@
-# codegen.py
-# Copyright (C) 2006, 2007, 2008, 2009, 2010 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)
-
- @property
- def identifiers(self):
- return 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 = %r" % MAGIC_NUMBER)
- self.printer.writeline("_modified_time = %r" % time.time())
- self.printer.writeline(
- "_template_filename=%r" % self.compiler.filename)
- self.printer.writeline("_template_uri=%r" % self.compiler.uri)
- self.printer.writeline(
- "_template_cache=cache.Cache(__name__, _modified_time)")
- self.printer.writeline(
- "_source_encoding=%r" % 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("UNDEFINED")
- if impcode:
- module_identifiers.declared.update(impcode.declared_identifiers)
-
- self.compiler.identifiers = module_identifiers
- self.printer.writeline("_exports = %r" %
- [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()
-
-##### continue [ticket:98] below ####
-
- 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."""
-
- if self.in_def:
- decorator = node.decorator
- if decorator:
- self.printer.writeline("@runtime._decorate_toplevel(%s)" % decorator)
-
- 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()
-
- decorator = node.decorator
- if decorator:
- self.printer.writeline("@runtime._decorate_inline(context, %s)" % decorator)
- 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 visitCallNamespaceTag(self, node):
- # TODO: we can put namespace-specific checks here, such
- # as ensure the given namespace will be imported,
- # pre-import the namespace, etc.
- self.visitCallTag(node)
-
- 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.expression, 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 visitCallNamespaceTag(self, node):
- self.visitCallTag(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/lib/mako/exceptions.py b/lib/mako/exceptions.py
deleted file mode 100644
index dcd6a64..0000000
--- a/lib/mako/exceptions.py
+++ /dev/null
@@ -1,283 +0,0 @@
-# exceptions.py
-# Copyright (C) 2006, 2007, 2008, 2009, 2010 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.
- message - the exception error message as unicode
- 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, traceback=None):
- (self.source, self.lineno) = ("", 0)
- (t, self.error, self.records) = self._init(traceback)
- 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()
- self.init_message()
-
- def init_message(self):
- """Find a unicode representation of self.error"""
- try:
- self.message = unicode(self.error)
- except UnicodeError:
- try:
- self.message = str(self.error)
- except UnicodeEncodeError:
- # Fallback to args as neither unicode nor
- # str(Exception(u'\xe6')) work in Python < 2.6
- self.message = self.error.args[0]
- if not isinstance(self.message, unicode):
- self.message = unicode(self.message, 'ascii', 'replace')
-
- 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, trcback):
- """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 = {}
- if not trcback:
- (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:
- # A normal .py file (not a Template)
- try:
- fp = open(filename)
- encoding = util.parse_encoding(fp)
- fp.close()
- except IOError:
- encoding = None
- if encoding:
- line = line.decode(encoding)
- else:
- line = line.decode('ascii', 'replace')
- 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"""
-<%page args="traceback=None"/>
-<%!
- from mako.exceptions import RichTraceback
-%>\
-<%
- tback = RichTraceback(traceback=traceback)
-%>\
-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__)}: ${tback.message}
-""")
-
-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, traceback=None"/>
-% 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(traceback=traceback)
- src = tback.source
- line = tback.lineno
- if src:
- lines = src.split('\n')
- else:
- lines = None
-%>
-<h3>${str(tback.error.__class__.__name__)}: ${tback.message}</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/lib/mako/ext/__init__.py b/lib/mako/ext/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/lib/mako/ext/__init__.py
+++ /dev/null
diff --git a/lib/mako/ext/autohandler.py b/lib/mako/ext/autohandler.py
deleted file mode 100644
index 3025f8e..0000000
--- a/lib/mako/ext/autohandler.py
+++ /dev/null
@@ -1,57 +0,0 @@
-"""adds autohandler functionality to Mako templates.
-
-requires that the TemplateLookup class is used with templates.
-
-usage:
-
-<%!
- from mako.ext.autohandler import autohandler
-%>
-<%inherit file="${autohandler(template, context)}"/>
-
-
-or with custom autohandler filename:
-
-<%!
- from mako.ext.autohandler import autohandler
-%>
-<%inherit file="${autohandler(template, context, name='somefilename')}"/>
-
-"""
-
-import posixpath, os, re
-
-def autohandler(template, context, name='autohandler'):
- lookup = context.lookup
- _template_uri = template.module._template_uri
- if not lookup.filesystem_checks:
- try:
- return lookup._uri_cache[(autohandler, _template_uri, name)]
- except KeyError:
- pass
-
- tokens = re.findall(r'([^/]+)', posixpath.dirname(_template_uri)) + [name]
- while len(tokens):
- path = '/' + '/'.join(tokens)
- if path != _template_uri and _file_exists(lookup, path):
- if not lookup.filesystem_checks:
- return lookup._uri_cache.setdefault((autohandler, _template_uri, name), path)
- else:
- return path
- if len(tokens) == 1:
- break
- tokens[-2:] = [name]
-
- if not lookup.filesystem_checks:
- return lookup._uri_cache.setdefault((autohandler, _template_uri, name), None)
- else:
- return None
-
-def _file_exists(lookup, path):
- psub = re.sub(r'^/', '',path)
- for d in lookup.directories:
- if os.path.exists(d + '/' + psub):
- return True
- else:
- return False
-
diff --git a/lib/mako/ext/babelplugin.py b/lib/mako/ext/babelplugin.py
deleted file mode 100644
index 9f08c5e..0000000
--- a/lib/mako/ext/babelplugin.py
+++ /dev/null
@@ -1,123 +0,0 @@
-"""gettext message extraction via Babel: http://babel.edgewall.org/"""
-from StringIO import StringIO
-
-from babel.messages.extract import extract_python
-
-from mako import lexer, parsetree
-
-def extract(fileobj, keywords, comment_tags, options):
- """Extract messages from Mako templates.
-
- :param fileobj: the file-like object the messages should be extracted from
- :param keywords: a list of keywords (i.e. function names) that should be
- recognized as translation functions
- :param comment_tags: a list of translator tags to search for and include
- in the results
- :param options: a dictionary of additional options (optional)
- :return: an iterator over ``(lineno, funcname, message, comments)`` tuples
- :rtype: ``iterator``
- """
- encoding = options.get('input_encoding', options.get('encoding', None))
-
- template_node = lexer.Lexer(fileobj.read(),
- input_encoding=encoding).parse()
- for extracted in extract_nodes(template_node.get_children(),
- keywords, comment_tags, options):
- yield extracted
-
-def extract_nodes(nodes, keywords, comment_tags, options):
- """Extract messages from Mako's lexer node objects
-
- :param nodes: an iterable of Mako parsetree.Node objects to extract from
- :param keywords: a list of keywords (i.e. function names) that should be
- recognized as translation functions
- :param comment_tags: a list of translator tags to search for and include
- in the results
- :param options: a dictionary of additional options (optional)
- :return: an iterator over ``(lineno, funcname, message, comments)`` tuples
- :rtype: ``iterator``
- """
- translator_comments = []
- in_translator_comments = False
-
- for node in nodes:
- child_nodes = None
- if in_translator_comments and isinstance(node, parsetree.Text) and \
- not node.content.strip():
- # Ignore whitespace within translator comments
- continue
-
- if isinstance(node, parsetree.Comment):
- value = node.text.strip()
- if in_translator_comments:
- translator_comments.extend(_split_comment(node.lineno, value))
- continue
- for comment_tag in comment_tags:
- if value.startswith(comment_tag):
- in_translator_comments = True
- translator_comments.extend(_split_comment(node.lineno,
- value))
- continue
-
- if isinstance(node, parsetree.DefTag):
- code = node.function_decl.code
- child_nodes = node.nodes
- elif isinstance(node, parsetree.CallTag):
- code = node.code.code
- child_nodes = node.nodes
- elif isinstance(node, parsetree.PageTag):
- code = node.body_decl.code
- elif isinstance(node, parsetree.CallNamespaceTag):
- attribs = ', '.join(['%s=%s' % (key, val)
- for key, val in node.attributes.iteritems()])
- code = '{%s}' % attribs
- child_nodes = node.nodes
- elif isinstance(node, parsetree.ControlLine):
- if node.isend:
- translator_comments = []
- in_translator_comments = False
- continue
- code = node.text
- elif isinstance(node, parsetree.Code):
- # <% and <%! blocks would provide their own translator comments
- translator_comments = []
- in_translator_comments = False
-
- code = node.code.code
- elif isinstance(node, parsetree.Expression):
- code = node.code.code
- else:
- translator_comments = []
- in_translator_comments = False
- continue
-
- # Comments don't apply unless they immediately preceed the message
- if translator_comments and \
- translator_comments[-1][0] < node.lineno - 1:
- translator_comments = []
- else:
- translator_comments = \
- [comment[1] for comment in translator_comments]
-
- if isinstance(code, unicode):
- code = code.encode('ascii', 'backslashreplace')
- code = StringIO(code)
- for lineno, funcname, messages, python_translator_comments \
- in extract_python(code, keywords, comment_tags, options):
- yield (node.lineno + (lineno - 1), funcname, messages,
- translator_comments + python_translator_comments)
-
- translator_comments = []
- in_translator_comments = False
-
- if child_nodes:
- for extracted in extract_nodes(child_nodes, keywords, comment_tags,
- options):
- yield extracted
-
-
-def _split_comment(lineno, comment):
- """Return the multiline comment at lineno split into a list of comment line
- numbers and the accompanying comment line"""
- return [(lineno + index, line) for index, line in
- enumerate(comment.splitlines())]
diff --git a/lib/mako/ext/preprocessors.py b/lib/mako/ext/preprocessors.py
deleted file mode 100644
index 601ac0d..0000000
--- a/lib/mako/ext/preprocessors.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""preprocessing functions, used with the 'preprocessor' argument on Template, TemplateLookup"""
-
-import re
-
-def convert_comments(text):
- """preprocess old style comments.
-
- example:
-
- from mako.ext.preprocessors import convert_comments
- t = Template(..., preprocessor=preprocess_comments)"""
- return re.sub(r'(?<=\n)\s*#[^#]', "##", text)
-
-# TODO
-def create_tag(callable):
- """given a callable, extract the *args and **kwargs, and produce a preprocessor
- that will parse for <%<funcname> <args>> and convert to an appropriate <%call> statement.
-
- this allows any custom tag to be created which looks like a pure Mako-style tag."""
- raise NotImplementedError("Future functionality....") \ No newline at end of file
diff --git a/lib/mako/ext/pygmentplugin.py b/lib/mako/ext/pygmentplugin.py
deleted file mode 100644
index 09ffe12..0000000
--- a/lib/mako/ext/pygmentplugin.py
+++ /dev/null
@@ -1,101 +0,0 @@
-import re
-try:
- set
-except NameError:
- from sets import Set as set
-
-from pygments.lexers.web import \
- HtmlLexer, XmlLexer, JavascriptLexer, CssLexer
-from pygments.lexers.agile import PythonLexer
-from pygments.lexer import Lexer, DelegatingLexer, RegexLexer, bygroups, \
- include, using, this
-from pygments.token import Error, Punctuation, \
- Text, Comment, Operator, Keyword, Name, String, Number, Other, Literal
-from pygments.util import html_doctype_matches, looks_like_xml
-
-class MakoLexer(RegexLexer):
- name = 'Mako'
- aliases = ['mako']
- filenames = ['*.mao']
-
- tokens = {
- 'root': [
- (r'(\s*)(\%)(\s*end(?:\w+))(\n|\Z)',
- bygroups(Text, Comment.Preproc, Keyword, Other)),
- (r'(\s*)(\%)([^\n]*)(\n|\Z)',
- bygroups(Text, Comment.Preproc, using(PythonLexer), Other)),
- (r'(\s*)(##[^\n]*)(\n|\Z)',
- bygroups(Text, Comment.Preproc, Other)),
- (r'''(?s)<%doc>.*?</%doc>''', Comment.Preproc),
- (r'(<%)([\w\.\:]+)', bygroups(Comment.Preproc, Name.Builtin), 'tag'),
- (r'(</%)([\w\.\:]+)(>)', bygroups(Comment.Preproc, Name.Builtin, Comment.Preproc)),
- (r'<%(?=([\w\.\:]+))', Comment.Preproc, 'ondeftags'),
- (r'(<%(?:!?))(.*?)(%>)(?s)', bygroups(Comment.Preproc, using(PythonLexer), Comment.Preproc)),
- (r'(\$\{)(.*?)(\})',
- bygroups(Comment.Preproc, using(PythonLexer), Comment.Preproc)),
- (r'''(?sx)
- (.+?) # anything, followed by:
- (?:
- (?<=\n)(?=%|\#\#) | # an eval or comment line
- (?=\#\*) | # multiline comment
- (?=</?%) | # a python block
- # call start or end
- (?=\$\{) | # a substitution
- (?<=\n)(?=\s*%) |
- # - don't consume
- (\\\n) | # an escaped newline
- \Z # end of string
- )
- ''', bygroups(Other, Operator)),
- (r'\s+', Text),
- ],
- 'ondeftags': [
- (r'<%', Comment.Preproc),
- (r'(?<=<%)(include|inherit|namespace|page)', Name.Builtin),
- include('tag'),
- ],
- 'tag': [
- (r'((?:\w+)\s*=)\s*(".*?")',
- bygroups(Name.Attribute, String)),
- (r'/?\s*>', Comment.Preproc, '#pop'),
- (r'\s+', Text),
- ],
- 'attr': [
- ('".*?"', String, '#pop'),
- ("'.*?'", String, '#pop'),
- (r'[^\s>]+', String, '#pop'),
- ],
- }
-
-
-class MakoHtmlLexer(DelegatingLexer):
- name = 'HTML+Mako'
- aliases = ['html+mako']
-
- def __init__(self, **options):
- super(MakoHtmlLexer, self).__init__(HtmlLexer, MakoLexer,
- **options)
-
-class MakoXmlLexer(DelegatingLexer):
- name = 'XML+Mako'
- aliases = ['xml+mako']
-
- def __init__(self, **options):
- super(MakoXmlLexer, self).__init__(XmlLexer, MakoLexer,
- **options)
-
-class MakoJavascriptLexer(DelegatingLexer):
- name = 'JavaScript+Mako'
- aliases = ['js+mako', 'javascript+mako']
-
- def __init__(self, **options):
- super(MakoJavascriptLexer, self).__init__(JavascriptLexer,
- MakoLexer, **options)
-
-class MakoCssLexer(DelegatingLexer):
- name = 'CSS+Mako'
- aliases = ['css+mako']
-
- def __init__(self, **options):
- super(MakoCssLexer, self).__init__(CssLexer, MakoLexer,
- **options)
diff --git a/lib/mako/ext/turbogears.py b/lib/mako/ext/turbogears.py
deleted file mode 100644
index f82f907..0000000
--- a/lib/mako/ext/turbogears.py
+++ /dev/null
@@ -1,50 +0,0 @@
-import re, inspect
-from mako.lookup import TemplateLookup
-from mako.template import Template
-
-class TGPlugin(object):
- """TurboGears compatible Template Plugin."""
-
- def __init__(self, extra_vars_func=None, options=None, extension='mak'):
- self.extra_vars_func = extra_vars_func
- self.extension = extension
- if not options:
- options = {}
-
- # Pull the options out and initialize the lookup
- lookup_options = {}
- for k, v in options.iteritems():
- if k.startswith('mako.'):
- lookup_options[k[5:]] = v
- elif k in ['directories', 'filesystem_checks', 'module_directory']:
- lookup_options[k] = v
- self.lookup = TemplateLookup(**lookup_options)
-
- self.tmpl_options = {}
- # transfer lookup args to template args, based on those available
- # in getargspec
- for kw in inspect.getargspec(Template.__init__)[0]:
- if kw in lookup_options:
- self.tmpl_options[kw] = lookup_options[kw]
-
- def load_template(self, templatename, template_string=None):
- """Loads a template from a file or a string"""
- if template_string is not None:
- return Template(template_string, **self.tmpl_options)
- # Translate TG dot notation to normal / template path
- if '/' not in templatename:
- templatename = '/' + templatename.replace('.', '/') + '.' + self.extension
-
- # Lookup template
- return self.lookup.get_template(templatename)
-
- def render(self, info, format="html", fragment=False, template=None):
- if isinstance(template, basestring):
- template = self.load_template(template)
-
- # Load extra vars func if provided
- if self.extra_vars_func:
- info.update(self.extra_vars_func())
-
- return template.render(**info)
-
diff --git a/lib/mako/filters.py b/lib/mako/filters.py
deleted file mode 100644
index 9a5b21d..0000000
--- a/lib/mako/filters.py
+++ /dev/null
@@ -1,170 +0,0 @@
-# filters.py
-# Copyright (C) 2006, 2007, 2008, 2009, 2010 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/lib/mako/lexer.py b/lib/mako/lexer.py
deleted file mode 100644
index 52a4b6d..0000000
--- a/lib/mako/lexer.py
+++ /dev/null
@@ -1,328 +0,0 @@
-# lexer.py
-# Copyright (C) 2006, 2007, 2008, 2009, 2010 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+|\s*=\s*|".*?"|'.*?')*) # attrname, = sign, string expression
-
- \s* # more whitespace
-
- (/)?> # closing
-
- ''',
-
- re.I | re.S | re.X)
-
- if match:
- (keyword, attr, isend) = (match.group(1), 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/lib/mako/lookup.py b/lib/mako/lookup.py
deleted file mode 100644
index 0398c5e..0000000
--- a/lib/mako/lookup.py
+++ /dev/null
@@ -1,202 +0,0 @@
-# lookup.py
-# Copyright (C) 2006, 2007, 2008, 2009, 2010 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:
- 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,
- cache_enabled=True,
- modulename_callable=None,
- default_filters=None,
- buffer_filters=(),
- imports=None,
- input_encoding=None,
- preprocessor=None):
-
- self.directories = [posixpath.normpath(d) for d in
- util.to_list(directories, ())
- ]
- 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,
- 'cache_enabled':cache_enabled,
- '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 %r" % 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:
- if self.modulename_callable is not None:
- module_filename = self.modulename_callable(filename, uri)
- else:
- module_filename = None
- self._collection[uri] = template = Template(
- uri=uri,
- filename=posixpath.normpath(filename),
- lookup=self,
- module_filename=module_filename,
- **self.template_args)
- return template
- except:
- # if compilation fails etc, ensure
- # template is removed from collection,
- # re-raise
- 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 %r" % 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/lib/mako/parsetree.py b/lib/mako/parsetree.py
deleted file mode 100644
index 347c31a..0000000
--- a/lib/mako/parsetree.py
+++ /dev/null
@@ -1,422 +0,0 @@
-# parsetree.py
-# Copyright (C) 2006, 2007, 2008, 2009, 2010 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
-
- def exception_kwargs(self):
- return {'source':self.source, 'lineno':self.lineno, 'pos':self.pos, 'filename':self.filename}
- exception_kwargs = property(exception_kwargs)
-
- 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, %r)" % (util.sorted_dict_repr(self.page_attributes), self.nodes)
-
-class ControlLine(Node):
- """defines a control line, a line-oriented python line or end tag.
-
- e.g.::
-
- % 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 = code.declared_identifiers
- self._undeclared_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(%r, %r, %r, %r)" % (
- self.keyword,
- self.text,
- self.isend,
- (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(%r, %r)" % (self.content, (self.lineno, self.pos))
-
-class Code(Node):
- """defines a Python code block, either inline or module level.
-
- e.g.::
-
- 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(%r, %r, %r)" % (
- self.text,
- self.ismodule,
- (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(%r, %r)" % (self.text, (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(%r, %r, %r)" % (
- self.text,
- self.escapes_code.args,
- (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):
- if ":" in keyword:
- ns, defname = keyword.split(':')
- return type.__call__(CallNamespaceTag, ns, defname, 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("(%s)" % m.group(1))
- else:
- if x:
- expr.append(repr(x))
- self.parsed_attributes[key] = " + ".join(expr) or repr('')
- 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(%r, %s, %r, %r)" % (self.__class__.__name__,
- self.keyword,
- util.sorted_dict_repr(self.attributes),
- (self.lineno, self.pos),
- [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', 'decorator'),
- ('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.decorator = attributes.get('decorator', '')
- 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.expression = attributes['expr']
- self.code = ast.PythonCode(self.expression, **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 CallNamespaceTag(Tag):
-
- def __init__(self, namespace, defname, attributes, **kwargs):
- super(CallNamespaceTag, self).__init__(
- namespace + ":" + defname,
- attributes,
- tuple(attributes.keys()) + ('args', ),
- (),
- (),
- **kwargs)
- self.expression = "%s.%s(%s)" % (namespace, defname, ",".join(["%s=%s" % (k, v) for k, v in self.parsed_attributes.iteritems() if k != 'args']))
- self.code = ast.PythonCode(self.expression, **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/lib/mako/pygen.py b/lib/mako/pygen.py
deleted file mode 100644
index 914443b..0000000
--- a/lib/mako/pygen.py
+++ /dev/null
@@ -1,267 +0,0 @@
-# pygen.py
-# Copyright (C) 2006, 2007, 2008, 2009, 2010 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/lib/mako/pyparser.py b/lib/mako/pyparser.py
deleted file mode 100644
index c79692c..0000000
--- a/lib/mako/pyparser.py
+++ /dev/null
@@ -1,371 +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.
-"""
-
-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'])
-
-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 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/lib/mako/runtime.py b/lib/mako/runtime.py
deleted file mode 100644
index a475b71..0000000
--- a/lib/mako/runtime.py
+++ /dev/null
@@ -1,419 +0,0 @@
-# runtime.py
-# Copyright (C) 2006, 2007, 2008, 2009, 2010 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 __builtin__, inspect, sys
-
-class Context(object):
- """provides runtime namespace, output buffer, and various callstacks for templates."""
- def __init__(self, buffer, **data):
- self._buffer_stack = [buffer]
- self._orig = data # original data, minus the builtins
- self._data = __builtin__.__dict__.copy() # the context data which includes builtins
- 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._orig = self._orig
- 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 not self.template.cache_enabled:
- createfunc = kwargs.get('createfunc', None)
- if createfunc:
- return createfunc()
- else:
- return None
-
- 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_callable(key)
- 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_callable(key)
- 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 AttributeError("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 _decorate_toplevel(fn):
- def decorate_render(render_fn):
- def go(context, *args, **kw):
- def y(*args, **kw):
- return render_fn(context, *args, **kw)
- try:
- y.__name__ = render_fn.__name__[7:]
- except TypeError:
- # < Python 2.4
- pass
- return fn(y)(context, *args, **kw)
- return go
- return decorate_render
-
-def _decorate_inline(context, fn):
- def decorate_render(render_fn):
- dec = fn(render_fn)
- def go(*args, **kw):
- return dec(context, *args, **kw)
- return go
- return decorate_render
-
-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._orig, **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/lib/mako/template.py b/lib/mako/template.py
deleted file mode 100644
index 4bf01e0..0000000
--- a/lib/mako/template.py
+++ /dev/null
@@ -1,392 +0,0 @@
-# template.py
-# Copyright (C) 2006, 2007, 2008, 2009, 2010 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 runtime, util, exceptions, codegen
-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,
- cache_enabled=True):
- """Construct a new Template instance using either literal template
- text, or a previously loaded template module
-
- :param text: textual template source, or None if a module is to be
- provided
-
- :param 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
-
- :param filename: filename of the source template, if any
-
- :param 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
- self.cache_enabled = cache_enabled
-
- @property
- def source(self):
- """return the template source code for this Template."""
-
- return _get_module_info_from_callable(self.callable_).source
-
- @property
- def code(self):
- """return the module source code for this Template"""
-
- return _get_module_info_from_callable(self.callable_).code
-
- @property
- def cache(self):
- return self.module._template_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 a DefTemplate."""
-
- return DefTemplate(self, getattr(self.module, "render_%s" % name))
-
- def _get_def_callable(self, name):
- return getattr(self.module, "render_%s" % name)
-
- @property
- def last_modified(self):
- return self.module._modified_time
- last_modified = property(last_modified)
-
-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,
- cache_enabled=True
- ):
- 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
- self.cache_enabled = cache_enabled
-
-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.module = parent.module
- 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
-
- @property
- def code(self):
- if self.module_source is not None:
- return self.module_source
- else:
- return file(self.module_filename).read()
-
- @property
- def 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()
-
-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)
-
- 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/lib/mako/util.py b/lib/mako/util.py
deleted file mode 100644
index 1f9f3d4..0000000
--- a/lib/mako/util.py
+++ /dev/null
@@ -1,274 +0,0 @@
-# util.py
-# Copyright (C) 2006, 2007, 2008, 2009, 2010 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, 0775)
- except:
- if tries > 5:
- raise
-
-def to_list(x, default=None):
- if x is None:
- return default
- if not isinstance(x, (list, tuple)):
- return [x]
- else:
- return x
-
-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 sorted_dict_repr(d):
- """repr() a dictionary with the keys in order.
-
- Used by the lexer unit test to compare parse trees based on strings.
-
- """
- keys = d.keys()
- keys.sort()
- return "{" + ", ".join(["%r: %r" % (k, d[k]) for k in keys]) + "}"
-
-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])