Index: third_party/jinja2/compiler.py |
diff --git a/third_party/jinja2/compiler.py b/third_party/jinja2/compiler.py |
index b21cb3865db61c08c321117b8cf6c8a08fa44f15..75a60b8d2d6b326d6248b64a0b74538316d4f82c 100644 |
--- a/third_party/jinja2/compiler.py |
+++ b/third_party/jinja2/compiler.py |
@@ -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, next, 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' |
@@ -1032,7 +1031,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 +1059,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 +1067,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 +1118,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 +1216,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 +1367,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 +1555,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: |