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,12 +8,14 @@
:copyright: (c) 2010 by the Jinja Team.
:license: BSD.
"""
from itertools import chain, imap
from itertools import chain
from jinja2.nodes import EvalContext, _context_function_types
from jinja2.utils import Markup, partial, soft_unicode, escape, missing, \
concat, internalcode, next, object_type_repr
from jinja2.utils import Markup, soft_unicode, escape, missing, concat, \
internalcode, object_type_repr
from jinja2.exceptions import UndefinedError, TemplateRuntimeError, \
TemplateNotFound
from jinja2._compat import imap, text_type, iteritems, \
implements_iterator, implements_to_string, string_types, PY2
# these variables are exported to the template runtime
@@ -23,9 +25,8 @@ __all__ = ['LoopContext', 'TemplateReference', 'Macro', 'Markup',
'TemplateNotFound']
#: the name of the function that is used to convert something into
#: a string. 2to3 will adopt that automatically and the generated
#: code can take advantage of it.
to_string = unicode
#: a string. We can just use the text type here.
to_string = text_type
#: the identity function. Useful for certain things in the environment
identity = lambda x: x
@@ -46,7 +47,7 @@ def markup_join(seq):
def unicode_join(seq):
"""Simple args to unicode conversion and concatenation."""
return concat(imap(unicode, seq))
return concat(imap(text_type, seq))
def new_context(environment, template_name, blocks, vars=None,
@@ -63,7 +64,7 @@ def new_context(environment, template_name, blocks, vars=None,
# we don't want to modify the dict passed
if shared:
parent = dict(parent)
for key, value in locals.iteritems():
for key, value in iteritems(locals):
if key[:2] == 'l_' and value is not missing:
parent[key[2:]] = value
return Context(environment, parent, template_name, blocks)
@@ -119,7 +120,7 @@ class Context(object):
# create the initial mapping of blocks. Whenever template inheritance
# takes place the runtime will update this mapping with the new blocks
# from the template.
self.blocks = dict((k, [v]) for k, v in blocks.iteritems())
self.blocks = dict((k, [v]) for k, v in iteritems(blocks))
def super(self, name, current):
"""Render a parent block."""
@@ -171,6 +172,16 @@ class Context(object):
"""
if __debug__:
__traceback_hide__ = True
# Allow callable classes to take a context
fn = __obj.__call__
for fn_type in ('contextfunction',
'evalcontextfunction',
'environmentfunction'):
if hasattr(fn, fn_type):
__obj = fn
break
if isinstance(__obj, _context_function_types):
if getattr(__obj, 'contextfunction', 0):
args = (__self,) + args
@@ -191,7 +202,7 @@ class Context(object):
self.parent, True, None, locals)
context.vars.update(self.vars)
context.eval_ctx = self.eval_ctx
context.blocks.update((k, list(v)) for k, v in self.blocks.iteritems())
context.blocks.update((k, list(v)) for k, v in iteritems(self.blocks))
return context
def _all(meth):
@@ -205,7 +216,7 @@ class Context(object):
items = _all('items')
# not available on python 3
if hasattr(dict, 'iterkeys'):
if PY2:
iterkeys = _all('iterkeys')
itervalues = _all('itervalues')
iteritems = _all('iteritems')
@@ -269,11 +280,12 @@ class BlockReference(object):
class LoopContext(object):
"""A loop context for dynamic iteration."""
def __init__(self, iterable, recurse=None):
def __init__(self, iterable, recurse=None, depth0=0):
self._iterator = iter(iterable)
self._recurse = recurse
self._after = self._safe_next()
self.index0 = -1
self.depth0 = depth0
# try to get the length of the iterable early. This must be done
# here because there are some broken iterators around where there
@@ -295,6 +307,7 @@ class LoopContext(object):
index = property(lambda x: x.index0 + 1)
revindex = property(lambda x: x.length - x.index0)
revindex0 = property(lambda x: x.length - x.index)
depth = property(lambda x: x.depth0 + 1)
def __len__(self):
return self.length
@@ -313,7 +326,7 @@ class LoopContext(object):
if self._recurse is None:
raise TypeError('Tried to call non recursive loop. Maybe you '
"forgot the 'recursive' modifier.")
return self._recurse(iterable, self._recurse)
return self._recurse(iterable, self._recurse, self.depth0 + 1)
# a nifty trick to enhance the error message if someone tried to call
# the the loop without or with too many arguments.
@@ -340,6 +353,7 @@ class LoopContext(object):
)
@implements_iterator
class LoopContextIterator(object):
"""The iterator for a loop context."""
__slots__ = ('context',)
@@ -350,7 +364,7 @@ class LoopContextIterator(object):
def __iter__(self):
return self
def next(self):
def __next__(self):
ctx = self.context
ctx.index0 += 1
if ctx._after is _last_iteration:
@@ -424,6 +438,7 @@ class Macro(object):
)
@implements_to_string
class Undefined(object):
"""The default undefined type. This undefined type can be printed and
iterated over, but every other access will raise an :exc:`UndefinedError`:
@@ -455,7 +470,7 @@ class Undefined(object):
if self._undefined_hint is None:
if self._undefined_obj is missing:
hint = '%r is undefined' % self._undefined_name
elif not isinstance(self._undefined_name, basestring):
elif not isinstance(self._undefined_name, string_types):
hint = '%s has no element %r' % (
object_type_repr(self._undefined_obj),
self._undefined_name
@@ -483,13 +498,6 @@ class Undefined(object):
_fail_with_undefined_error
def __str__(self):
return unicode(self).encode('utf-8')
# unicode goes after __str__ because we configured 2to3 to rename
# __unicode__ to __str__. because the 2to3 tree is not designed to
# remove nodes from it, we leave the above __str__ around and let
# it override at runtime.
def __unicode__(self):
return u''
def __len__(self):
@@ -506,6 +514,7 @@ class Undefined(object):
return 'Undefined'
@implements_to_string
class DebugUndefined(Undefined):
"""An undefined that returns the debug info when printed.
@@ -521,7 +530,7 @@ class DebugUndefined(Undefined):
"""
__slots__ = ()
def __unicode__(self):
def __str__(self):
if self._undefined_hint is None:
if self._undefined_obj is missing:
return u'{{ %s }}' % self._undefined_name
@@ -532,6 +541,7 @@ class DebugUndefined(Undefined):
return u'{{ undefined value printed: %s }}' % self._undefined_hint
@implements_to_string
class StrictUndefined(Undefined):
"""An undefined that barks on print and iteration as well as boolean
tests and all kinds of comparisons. In other words: you can do nothing
@@ -552,7 +562,7 @@ class StrictUndefined(Undefined):
UndefinedError: 'foo' is undefined
"""
__slots__ = ()
__iter__ = __unicode__ = __str__ = __len__ = __nonzero__ = __eq__ = \
__iter__ = __str__ = __len__ = __nonzero__ = __eq__ = \
__ne__ = __bool__ = Undefined._fail_with_undefined_error