Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Unified Diff: third_party/jinja2/runtime.py

Issue 23506004: Update Jinja2 (Python template library) to 2.7.1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/jinja2/parser.py ('k') | third_party/jinja2/sandbox.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/jinja2/runtime.py
diff --git a/third_party/jinja2/runtime.py b/third_party/jinja2/runtime.py
index a4a47a284ed4a51ec9e54ae9b439682884e1905c..7791c645afe997d45e75355fddad384f9d525d94 100644
--- a/third_party/jinja2/runtime.py
+++ b/third_party/jinja2/runtime.py
@@ -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 next, imap, text_type, iteritems, \
+ implements_iterator, implements_to_string, string_types, PY2
# these variables are exported to the template runtime
@@ -23,13 +25,14 @@ __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
+_last_iteration = object()
+
def markup_join(seq):
"""Concatenation that escapes if necessary and converts to unicode."""
@@ -44,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,
@@ -61,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)
@@ -117,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."""
@@ -169,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
@@ -189,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):
@@ -203,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')
@@ -267,10 +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
@@ -288,10 +303,11 @@ class LoopContext(object):
return args[self.index0 % len(args)]
first = property(lambda x: x.index0 == 0)
- last = property(lambda x: x.index0 + 1 == x.length)
+ last = property(lambda x: x._after is _last_iteration)
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
@@ -299,12 +315,18 @@ class LoopContext(object):
def __iter__(self):
return LoopContextIterator(self)
+ def _safe_next(self):
+ try:
+ return next(self._iterator)
+ except StopIteration:
+ return _last_iteration
+
@internalcode
def loop(self, iterable):
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.
@@ -331,6 +353,7 @@ class LoopContext(object):
)
+@implements_iterator
class LoopContextIterator(object):
"""The iterator for a loop context."""
__slots__ = ('context',)
@@ -341,10 +364,14 @@ class LoopContextIterator(object):
def __iter__(self):
return self
- def next(self):
+ def __next__(self):
ctx = self.context
ctx.index0 += 1
- return next(ctx._iterator), ctx
+ if ctx._after is _last_iteration:
+ raise StopIteration()
+ next_elem = ctx._after
+ ctx._after = ctx._safe_next()
+ return next_elem, ctx
class Macro(object):
@@ -411,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`:
@@ -442,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
@@ -469,14 +497,16 @@ class Undefined(object):
__float__ = __complex__ = __pow__ = __rpow__ = \
_fail_with_undefined_error
- def __str__(self):
- return unicode(self).encode('utf-8')
+ def __eq__(self, other):
+ return type(self) is type(other)
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def __hash__(self):
+ return id(type(self))
- # 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):
+ def __str__(self):
return u''
def __len__(self):
@@ -493,6 +523,7 @@ class Undefined(object):
return 'Undefined'
+@implements_to_string
class DebugUndefined(Undefined):
"""An undefined that returns the debug info when printed.
@@ -508,7 +539,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
@@ -519,6 +550,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
@@ -539,8 +571,9 @@ class StrictUndefined(Undefined):
UndefinedError: 'foo' is undefined
"""
__slots__ = ()
- __iter__ = __unicode__ = __str__ = __len__ = __nonzero__ = __eq__ = \
- __ne__ = __bool__ = Undefined._fail_with_undefined_error
+ __iter__ = __str__ = __len__ = __nonzero__ = __eq__ = \
+ __ne__ = __bool__ = __hash__ = \
+ Undefined._fail_with_undefined_error
# remove remaining slots attributes, after the metaclass did the magic they
« no previous file with comments | « third_party/jinja2/parser.py ('k') | third_party/jinja2/sandbox.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698