Updated jinja version

This commit is contained in:
hbristow
2013-06-18 17:27:09 +10:00
parent 2059972bf7
commit 304fd03e64
21 changed files with 1031 additions and 467 deletions

View File

@@ -8,14 +8,16 @@
:copyright: (c) 2010 by the Jinja Team.
:license: BSD, see LICENSE for more details.
"""
from cStringIO import StringIO
from itertools import chain
from copy import deepcopy
from keyword import iskeyword as is_python_keyword
from jinja2 import nodes
from jinja2.nodes import EvalContext
from jinja2.visitor import NodeVisitor
from jinja2.exceptions import TemplateAssertionError
from jinja2.utils import Markup, concat, escape, is_python_keyword, next
from jinja2.utils import Markup, concat, escape
from jinja2._compat import range_type, text_type, string_types, \
iteritems, NativeStringIO, imap
operators = {
@@ -29,14 +31,6 @@ operators = {
'notin': 'not in'
}
try:
exec '(0 if 0 else 0)'
except SyntaxError:
have_condexpr = False
else:
have_condexpr = True
# what method to iterate over items do we want to use for dict iteration
# in generated code? on 2.x let's go with iteritems, on 3.x with items
if hasattr(dict, 'iteritems'):
@@ -51,7 +45,11 @@ def unoptimize_before_dead_code():
def f():
if 0: dummy(x)
return f
unoptimize_before_dead_code = bool(unoptimize_before_dead_code().func_closure)
# The getattr is necessary for pypy which does not set this attribute if
# no closure is on the function
unoptimize_before_dead_code = bool(
getattr(unoptimize_before_dead_code(), '__closure__', None))
def generate(node, environment, name, filename, stream=None,
@@ -69,8 +67,8 @@ def has_safe_repr(value):
"""Does the node have a safe representation?"""
if value is None or value is NotImplemented or value is Ellipsis:
return True
if isinstance(value, (bool, int, long, float, complex, basestring,
xrange, Markup)):
if isinstance(value, (bool, int, float, complex, range_type,
Markup) + string_types):
return True
if isinstance(value, (tuple, list, set, frozenset)):
for item in value:
@@ -78,7 +76,7 @@ def has_safe_repr(value):
return False
return True
elif isinstance(value, dict):
for key, value in value.iteritems():
for key, value in iteritems(value):
if not has_safe_repr(key):
return False
if not has_safe_repr(value):
@@ -368,7 +366,7 @@ class CodeGenerator(NodeVisitor):
def __init__(self, environment, name, filename, stream=None,
defer_init=False):
if stream is None:
stream = StringIO()
stream = NativeStringIO()
self.environment = environment
self.name = name
self.filename = filename
@@ -542,7 +540,7 @@ class CodeGenerator(NodeVisitor):
self.write(', ')
self.visit(kwarg, frame)
if extra_kwargs is not None:
for key, value in extra_kwargs.iteritems():
for key, value in iteritems(extra_kwargs):
self.write(', %s=%s' % (key, value))
if node.dyn_args:
self.write(', *')
@@ -558,7 +556,7 @@ class CodeGenerator(NodeVisitor):
self.visit(kwarg.value, frame)
self.write(', ')
if extra_kwargs is not None:
for key, value in extra_kwargs.iteritems():
for key, value in iteritems(extra_kwargs):
self.write('%r: %s, ' % (key, value))
if node.dyn_kwargs is not None:
self.write('}, **')
@@ -625,7 +623,7 @@ class CodeGenerator(NodeVisitor):
def pop_scope(self, aliases, frame):
"""Restore all aliases and delete unused variables."""
for name, alias in aliases.iteritems():
for name, alias in iteritems(aliases):
self.writeline('l_%s = %s' % (name, alias))
to_delete = set()
for name in frame.identifiers.declared_locally:
@@ -663,16 +661,16 @@ class CodeGenerator(NodeVisitor):
# it without aliasing all the variables.
# this could be fixed in Python 3 where we have the nonlocal
# keyword or if we switch to bytecode generation
overriden_closure_vars = (
overridden_closure_vars = (
func_frame.identifiers.undeclared &
func_frame.identifiers.declared &
(func_frame.identifiers.declared_locally |
func_frame.identifiers.declared_parameter)
)
if overriden_closure_vars:
if overridden_closure_vars:
self.fail('It\'s not possible to set and access variables '
'derived from an outer scope! (affects: %s)' %
', '.join(sorted(overriden_closure_vars)), node.lineno)
', '.join(sorted(overridden_closure_vars)), node.lineno)
# remove variables from a closure from the frame's undeclared
# identifiers.
@@ -827,7 +825,7 @@ class CodeGenerator(NodeVisitor):
self.outdent(2 + (not self.has_known_extends))
# at this point we now have the blocks collected and can visit them too.
for name, block in self.blocks.iteritems():
for name, block in iteritems(self.blocks):
block_frame = Frame(eval_ctx)
block_frame.inspect(block.body)
block_frame.block = name
@@ -894,12 +892,13 @@ class CodeGenerator(NodeVisitor):
self.indent()
self.writeline('raise TemplateRuntimeError(%r)' %
'extended multiple times')
self.outdent()
# if we have a known extends already we don't need that code here
# as we know that the template execution will end here.
if self.has_known_extends:
raise CompilerExit()
else:
self.outdent()
self.writeline('parent_template = environment.get_template(', node)
self.visit(node.template, frame)
@@ -930,7 +929,7 @@ class CodeGenerator(NodeVisitor):
func_name = 'get_or_select_template'
if isinstance(node.template, nodes.Const):
if isinstance(node.template.value, basestring):
if isinstance(node.template.value, string_types):
func_name = 'get_template'
elif isinstance(node.template.value, (tuple, list)):
func_name = 'select_template'
@@ -950,9 +949,16 @@ class CodeGenerator(NodeVisitor):
self.indent()
if node.with_context:
self.writeline('include_context = template.new_context('
'context.parent, True, locals())')
self.writeline('for name, context_blocks in context.'
'blocks.%s():' % dict_item_iter)
self.indent()
self.writeline('include_context.blocks.setdefault('
'name, [])[0:0] = context_blocks')
self.outdent()
self.writeline('for event in template.root_render_func('
'template.new_context(context.parent, True, '
'locals())):')
'include_context):')
else:
self.writeline('for event in template.module._body_stream:')
@@ -1032,7 +1038,7 @@ class CodeGenerator(NodeVisitor):
discarded_names[0])
else:
self.writeline('context.exported_vars.difference_'
'update((%s))' % ', '.join(map(repr, discarded_names)))
'update((%s))' % ', '.join(imap(repr, discarded_names)))
def visit_For(self, node, frame):
# when calculating the nodes for the inner frame we have to exclude
@@ -1060,7 +1066,7 @@ class CodeGenerator(NodeVisitor):
# otherwise we set up a buffer and add a function def
else:
self.writeline('def loop(reciter, loop_render_func):', node)
self.writeline('def loop(reciter, loop_render_func, depth=0):', node)
self.indent()
self.buffer(loop_frame)
aliases = {}
@@ -1068,6 +1074,7 @@ class CodeGenerator(NodeVisitor):
# make sure the loop variable is a special one and raise a template
# assertion error if a loop tries to write to loop
if extended_loop:
self.writeline('l_loop = missing')
loop_frame.identifiers.add_special('loop')
for name in node.find_all(nodes.Name):
if name.ctx == 'store' and name.name == 'loop':
@@ -1118,7 +1125,7 @@ class CodeGenerator(NodeVisitor):
self.visit(node.iter, loop_frame)
if node.recursive:
self.write(', recurse=loop_render_func):')
self.write(', loop_render_func, depth):')
else:
self.write(extended_loop and '):' or ':')
@@ -1216,9 +1223,9 @@ class CodeGenerator(NodeVisitor):
return
if self.environment.finalize:
finalize = lambda x: unicode(self.environment.finalize(x))
finalize = lambda x: text_type(self.environment.finalize(x))
else:
finalize = unicode
finalize = text_type
# if we are inside a frame that requires output checking, we do so
outdent_later = False
@@ -1367,7 +1374,7 @@ class CodeGenerator(NodeVisitor):
public_names[0])
else:
self.writeline('context.exported_vars.update((%s))' %
', '.join(map(repr, public_names)))
', '.join(imap(repr, public_names)))
# -- Expression Visitors
@@ -1555,22 +1562,13 @@ class CodeGenerator(NodeVisitor):
'expression on %s evaluated to false and '
'no else section was defined.' % self.position(node)))
if not have_condexpr:
self.write('((')
self.visit(node.test, frame)
self.write(') and (')
self.visit(node.expr1, frame)
self.write(',) or (')
write_expr2()
self.write(',))[0]')
else:
self.write('(')
self.visit(node.expr1, frame)
self.write(' if ')
self.visit(node.test, frame)
self.write(' else ')
write_expr2()
self.write(')')
self.write('(')
self.visit(node.expr1, frame)
self.write(' if ')
self.visit(node.test, frame)
self.write(' else ')
write_expr2()
self.write(')')
def visit_Call(self, node, frame, forward_caller=False):
if self.environment.sandboxed: