summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2014-04-28 17:33:15 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2014-04-28 17:33:15 -0400
commit12856b1297451b26468657218cc3e176b732381f (patch)
treec585b40516fb3ded666f74af2ba5f87d709a5c1e
parent70981099103828afbe33eb4d1f668dc20894b399 (diff)
downloadmako-12856b1297451b26468657218cc3e176b732381f.tar.gz
- will now be 1.0
- drop python 2.4, 2.5 support - various pep8ing
-rw-r--r--doc/build/changelog.rst23
-rw-r--r--mako/__init__.py4
-rw-r--r--mako/_ast_util.py58
-rw-r--r--mako/ast.py5
-rw-r--r--mako/codegen.py122
-rw-r--r--mako/compat.py20
-rw-r--r--mako/exceptions.py13
-rw-r--r--mako/lexer.py62
-rw-r--r--mako/pygen.py6
-rw-r--r--mako/pyparser.py653
-rw-r--r--mako/runtime.py20
-rw-r--r--setup.py5
-rw-r--r--test/__init__.py5
-rw-r--r--test/test_exceptions.py5
14 files changed, 323 insertions, 678 deletions
diff --git a/doc/build/changelog.rst b/doc/build/changelog.rst
index 279a0d5..f43b26d 100644
--- a/doc/build/changelog.rst
+++ b/doc/build/changelog.rst
@@ -2,14 +2,21 @@
Changelog
=========
-0.9
+1.0
===
.. changelog::
- :version: 0.9.2
+ :version: 1.0.0
:released:
.. change::
+ :tags: general
+
+ Compatibility changes; in order to modernize the codebase, Mako
+ is now dropping support for Python 2.4 and Python 2.5 altogether.
+ The source base is now targeted at Python 2.6 and forwards.
+
+ .. change::
:tags: bug, py3k
Fixed bug in ``decode.<encoding>`` filter where a non-string object
@@ -25,6 +32,15 @@ Changelog
.. change::
:tags: feature
+ :pullreq: bitbucket:5
+
+ mako-render is now implemented as a setuptools entrypoint script;
+ a standalone mako.cmd.cmdline() callable is now available, and the
+ system also uses argparse now instead of optparse. Pull request
+ courtesy Derek Harland.
+
+ .. change::
+ :tags: feature
:pullreq: bitbucket:4
The mako-render script will now catch exceptions and run them
@@ -51,6 +67,9 @@ Changelog
template lookup directories. Standard input for templates also works
now too. Pull request courtesy Derek Harland.
+0.9
+===
+
.. changelog::
:version: 0.9.1
:released: Thu Dec 26 2013
diff --git a/mako/__init__.py b/mako/__init__.py
index aa99505..52a1c05 100644
--- a/mako/__init__.py
+++ b/mako/__init__.py
@@ -5,5 +5,7 @@
# the MIT License: http://www.opensource.org/licenses/mit-license.php
-__version__ = '0.9.2'
+__version__ = '1.0.0'
+
+
diff --git a/mako/_ast_util.py b/mako/_ast_util.py
index 788b86a..5c274be 100644
--- a/mako/_ast_util.py
+++ b/mako/_ast_util.py
@@ -34,42 +34,42 @@ from _ast import *
from mako.compat import arg_stringname
BOOLOP_SYMBOLS = {
- And: 'and',
- Or: 'or'
+ And: 'and',
+ Or: 'or'
}
BINOP_SYMBOLS = {
- Add: '+',
- Sub: '-',
- Mult: '*',
- Div: '/',
- FloorDiv: '//',
- Mod: '%',
- LShift: '<<',
- RShift: '>>',
- BitOr: '|',
- BitAnd: '&',
- BitXor: '^'
+ 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'
+ Eq: '==',
+ Gt: '>',
+ GtE: '>=',
+ In: 'in',
+ Is: 'is',
+ IsNot: 'is not',
+ Lt: '<',
+ LtE: '<=',
+ NotEq: '!=',
+ NotIn: 'not in'
}
UNARYOP_SYMBOLS = {
- Invert: '~',
- Not: 'not',
- UAdd: '+',
- USub: '-'
+ Invert: '~',
+ Not: 'not',
+ UAdd: '+',
+ USub: '-'
}
ALL_SYMBOLS = {}
@@ -215,8 +215,8 @@ def get_compile_mode(node):
if not isinstance(node, mod):
raise TypeError('expected mod node, got %r' % node.__class__.__name__)
return {
- Expression: 'eval',
- Interactive: 'single'
+ Expression: 'eval',
+ Interactive: 'single'
}.get(node.__class__, 'expr')
diff --git a/mako/ast.py b/mako/ast.py
index 8f711b4..44355bc 100644
--- a/mako/ast.py
+++ b/mako/ast.py
@@ -8,7 +8,6 @@
code, as well as generating Python from AST nodes"""
from mako import exceptions, pyparser, compat
-from mako.compat import arg_stringname
import re
class PythonCode(object):
@@ -107,8 +106,8 @@ class FunctionDecl(object):
f.visit(expr)
if not hasattr(self, 'funcname'):
raise exceptions.CompileException(
- "Code '%s' is not a function declaration" % code,
- **exception_kwargs)
+ "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" %
diff --git a/mako/codegen.py b/mako/codegen.py
index 045d03c..2240ba2 100644
--- a/mako/codegen.py
+++ b/mako/codegen.py
@@ -187,7 +187,7 @@ class _GenerateRenderMethod(object):
# module-level names, python code
if self.compiler.generate_magic_comment and \
- self.compiler.source_encoding:
+ self.compiler.source_encoding:
self.printer.writeline("# -*- coding:%s -*-" %
self.compiler.source_encoding)
@@ -255,7 +255,7 @@ class _GenerateRenderMethod(object):
decorator = node.decorator
if decorator:
self.printer.writeline(
- "@runtime._decorate_toplevel(%s)" % decorator)
+ "@runtime._decorate_toplevel(%s)" % decorator)
self.printer.writelines(
"def %s(%s):" % (name, ','.join(args)),
@@ -267,7 +267,7 @@ class _GenerateRenderMethod(object):
self.printer.writeline("context._push_buffer()")
self.identifier_stack.append(
- self.compiler.identifiers.branch(self.node))
+ self.compiler.identifiers.branch(self.node))
if (not self.in_def or self.node.is_block) and '**pageargs' in args:
self.identifier_stack[-1].argument_declared.add('pageargs')
@@ -309,9 +309,9 @@ class _GenerateRenderMethod(object):
"def _mako_inherit(template, context):",
"_mako_generate_namespaces(context)",
"return runtime._inherit_from(context, %s, _template_uri)" %
- (node.parsed_attributes['file']),
+ (node.parsed_attributes['file']),
None
- )
+ )
def write_namespaces(self, namespaces):
"""write the module-level namespace-generating callable."""
@@ -323,7 +323,7 @@ class _GenerateRenderMethod(object):
"_mako_generate_namespaces(context)",
"return context.namespaces[(__name__, name)]",
None, None
- )
+ )
self.printer.writeline("def _mako_generate_namespaces(context):")
@@ -369,9 +369,9 @@ class _GenerateRenderMethod(object):
" templateuri=%s, callables=%s, "
" calling_uri=_template_uri)" %
(
- node.name,
- node.parsed_attributes.get('file', 'None'),
- callable_name,
+ node.name,
+ node.parsed_attributes.get('file', 'None'),
+ callable_name,
)
)
elif 'module' in node.parsed_attributes:
@@ -381,9 +381,10 @@ class _GenerateRenderMethod(object):
" callables=%s, calling_uri=_template_uri,"
" module=%s)" %
(
- node.name,
- callable_name,
- node.parsed_attributes.get('module', 'None')
+ node.name,
+ callable_name,
+ node.parsed_attributes.get(
+ 'module', 'None')
)
)
else:
@@ -400,7 +401,7 @@ class _GenerateRenderMethod(object):
self.printer.writeline("context['self'].%s = ns" % (node.name))
self.printer.writeline(
- "context.namespaces[(__name__, %s)] = ns" % repr(node.name))
+ "context.namespaces[(__name__, %s)] = ns" % repr(node.name))
self.printer.write("\n")
if not len(namespaces):
self.printer.writeline("pass")
@@ -466,7 +467,7 @@ class _GenerateRenderMethod(object):
for ident, ns in self.compiler.namespaces.items():
if 'import' in ns.attributes:
self.printer.writeline(
- "_mako_get_namespace(context, %r)."\
+ "_mako_get_namespace(context, %r)."
"_populate(_import_ns, %r)" %
(
ident,
@@ -553,7 +554,7 @@ class _GenerateRenderMethod(object):
nameargs.insert(0, 'context')
self.printer.writeline("def %s(%s):" % (funcname, ",".join(namedecls)))
self.printer.writeline(
- "return render_%s(%s)" % (funcname, ",".join(nameargs)))
+ "return render_%s(%s)" % (funcname, ",".join(nameargs)))
self.printer.writeline(None)
def write_inline_def(self, node, identifiers, nested):
@@ -564,9 +565,9 @@ class _GenerateRenderMethod(object):
decorator = node.decorator
if decorator:
self.printer.writeline(
- "@runtime._decorate_inline(context, %s)" % decorator)
+ "@runtime._decorate_inline(context, %s)" % decorator)
self.printer.writeline(
- "def %s(%s):" % (node.funcname, ",".join(namedecls)))
+ "def %s(%s):" % (node.funcname, ",".join(namedecls)))
filtered = len(node.filter_args.args) > 0
buffered = eval(node.attributes.get('buffered', 'False'))
cached = eval(node.attributes.get('cached', 'False'))
@@ -574,11 +575,11 @@ class _GenerateRenderMethod(object):
# push new frame, assign current frame to __M_caller
"__M_caller = context.caller_stack._push_frame()",
"try:"
- )
+ )
if buffered or filtered or cached:
self.printer.writelines(
"context._push_buffer()",
- )
+ )
identifiers = identifiers.branch(node, nested=nested)
@@ -627,8 +628,8 @@ class _GenerateRenderMethod(object):
)
else:
self.printer.writelines(
- "finally:",
- "__M_buf, __M_writer = context._pop_buffer_and_writer()"
+ "finally:",
+ "__M_buf, __M_writer = context._pop_buffer_and_writer()"
)
if callstack:
@@ -684,7 +685,7 @@ class _GenerateRenderMethod(object):
# form "arg1, arg2, arg3=arg3, arg4=arg4", etc.
pass_args = [
- '=' in a and "%s=%s" % ((a.split('=')[0],)*2) or a
+ "%s=%s" % ((a.split('=')[0],) * 2) if '=' in a else a
for a in args
]
@@ -696,11 +697,11 @@ class _GenerateRenderMethod(object):
if buffered:
s = "context.get('local')."\
"cache._ctx_get_or_create("\
- "%s, lambda:__M_%s(%s), context, %s__M_defname=%r)" % \
- (cachekey, name, ','.join(pass_args),
- ''.join(["%s=%s, " % (k, v)
- for k, v in cache_args.items()]),
- name
+ "%s, lambda:__M_%s(%s), context, %s__M_defname=%r)" % (
+ cachekey, name, ','.join(pass_args),
+ ''.join(["%s=%s, " % (k, v)
+ for k, v in cache_args.items()]),
+ name
)
# apply buffer_filters
s = self.create_filter_callable(self.compiler.buffer_filters, s,
@@ -709,12 +710,13 @@ class _GenerateRenderMethod(object):
else:
self.printer.writelines(
"__M_writer(context.get('local')."
- "cache._ctx_get_or_create("\
+ "cache._ctx_get_or_create("
"%s, lambda:__M_%s(%s), context, %s__M_defname=%r))" %
- (cachekey, name, ','.join(pass_args),
- ''.join(["%s=%s, " % (k, v)
+ (
+ cachekey, name, ','.join(pass_args),
+ ''.join(["%s=%s, " % (k, v)
for k, v in cache_args.items()]),
- name,
+ name,
),
"return ''",
None
@@ -745,11 +747,10 @@ class _GenerateRenderMethod(object):
continue
m = re.match(r'(.+?)(\(.*\))', e)
if m:
- (ident, fargs) = m.group(1,2)
+ 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)
@@ -822,7 +823,7 @@ class _GenerateRenderMethod(object):
"__M_buf.getvalue()",
False),
None
- )
+ )
def visitCode(self, node):
if not node.ismodule:
@@ -835,20 +836,20 @@ class _GenerateRenderMethod(object):
# which is used for def calls within the same template,
# to simulate "enclosing scope"
self.printer.writeline(
- '__M_locals_builtin_stored = __M_locals_builtin()')
+ '__M_locals_builtin_stored = __M_locals_builtin()')
self.printer.writeline(
- '__M_locals.update(__M_dict_builtin([(__M_key,'
- ' __M_locals_builtin_stored[__M_key]) for __M_key in'
- ' [%s] if __M_key in __M_locals_builtin_stored]))' %
- ','.join([repr(x) for x in node.declared_identifiers()]))
+ '__M_locals.update(__M_dict_builtin([(__M_key,'
+ ' __M_locals_builtin_stored[__M_key]) for __M_key in'
+ ' [%s] if __M_key in __M_locals_builtin_stored]))' %
+ ','.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))
+ "runtime._include_file(context, %s, _template_uri, %s)" %
+ (node.parsed_attributes['file'], args))
else:
self.printer.writeline(
"runtime._include_file(context, %s, _template_uri)" %
@@ -941,7 +942,7 @@ class _GenerateRenderMethod(object):
# push on caller for nested call
"context.caller_stack.nextcaller = "
"runtime.Namespace('caller', context, "
- "callables=ccall(__M_caller))",
+ "callables=ccall(__M_caller))",
"try:")
self.write_source_comment(node)
self.printer.writelines(
@@ -966,9 +967,9 @@ class _Identifiers(object):
# things that have already been declared
# in an enclosing namespace (i.e. names we can just use)
self.declared = set(parent.declared).\
- union([c.name for c in parent.closuredefs.values()]).\
- union(parent.locally_declared).\
- union(parent.argument_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
@@ -1012,7 +1013,7 @@ class _Identifiers(object):
node.accept_visitor(self)
illegal_names = self.compiler.reserved_names.intersection(
- self.locally_declared)
+ self.locally_declared)
if illegal_names:
raise exceptions.NameConflictError(
"Reserved words declared in template: %s" %
@@ -1047,7 +1048,7 @@ class _Identifiers(object):
for ident in node.undeclared_identifiers():
if ident != 'context' and\
- ident not in self.declared.union(self.locally_declared):
+ ident not in self.declared.union(self.locally_declared):
self.undeclared.add(ident)
for ident in node.declared_identifiers():
self.locally_declared.add(ident)
@@ -1067,7 +1068,7 @@ class _Identifiers(object):
if not node.ismodule:
self.check_declared(node)
self.locally_assigned = self.locally_assigned.union(
- node.declared_identifiers())
+ node.declared_identifiers())
def visitNamespaceTag(self, node):
# only traverse into the sub-elements of a
@@ -1095,8 +1096,8 @@ class _Identifiers(object):
self._check_name_exists(self.closuredefs, node)
for ident in node.undeclared_identifiers():
- if ident != 'context' and\
- ident not in self.declared.union(self.locally_declared):
+ if ident != 'context' and \
+ ident not in self.declared.union(self.locally_declared):
self.undeclared.add(ident)
# visit defs only one level deep
@@ -1108,8 +1109,7 @@ class _Identifiers(object):
n.accept_visitor(self)
def visitBlockTag(self, node):
- if node is not self.node and \
- not node.is_anonymous:
+ if node is not self.node and not node.is_anonymous:
if isinstance(self.node, parsetree.DefTag):
raise exceptions.CompileException(
@@ -1123,7 +1123,7 @@ class _Identifiers(object):
for ident in node.undeclared_identifiers():
if ident != 'context' and \
- ident not in self.declared.union(self.locally_declared):
+ ident not in self.declared.union(self.locally_declared):
self.undeclared.add(ident)
if not node.is_anonymous:
@@ -1139,7 +1139,7 @@ class _Identifiers(object):
def visitTextTag(self, node):
for ident in node.undeclared_identifiers():
if ident != 'context' and \
- ident not in self.declared.union(self.locally_declared):
+ ident not in self.declared.union(self.locally_declared):
self.undeclared.add(ident)
def visitIncludeTag(self, node):
@@ -1156,8 +1156,9 @@ class _Identifiers(object):
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):
+ 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)
@@ -1165,15 +1166,16 @@ class _Identifiers(object):
n.accept_visitor(self)
else:
for ident in node.undeclared_identifiers():
- if ident != 'context' and\
- ident not in self.declared.union(self.locally_declared):
+ if ident != 'context' and \
+ ident not in self.declared.union(
+ self.locally_declared):
self.undeclared.add(ident)
_FOR_LOOP = re.compile(
r'^for\s+((?:\(?)\s*[A-Za-z_][A-Za-z_0-9]*'
r'(?:\s*,\s*(?:[A-Za-z_][A-Za-z0-9_]*),??)*\s*(?:\)?))\s+in\s+(.*):'
- )
+)
def mangle_mako_loop(node, printer):
"""converts a for loop into a context manager wrapped around a for loop
@@ -1189,7 +1191,7 @@ def mangle_mako_loop(node, printer):
'loop = __M_loop._enter(%s)' % match.group(2),
'try:'
#'with __M_loop(%s) as loop:' % match.group(2)
- )
+ )
text = 'for %s in loop:' % match.group(1)
else:
raise SyntaxError("Couldn't apply loop context: %s" % node.text)
diff --git a/mako/compat.py b/mako/compat.py
index 82b6c05..f782aa9 100644
--- a/mako/compat.py
+++ b/mako/compat.py
@@ -5,7 +5,6 @@ py3k = sys.version_info >= (3, 0)
py33 = sys.version_info >= (3, 3)
py2k = sys.version_info < (3,)
py26 = sys.version_info >= (2, 6)
-py25 = sys.version_info >= (2, 5)
jython = sys.platform.startswith('java')
win32 = sys.platform.startswith('win')
pypy = hasattr(sys, 'pypy_version_info')
@@ -100,23 +99,10 @@ except:
return func(*(args + fargs), **newkeywords)
return newfunc
-if not py25:
- def all(iterable):
- for i in iterable:
- if not i:
- return False
- return True
+all = all
- def exception_name(exc):
- try:
- return exc.__class__.__name__
- except AttributeError:
- return exc.__name__
-else:
- all = all
-
- def exception_name(exc):
- return exc.__class__.__name__
+def exception_name(exc):
+ return exc.__class__.__name__
try:
from inspect import CO_VARKEYWORDS, CO_VARARGS
diff --git a/mako/exceptions.py b/mako/exceptions.py
index b8f97ee..a7bab8c 100644
--- a/mako/exceptions.py
+++ b/mako/exceptions.py
@@ -28,7 +28,7 @@ class CompileException(MakoException):
def __init__(self, message, source, lineno, pos, filename):
MakoException.__init__(self,
message + _format_filepos(lineno, pos, filename))
- self.lineno =lineno
+ self.lineno = lineno
self.pos = pos
self.filename = filename
self.source = source
@@ -37,7 +37,7 @@ class SyntaxException(MakoException):
def __init__(self, message, source, lineno, pos, filename):
MakoException.__init__(self,
message + _format_filepos(lineno, pos, filename))
- self.lineno =lineno
+ self.lineno = lineno
self.pos = pos
self.filename = filename
self.source = source
@@ -260,10 +260,11 @@ def html_error_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.
+ 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
diff --git a/mako/lexer.py b/mako/lexer.py
index dca88e1..dd46b10 100644
--- a/mako/lexer.py
+++ b/mako/lexer.py
@@ -44,10 +44,10 @@ class Lexer(object):
@property
def exception_kwargs(self):
- return {'source':self.text,
- 'lineno':self.matched_lineno,
- 'pos':self.matched_charpos,
- 'filename':self.filename}
+ return {'source': self.text,
+ 'lineno': self.matched_lineno,
+ 'pos': self.matched_charpos,
+ 'filename': self.filename}
def match(self, regexp, flags=None):
"""compile the given regexp, cache the reg, and call match_reg()."""
@@ -83,8 +83,8 @@ class Lexer(object):
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
+ 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:",
@@ -111,8 +111,8 @@ class Lexer(object):
brace_level -= 1
continue
return \
- self.text[startpos:\
- self.match_position-len(match.group(1))],\
+ self.text[startpos:
+ self.match_position - len(match.group(1))],\
match.group(1)
match = self.match(r"(.*?)(?=\"|\'|#|%s)" % text_re, re.S)
if match:
@@ -162,9 +162,9 @@ class Lexer(object):
elif 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)
+ "Keyword '%s' not a legal ternary for keyword '%s'" %
+ (node.keyword, self.control_line[-1].keyword),
+ **self.exception_kwargs)
_coding_re = re.compile(r'#.*coding[:=]\s*([-\w.]+).*\r?\n')
@@ -201,10 +201,10 @@ class Lexer(object):
text = text.decode(parsed_encoding)
except UnicodeDecodeError:
raise exceptions.CompileException(
- "Unicode decode operation of encoding '%s' failed" %
- parsed_encoding,
- text.decode('utf-8', 'ignore'),
- 0, 0, filename)
+ "Unicode decode operation of encoding '%s' failed" %
+ parsed_encoding,
+ text.decode('utf-8', 'ignore'),
+ 0, 0, filename)
return parsed_encoding, text
@@ -254,11 +254,11 @@ class Lexer(object):
**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)
+ "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_tag_start(self):
@@ -311,14 +311,14 @@ class Lexer(object):
if match:
if not len(self.tag):
raise exceptions.SyntaxException(
- "Closing tag without opening tag: </%%%s>" %
- match.group(1),
- **self.exception_kwargs)
+ "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)
+ "Closing tag </%%%s> does not match tag: <%%%s>" %
+ (match.group(1), self.tag[-1].keyword),
+ **self.exception_kwargs)
self.tag.pop()
return True
else:
@@ -370,9 +370,9 @@ class Lexer(object):
# compiler.parse() not complain about indentation
text = adjust_whitespace(text) + "\n"
self.append_node(
- parsetree.Code,
- text,
- match.group(1)=='!', lineno=line, pos=pos)
+ parsetree.Code,
+ text,
+ match.group(1) == '!', lineno=line, pos=pos)
return True
else:
return False
@@ -397,8 +397,8 @@ class Lexer(object):
def match_control_line(self):
match = self.match(
- r"(?<=^)[\t ]*(%(?!%)|##)[\t ]*((?:(?:\\r?\n)|[^\r\n])*)"
- r"(?:\r?\n|\Z)", re.M)
+ r"(?<=^)[\t ]*(%(?!%)|##)[\t ]*((?:(?:\\r?\n)|[^\r\n])*)"
+ r"(?:\r?\n|\Z)", re.M)
if match:
operator = match.group(1)
text = match.group(2)
diff --git a/mako/pygen.py b/mako/pygen.py
index cba9464..52e32be 100644
--- a/mako/pygen.py
+++ b/mako/pygen.py
@@ -80,7 +80,7 @@ class PythonPrinter(object):
):
if self.indent > 0:
- self.indent -=1
+ self.indent -= 1
# if the indent_detail stack is empty, the user
# probably put extra closures - the resulting
# module wont compile.
@@ -108,7 +108,7 @@ class PythonPrinter(object):
if match:
# its a "compound" keyword, so we will check for "unindentors"
indentor = match.group(1)
- self.indent +=1
+ self.indent += 1
self.indent_detail.append(indentor)
else:
indentor = None
@@ -265,7 +265,7 @@ def adjust_whitespace(text):
return start_state
- def _indent_line(line, stripspace = ''):
+ def _indent_line(line, stripspace=''):
return re.sub(r"^%s" % stripspace, '', line)
lines = []
diff --git a/mako/pyparser.py b/mako/pyparser.py
index db5c295..e1edc5b 100644
--- a/mako/pyparser.py
+++ b/mako/pyparser.py
@@ -11,7 +11,7 @@ module is used.
"""
from mako import exceptions, util, compat
-from mako.compat import StringIO, arg_stringname
+from mako.compat import arg_stringname
import operator
if compat.py3k:
@@ -29,29 +29,16 @@ else:
# the "id" attribute on a function node
arg_id = operator.attrgetter('id')
-
-try:
- import _ast
- util.restore__ast(_ast)
- from mako import _ast_util
-except ImportError:
- _ast = None
- from compiler import parse as compiler_parse
- from compiler import visitor
-
+import _ast
+util.restore__ast(_ast)
+from mako import _ast_util
def parse(code, mode='exec', **exception_kwargs):
"""Parse an expression into AST"""
-
try:
- if _ast:
- return _ast_util.parse(code, '<unknown>', mode)
- else:
- if isinstance(code, compat.text_type):
- code = code.encode('ascii', 'backslashreplace')
- return compiler_parse(code, mode)
+ return _ast_util.parse(code, '<unknown>', mode)
except Exception:
raise exceptions.SyntaxException(
"(%s) %s (%r)" % (
@@ -61,529 +48,185 @@ def parse(code, mode='exec', **exception_kwargs):
), **exception_kwargs)
-if _ast:
- class FindIdentifiers(_ast_util.NodeVisitor):
+class FindIdentifiers(_ast_util.NodeVisitor):
- def __init__(self, listener, **exception_kwargs):
- self.in_function = False
- self.in_assign_targets = False
- self.local_ident_stack = set()
- self.listener = listener
- self.exception_kwargs = exception_kwargs
+ def __init__(self, listener, **exception_kwargs):
+ self.in_function = False
+ self.in_assign_targets = False
+ self.local_ident_stack = set()
+ self.listener = listener
+ self.exception_kwargs = exception_kwargs
- def _add_declared(self, name):
- if not self.in_function:
- self.listener.declared_identifiers.add(name)
- else:
- self.local_ident_stack.add(name)
+ def _add_declared(self, name):
+ if not self.in_function:
+ self.listener.declared_identifiers.add(name)
+ else:
+ self.local_ident_stack.add(name)
- def visit_ClassDef(self, node):
- self._add_declared(node.name)
+ def visit_ClassDef(self, node):
+ self._add_declared(node.name)
- def visit_Assign(self, node):
+ 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)
+ # 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
-
- if compat.py3k:
-
- # ExceptHandler is in Python 2, but this block only works in
- # Python 3 (and is required there)
-
- def visit_ExceptHandler(self, node):
- if node.name is not None:
- self._add_declared(node.name)
- if node.type is not None:
- self.visit(node.type)
- for statement in node.body:
- self.visit(statement)
-
- def visit_Lambda(self, node, *args):
- self._visit_function(node, True)
-
- def visit_FunctionDef(self, node):
- self._add_declared(node.name)
- self._visit_function(node, False)
-
- def _expand_tuples(self, args):
- for arg in args:
- if isinstance(arg, _ast.Tuple):
- for n in arg.elts:
- yield n
- else:
- yield arg
-
- def _visit_function(self, node, islambda):
-
- # 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"
-
- inf = self.in_function
- self.in_function = True
-
- local_ident_stack = self.local_ident_stack
- self.local_ident_stack = local_ident_stack.union([
- arg_id(arg) for arg in self._expand_tuples(node.args.args)
- ])
- if islambda:
- self.visit(node.body)
- else:
- for n in node.body:
- self.visit(n)
- self.in_function = inf
- self.local_ident_stack = local_ident_stack
+ 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_For(self, node):
+ if compat.py3k:
- # flip around visit
+ # ExceptHandler is in Python 2, but this block only works in
+ # Python 3 (and is required there)
- self.visit(node.iter)
- self.visit(node.target)
+ def visit_ExceptHandler(self, node):
+ if node.name is not None:
+ self._add_declared(node.name)
+ if node.type is not None:
+ self.visit(node.type)
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):
- # this is eqiuvalent to visit_AssName in
- # compiler
- self._add_declared(node.id)
- elif 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(arg) for arg in node.args.args]
- if node.args.vararg:
- argnames.append(arg_stringname(node.args.vararg))
-
- if compat.py2k:
- # kw-only args don't exist in Python 2
- kwargnames = []
- else:
- kwargnames = [arg_id(arg) for arg in node.args.kwonlyargs]
- if node.args.kwarg:
- kwargnames.append(arg_stringname(node.args.kwarg))
- self.listener.argnames = argnames
- self.listener.defaults = node.args.defaults # ast
- self.listener.kwargnames = kwargnames
- if compat.py2k:
- self.listener.kwdefaults = []
- else:
- self.listener.kwdefaults = node.args.kw_defaults
- self.listener.varargs = node.args.vararg
- self.listener.kwargs = node.args.kwarg
+ def visit_Lambda(self, node, *args):
+ self._visit_function(node, True)
- 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 visit_FunctionDef(self, node):
+ self._add_declared(node.name)
+ self._visit_function(node, False)
- def __init__(self, listener, **exception_kwargs):
- self.in_function = False
- self.local_ident_stack = set()
- 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 _expand_tuples(self, args):
+ for arg in args:
+ if isinstance(arg, _ast.Tuple):
+ for n in arg.elts:
+ yield n
else:
- self.local_ident_stack.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 visitLambda(self, node, *args):
- self._visit_function(node, args)
-
- def visitFunction(self, node, *args):
- self._add_declared(node.name)
- self._visit_function(node, args)
+ yield arg
- def _expand_tuples(self, args):
- for arg in args:
- if isinstance(arg, tuple):
- for n in arg:
- yield n
- else:
- yield arg
+ def _visit_function(self, node, islambda):
- def _visit_function(self, node, args):
+ # 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"
- # 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"
+ inf = self.in_function
+ self.in_function = True
- inf = self.in_function
- self.in_function = True
-
- local_ident_stack = self.local_ident_stack
- self.local_ident_stack = local_ident_stack.union([
- arg for arg in self._expand_tuples(node.argnames)
- ])
-
- for n in node.getChildNodes():
- self.visit(n, *args)
- self.in_function = inf
- self.local_ident_stack = local_ident_stack
-
- def visitFor(self, node, *args):
-
- # flip around visit
+ local_ident_stack = self.local_ident_stack
+ self.local_ident_stack = local_ident_stack.union([
+ arg_id(arg) for arg in self._expand_tuples(node.args.args)
+ ])
+ if islambda:
+ self.visit(node.body)
+ else:
+ for n in node.body:
+ self.visit(n)
+ self.in_function = inf
+ self.local_ident_stack = local_ident_stack
+
+ 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):
+ # this is eqiuvalent to visit_AssName in
+ # compiler
+ self._add_declared(node.id)
+ elif 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)
- self.visit(node.list, *args)
- self.visit(node.assign, *args)
- self.visit(node.body, *args)
+ 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 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(
+ 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(mod)
+ self._add_declared(name.name)
- def visit(self, expr):
- visitor.walk(expr, self) # , walker=walker())
+class FindTuple(_ast_util.NodeVisitor):
- 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 __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)
- 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(_ast_util.NodeVisitor):
+ def __init__(self, listener, **exception_kwargs):
+ self.listener = listener
+ self.exception_kwargs = exception_kwargs
- class ParseFunc(object):
+ def visit_FunctionDef(self, node):
+ self.listener.funcname = node.name
- def __init__(self, listener, **exception_kwargs):
- self.listener = listener
- self.exception_kwargs = exception_kwargs
+ argnames = [arg_id(arg) for arg in node.args.args]
+ if node.args.vararg:
+ argnames.append(arg_stringname(node.args.vararg))
- def visitFunction(self, node, *args):
- self.listener.funcname = node.name
- self.listener.argnames = list(node.argnames)
- if node.kwargs:
- self.listener.kwargnames = [self.listener.argnames.pop()]
- else:
- self.listener.kwargnames = []
- self.listener.defaults = node.defaults
+ if compat.py2k:
+ # kw-only args don't exist in Python 2
+ kwargnames = []
+ else:
+ kwargnames = [arg_id(arg) for arg in node.args.kwonlyargs]
+ if node.args.kwarg:
+ kwargnames.append(arg_stringname(node.args.kwarg))
+ self.listener.argnames = argnames
+ self.listener.defaults = node.args.defaults # ast
+ self.listener.kwargnames = kwargnames
+ if compat.py2k:
self.listener.kwdefaults = []
- 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(')')
-
- def visitLambda(self, node, *args):
- self.buf.write('lambda ')
-
- argnames = list(node.argnames)
-
- kw = arg = None
- if node.kwargs > 0:
- kw = argnames.pop(-1)
- if node.varargs > 0:
- arg = argnames.pop(-1)
-
- if arg:
- argnames.append("*%s" % arg)
- if kw:
- argnames.append("**%s" % kw)
-
- self.buf.write(", ".join(argnames))
-
- self.buf.write(': ')
- self.visit(node.code)
-
-
- class walker(visitor.ASTVisitor):
+ else:
+ self.listener.kwdefaults = node.args.kw_defaults
+ self.listener.varargs = node.args.vararg
+ self.listener.kwargs = node.args.kwarg
- def dispatch(self, node, *args):
- print('Node:', str(node))
+class ExpressionGenerator(object):
- # print "dir:", dir(node)
+ def __init__(self, astnode):
+ self.generator = _ast_util.SourceGenerator(' ' * 4)
+ self.generator.visit(astnode)
- return visitor.ASTVisitor.dispatch(self, node, *args)
+ def value(self):
+ return ''.join(self.generator.result)
diff --git a/mako/runtime.py b/mako/runtime.py
index 5a3489b..d7b9681 100644
--- a/mako/runtime.py
+++ b/mako/runtime.py
@@ -9,9 +9,7 @@ Namespace, and various helper functions."""
from mako import exceptions, util, compat
from mako.compat import compat_builtins
-import inspect
import sys
-import collections
class Context(object):
@@ -132,9 +130,7 @@ class Context(object):
def get(self, key, default=None):
"""Return a value from this :class:`.Context`."""
- return self._data.get(key,
- compat_builtins.__dict__.get(key, default)
- )
+ return self._data.get(key, compat_builtins.__dict__.get(key, default))
def write(self, string):
"""Write a string to this :class:`.Context` object's
@@ -474,8 +470,8 @@ class Namespace(object):
def get_template(self, uri):
"""Return a :class:`.Template` from the given ``uri``.
- The ``uri`` resolution is relative to the ``uri`` of this :class:`.Namespace`
- object's :class:`.Template`.
+ The ``uri`` resolution is relative to the ``uri`` of this
+ :class:`.Namespace` object's :class:`.Template`.
"""
return _lookup_template(self.context, uri, self._templateuri)
@@ -673,7 +669,7 @@ def supports_caller(func):
"""
- def wrap_stackframe(context, *args, **kwargs):
+ def wrap_stackframe(context, *args, **kwargs):
context.caller_stack._push_frame()
try:
return func(context, *args, **kwargs)
@@ -691,8 +687,8 @@ def capture(context, callable_, *args, **kwargs):
if not compat.callable(callable_):
raise exceptions.RuntimeException(
- "capture() function expects a callable as "
- "its argument (i.e. capture(func, *args, **kwargs))"
+ "capture() function expects a callable as "
+ "its argument (i.e. capture(func, *args, **kwargs))"
)
context._push_buffer()
try:
@@ -853,7 +849,6 @@ def _exec_template(callable_, context, args=None, kwargs=None):
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:
@@ -872,7 +867,8 @@ def _render_error(template, context, error):
else:
error_template = exceptions.html_error_template()
if context._outputting_as_unicode:
- context._buffer_stack[:] = [util.FastEncodingBuffer(as_unicode=True)]
+ context._buffer_stack[:] = [
+ util.FastEncodingBuffer(as_unicode=True)]
else:
context._buffer_stack[:] = [util.FastEncodingBuffer(
error_template.output_encoding,
diff --git a/setup.py b/setup.py
index 91b5769..bbab08e 100644
--- a/setup.py
+++ b/setup.py
@@ -9,6 +9,9 @@ v.close()
readme = open(os.path.join(os.path.dirname(__file__), 'README.rst')).read()
+if sys.version_info < (2, 6):
+ raise Exception("Mako requires Python 2.6 or higher.")
+
markupsafe_installs = (
sys.version_info >= (2, 6) and sys.version_info < (3, 0)
) or sys.version_info >= (3, 3)
@@ -48,7 +51,7 @@ setup(name='Mako',
test_suite="nose.collector",
zip_safe=False,
install_requires=install_requires,
- extras_require={'beaker': ['Beaker>=1.1']},
+ extras_require={},
entry_points="""
[python.templating.engines]
mako = mako.ext.turbogears:TGPlugin
diff --git a/test/__init__.py b/test/__init__.py
index 91ff54e..cf5f36a 100644
--- a/test/__init__.py
+++ b/test/__init__.py
@@ -1,7 +1,7 @@
from mako.template import Template
import unittest
import os
-from mako.compat import py3k, py26, py25
+from mako.compat import py3k, py26
from mako import compat
from mako.util import update_wrapper
import re
@@ -111,9 +111,6 @@ def requires_python_2(fn):
def requires_python_26_or_greater(fn):
return skip_if(lambda: not py26, "Requires Python 2.6 or greater")(fn)
-def requires_python_25_or_greater(fn):
- return skip_if(lambda: not py25, "Requires Python 2.5 or greater")(fn)
-
def requires_pygments_14(fn):
try:
import pygments
diff --git a/test/test_exceptions.py b/test/test_exceptions.py
index 5160f8e..3330a1f 100644
--- a/test/test_exceptions.py
+++ b/test/test_exceptions.py
@@ -7,8 +7,7 @@ from mako.lookup import TemplateLookup
from mako.compat import u
from test.util import result_lines
from test import TemplateTest
-from test import requires_pygments_14, requires_no_pygments_exceptions, \
- requires_python_25_or_greater
+from test import requires_pygments_14, requires_no_pygments_exceptions
class ExceptionsTest(TemplateTest):
def test_html_error_template(self):
@@ -156,7 +155,6 @@ ${u'привет'}
html_error = exceptions.html_error_template().render()
assert "RuntimeError: test" in str(html_error)
- @requires_python_25_or_greater
def test_py_utf8_html_error_template(self):
try:
foo = u('日本')
@@ -264,7 +262,6 @@ ${foobar}
result_lines(l.get_template("foo.html").render().decode('utf-8'))
- @requires_python_25_or_greater
def test_custom_tback(self):
try:
raise RuntimeError("error 1")