summaryrefslogtreecommitdiff
path: root/chromium/third_party/jinja2
diff options
context:
space:
mode:
authorAndras Becsi <andras.becsi@digia.com>2013-12-11 21:33:03 +0100
committerAndras Becsi <andras.becsi@digia.com>2013-12-13 12:34:07 +0100
commitf2a33ff9cbc6d19943f1c7fbddd1f23d23975577 (patch)
tree0586a32aa390ade8557dfd6b4897f43a07449578 /chromium/third_party/jinja2
parent5362912cdb5eea702b68ebe23702468d17c3017a (diff)
downloadqtwebengine-chromium-f2a33ff9cbc6d19943f1c7fbddd1f23d23975577.tar.gz
Update Chromium to branch 1650 (31.0.1650.63)
Change-Id: I57d8c832eaec1eb2364e0a8e7352a6dd354db99f Reviewed-by: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
Diffstat (limited to 'chromium/third_party/jinja2')
-rw-r--r--chromium/third_party/jinja2/AUTHORS2
-rw-r--r--chromium/third_party/jinja2/Jinja2-2.7.1.tar.gz.md51
-rw-r--r--chromium/third_party/jinja2/Jinja2-2.7.1.tar.gz.sha5121
-rw-r--r--chromium/third_party/jinja2/OWNERS3
-rw-r--r--chromium/third_party/jinja2/README.chromium16
-rw-r--r--chromium/third_party/jinja2/__init__.py2
-rw-r--r--chromium/third_party/jinja2/_compat.py150
-rw-r--r--chromium/third_party/jinja2/_markupsafe/__init__.py225
-rw-r--r--chromium/third_party/jinja2/_markupsafe/_bundle.py49
-rw-r--r--chromium/third_party/jinja2/_markupsafe/_constants.py267
-rw-r--r--chromium/third_party/jinja2/_markupsafe/_native.py45
-rw-r--r--chromium/third_party/jinja2/_stringdefs.py2
-rw-r--r--chromium/third_party/jinja2/bccache.py34
-rw-r--r--chromium/third_party/jinja2/compiler.py83
-rw-r--r--chromium/third_party/jinja2/debug.py34
-rw-r--r--chromium/third_party/jinja2/defaults.py5
-rw-r--r--chromium/third_party/jinja2/environment.py162
-rw-r--r--chromium/third_party/jinja2/exceptions.py59
-rw-r--r--chromium/third_party/jinja2/ext.py52
-rw-r--r--chromium/third_party/jinja2/filters.py280
-rwxr-xr-xchromium/third_party/jinja2/get_jinja2.sh123
-rw-r--r--chromium/third_party/jinja2/lexer.py96
-rw-r--r--chromium/third_party/jinja2/loaders.py43
-rw-r--r--chromium/third_party/jinja2/meta.py7
-rw-r--r--chromium/third_party/jinja2/nodes.py22
-rw-r--r--chromium/third_party/jinja2/parser.py7
-rw-r--r--chromium/third_party/jinja2/runtime.py87
-rw-r--r--chromium/third_party/jinja2/sandbox.py27
-rw-r--r--chromium/third_party/jinja2/tests.py26
-rw-r--r--chromium/third_party/jinja2/utils.py201
30 files changed, 1064 insertions, 1047 deletions
diff --git a/chromium/third_party/jinja2/AUTHORS b/chromium/third_party/jinja2/AUTHORS
index c6cd9ba2d18..943f625f876 100644
--- a/chromium/third_party/jinja2/AUTHORS
+++ b/chromium/third_party/jinja2/AUTHORS
@@ -29,3 +29,5 @@ Patches and suggestions:
- Peter van Dijk (Habbie)
- Stefan Ebner
- Rene Leonhardt
+- Thomas Waldmann
+- Cory Benfield (Lukasa)
diff --git a/chromium/third_party/jinja2/Jinja2-2.7.1.tar.gz.md5 b/chromium/third_party/jinja2/Jinja2-2.7.1.tar.gz.md5
new file mode 100644
index 00000000000..5c9e7579f60
--- /dev/null
+++ b/chromium/third_party/jinja2/Jinja2-2.7.1.tar.gz.md5
@@ -0,0 +1 @@
+282aed153e69f970d6e76f78ed9d027a Jinja2-2.7.1.tar.gz
diff --git a/chromium/third_party/jinja2/Jinja2-2.7.1.tar.gz.sha512 b/chromium/third_party/jinja2/Jinja2-2.7.1.tar.gz.sha512
new file mode 100644
index 00000000000..44b486de320
--- /dev/null
+++ b/chromium/third_party/jinja2/Jinja2-2.7.1.tar.gz.sha512
@@ -0,0 +1 @@
+c5d4262f6dfec77c74496f0b3afd88a37fc0573133810cfdc29fadbd9d02bb7af10b2a3ddf3075f8b682629cd41a949dcbccb293b84b0aeff9090b0aa9669e02 Jinja2-2.7.1.tar.gz
diff --git a/chromium/third_party/jinja2/OWNERS b/chromium/third_party/jinja2/OWNERS
new file mode 100644
index 00000000000..8edbdf893c2
--- /dev/null
+++ b/chromium/third_party/jinja2/OWNERS
@@ -0,0 +1,3 @@
+timloh@chromium.org
+haraken@chromium.org
+nbarth@chromium.org
diff --git a/chromium/third_party/jinja2/README.chromium b/chromium/third_party/jinja2/README.chromium
index a97abd5bd0b..9ab2426dbdd 100644
--- a/chromium/third_party/jinja2/README.chromium
+++ b/chromium/third_party/jinja2/README.chromium
@@ -1,7 +1,7 @@
Name: Jinja2 Python Template Engine
Short Name: jinja2
URL: http://jinja.pocoo.org/
-Version: 2.6
+Version: 2.7.1
License: BSD 3-clause License
License File: NOT_SHIPPED
Security Critical: no
@@ -9,5 +9,17 @@ Security Critical: no
Description:
Template engine for code generation in Blink.
+Source: https://pypi.python.org/packages/source/J/Jinja2/Jinja2-2.7.1.tar.gz
+MD5: 282aed153e69f970d6e76f78ed9d027a
+SHA-1: a9b24d887f2be772921b3ee30a0b9d435cffadda
+
Local Modifications:
-This only includes the jinja2 directory from the tarball and the LICENSE and AUTHORS files. Unit tests have been removed.
+This only includes the jinja2 directory from the tarball and the LICENSE and
+AUTHORS files. Unit tests (testsuite directory) have been removed.
+Additional chromium-specific files are:
+* README.chromium (this file)
+* OWNERS
+* install script (get_jinja2.sh)
+* files of hashes (MD5 is also posted on website, SHA-512 computed locally).
+Script checks hash then unpacks archive and installs desired files.
+Retrieve or update by executing jinja2/get_jinja2.sh from third_party.
diff --git a/chromium/third_party/jinja2/__init__.py b/chromium/third_party/jinja2/__init__.py
index 0cf967d7b9d..6fa11c3a6db 100644
--- a/chromium/third_party/jinja2/__init__.py
+++ b/chromium/third_party/jinja2/__init__.py
@@ -27,7 +27,7 @@
:license: BSD, see LICENSE for more details.
"""
__docformat__ = 'restructuredtext en'
-__version__ = '2.6'
+__version__ = '2.7.1'
# high level interface
from jinja2.environment import Environment, Template
diff --git a/chromium/third_party/jinja2/_compat.py b/chromium/third_party/jinja2/_compat.py
new file mode 100644
index 00000000000..8fa8a49a0a2
--- /dev/null
+++ b/chromium/third_party/jinja2/_compat.py
@@ -0,0 +1,150 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2._compat
+ ~~~~~~~~~~~~~~
+
+ Some py2/py3 compatibility support based on a stripped down
+ version of six so we don't have to depend on a specific version
+ of it.
+
+ :copyright: Copyright 2013 by the Jinja team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+import sys
+
+PY2 = sys.version_info[0] == 2
+PYPY = hasattr(sys, 'pypy_translation_info')
+_identity = lambda x: x
+
+
+if not PY2:
+ unichr = chr
+ range_type = range
+ text_type = str
+ string_types = (str,)
+
+ iterkeys = lambda d: iter(d.keys())
+ itervalues = lambda d: iter(d.values())
+ iteritems = lambda d: iter(d.items())
+
+ import pickle
+ from io import BytesIO, StringIO
+ NativeStringIO = StringIO
+
+ def reraise(tp, value, tb=None):
+ if value.__traceback__ is not tb:
+ raise value.with_traceback(tb)
+ raise value
+
+ ifilter = filter
+ imap = map
+ izip = zip
+ intern = sys.intern
+
+ implements_iterator = _identity
+ implements_to_string = _identity
+ encode_filename = _identity
+ get_next = lambda x: x.__next__
+
+else:
+ unichr = unichr
+ text_type = unicode
+ range_type = xrange
+ string_types = (str, unicode)
+
+ iterkeys = lambda d: d.iterkeys()
+ itervalues = lambda d: d.itervalues()
+ iteritems = lambda d: d.iteritems()
+
+ import cPickle as pickle
+ from cStringIO import StringIO as BytesIO, StringIO
+ NativeStringIO = BytesIO
+
+ exec('def reraise(tp, value, tb=None):\n raise tp, value, tb')
+
+ from itertools import imap, izip, ifilter
+ intern = intern
+
+ def implements_iterator(cls):
+ cls.next = cls.__next__
+ del cls.__next__
+ return cls
+
+ def implements_to_string(cls):
+ cls.__unicode__ = cls.__str__
+ cls.__str__ = lambda x: x.__unicode__().encode('utf-8')
+ return cls
+
+ get_next = lambda x: x.next
+
+ def encode_filename(filename):
+ if isinstance(filename, unicode):
+ return filename.encode('utf-8')
+ return filename
+
+try:
+ next = next
+except NameError:
+ def next(it):
+ return it.next()
+
+
+def with_metaclass(meta, *bases):
+ # This requires a bit of explanation: the basic idea is to make a
+ # dummy metaclass for one level of class instanciation that replaces
+ # itself with the actual metaclass. Because of internal type checks
+ # we also need to make sure that we downgrade the custom metaclass
+ # for one level to something closer to type (that's why __call__ and
+ # __init__ comes back from type etc.).
+ #
+ # This has the advantage over six.with_metaclass in that it does not
+ # introduce dummy classes into the final MRO.
+ class metaclass(meta):
+ __call__ = type.__call__
+ __init__ = type.__init__
+ def __new__(cls, name, this_bases, d):
+ if this_bases is None:
+ return type.__new__(cls, name, (), d)
+ return meta(name, bases, d)
+ return metaclass('temporary_class', None, {})
+
+
+try:
+ from collections import Mapping as mapping_types
+except ImportError:
+ import UserDict
+ mapping_types = (UserDict.UserDict, UserDict.DictMixin, dict)
+
+
+# common types. These do exist in the special types module too which however
+# does not exist in IronPython out of the box. Also that way we don't have
+# to deal with implementation specific stuff here
+class _C(object):
+ def method(self): pass
+def _func():
+ yield None
+function_type = type(_func)
+generator_type = type(_func())
+method_type = type(_C().method)
+code_type = type(_C.method.__code__)
+try:
+ raise TypeError()
+except TypeError:
+ _tb = sys.exc_info()[2]
+ traceback_type = type(_tb)
+ frame_type = type(_tb.tb_frame)
+
+
+try:
+ from urllib.parse import quote_from_bytes as url_quote
+except ImportError:
+ from urllib import quote as url_quote
+
+
+try:
+ from thread import allocate_lock
+except ImportError:
+ try:
+ from threading import Lock as allocate_lock
+ except ImportError:
+ from dummy_thread import allocate_lock
diff --git a/chromium/third_party/jinja2/_markupsafe/__init__.py b/chromium/third_party/jinja2/_markupsafe/__init__.py
deleted file mode 100644
index ec7bd572d0b..00000000000
--- a/chromium/third_party/jinja2/_markupsafe/__init__.py
+++ /dev/null
@@ -1,225 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- markupsafe
- ~~~~~~~~~~
-
- Implements a Markup string.
-
- :copyright: (c) 2010 by Armin Ronacher.
- :license: BSD, see LICENSE for more details.
-"""
-import re
-from itertools import imap
-
-
-__all__ = ['Markup', 'soft_unicode', 'escape', 'escape_silent']
-
-
-_striptags_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
-_entity_re = re.compile(r'&([^;]+);')
-
-
-class Markup(unicode):
- r"""Marks a string as being safe for inclusion in HTML/XML output without
- needing to be escaped. This implements the `__html__` interface a couple
- of frameworks and web applications use. :class:`Markup` is a direct
- subclass of `unicode` and provides all the methods of `unicode` just that
- it escapes arguments passed and always returns `Markup`.
-
- The `escape` function returns markup objects so that double escaping can't
- happen.
-
- The constructor of the :class:`Markup` class can be used for three
- different things: When passed an unicode object it's assumed to be safe,
- when passed an object with an HTML representation (has an `__html__`
- method) that representation is used, otherwise the object passed is
- converted into a unicode string and then assumed to be safe:
-
- >>> Markup("Hello <em>World</em>!")
- Markup(u'Hello <em>World</em>!')
- >>> class Foo(object):
- ... def __html__(self):
- ... return '<a href="#">foo</a>'
- ...
- >>> Markup(Foo())
- Markup(u'<a href="#">foo</a>')
-
- If you want object passed being always treated as unsafe you can use the
- :meth:`escape` classmethod to create a :class:`Markup` object:
-
- >>> Markup.escape("Hello <em>World</em>!")
- Markup(u'Hello &lt;em&gt;World&lt;/em&gt;!')
-
- Operations on a markup string are markup aware which means that all
- arguments are passed through the :func:`escape` function:
-
- >>> em = Markup("<em>%s</em>")
- >>> em % "foo & bar"
- Markup(u'<em>foo &amp; bar</em>')
- >>> strong = Markup("<strong>%(text)s</strong>")
- >>> strong % {'text': '<blink>hacker here</blink>'}
- Markup(u'<strong>&lt;blink&gt;hacker here&lt;/blink&gt;</strong>')
- >>> Markup("<em>Hello</em> ") + "<foo>"
- Markup(u'<em>Hello</em> &lt;foo&gt;')
- """
- __slots__ = ()
-
- def __new__(cls, base=u'', encoding=None, errors='strict'):
- if hasattr(base, '__html__'):
- base = base.__html__()
- if encoding is None:
- return unicode.__new__(cls, base)
- return unicode.__new__(cls, base, encoding, errors)
-
- def __html__(self):
- return self
-
- def __add__(self, other):
- if hasattr(other, '__html__') or isinstance(other, basestring):
- return self.__class__(unicode(self) + unicode(escape(other)))
- return NotImplemented
-
- def __radd__(self, other):
- if hasattr(other, '__html__') or isinstance(other, basestring):
- return self.__class__(unicode(escape(other)) + unicode(self))
- return NotImplemented
-
- def __mul__(self, num):
- if isinstance(num, (int, long)):
- return self.__class__(unicode.__mul__(self, num))
- return NotImplemented
- __rmul__ = __mul__
-
- def __mod__(self, arg):
- if isinstance(arg, tuple):
- arg = tuple(imap(_MarkupEscapeHelper, arg))
- else:
- arg = _MarkupEscapeHelper(arg)
- return self.__class__(unicode.__mod__(self, arg))
-
- def __repr__(self):
- return '%s(%s)' % (
- self.__class__.__name__,
- unicode.__repr__(self)
- )
-
- def join(self, seq):
- return self.__class__(unicode.join(self, imap(escape, seq)))
- join.__doc__ = unicode.join.__doc__
-
- def split(self, *args, **kwargs):
- return map(self.__class__, unicode.split(self, *args, **kwargs))
- split.__doc__ = unicode.split.__doc__
-
- def rsplit(self, *args, **kwargs):
- return map(self.__class__, unicode.rsplit(self, *args, **kwargs))
- rsplit.__doc__ = unicode.rsplit.__doc__
-
- def splitlines(self, *args, **kwargs):
- return map(self.__class__, unicode.splitlines(self, *args, **kwargs))
- splitlines.__doc__ = unicode.splitlines.__doc__
-
- def unescape(self):
- r"""Unescape markup again into an unicode string. This also resolves
- known HTML4 and XHTML entities:
-
- >>> Markup("Main &raquo; <em>About</em>").unescape()
- u'Main \xbb <em>About</em>'
- """
- from jinja2._markupsafe._constants import HTML_ENTITIES
- def handle_match(m):
- name = m.group(1)
- if name in HTML_ENTITIES:
- return unichr(HTML_ENTITIES[name])
- try:
- if name[:2] in ('#x', '#X'):
- return unichr(int(name[2:], 16))
- elif name.startswith('#'):
- return unichr(int(name[1:]))
- except ValueError:
- pass
- return u''
- return _entity_re.sub(handle_match, unicode(self))
-
- def striptags(self):
- r"""Unescape markup into an unicode string and strip all tags. This
- also resolves known HTML4 and XHTML entities. Whitespace is
- normalized to one:
-
- >>> Markup("Main &raquo; <em>About</em>").striptags()
- u'Main \xbb About'
- """
- stripped = u' '.join(_striptags_re.sub('', self).split())
- return Markup(stripped).unescape()
-
- @classmethod
- def escape(cls, s):
- """Escape the string. Works like :func:`escape` with the difference
- that for subclasses of :class:`Markup` this function would return the
- correct subclass.
- """
- rv = escape(s)
- if rv.__class__ is not cls:
- return cls(rv)
- return rv
-
- def make_wrapper(name):
- orig = getattr(unicode, name)
- def func(self, *args, **kwargs):
- args = _escape_argspec(list(args), enumerate(args))
- _escape_argspec(kwargs, kwargs.iteritems())
- return self.__class__(orig(self, *args, **kwargs))
- func.__name__ = orig.__name__
- func.__doc__ = orig.__doc__
- return func
-
- for method in '__getitem__', 'capitalize', \
- 'title', 'lower', 'upper', 'replace', 'ljust', \
- 'rjust', 'lstrip', 'rstrip', 'center', 'strip', \
- 'translate', 'expandtabs', 'swapcase', 'zfill':
- locals()[method] = make_wrapper(method)
-
- # new in python 2.5
- if hasattr(unicode, 'partition'):
- partition = make_wrapper('partition'),
- rpartition = make_wrapper('rpartition')
-
- # new in python 2.6
- if hasattr(unicode, 'format'):
- format = make_wrapper('format')
-
- # not in python 3
- if hasattr(unicode, '__getslice__'):
- __getslice__ = make_wrapper('__getslice__')
-
- del method, make_wrapper
-
-
-def _escape_argspec(obj, iterable):
- """Helper for various string-wrapped functions."""
- for key, value in iterable:
- if hasattr(value, '__html__') or isinstance(value, basestring):
- obj[key] = escape(value)
- return obj
-
-
-class _MarkupEscapeHelper(object):
- """Helper for Markup.__mod__"""
-
- def __init__(self, obj):
- self.obj = obj
-
- __getitem__ = lambda s, x: _MarkupEscapeHelper(s.obj[x])
- __str__ = lambda s: str(escape(s.obj))
- __unicode__ = lambda s: unicode(escape(s.obj))
- __repr__ = lambda s: str(escape(repr(s.obj)))
- __int__ = lambda s: int(s.obj)
- __float__ = lambda s: float(s.obj)
-
-
-# we have to import it down here as the speedups and native
-# modules imports the markup type which is define above.
-try:
- from jinja2._markupsafe._speedups import escape, escape_silent, soft_unicode
-except ImportError:
- from jinja2._markupsafe._native import escape, escape_silent, soft_unicode
diff --git a/chromium/third_party/jinja2/_markupsafe/_bundle.py b/chromium/third_party/jinja2/_markupsafe/_bundle.py
deleted file mode 100644
index e694faf23d4..00000000000
--- a/chromium/third_party/jinja2/_markupsafe/_bundle.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- jinja2._markupsafe._bundle
- ~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- This script pulls in markupsafe from a source folder and
- bundles it with Jinja2. It does not pull in the speedups
- module though.
-
- :copyright: Copyright 2010 by the Jinja team, see AUTHORS.
- :license: BSD, see LICENSE for details.
-"""
-import sys
-import os
-import re
-
-
-def rewrite_imports(lines):
- for idx, line in enumerate(lines):
- new_line = re.sub(r'(import|from)\s+markupsafe\b',
- r'\1 jinja2._markupsafe', line)
- if new_line != line:
- lines[idx] = new_line
-
-
-def main():
- if len(sys.argv) != 2:
- print 'error: only argument is path to markupsafe'
- sys.exit(1)
- basedir = os.path.dirname(__file__)
- markupdir = sys.argv[1]
- for filename in os.listdir(markupdir):
- if filename.endswith('.py'):
- f = open(os.path.join(markupdir, filename))
- try:
- lines = list(f)
- finally:
- f.close()
- rewrite_imports(lines)
- f = open(os.path.join(basedir, filename), 'w')
- try:
- for line in lines:
- f.write(line)
- finally:
- f.close()
-
-
-if __name__ == '__main__':
- main()
diff --git a/chromium/third_party/jinja2/_markupsafe/_constants.py b/chromium/third_party/jinja2/_markupsafe/_constants.py
deleted file mode 100644
index 919bf03c509..00000000000
--- a/chromium/third_party/jinja2/_markupsafe/_constants.py
+++ /dev/null
@@ -1,267 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- markupsafe._constants
- ~~~~~~~~~~~~~~~~~~~~~
-
- Highlevel implementation of the Markup string.
-
- :copyright: (c) 2010 by Armin Ronacher.
- :license: BSD, see LICENSE for more details.
-"""
-
-
-HTML_ENTITIES = {
- 'AElig': 198,
- 'Aacute': 193,
- 'Acirc': 194,
- 'Agrave': 192,
- 'Alpha': 913,
- 'Aring': 197,
- 'Atilde': 195,
- 'Auml': 196,
- 'Beta': 914,
- 'Ccedil': 199,
- 'Chi': 935,
- 'Dagger': 8225,
- 'Delta': 916,
- 'ETH': 208,
- 'Eacute': 201,
- 'Ecirc': 202,
- 'Egrave': 200,
- 'Epsilon': 917,
- 'Eta': 919,
- 'Euml': 203,
- 'Gamma': 915,
- 'Iacute': 205,
- 'Icirc': 206,
- 'Igrave': 204,
- 'Iota': 921,
- 'Iuml': 207,
- 'Kappa': 922,
- 'Lambda': 923,
- 'Mu': 924,
- 'Ntilde': 209,
- 'Nu': 925,
- 'OElig': 338,
- 'Oacute': 211,
- 'Ocirc': 212,
- 'Ograve': 210,
- 'Omega': 937,
- 'Omicron': 927,
- 'Oslash': 216,
- 'Otilde': 213,
- 'Ouml': 214,
- 'Phi': 934,
- 'Pi': 928,
- 'Prime': 8243,
- 'Psi': 936,
- 'Rho': 929,
- 'Scaron': 352,
- 'Sigma': 931,
- 'THORN': 222,
- 'Tau': 932,
- 'Theta': 920,
- 'Uacute': 218,
- 'Ucirc': 219,
- 'Ugrave': 217,
- 'Upsilon': 933,
- 'Uuml': 220,
- 'Xi': 926,
- 'Yacute': 221,
- 'Yuml': 376,
- 'Zeta': 918,
- 'aacute': 225,
- 'acirc': 226,
- 'acute': 180,
- 'aelig': 230,
- 'agrave': 224,
- 'alefsym': 8501,
- 'alpha': 945,
- 'amp': 38,
- 'and': 8743,
- 'ang': 8736,
- 'apos': 39,
- 'aring': 229,
- 'asymp': 8776,
- 'atilde': 227,
- 'auml': 228,
- 'bdquo': 8222,
- 'beta': 946,
- 'brvbar': 166,
- 'bull': 8226,
- 'cap': 8745,
- 'ccedil': 231,
- 'cedil': 184,
- 'cent': 162,
- 'chi': 967,
- 'circ': 710,
- 'clubs': 9827,
- 'cong': 8773,
- 'copy': 169,
- 'crarr': 8629,
- 'cup': 8746,
- 'curren': 164,
- 'dArr': 8659,
- 'dagger': 8224,
- 'darr': 8595,
- 'deg': 176,
- 'delta': 948,
- 'diams': 9830,
- 'divide': 247,
- 'eacute': 233,
- 'ecirc': 234,
- 'egrave': 232,
- 'empty': 8709,
- 'emsp': 8195,
- 'ensp': 8194,
- 'epsilon': 949,
- 'equiv': 8801,
- 'eta': 951,
- 'eth': 240,
- 'euml': 235,
- 'euro': 8364,
- 'exist': 8707,
- 'fnof': 402,
- 'forall': 8704,
- 'frac12': 189,
- 'frac14': 188,
- 'frac34': 190,
- 'frasl': 8260,
- 'gamma': 947,
- 'ge': 8805,
- 'gt': 62,
- 'hArr': 8660,
- 'harr': 8596,
- 'hearts': 9829,
- 'hellip': 8230,
- 'iacute': 237,
- 'icirc': 238,
- 'iexcl': 161,
- 'igrave': 236,
- 'image': 8465,
- 'infin': 8734,
- 'int': 8747,
- 'iota': 953,
- 'iquest': 191,
- 'isin': 8712,
- 'iuml': 239,
- 'kappa': 954,
- 'lArr': 8656,
- 'lambda': 955,
- 'lang': 9001,
- 'laquo': 171,
- 'larr': 8592,
- 'lceil': 8968,
- 'ldquo': 8220,
- 'le': 8804,
- 'lfloor': 8970,
- 'lowast': 8727,
- 'loz': 9674,
- 'lrm': 8206,
- 'lsaquo': 8249,
- 'lsquo': 8216,
- 'lt': 60,
- 'macr': 175,
- 'mdash': 8212,
- 'micro': 181,
- 'middot': 183,
- 'minus': 8722,
- 'mu': 956,
- 'nabla': 8711,
- 'nbsp': 160,
- 'ndash': 8211,
- 'ne': 8800,
- 'ni': 8715,
- 'not': 172,
- 'notin': 8713,
- 'nsub': 8836,
- 'ntilde': 241,
- 'nu': 957,
- 'oacute': 243,
- 'ocirc': 244,
- 'oelig': 339,
- 'ograve': 242,
- 'oline': 8254,
- 'omega': 969,
- 'omicron': 959,
- 'oplus': 8853,
- 'or': 8744,
- 'ordf': 170,
- 'ordm': 186,
- 'oslash': 248,
- 'otilde': 245,
- 'otimes': 8855,
- 'ouml': 246,
- 'para': 182,
- 'part': 8706,
- 'permil': 8240,
- 'perp': 8869,
- 'phi': 966,
- 'pi': 960,
- 'piv': 982,
- 'plusmn': 177,
- 'pound': 163,
- 'prime': 8242,
- 'prod': 8719,
- 'prop': 8733,
- 'psi': 968,
- 'quot': 34,
- 'rArr': 8658,
- 'radic': 8730,
- 'rang': 9002,
- 'raquo': 187,
- 'rarr': 8594,
- 'rceil': 8969,
- 'rdquo': 8221,
- 'real': 8476,
- 'reg': 174,
- 'rfloor': 8971,
- 'rho': 961,
- 'rlm': 8207,
- 'rsaquo': 8250,
- 'rsquo': 8217,
- 'sbquo': 8218,
- 'scaron': 353,
- 'sdot': 8901,
- 'sect': 167,
- 'shy': 173,
- 'sigma': 963,
- 'sigmaf': 962,
- 'sim': 8764,
- 'spades': 9824,
- 'sub': 8834,
- 'sube': 8838,
- 'sum': 8721,
- 'sup': 8835,
- 'sup1': 185,
- 'sup2': 178,
- 'sup3': 179,
- 'supe': 8839,
- 'szlig': 223,
- 'tau': 964,
- 'there4': 8756,
- 'theta': 952,
- 'thetasym': 977,
- 'thinsp': 8201,
- 'thorn': 254,
- 'tilde': 732,
- 'times': 215,
- 'trade': 8482,
- 'uArr': 8657,
- 'uacute': 250,
- 'uarr': 8593,
- 'ucirc': 251,
- 'ugrave': 249,
- 'uml': 168,
- 'upsih': 978,
- 'upsilon': 965,
- 'uuml': 252,
- 'weierp': 8472,
- 'xi': 958,
- 'yacute': 253,
- 'yen': 165,
- 'yuml': 255,
- 'zeta': 950,
- 'zwj': 8205,
- 'zwnj': 8204
-}
diff --git a/chromium/third_party/jinja2/_markupsafe/_native.py b/chromium/third_party/jinja2/_markupsafe/_native.py
deleted file mode 100644
index 7b95828ec87..00000000000
--- a/chromium/third_party/jinja2/_markupsafe/_native.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- markupsafe._native
- ~~~~~~~~~~~~~~~~~~
-
- Native Python implementation the C module is not compiled.
-
- :copyright: (c) 2010 by Armin Ronacher.
- :license: BSD, see LICENSE for more details.
-"""
-from jinja2._markupsafe import Markup
-
-
-def escape(s):
- """Convert the characters &, <, >, ' and " in string s to HTML-safe
- sequences. Use this if you need to display text that might contain
- such characters in HTML. Marks return value as markup string.
- """
- if hasattr(s, '__html__'):
- return s.__html__()
- return Markup(unicode(s)
- .replace('&', '&amp;')
- .replace('>', '&gt;')
- .replace('<', '&lt;')
- .replace("'", '&#39;')
- .replace('"', '&#34;')
- )
-
-
-def escape_silent(s):
- """Like :func:`escape` but converts `None` into an empty
- markup string.
- """
- if s is None:
- return Markup()
- return escape(s)
-
-
-def soft_unicode(s):
- """Make a string unicode if it isn't already. That way a markup
- string is not converted back to unicode.
- """
- if not isinstance(s, unicode):
- s = unicode(s)
- return s
diff --git a/chromium/third_party/jinja2/_stringdefs.py b/chromium/third_party/jinja2/_stringdefs.py
index 1161b7f4a47..da5830e9f19 100644
--- a/chromium/third_party/jinja2/_stringdefs.py
+++ b/chromium/third_party/jinja2/_stringdefs.py
@@ -13,6 +13,8 @@
:license: BSD, see LICENSE for details.
"""
+from jinja2._compat import unichr
+
Cc = u'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f'
Cf = u'\xad\u0600\u0601\u0602\u0603\u06dd\u070f\u17b4\u17b5\u200b\u200c\u200d\u200e\u200f\u202a\u202b\u202c\u202d\u202e\u2060\u2061\u2062\u2063\u206a\u206b\u206c\u206d\u206e\u206f\ufeff\ufff9\ufffa\ufffb'
diff --git a/chromium/third_party/jinja2/bccache.py b/chromium/third_party/jinja2/bccache.py
index 0b0ccad1f24..f2f9db61b31 100644
--- a/chromium/third_party/jinja2/bccache.py
+++ b/chromium/third_party/jinja2/bccache.py
@@ -18,22 +18,17 @@ from os import path, listdir
import sys
import marshal
import tempfile
-import cPickle as pickle
import fnmatch
-try:
- from hashlib import sha1
-except ImportError:
- from sha import new as sha1
+from hashlib import sha1
from jinja2.utils import open_if_exists
+from jinja2._compat import BytesIO, pickle, PY2, text_type
# marshal works better on 3.x, one hack less required
-if sys.version_info > (3, 0):
- from io import BytesIO
+if not PY2:
marshal_dump = marshal.dump
marshal_load = marshal.load
else:
- from cStringIO import StringIO as BytesIO
def marshal_dump(code, f):
if isinstance(f, file):
@@ -165,7 +160,7 @@ class BytecodeCache(object):
hash = sha1(name.encode('utf-8'))
if filename is not None:
filename = '|' + filename
- if isinstance(filename, unicode):
+ if isinstance(filename, text_type):
filename = filename.encode('utf-8')
hash.update(filename)
return hash.hexdigest()
@@ -282,15 +277,26 @@ class MemcachedBytecodeCache(BytecodeCache):
This bytecode cache does not support clearing of used items in the cache.
The clear method is a no-operation function.
+
+ .. versionadded:: 2.7
+ Added support for ignoring memcache errors through the
+ `ignore_memcache_errors` parameter.
"""
- def __init__(self, client, prefix='jinja2/bytecode/', timeout=None):
+ def __init__(self, client, prefix='jinja2/bytecode/', timeout=None,
+ ignore_memcache_errors=True):
self.client = client
self.prefix = prefix
self.timeout = timeout
+ self.ignore_memcache_errors = ignore_memcache_errors
def load_bytecode(self, bucket):
- code = self.client.get(self.prefix + bucket.key)
+ try:
+ code = self.client.get(self.prefix + bucket.key)
+ except Exception:
+ if not self.ignore_memcache_errors:
+ raise
+ code = None
if code is not None:
bucket.bytecode_from_string(code)
@@ -298,4 +304,8 @@ class MemcachedBytecodeCache(BytecodeCache):
args = (self.prefix + bucket.key, bucket.bytecode_to_string())
if self.timeout is not None:
args += (self.timeout,)
- self.client.set(*args)
+ try:
+ self.client.set(*args)
+ except Exception:
+ if not self.ignore_memcache_errors:
+ raise
diff --git a/chromium/third_party/jinja2/compiler.py b/chromium/third_party/jinja2/compiler.py
index b21cb3865db..75a60b8d2d6 100644
--- a/chromium/third_party/jinja2/compiler.py
+++ b/chromium/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:
diff --git a/chromium/third_party/jinja2/debug.py b/chromium/third_party/jinja2/debug.py
index 2af22223227..815cc18a4f8 100644
--- a/chromium/third_party/jinja2/debug.py
+++ b/chromium/third_party/jinja2/debug.py
@@ -13,8 +13,9 @@
import sys
import traceback
from types import TracebackType
-from jinja2.utils import CodeType, missing, internal_code
+from jinja2.utils import missing, internal_code
from jinja2.exceptions import TemplateSyntaxError
+from jinja2._compat import iteritems, reraise, code_type
# on pypy we can take advantage of transparent proxies
try:
@@ -25,7 +26,7 @@ except ImportError:
# how does the raise helper look like?
try:
- exec "raise TypeError, 'foo'"
+ exec("raise TypeError, 'foo'")
except SyntaxError:
raise_helper = 'raise __jinja_exception__[1]'
except TypeError:
@@ -77,7 +78,7 @@ def make_frame_proxy(frame):
class ProcessedTraceback(object):
- """Holds a Jinja preprocessed traceback for priting or reraising."""
+ """Holds a Jinja preprocessed traceback for printing or reraising."""
def __init__(self, exc_type, exc_value, frames):
assert frames, 'no frames for this traceback?'
@@ -158,7 +159,7 @@ def translate_exception(exc_info, initial_skip=0):
frames = []
# skip some internal frames if wanted
- for x in xrange(initial_skip):
+ for x in range(initial_skip):
if tb is not None:
tb = tb.tb_next
initial_tb = tb
@@ -189,7 +190,7 @@ def translate_exception(exc_info, initial_skip=0):
# reraise it unchanged.
# XXX: can we backup here? when could this happen?
if not frames:
- raise exc_info[0], exc_info[1], exc_info[2]
+ reraise(exc_info[0], exc_info[1], exc_info[2])
return ProcessedTraceback(exc_info[0], exc_info[1], frames)
@@ -206,7 +207,7 @@ def fake_exc_info(exc_info, filename, lineno):
locals = ctx.get_all()
else:
locals = {}
- for name, value in real_locals.iteritems():
+ for name, value in iteritems(real_locals):
if name.startswith('l_') and value is not missing:
locals[name[2:]] = value
@@ -244,17 +245,17 @@ def fake_exc_info(exc_info, filename, lineno):
location = 'block "%s"' % function[6:]
else:
location = 'template'
- code = CodeType(0, code.co_nlocals, code.co_stacksize,
- code.co_flags, code.co_code, code.co_consts,
- code.co_names, code.co_varnames, filename,
- location, code.co_firstlineno,
- code.co_lnotab, (), ())
+ code = code_type(0, code.co_nlocals, code.co_stacksize,
+ code.co_flags, code.co_code, code.co_consts,
+ code.co_names, code.co_varnames, filename,
+ location, code.co_firstlineno,
+ code.co_lnotab, (), ())
except:
pass
# execute the code and catch the new traceback
try:
- exec code in globals, locals
+ exec(code, globals, locals)
except:
exc_info = sys.exc_info()
new_tb = exc_info[2].tb_next
@@ -330,10 +331,7 @@ def _init_ugly_crap():
tb_set_next = None
if tproxy is None:
try:
- from jinja2._debugsupport import tb_set_next
- except ImportError:
- try:
- tb_set_next = _init_ugly_crap()
- except:
- pass
+ tb_set_next = _init_ugly_crap()
+ except:
+ pass
del _init_ugly_crap
diff --git a/chromium/third_party/jinja2/defaults.py b/chromium/third_party/jinja2/defaults.py
index d2d45443add..a27cb80cbf0 100644
--- a/chromium/third_party/jinja2/defaults.py
+++ b/chromium/third_party/jinja2/defaults.py
@@ -8,6 +8,7 @@
:copyright: (c) 2010 by the Jinja Team.
:license: BSD, see LICENSE for more details.
"""
+from jinja2._compat import range_type
from jinja2.utils import generate_lorem_ipsum, Cycler, Joiner
@@ -21,14 +22,16 @@ COMMENT_END_STRING = '#}'
LINE_STATEMENT_PREFIX = None
LINE_COMMENT_PREFIX = None
TRIM_BLOCKS = False
+LSTRIP_BLOCKS = False
NEWLINE_SEQUENCE = '\n'
+KEEP_TRAILING_NEWLINE = False
# default filters, tests and namespace
from jinja2.filters import FILTERS as DEFAULT_FILTERS
from jinja2.tests import TESTS as DEFAULT_TESTS
DEFAULT_NAMESPACE = {
- 'range': xrange,
+ 'range': range_type,
'dict': lambda **kw: kw,
'lipsum': generate_lorem_ipsum,
'cycler': Cycler,
diff --git a/chromium/third_party/jinja2/environment.py b/chromium/third_party/jinja2/environment.py
index 7a9a59fce46..45fabada2eb 100644
--- a/chromium/third_party/jinja2/environment.py
+++ b/chromium/third_party/jinja2/environment.py
@@ -11,16 +11,26 @@
import os
import sys
from jinja2 import nodes
-from jinja2.defaults import *
+from jinja2.defaults import BLOCK_START_STRING, \
+ BLOCK_END_STRING, VARIABLE_START_STRING, VARIABLE_END_STRING, \
+ COMMENT_START_STRING, COMMENT_END_STRING, LINE_STATEMENT_PREFIX, \
+ LINE_COMMENT_PREFIX, TRIM_BLOCKS, NEWLINE_SEQUENCE, \
+ DEFAULT_FILTERS, DEFAULT_TESTS, DEFAULT_NAMESPACE, \
+ KEEP_TRAILING_NEWLINE, LSTRIP_BLOCKS
from jinja2.lexer import get_lexer, TokenStream
from jinja2.parser import Parser
+from jinja2.nodes import EvalContext
from jinja2.optimizer import optimize
from jinja2.compiler import generate
from jinja2.runtime import Undefined, new_context
from jinja2.exceptions import TemplateSyntaxError, TemplateNotFound, \
- TemplatesNotFound
+ TemplatesNotFound, TemplateRuntimeError
from jinja2.utils import import_string, LRUCache, Markup, missing, \
- concat, consume, internalcode, _encode_filename
+ concat, consume, internalcode
+from jinja2._compat import imap, ifilter, string_types, iteritems, \
+ text_type, reraise, implements_iterator, implements_to_string, \
+ get_next, encode_filename, PY2, PYPY
+from functools import reduce
# for direct template usage we have up to ten living environments
@@ -67,11 +77,11 @@ def copy_cache(cache):
def load_extensions(environment, extensions):
"""Load the extensions from the list and bind it to the environment.
- Returns a dict of instanciated environments.
+ Returns a dict of instantiated environments.
"""
result = {}
for extension in extensions:
- if isinstance(extension, basestring):
+ if isinstance(extension, string_types):
extension = import_string(extension)
result[extension.identifier] = extension(environment)
return result
@@ -134,12 +144,23 @@ class Environment(object):
If this is set to ``True`` the first newline after a block is
removed (block, not variable tag!). Defaults to `False`.
+ `lstrip_blocks`
+ If this is set to ``True`` leading spaces and tabs are stripped
+ from the start of a line to a block. Defaults to `False`.
+
`newline_sequence`
The sequence that starts a newline. Must be one of ``'\r'``,
``'\n'`` or ``'\r\n'``. The default is ``'\n'`` which is a
useful default for Linux and OS X systems as well as web
applications.
+ `keep_trailing_newline`
+ Preserve the trailing newline when rendering templates.
+ The default is ``False``, which causes a single newline,
+ if present, to be stripped from the end of the template.
+
+ .. versionadded:: 2.7
+
`extensions`
List of Jinja extensions to use. This can either be import paths
as strings or extension classes. For more information have a
@@ -224,7 +245,9 @@ class Environment(object):
line_statement_prefix=LINE_STATEMENT_PREFIX,
line_comment_prefix=LINE_COMMENT_PREFIX,
trim_blocks=TRIM_BLOCKS,
+ lstrip_blocks=LSTRIP_BLOCKS,
newline_sequence=NEWLINE_SEQUENCE,
+ keep_trailing_newline=KEEP_TRAILING_NEWLINE,
extensions=(),
optimized=True,
undefined=Undefined,
@@ -239,7 +262,7 @@ class Environment(object):
# passed by keyword rather than position. However it's important to
# not change the order of arguments because it's used at least
# internally in those cases:
- # - spontaneus environments (i18n extension and Template)
+ # - spontaneous environments (i18n extension and Template)
# - unittests
# If parameter changes are required only add parameters at the end
# and don't change the arguments (or the defaults!) of the arguments
@@ -255,7 +278,9 @@ class Environment(object):
self.line_statement_prefix = line_statement_prefix
self.line_comment_prefix = line_comment_prefix
self.trim_blocks = trim_blocks
+ self.lstrip_blocks = lstrip_blocks
self.newline_sequence = newline_sequence
+ self.keep_trailing_newline = keep_trailing_newline
# runtime information
self.undefined = undefined
@@ -270,7 +295,6 @@ class Environment(object):
# set the loader provided
self.loader = loader
- self.bytecode_cache = None
self.cache = create_cache(cache_size)
self.bytecode_cache = bytecode_cache
self.auto_reload = auto_reload
@@ -292,7 +316,7 @@ class Environment(object):
yet. This is used by :ref:`extensions <writing-extensions>` to register
callbacks and configuration values without breaking inheritance.
"""
- for key, value in attributes.iteritems():
+ for key, value in iteritems(attributes):
if not hasattr(self, key):
setattr(self, key, value)
@@ -300,7 +324,8 @@ class Environment(object):
variable_start_string=missing, variable_end_string=missing,
comment_start_string=missing, comment_end_string=missing,
line_statement_prefix=missing, line_comment_prefix=missing,
- trim_blocks=missing, extensions=missing, optimized=missing,
+ trim_blocks=missing, lstrip_blocks=missing,
+ extensions=missing, optimized=missing,
undefined=missing, finalize=missing, autoescape=missing,
loader=missing, cache_size=missing, auto_reload=missing,
bytecode_cache=missing):
@@ -323,7 +348,7 @@ class Environment(object):
rv.overlayed = True
rv.linked_to = self
- for key, value in args.iteritems():
+ for key, value in iteritems(args):
if value is not missing:
setattr(rv, key, value)
@@ -333,7 +358,7 @@ class Environment(object):
rv.cache = copy_cache(self.cache)
rv.extensions = {}
- for key, value in self.extensions.iteritems():
+ for key, value in iteritems(self.extensions):
rv.extensions[key] = value.bind(rv)
if extensions is not missing:
rv.extensions.update(load_extensions(rv, extensions))
@@ -352,7 +377,7 @@ class Environment(object):
try:
return obj[argument]
except (TypeError, LookupError):
- if isinstance(argument, basestring):
+ if isinstance(argument, string_types):
try:
attr = str(argument)
except Exception:
@@ -377,6 +402,42 @@ class Environment(object):
except (TypeError, LookupError, AttributeError):
return self.undefined(obj=obj, name=attribute)
+ def call_filter(self, name, value, args=None, kwargs=None,
+ context=None, eval_ctx=None):
+ """Invokes a filter on a value the same way the compiler does it.
+
+ .. versionadded:: 2.7
+ """
+ func = self.filters.get(name)
+ if func is None:
+ raise TemplateRuntimeError('no filter named %r' % name)
+ args = [value] + list(args or ())
+ if getattr(func, 'contextfilter', False):
+ if context is None:
+ raise TemplateRuntimeError('Attempted to invoke context '
+ 'filter without context')
+ args.insert(0, context)
+ elif getattr(func, 'evalcontextfilter', False):
+ if eval_ctx is None:
+ if context is not None:
+ eval_ctx = context.eval_ctx
+ else:
+ eval_ctx = EvalContext(self)
+ args.insert(0, eval_ctx)
+ elif getattr(func, 'environmentfilter', False):
+ args.insert(0, self)
+ return func(*args, **(kwargs or {}))
+
+ def call_test(self, name, value, args=None, kwargs=None):
+ """Invokes a test on a value the same way the compiler does it.
+
+ .. versionadded:: 2.7
+ """
+ func = self.tests.get(name)
+ if func is None:
+ raise TemplateRuntimeError('no test named %r' % name)
+ return func(value, *(args or ()), **(kwargs or {}))
+
@internalcode
def parse(self, source, name=None, filename=None):
"""Parse the sourcecode and return the abstract syntax tree. This
@@ -395,7 +456,7 @@ class Environment(object):
def _parse(self, source, name, filename):
"""Internal parsing function used by `parse` and `compile`."""
- return Parser(self, source, name, _encode_filename(filename)).parse()
+ return Parser(self, source, name, encode_filename(filename)).parse()
def lex(self, source, name=None, filename=None):
"""Lex the given sourcecode and return a generator that yields
@@ -407,7 +468,7 @@ class Environment(object):
of the extensions to be applied you have to filter source through
the :meth:`preprocess` method.
"""
- source = unicode(source)
+ source = text_type(source)
try:
return self.lexer.tokeniter(source, name, filename)
except TemplateSyntaxError:
@@ -420,7 +481,7 @@ class Environment(object):
because there you usually only want the actual source tokenized.
"""
return reduce(lambda s, e: e.preprocess(s, name, filename),
- self.iter_extensions(), unicode(source))
+ self.iter_extensions(), text_type(source))
def _tokenize(self, source, name, filename=None, state=None):
"""Called by the parser to do the preprocessing and filtering
@@ -435,7 +496,7 @@ class Environment(object):
return stream
def _generate(self, source, name, filename, defer_init=False):
- """Internal hook that can be overriden to hook a different generate
+ """Internal hook that can be overridden to hook a different generate
method in.
.. versionadded:: 2.5
@@ -443,7 +504,7 @@ class Environment(object):
return generate(source, self, name, filename, defer_init=defer_init)
def _compile(self, source, filename):
- """Internal hook that can be overriden to hook a different compile
+ """Internal hook that can be overridden to hook a different compile
method in.
.. versionadded:: 2.5
@@ -474,7 +535,7 @@ class Environment(object):
"""
source_hint = None
try:
- if isinstance(source, basestring):
+ if isinstance(source, string_types):
source_hint = source
source = self._parse(source, name, filename)
if self.optimized:
@@ -486,7 +547,7 @@ class Environment(object):
if filename is None:
filename = '<template>'
else:
- filename = _encode_filename(filename)
+ filename = encode_filename(filename)
return self._compile(source, filename)
except TemplateSyntaxError:
exc_info = sys.exc_info()
@@ -556,7 +617,9 @@ class Environment(object):
to `False` and you will get an exception on syntax errors.
If `py_compile` is set to `True` .pyc files will be written to the
- target instead of standard .py files.
+ target instead of standard .py files. This flag does not do anything
+ on pypy and Python 3 where pyc files are not picked up by itself and
+ don't give much benefit.
.. versionadded:: 2.4
"""
@@ -566,14 +629,23 @@ class Environment(object):
log_function = lambda x: None
if py_compile:
- import imp, marshal
- py_header = imp.get_magic() + \
- u'\xff\xff\xff\xff'.encode('iso-8859-15')
+ if not PY2 or PYPY:
+ from warnings import warn
+ warn(Warning('py_compile has no effect on pypy or Python 3'))
+ py_compile = False
+ else:
+ import imp, marshal
+ py_header = imp.get_magic() + \
+ u'\xff\xff\xff\xff'.encode('iso-8859-15')
+
+ # Python 3.3 added a source filesize to the header
+ if sys.version_info >= (3, 3):
+ py_header += u'\x00\x00\x00\x00'.encode('iso-8859-15')
def write_file(filename, data, mode):
if zip:
info = ZipInfo(filename)
- info.external_attr = 0755 << 16L
+ info.external_attr = 0o755 << 16
zip_file.writestr(info, data)
else:
f = open(os.path.join(target, filename), mode)
@@ -597,7 +669,7 @@ class Environment(object):
source, filename, _ = self.loader.get_source(self, name)
try:
code = self.compile(source, name, filename, True, True)
- except TemplateSyntaxError, e:
+ except TemplateSyntaxError as e:
if not ignore_errors:
raise
log_function('Could not compile "%s": %s' % (name, e))
@@ -606,7 +678,7 @@ class Environment(object):
filename = ModuleLoader.get_module_filename(name)
if py_compile:
- c = self._compile(code, _encode_filename(filename))
+ c = self._compile(code, encode_filename(filename))
write_file(filename + 'c', py_header +
marshal.dumps(c), 'wb')
log_function('Byte-compiled "%s" as %s' %
@@ -644,7 +716,7 @@ class Environment(object):
filter_func = lambda x: '.' in x and \
x.rsplit('.', 1)[1] in extensions
if filter_func is not None:
- x = filter(filter_func, x)
+ x = ifilter(filter_func, x)
return x
def handle_exception(self, exc_info=None, rendered=False, source_hint=None):
@@ -667,7 +739,7 @@ class Environment(object):
if self.exception_handler is not None:
self.exception_handler(traceback)
exc_type, exc_value, tb = traceback.standard_exc_info
- raise exc_type, exc_value, tb
+ reraise(exc_type, exc_value, tb)
def join_path(self, template, parent):
"""Join a template with the parent. By default all the lookups are
@@ -754,7 +826,7 @@ class Environment(object):
.. versionadded:: 2.3
"""
- if isinstance(template_name_or_list, basestring):
+ if isinstance(template_name_or_list, string_types):
return self.get_template(template_name_or_list, parent, globals)
elif isinstance(template_name_or_list, Template):
return template_name_or_list
@@ -816,7 +888,9 @@ class Template(object):
line_statement_prefix=LINE_STATEMENT_PREFIX,
line_comment_prefix=LINE_COMMENT_PREFIX,
trim_blocks=TRIM_BLOCKS,
+ lstrip_blocks=LSTRIP_BLOCKS,
newline_sequence=NEWLINE_SEQUENCE,
+ keep_trailing_newline=KEEP_TRAILING_NEWLINE,
extensions=(),
optimized=True,
undefined=Undefined,
@@ -826,8 +900,9 @@ class Template(object):
block_start_string, block_end_string, variable_start_string,
variable_end_string, comment_start_string, comment_end_string,
line_statement_prefix, line_comment_prefix, trim_blocks,
- newline_sequence, frozenset(extensions), optimized, undefined,
- finalize, autoescape, None, 0, False, None)
+ lstrip_blocks, newline_sequence, keep_trailing_newline,
+ frozenset(extensions), optimized, undefined, finalize, autoescape,
+ None, 0, False, None)
return env.from_string(source, template_class=cls)
@classmethod
@@ -839,7 +914,7 @@ class Template(object):
'environment': environment,
'__file__': code.co_filename
}
- exec code in namespace
+ exec(code, namespace)
rv = cls._from_namespace(environment, namespace, globals)
rv._uptodate = uptodate
return rv
@@ -973,7 +1048,7 @@ class Template(object):
@property
def debug_info(self):
"""The debug info mapping."""
- return [tuple(map(int, x.split('='))) for x in
+ return [tuple(imap(int, x.split('='))) for x in
self._debug_info.split('&')]
def __repr__(self):
@@ -984,6 +1059,7 @@ class Template(object):
return '<%s %s>' % (self.__class__.__name__, name)
+@implements_to_string
class TemplateModule(object):
"""Represents an imported template. All the exported names of the
template are available as attributes on this object. Additionally
@@ -999,13 +1075,6 @@ class TemplateModule(object):
return Markup(concat(self._body_stream))
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 concat(self._body_stream)
def __repr__(self):
@@ -1035,6 +1104,7 @@ class TemplateExpression(object):
return rv
+@implements_iterator
class TemplateStream(object):
"""A template stream works pretty much like an ordinary python generator
but it can buffer multiple items to reduce the number of total iterations.
@@ -1053,15 +1123,15 @@ class TemplateStream(object):
def dump(self, fp, encoding=None, errors='strict'):
"""Dump the complete stream into a file or file-like object.
Per default unicode strings are written, if you want to encode
- before writing specifiy an `encoding`.
+ before writing specify an `encoding`.
Example usage::
Template('Hello {{ name }}!').stream(name='foo').dump('hello.html')
"""
close = False
- if isinstance(fp, basestring):
- fp = file(fp, 'w')
+ if isinstance(fp, string_types):
+ fp = open(fp, encoding is None and 'w' or 'wb')
close = True
try:
if encoding is not None:
@@ -1079,7 +1149,7 @@ class TemplateStream(object):
def disable_buffering(self):
"""Disable the output buffering."""
- self._next = self._gen.next
+ self._next = get_next(self._gen)
self.buffered = False
def enable_buffering(self, size=5):
@@ -1107,12 +1177,12 @@ class TemplateStream(object):
c_size = 0
self.buffered = True
- self._next = generator(self._gen.next).next
+ self._next = get_next(generator(get_next(self._gen)))
def __iter__(self):
return self
- def next(self):
+ def __next__(self):
return self._next()
diff --git a/chromium/third_party/jinja2/exceptions.py b/chromium/third_party/jinja2/exceptions.py
index 771f6a8d7a7..c9df6dc7c28 100644
--- a/chromium/third_party/jinja2/exceptions.py
+++ b/chromium/third_party/jinja2/exceptions.py
@@ -8,24 +8,40 @@
:copyright: (c) 2010 by the Jinja Team.
:license: BSD, see LICENSE for more details.
"""
+from jinja2._compat import imap, text_type, PY2, implements_to_string
class TemplateError(Exception):
"""Baseclass for all template errors."""
- def __init__(self, message=None):
- if message is not None:
- message = unicode(message).encode('utf-8')
- Exception.__init__(self, message)
-
- @property
- def message(self):
- if self.args:
- message = self.args[0]
+ if PY2:
+ def __init__(self, message=None):
if message is not None:
- return message.decode('utf-8', 'replace')
-
-
+ message = text_type(message).encode('utf-8')
+ Exception.__init__(self, message)
+
+ @property
+ def message(self):
+ if self.args:
+ message = self.args[0]
+ if message is not None:
+ return message.decode('utf-8', 'replace')
+
+ def __unicode__(self):
+ return self.message or u''
+ else:
+ def __init__(self, message=None):
+ Exception.__init__(self, message)
+
+ @property
+ def message(self):
+ if self.args:
+ message = self.args[0]
+ if message is not None:
+ return message
+
+
+@implements_to_string
class TemplateNotFound(IOError, LookupError, TemplateError):
"""Raised if a template does not exist."""
@@ -42,13 +58,6 @@ class TemplateNotFound(IOError, LookupError, TemplateError):
self.templates = [name]
def __str__(self):
- return self.message.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 self.message
@@ -62,12 +71,13 @@ class TemplatesNotFound(TemplateNotFound):
def __init__(self, names=(), message=None):
if message is None:
- message = u'non of the templates given were found: ' + \
- u', '.join(map(unicode, names))
+ message = u'none of the templates given were found: ' + \
+ u', '.join(imap(text_type, names))
TemplateNotFound.__init__(self, names and names[-1] or None, message)
self.templates = list(names)
+@implements_to_string
class TemplateSyntaxError(TemplateError):
"""Raised to tell the user that there is a problem with the template."""
@@ -83,13 +93,6 @@ class TemplateSyntaxError(TemplateError):
self.translated = False
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):
# for translated errors we only return the message
if self.translated:
return self.message
diff --git a/chromium/third_party/jinja2/ext.py b/chromium/third_party/jinja2/ext.py
index 5ba6efdbf87..c2df12d5592 100644
--- a/chromium/third_party/jinja2/ext.py
+++ b/chromium/third_party/jinja2/ext.py
@@ -10,13 +10,17 @@
:copyright: (c) 2010 by the Jinja Team.
:license: BSD.
"""
-from collections import deque
from jinja2 import nodes
-from jinja2.defaults import *
+from jinja2.defaults import BLOCK_START_STRING, \
+ BLOCK_END_STRING, VARIABLE_START_STRING, VARIABLE_END_STRING, \
+ COMMENT_START_STRING, COMMENT_END_STRING, LINE_STATEMENT_PREFIX, \
+ LINE_COMMENT_PREFIX, TRIM_BLOCKS, NEWLINE_SEQUENCE, \
+ KEEP_TRAILING_NEWLINE, LSTRIP_BLOCKS
from jinja2.environment import Environment
-from jinja2.runtime import Undefined, concat
+from jinja2.runtime import concat
from jinja2.exceptions import TemplateAssertionError, TemplateSyntaxError
-from jinja2.utils import contextfunction, import_string, Markup, next
+from jinja2.utils import contextfunction, import_string, Markup
+from jinja2._compat import next, with_metaclass, string_types, iteritems
# the only real useful gettext functions for a Jinja template. Note
@@ -34,7 +38,7 @@ class ExtensionRegistry(type):
return rv
-class Extension(object):
+class Extension(with_metaclass(ExtensionRegistry, object)):
"""Extensions can be used to add extra functionality to the Jinja template
system at the parser level. Custom extensions are bound to an environment
but may not store environment specific data on `self`. The reason for
@@ -52,7 +56,6 @@ class Extension(object):
is a terrible name, ``fragment_cache_prefix`` on the other hand is a good
name as includes the name of the extension (fragment cache).
"""
- __metaclass__ = ExtensionRegistry
#: if this extension parses this is the list of tags it's listening to.
tags = set()
@@ -205,7 +208,7 @@ class InternationalizationExtension(Extension):
self.environment.globals.pop(key, None)
def _extract(self, source, gettext_functions=GETTEXT_FUNCTIONS):
- if isinstance(source, basestring):
+ if isinstance(source, string_types):
source = self.environment.parse(source)
return extract_from_ast(source, gettext_functions)
@@ -218,6 +221,7 @@ class InternationalizationExtension(Extension):
# defined in the body of the trans block too, but this is checked at
# a later state.
plural_expr = None
+ plural_expr_assignment = None
variables = {}
while parser.stream.current.type != 'block_end':
if variables:
@@ -241,7 +245,13 @@ class InternationalizationExtension(Extension):
variables[name.value] = var = nodes.Name(name.value, 'load')
if plural_expr is None:
- plural_expr = var
+ if isinstance(var, nodes.Call):
+ plural_expr = nodes.Name('_trans', 'load')
+ variables[name.value] = plural_expr
+ plural_expr_assignment = nodes.Assign(
+ nodes.Name('_trans', 'store'), var)
+ else:
+ plural_expr = var
num_called_num = name.value == 'num'
parser.stream.expect('block_end')
@@ -291,7 +301,10 @@ class InternationalizationExtension(Extension):
bool(referenced),
num_called_num and have_plural)
node.set_lineno(lineno)
- return node
+ if plural_expr_assignment is not None:
+ return [plural_expr_assignment, node]
+ else:
+ return node
def _parse_block(self, parser, allow_pluralize):
"""Parse until the next block tag with a given name."""
@@ -354,7 +367,7 @@ class InternationalizationExtension(Extension):
# enough to handle the variable expansion and autoescape
# handling itself
if self.environment.newstyle_gettext:
- for key, value in variables.iteritems():
+ for key, value in iteritems(variables):
# the function adds that later anyways in case num was
# called num, so just skip it.
if num_called_num and key == 'num':
@@ -476,7 +489,7 @@ def extract_from_ast(node, gettext_functions=GETTEXT_FUNCTIONS,
strings = []
for arg in node.args:
if isinstance(arg, nodes.Const) and \
- isinstance(arg.value, basestring):
+ isinstance(arg.value, string_types):
strings.append(arg.value)
else:
strings.append(None)
@@ -552,6 +565,10 @@ def babel_extract(fileobj, keywords, comment_tags, options):
The `newstyle_gettext` flag can be set to `True` to enable newstyle
gettext calls.
+ .. versionchanged:: 2.7
+ A `silent` option can now be provided. If set to `False` template
+ syntax errors are propagated instead of being ignored.
+
:param fileobj: the file-like object the messages should be extracted from
:param keywords: a list of keywords (i.e. function names) that should be
recognized as translation functions
@@ -571,8 +588,10 @@ def babel_extract(fileobj, keywords, comment_tags, options):
extensions.add(InternationalizationExtension)
def getbool(options, key, default=False):
- options.get(key, str(default)).lower() in ('1', 'on', 'yes', 'true')
+ return options.get(key, str(default)).lower() in \
+ ('1', 'on', 'yes', 'true')
+ silent = getbool(options, 'silent', True)
environment = Environment(
options.get('block_start_string', BLOCK_START_STRING),
options.get('block_end_string', BLOCK_END_STRING),
@@ -583,7 +602,10 @@ def babel_extract(fileobj, keywords, comment_tags, options):
options.get('line_statement_prefix') or LINE_STATEMENT_PREFIX,
options.get('line_comment_prefix') or LINE_COMMENT_PREFIX,
getbool(options, 'trim_blocks', TRIM_BLOCKS),
- NEWLINE_SEQUENCE, frozenset(extensions),
+ getbool(options, 'lstrip_blocks', LSTRIP_BLOCKS),
+ NEWLINE_SEQUENCE,
+ getbool(options, 'keep_trailing_newline', KEEP_TRAILING_NEWLINE),
+ frozenset(extensions),
cache_size=0,
auto_reload=False
)
@@ -595,7 +617,9 @@ def babel_extract(fileobj, keywords, comment_tags, options):
try:
node = environment.parse(source)
tokens = list(environment.lex(environment.preprocess(source)))
- except TemplateSyntaxError, e:
+ except TemplateSyntaxError as e:
+ if not silent:
+ raise
# skip templates with syntax errors
return
diff --git a/chromium/third_party/jinja2/filters.py b/chromium/third_party/jinja2/filters.py
index 1ef47f95161..fd0db04aa41 100644
--- a/chromium/third_party/jinja2/filters.py
+++ b/chromium/third_party/jinja2/filters.py
@@ -10,12 +10,15 @@
"""
import re
import math
+
from random import choice
from operator import itemgetter
-from itertools import imap, groupby
-from jinja2.utils import Markup, escape, pformat, urlize, soft_unicode
+from itertools import groupby
+from jinja2.utils import Markup, escape, pformat, urlize, soft_unicode, \
+ unicode_urlencode
from jinja2.runtime import Undefined
-from jinja2.exceptions import FilterArgumentError, SecurityError
+from jinja2.exceptions import FilterArgumentError
+from jinja2._compat import next, imap, string_types, text_type, iteritems
_word_re = re.compile(r'\w+(?u)')
@@ -51,13 +54,17 @@ def environmentfilter(f):
def make_attrgetter(environment, attribute):
"""Returns a callable that looks up the given attribute from a
passed object with the rules of the environment. Dots are allowed
- to access attributes of attributes.
+ to access attributes of attributes. Integer parts in paths are
+ looked up as integers.
"""
- if not isinstance(attribute, basestring) or '.' not in attribute:
+ if not isinstance(attribute, string_types) \
+ or ('.' not in attribute and not attribute.isdigit()):
return lambda x: environment.getitem(x, attribute)
attribute = attribute.split('.')
def attrgetter(item):
for part in attribute:
+ if part.isdigit():
+ part = int(part)
item = environment.getitem(item, part)
return item
return attrgetter
@@ -67,7 +74,27 @@ def do_forceescape(value):
"""Enforce HTML escaping. This will probably double escape variables."""
if hasattr(value, '__html__'):
value = value.__html__()
- return escape(unicode(value))
+ return escape(text_type(value))
+
+
+def do_urlencode(value):
+ """Escape strings for use in URLs (uses UTF-8 encoding). It accepts both
+ dictionaries and regular strings as well as pairwise iterables.
+
+ .. versionadded:: 2.7
+ """
+ itemiter = None
+ if isinstance(value, dict):
+ itemiter = iteritems(value)
+ elif not isinstance(value, string_types):
+ try:
+ itemiter = iter(value)
+ except TypeError:
+ pass
+ if itemiter is None:
+ return unicode_urlencode(value)
+ return u'&'.join(unicode_urlencode(k) + '=' +
+ unicode_urlencode(v) for k, v in itemiter)
@evalcontextfilter
@@ -89,7 +116,7 @@ def do_replace(eval_ctx, s, old, new, count=None):
if count is None:
count = -1
if not eval_ctx.autoescape:
- return unicode(s).replace(unicode(old), unicode(new), count)
+ return text_type(s).replace(text_type(old), text_type(new), count)
if hasattr(old, '__html__') or hasattr(new, '__html__') and \
not hasattr(s, '__html__'):
s = escape(s)
@@ -134,7 +161,7 @@ def do_xmlattr(_eval_ctx, d, autospace=True):
"""
rv = u' '.join(
u'%s="%s"' % (escape(key), escape(value))
- for key, value in d.iteritems()
+ for key, value in iteritems(d)
if value is not None and not isinstance(value, Undefined)
)
if autospace and rv:
@@ -155,7 +182,12 @@ def do_title(s):
"""Return a titlecased version of the value. I.e. words will start with
uppercase letters, all remaining characters are lowercase.
"""
- return soft_unicode(s).title()
+ rv = []
+ for item in re.compile(r'([-\s]+)(?u)').split(s):
+ if not item:
+ continue
+ rv.append(item[0].upper() + item[1:].lower())
+ return ''.join(rv)
def do_dictsort(value, case_sensitive=False, by='key'):
@@ -168,7 +200,7 @@ def do_dictsort(value, case_sensitive=False, by='key'):
{% for item in mydict|dictsort %}
sort the dict by key, case insensitive
- {% for item in mydict|dicsort(true) %}
+ {% for item in mydict|dictsort(true) %}
sort the dict by key, case sensitive
{% for item in mydict|dictsort(false, 'value') %}
@@ -184,7 +216,7 @@ def do_dictsort(value, case_sensitive=False, by='key'):
'"key" or "value"')
def sort_func(item):
value = item[pos]
- if isinstance(value, basestring) and not case_sensitive:
+ if isinstance(value, string_types) and not case_sensitive:
value = value.lower()
return value
@@ -221,7 +253,7 @@ def do_sort(environment, value, reverse=False, case_sensitive=False,
"""
if not case_sensitive:
def sort_func(item):
- if isinstance(item, basestring):
+ if isinstance(item, string_types):
item = item.lower()
return item
else:
@@ -250,7 +282,7 @@ def do_default(value, default_value=u'', boolean=False):
{{ ''|default('the string was empty', true) }}
"""
- if (boolean and not value) or isinstance(value, Undefined):
+ if isinstance(value, Undefined) or (boolean and not value):
return default_value
return value
@@ -283,7 +315,7 @@ def do_join(eval_ctx, value, d=u'', attribute=None):
# no automatic escaping? joining is a lot eaiser then
if not eval_ctx.autoescape:
- return unicode(d).join(imap(unicode, value))
+ return text_type(d).join(imap(text_type, value))
# if the delimiter doesn't have an html representation we check
# if any of the items has. If yes we do a coercion to Markup
@@ -294,11 +326,11 @@ def do_join(eval_ctx, value, d=u'', attribute=None):
if hasattr(item, '__html__'):
do_escape = True
else:
- value[idx] = unicode(item)
+ value[idx] = text_type(item)
if do_escape:
d = escape(d)
else:
- d = unicode(d)
+ d = text_type(d)
return d.join(value)
# no html involved, to normal joining
@@ -307,14 +339,14 @@ def do_join(eval_ctx, value, d=u'', attribute=None):
def do_center(value, width=80):
"""Centers the value in a field of a given width."""
- return unicode(value).center(width)
+ return text_type(value).center(width)
@environmentfilter
def do_first(environment, seq):
"""Return the first item of a sequence."""
try:
- return iter(seq).next()
+ return next(iter(seq))
except StopIteration:
return environment.undefined('No first item, sequence was empty.')
@@ -323,7 +355,7 @@ def do_first(environment, seq):
def do_last(environment, seq):
"""Return the last item of a sequence."""
try:
- return iter(reversed(seq)).next()
+ return next(iter(reversed(seq)))
except StopIteration:
return environment.undefined('No last item, sequence was empty.')
@@ -346,25 +378,25 @@ def do_filesizeformat(value, binary=False):
bytes = float(value)
base = binary and 1024 or 1000
prefixes = [
- (binary and "KiB" or "kB"),
- (binary and "MiB" or "MB"),
- (binary and "GiB" or "GB"),
- (binary and "TiB" or "TB"),
- (binary and "PiB" or "PB"),
- (binary and "EiB" or "EB"),
- (binary and "ZiB" or "ZB"),
- (binary and "YiB" or "YB")
+ (binary and 'KiB' or 'kB'),
+ (binary and 'MiB' or 'MB'),
+ (binary and 'GiB' or 'GB'),
+ (binary and 'TiB' or 'TB'),
+ (binary and 'PiB' or 'PB'),
+ (binary and 'EiB' or 'EB'),
+ (binary and 'ZiB' or 'ZB'),
+ (binary and 'YiB' or 'YB')
]
if bytes == 1:
- return "1 Byte"
+ return '1 Byte'
elif bytes < base:
- return "%d Bytes" % bytes
+ return '%d Bytes' % bytes
else:
for i, prefix in enumerate(prefixes):
- unit = base * base ** (i + 1)
+ unit = base ** (i + 2)
if bytes < unit:
- return "%.1f %s" % ((bytes / unit), prefix)
- return "%.1f %s" % ((bytes / unit), prefix)
+ return '%.1f %s' % ((base * bytes / unit), prefix)
+ return '%.1f %s' % ((base * bytes / unit), prefix)
def do_pprint(value, verbose=False):
@@ -417,16 +449,17 @@ def do_truncate(s, length=255, killwords=False, end='...'):
"""Return a truncated copy of the string. The length is specified
with the first parameter which defaults to ``255``. If the second
parameter is ``true`` the filter will cut the text at length. Otherwise
- it will try to save the last word. If the text was in fact
+ it will discard the last word. If the text was in fact
truncated it will append an ellipsis sign (``"..."``). If you want a
different ellipsis sign than ``"..."`` you can specify it using the
third parameter.
- .. sourcecode jinja::
+ .. sourcecode:: jinja
- {{ mytext|truncate(300, false, '&raquo;') }}
- truncate mytext to 300 chars, don't split up words, use a
- right pointing double arrow as ellipsis sign.
+ {{ "foo bar"|truncate(5) }}
+ -> "foo ..."
+ {{ "foo bar"|truncate(5, True) }}
+ -> "foo b..."
"""
if len(s) <= length:
return s
@@ -444,15 +477,23 @@ def do_truncate(s, length=255, killwords=False, end='...'):
return u' '.join(result)
@environmentfilter
-def do_wordwrap(environment, s, width=79, break_long_words=True):
+def do_wordwrap(environment, s, width=79, break_long_words=True,
+ wrapstring=None):
"""
Return a copy of the string passed to the filter wrapped after
``79`` characters. You can override this default using the first
parameter. If you set the second parameter to `false` Jinja will not
- split words apart if they are longer than `width`.
+ split words apart if they are longer than `width`. By default, the newlines
+ will be the default newlines for the environment, but this can be changed
+ using the wrapstring keyword argument.
+
+ .. versionadded:: 2.7
+ Added support for the `wrapstring` parameter.
"""
+ if not wrapstring:
+ wrapstring = environment.newline_sequence
import textwrap
- return environment.newline_sequence.join(textwrap.wrap(s, width=width, expand_tabs=False,
+ return wrapstring.join(textwrap.wrap(s, width=width, expand_tabs=False,
replace_whitespace=False,
break_long_words=break_long_words))
@@ -513,7 +554,7 @@ def do_striptags(value):
"""
if hasattr(value, '__html__'):
value = value.__html__()
- return Markup(unicode(value)).striptags()
+ return Markup(text_type(value)).striptags()
def do_slice(value, slices, fill_with=None):
@@ -541,7 +582,7 @@ def do_slice(value, slices, fill_with=None):
items_per_slice = length // slices
slices_with_extra = length % slices
offset = 0
- for slice_number in xrange(slices):
+ for slice_number in range(slices):
start = offset + slice_number * items_per_slice
if slice_number < slices_with_extra:
offset += 1
@@ -557,7 +598,7 @@ def do_batch(value, linecount, fill_with=None):
A filter that batches items. It works pretty much like `slice`
just the other way round. It returns a list of lists with the
given number of items. If you provide a second parameter this
- is used to fill missing items. See this example:
+ is used to fill up missing items. See this example:
.. sourcecode:: html+jinja
@@ -666,7 +707,8 @@ class _GroupTuple(tuple):
grouper = property(itemgetter(0))
list = property(itemgetter(1))
- def __new__(cls, (key, value)):
+ def __new__(cls, xxx_todo_changeme):
+ (key, value) = xxx_todo_changeme
return tuple.__new__(cls, (key, list(value)))
@@ -707,14 +749,14 @@ def do_mark_safe(value):
def do_mark_unsafe(value):
"""Mark a value as unsafe. This is the reverse operation for :func:`safe`."""
- return unicode(value)
+ return text_type(value)
def do_reverse(value):
"""Reverse the object or return an iterator the iterates over it the other
way round.
"""
- if isinstance(value, basestring):
+ if isinstance(value, string_types):
return value[::-1]
try:
return reversed(value)
@@ -752,6 +794,144 @@ def do_attr(environment, obj, name):
return environment.undefined(obj=obj, name=name)
+@contextfilter
+def do_map(*args, **kwargs):
+ """Applies a filter on a sequence of objects or looks up an attribute.
+ This is useful when dealing with lists of objects but you are really
+ only interested in a certain value of it.
+
+ The basic usage is mapping on an attribute. Imagine you have a list
+ of users but you are only interested in a list of usernames:
+
+ .. sourcecode:: jinja
+
+ Users on this page: {{ users|map(attribute='username')|join(', ') }}
+
+ Alternatively you can let it invoke a filter by passing the name of the
+ filter and the arguments afterwards. A good example would be applying a
+ text conversion filter on a sequence:
+
+ .. sourcecode:: jinja
+
+ Users on this page: {{ titles|map('lower')|join(', ') }}
+
+ .. versionadded:: 2.7
+ """
+ context = args[0]
+ seq = args[1]
+
+ if len(args) == 2 and 'attribute' in kwargs:
+ attribute = kwargs.pop('attribute')
+ if kwargs:
+ raise FilterArgumentError('Unexpected keyword argument %r' %
+ next(iter(kwargs)))
+ func = make_attrgetter(context.environment, attribute)
+ else:
+ try:
+ name = args[2]
+ args = args[3:]
+ except LookupError:
+ raise FilterArgumentError('map requires a filter argument')
+ func = lambda item: context.environment.call_filter(
+ name, item, args, kwargs, context=context)
+
+ if seq:
+ for item in seq:
+ yield func(item)
+
+
+@contextfilter
+def do_select(*args, **kwargs):
+ """Filters a sequence of objects by appying a test to either the object
+ or the attribute and only selecting the ones with the test succeeding.
+
+ Example usage:
+
+ .. sourcecode:: jinja
+
+ {{ numbers|select("odd") }}
+
+ .. versionadded:: 2.7
+ """
+ return _select_or_reject(args, kwargs, lambda x: x, False)
+
+
+@contextfilter
+def do_reject(*args, **kwargs):
+ """Filters a sequence of objects by appying a test to either the object
+ or the attribute and rejecting the ones with the test succeeding.
+
+ Example usage:
+
+ .. sourcecode:: jinja
+
+ {{ numbers|reject("odd") }}
+
+ .. versionadded:: 2.7
+ """
+ return _select_or_reject(args, kwargs, lambda x: not x, False)
+
+
+@contextfilter
+def do_selectattr(*args, **kwargs):
+ """Filters a sequence of objects by appying a test to either the object
+ or the attribute and only selecting the ones with the test succeeding.
+
+ Example usage:
+
+ .. sourcecode:: jinja
+
+ {{ users|selectattr("is_active") }}
+ {{ users|selectattr("email", "none") }}
+
+ .. versionadded:: 2.7
+ """
+ return _select_or_reject(args, kwargs, lambda x: x, True)
+
+
+@contextfilter
+def do_rejectattr(*args, **kwargs):
+ """Filters a sequence of objects by appying a test to either the object
+ or the attribute and rejecting the ones with the test succeeding.
+
+ .. sourcecode:: jinja
+
+ {{ users|rejectattr("is_active") }}
+ {{ users|rejectattr("email", "none") }}
+
+ .. versionadded:: 2.7
+ """
+ return _select_or_reject(args, kwargs, lambda x: not x, True)
+
+
+def _select_or_reject(args, kwargs, modfunc, lookup_attr):
+ context = args[0]
+ seq = args[1]
+ if lookup_attr:
+ try:
+ attr = args[2]
+ except LookupError:
+ raise FilterArgumentError('Missing parameter for attribute name')
+ transfunc = make_attrgetter(context.environment, attr)
+ off = 1
+ else:
+ off = 0
+ transfunc = lambda x: x
+
+ try:
+ name = args[2 + off]
+ args = args[3 + off:]
+ func = lambda item: context.environment.call_test(
+ name, item, args, kwargs)
+ except LookupError:
+ func = bool
+
+ if seq:
+ for item in seq:
+ if modfunc(func(transfunc(item))):
+ yield item
+
+
FILTERS = {
'attr': do_attr,
'replace': do_replace,
@@ -776,7 +956,10 @@ FILTERS = {
'capitalize': do_capitalize,
'first': do_first,
'last': do_last,
+ 'map': do_map,
'random': do_random,
+ 'reject': do_reject,
+ 'rejectattr': do_rejectattr,
'filesizeformat': do_filesizeformat,
'pprint': do_pprint,
'truncate': do_truncate,
@@ -790,6 +973,8 @@ FILTERS = {
'format': do_format,
'trim': do_trim,
'striptags': do_striptags,
+ 'select': do_select,
+ 'selectattr': do_selectattr,
'slice': do_slice,
'batch': do_batch,
'sum': do_sum,
@@ -797,5 +982,6 @@ FILTERS = {
'round': do_round,
'groupby': do_groupby,
'safe': do_mark_safe,
- 'xmlattr': do_xmlattr
+ 'xmlattr': do_xmlattr,
+ 'urlencode': do_urlencode
}
diff --git a/chromium/third_party/jinja2/get_jinja2.sh b/chromium/third_party/jinja2/get_jinja2.sh
new file mode 100755
index 00000000000..950214653ba
--- /dev/null
+++ b/chromium/third_party/jinja2/get_jinja2.sh
@@ -0,0 +1,123 @@
+#!/bin/bash
+# Download and extract Jinja2
+# Homepage:
+# http://jinja.pocoo.org/
+# Installation instructions:
+# http://jinja.pocoo.org/docs/intro/#from-the-tarball-release
+# Download page:
+# https://pypi.python.org/pypi/Jinja2
+PACKAGE='Jinja2'
+VERSION='2.7.1'
+PACKAGE_DIR='jinja2'
+
+CHROMIUM_FILES="README.chromium OWNERS get_jinja2.sh"
+EXTRA_FILES='LICENSE AUTHORS'
+REMOVE_FILES='testsuite'
+
+SRC_URL='https://pypi.python.org/packages/source/'
+SRC_URL+="${PACKAGE:0:1}/$PACKAGE/$PACKAGE-$VERSION.tar.gz"
+FILENAME="$(basename $SRC_URL)"
+MD5_FILENAME="$FILENAME.md5"
+SHA512_FILENAME="$FILENAME.sha512"
+CHROMIUM_FILES+=" $MD5_FILENAME $SHA512_FILENAME"
+
+BUILD_DIR="$PACKAGE-$VERSION"
+THIRD_PARTY="$(dirname $(realpath $(dirname "${BASH_SOURCE[0]}")))"
+INSTALL_DIR="$THIRD_PARTY/$PACKAGE_DIR"
+OUT_DIR="$INSTALL_DIR/$BUILD_DIR/$PACKAGE_DIR"
+OLD_DIR="$THIRD_PARTY/$PACKAGE_DIR.old"
+
+function check_hashes {
+ # Hashes generated via:
+ # FILENAME=Jinja2-2.7.1.tar.gz
+ # md5sum "$FILENAME" > "$FILENAME.md5"
+ # sha512sum "$FILENAME" > "$FILENAME.sha512"
+ # unset FILENAME
+
+ # MD5
+ if ! [ -f "$MD5_FILENAME" ]
+ then
+ echo "MD5 hash file $MD5_FILENAME not found, could not verify archive"
+ exit 1
+ fi
+
+ # 32-digit hash, followed by filename
+ MD5_HASHFILE_REGEX="^[0-9a-f]{32} $FILENAME"
+ if ! grep --extended-regex --line-regex --silent \
+ "$MD5_HASHFILE_REGEX" "$MD5_FILENAME"
+ then
+ echo "MD5 hash file $MD5_FILENAME does not contain hash for $FILENAME," \
+ 'could not verify archive'
+ echo 'Hash file contents are:'
+ cat "$MD5_FILENAME"
+ exit 1
+ fi
+
+ if ! md5sum --check "$MD5_FILENAME"
+ then
+ echo 'MD5 hash does not match,' \
+ "archive file $FILENAME corrupt or compromised!"
+ exit 1
+ fi
+
+ # SHA-512
+ if ! [ -f "$SHA512_FILENAME" ]
+ then
+ echo "SHA-512 hash file $SHA512_FILENAME not found," \
+ 'could not verify archive'
+ exit 1
+ fi
+
+ # 128-digit hash, followed by filename
+ SHA512_HASHFILE_REGEX="^[0-9a-f]{128} $FILENAME"
+ if ! grep --extended-regex --line-regex --silent \
+ "$SHA512_HASHFILE_REGEX" "$SHA512_FILENAME"
+ then
+ echo "SHA-512 hash file $SHA512_FILENAME does not contain hash for" \
+ "$FILENAME, could not verify archive"
+ echo 'Hash file contents are:'
+ cat "$SHA512_FILENAME"
+ exit 1
+ fi
+
+ if ! sha512sum --check "$SHA512_FILENAME"
+ then
+ echo 'SHA-512 hash does not match,' \
+ "archive file $FILENAME corrupt or compromised!"
+ exit 1
+ fi
+}
+
+
+################################################################################
+# Body
+
+cd "$INSTALL_DIR"
+echo "Downloading $SRC_URL"
+curl --remote-name "$SRC_URL"
+check_hashes
+tar xvzf "$FILENAME"
+# Copy extra files over
+for FILE in $CHROMIUM_FILES
+do
+ cp "$FILE" "$OUT_DIR"
+done
+
+cd "$BUILD_DIR"
+for FILE in $EXTRA_FILES
+do
+ cp "$FILE" "$OUT_DIR"
+done
+
+cd "$OUT_DIR"
+for FILE in $REMOVE_FILES
+do
+ rm -fr "$FILE"
+done
+
+# Replace with new directory
+cd ..
+mv "$INSTALL_DIR" "$OLD_DIR"
+mv "$PACKAGE_DIR" "$INSTALL_DIR"
+cd "$INSTALL_DIR"
+rm -fr "$OLD_DIR"
diff --git a/chromium/third_party/jinja2/lexer.py b/chromium/third_party/jinja2/lexer.py
index 0d3f6961715..a50128507bb 100644
--- a/chromium/third_party/jinja2/lexer.py
+++ b/chromium/third_party/jinja2/lexer.py
@@ -15,10 +15,13 @@
:license: BSD, see LICENSE for more details.
"""
import re
+
from operator import itemgetter
from collections import deque
from jinja2.exceptions import TemplateSyntaxError
-from jinja2.utils import LRUCache, next
+from jinja2.utils import LRUCache
+from jinja2._compat import next, iteritems, implements_iterator, text_type, \
+ intern
# cache for the lexers. Exists in order to be able to have multiple
@@ -126,7 +129,7 @@ operators = {
';': TOKEN_SEMICOLON
}
-reverse_operators = dict([(v, k) for k, v in operators.iteritems()])
+reverse_operators = dict([(v, k) for k, v in iteritems(operators)])
assert len(operators) == len(reverse_operators), 'operators dropped'
operator_re = re.compile('(%s)' % '|'.join(re.escape(x) for x in
sorted(operators, key=lambda x: -len(x))))
@@ -197,7 +200,7 @@ def compile_rules(environment):
if environment.line_statement_prefix is not None:
rules.append((len(environment.line_statement_prefix), 'linestatement',
- r'^\s*' + e(environment.line_statement_prefix)))
+ r'^[ \t\v]*' + e(environment.line_statement_prefix)))
if environment.line_comment_prefix is not None:
rules.append((len(environment.line_comment_prefix), 'linecomment',
r'(?:^|(?<=\S))[^\S\r\n]*' +
@@ -262,6 +265,7 @@ class Token(tuple):
)
+@implements_iterator
class TokenStreamIterator(object):
"""The iterator for tokenstreams. Iterate over the stream
until the eof token is reached.
@@ -273,7 +277,7 @@ class TokenStreamIterator(object):
def __iter__(self):
return self
- def next(self):
+ def __next__(self):
token = self.stream.current
if token.type is TOKEN_EOF:
self.stream.close()
@@ -282,6 +286,7 @@ class TokenStreamIterator(object):
return token
+@implements_iterator
class TokenStream(object):
"""A token stream is an iterable that yields :class:`Token`\s. The
parser however does not iterate over it but calls :meth:`next` to go
@@ -289,7 +294,7 @@ class TokenStream(object):
"""
def __init__(self, generator, name, filename):
- self._next = iter(generator).next
+ self._iter = iter(generator)
self._pushed = deque()
self.name = name
self.filename = filename
@@ -300,8 +305,9 @@ class TokenStream(object):
def __iter__(self):
return TokenStreamIterator(self)
- def __nonzero__(self):
+ def __bool__(self):
return bool(self._pushed) or self.current.type is not TOKEN_EOF
+ __nonzero__ = __bool__ # py2
eos = property(lambda x: not x, doc="Are we at the end of the stream?")
@@ -319,7 +325,7 @@ class TokenStream(object):
def skip(self, n=1):
"""Got n tokens ahead."""
- for x in xrange(n):
+ for x in range(n):
next(self)
def next_if(self, expr):
@@ -333,14 +339,14 @@ class TokenStream(object):
"""Like :meth:`next_if` but only returns `True` or `False`."""
return self.next_if(expr) is not None
- def next(self):
+ def __next__(self):
"""Go one token ahead and return the old one"""
rv = self.current
if self._pushed:
self.current = self._pushed.popleft()
elif self.current.type is not TOKEN_EOF:
try:
- self.current = self._next()
+ self.current = next(self._iter)
except StopIteration:
self.close()
return rv
@@ -348,7 +354,7 @@ class TokenStream(object):
def close(self):
"""Close the stream."""
self.current = Token(self.current.lineno, TOKEN_EOF, '')
- self._next = None
+ self._iter = None
self.closed = True
def expect(self, expr):
@@ -383,7 +389,9 @@ def get_lexer(environment):
environment.line_statement_prefix,
environment.line_comment_prefix,
environment.trim_blocks,
- environment.newline_sequence)
+ environment.lstrip_blocks,
+ environment.newline_sequence,
+ environment.keep_trailing_newline)
lexer = _lexer_cache.get(key)
if lexer is None:
lexer = Lexer(environment)
@@ -414,7 +422,7 @@ class Lexer(object):
(operator_re, TOKEN_OPERATOR, None)
]
- # assamble the root lexing rule. because "|" is ungreedy
+ # assemble the root lexing rule. because "|" is ungreedy
# we have to sort by length so that the lexer continues working
# as expected when we have parsing rules like <% for block and
# <%= for variables. (if someone wants asp like syntax)
@@ -425,7 +433,44 @@ class Lexer(object):
# block suffix if trimming is enabled
block_suffix_re = environment.trim_blocks and '\\n?' or ''
+ # strip leading spaces if lstrip_blocks is enabled
+ prefix_re = {}
+ if environment.lstrip_blocks:
+ # use '{%+' to manually disable lstrip_blocks behavior
+ no_lstrip_re = e('+')
+ # detect overlap between block and variable or comment strings
+ block_diff = c(r'^%s(.*)' % e(environment.block_start_string))
+ # make sure we don't mistake a block for a variable or a comment
+ m = block_diff.match(environment.comment_start_string)
+ no_lstrip_re += m and r'|%s' % e(m.group(1)) or ''
+ m = block_diff.match(environment.variable_start_string)
+ no_lstrip_re += m and r'|%s' % e(m.group(1)) or ''
+
+ # detect overlap between comment and variable strings
+ comment_diff = c(r'^%s(.*)' % e(environment.comment_start_string))
+ m = comment_diff.match(environment.variable_start_string)
+ no_variable_re = m and r'(?!%s)' % e(m.group(1)) or ''
+
+ lstrip_re = r'^[ \t]*'
+ block_prefix_re = r'%s%s(?!%s)|%s\+?' % (
+ lstrip_re,
+ e(environment.block_start_string),
+ no_lstrip_re,
+ e(environment.block_start_string),
+ )
+ comment_prefix_re = r'%s%s%s|%s\+?' % (
+ lstrip_re,
+ e(environment.comment_start_string),
+ no_variable_re,
+ e(environment.comment_start_string),
+ )
+ prefix_re['block'] = block_prefix_re
+ prefix_re['comment'] = comment_prefix_re
+ else:
+ block_prefix_re = '%s' % e(environment.block_start_string)
+
self.newline_sequence = environment.newline_sequence
+ self.keep_trailing_newline = environment.keep_trailing_newline
# global lexing rules
self.rules = {
@@ -434,11 +479,11 @@ class Lexer(object):
(c('(.*?)(?:%s)' % '|'.join(
[r'(?P<raw_begin>(?:\s*%s\-|%s)\s*raw\s*(?:\-%s\s*|%s))' % (
e(environment.block_start_string),
- e(environment.block_start_string),
+ block_prefix_re,
e(environment.block_end_string),
e(environment.block_end_string)
)] + [
- r'(?P<%s_begin>\s*%s\-|%s)' % (n, r, r)
+ r'(?P<%s_begin>\s*%s\-|%s)' % (n, r, prefix_re.get(n,r))
for n, r in root_tag_rules
])), (TOKEN_DATA, '#bygroup'), '#bygroup'),
# data
@@ -472,7 +517,7 @@ class Lexer(object):
TOKEN_RAW_BEGIN: [
(c('(.*?)((?:\s*%s\-|%s)\s*endraw\s*(?:\-%s\s*|%s%s))' % (
e(environment.block_start_string),
- e(environment.block_start_string),
+ block_prefix_re,
e(environment.block_end_string),
e(environment.block_end_string),
block_suffix_re
@@ -491,7 +536,7 @@ class Lexer(object):
}
def _normalize_newlines(self, value):
- """Called for strings and template data to normlize it to unicode."""
+ """Called for strings and template data to normalize it to unicode."""
return newline_re.sub(self.newline_sequence, value)
def tokenize(self, source, name=None, filename=None, state=None):
@@ -526,7 +571,7 @@ class Lexer(object):
value = self._normalize_newlines(value[1:-1]) \
.encode('ascii', 'backslashreplace') \
.decode('unicode-escape')
- except Exception, e:
+ except Exception as e:
msg = str(e).split(':')[-1].strip()
raise TemplateSyntaxError(msg, lineno, name, filename)
# if we can express it as bytestring (ascii only)
@@ -549,7 +594,14 @@ class Lexer(object):
"""This method tokenizes the text and returns the tokens in a
generator. Use this method if you just want to tokenize a template.
"""
- source = '\n'.join(unicode(source).splitlines())
+ source = text_type(source)
+ lines = source.splitlines()
+ if self.keep_trailing_newline and source:
+ for newline in ('\r\n', '\r', '\n'):
+ if source.endswith(newline):
+ lines.append('')
+ break
+ source = '\n'.join(lines)
pos = 0
lineno = 1
stack = ['root']
@@ -571,7 +623,7 @@ class Lexer(object):
if m is None:
continue
- # we only match blocks and variables if brances / parentheses
+ # we only match blocks and variables if braces / parentheses
# are balanced. continue parsing with the lower rule which
# is the operator rule. do this only if the end tags look
# like operators
@@ -590,7 +642,7 @@ class Lexer(object):
# yield for the current token the first named
# group that matched
elif token == '#bygroup':
- for key, value in m.groupdict().iteritems():
+ for key, value in iteritems(m.groupdict()):
if value is not None:
yield lineno, key, value
lineno += value.count('\n')
@@ -647,7 +699,7 @@ class Lexer(object):
stack.pop()
# resolve the new state by group checking
elif new_state == '#bygroup':
- for key, value in m.groupdict().iteritems():
+ for key, value in iteritems(m.groupdict()):
if value is not None:
stack.append(key)
break
@@ -669,7 +721,7 @@ class Lexer(object):
# publish new function and start again
pos = pos2
break
- # if loop terminated without break we havn't found a single match
+ # if loop terminated without break we haven't found a single match
# either we are at the end of the file or we have a problem
else:
# end of text
diff --git a/chromium/third_party/jinja2/loaders.py b/chromium/third_party/jinja2/loaders.py
index 419a9c8c6c1..a9a2625274c 100644
--- a/chromium/third_party/jinja2/loaders.py
+++ b/chromium/third_party/jinja2/loaders.py
@@ -13,12 +13,10 @@ import sys
import weakref
from types import ModuleType
from os import path
-try:
- from hashlib import sha1
-except ImportError:
- from sha import new as sha1
+from hashlib import sha1
from jinja2.exceptions import TemplateNotFound
-from jinja2.utils import LRUCache, open_if_exists, internalcode
+from jinja2.utils import open_if_exists, internalcode
+from jinja2._compat import string_types, iteritems
def split_template_path(template):
@@ -153,7 +151,7 @@ class FileSystemLoader(BaseLoader):
"""
def __init__(self, searchpath, encoding='utf-8'):
- if isinstance(searchpath, basestring):
+ if isinstance(searchpath, string_types):
searchpath = [searchpath]
self.searchpath = list(searchpath)
self.encoding = encoding
@@ -274,7 +272,7 @@ class DictLoader(BaseLoader):
def get_source(self, environment, template):
if template in self.mapping:
source = self.mapping[template]
- return source, None, lambda: source != self.mapping.get(template)
+ return source, None, lambda: source == self.mapping.get(template)
raise TemplateNotFound(template)
def list_templates(self):
@@ -306,7 +304,7 @@ class FunctionLoader(BaseLoader):
rv = self.load_func(template)
if rv is None:
raise TemplateNotFound(template)
- elif isinstance(rv, basestring):
+ elif isinstance(rv, string_types):
return rv, None, None
return rv
@@ -330,12 +328,16 @@ class PrefixLoader(BaseLoader):
self.mapping = mapping
self.delimiter = delimiter
- def get_source(self, environment, template):
+ def get_loader(self, template):
try:
prefix, name = template.split(self.delimiter, 1)
loader = self.mapping[prefix]
except (ValueError, KeyError):
raise TemplateNotFound(template)
+ return loader, name
+
+ def get_source(self, environment, template):
+ loader, name = self.get_loader(template)
try:
return loader.get_source(environment, name)
except TemplateNotFound:
@@ -343,9 +345,19 @@ class PrefixLoader(BaseLoader):
# (the one that includes the prefix)
raise TemplateNotFound(template)
+ @internalcode
+ def load(self, environment, name, globals=None):
+ loader, local_name = self.get_loader(name)
+ try:
+ return loader.load(environment, local_name)
+ except TemplateNotFound:
+ # re-raise the exception with the correct fileame here.
+ # (the one that includes the prefix)
+ raise TemplateNotFound(name)
+
def list_templates(self):
result = []
- for prefix, loader in self.mapping.iteritems():
+ for prefix, loader in iteritems(self.mapping):
for template in loader.list_templates():
result.append(prefix + self.delimiter + template)
return result
@@ -376,6 +388,15 @@ class ChoiceLoader(BaseLoader):
pass
raise TemplateNotFound(template)
+ @internalcode
+ def load(self, environment, name, globals=None):
+ for loader in self.loaders:
+ try:
+ return loader.load(environment, name, globals)
+ except TemplateNotFound:
+ pass
+ raise TemplateNotFound(name)
+
def list_templates(self):
found = set()
for loader in self.loaders:
@@ -408,7 +429,7 @@ class ModuleLoader(BaseLoader):
# create a fake module that looks for the templates in the
# path given.
mod = _TemplateModule(package_name)
- if isinstance(path, basestring):
+ if isinstance(path, string_types):
path = [path]
else:
path = list(path)
diff --git a/chromium/third_party/jinja2/meta.py b/chromium/third_party/jinja2/meta.py
index 3a779a5e9a8..3110cff6066 100644
--- a/chromium/third_party/jinja2/meta.py
+++ b/chromium/third_party/jinja2/meta.py
@@ -11,6 +11,7 @@
"""
from jinja2 import nodes
from jinja2.compiler import CodeGenerator
+from jinja2._compat import string_types
class TrackingCodeGenerator(CodeGenerator):
@@ -77,7 +78,7 @@ def find_referenced_templates(ast):
# something const, only yield the strings and ignore
# non-string consts that really just make no sense
if isinstance(template_name, nodes.Const):
- if isinstance(template_name.value, basestring):
+ if isinstance(template_name.value, string_types):
yield template_name.value
# something dynamic in there
else:
@@ -87,7 +88,7 @@ def find_referenced_templates(ast):
yield None
continue
# constant is a basestring, direct template name
- if isinstance(node.template.value, basestring):
+ if isinstance(node.template.value, string_types):
yield node.template.value
# a tuple or list (latter *should* not happen) made of consts,
# yield the consts that are strings. We could warn here for
@@ -95,7 +96,7 @@ def find_referenced_templates(ast):
elif isinstance(node, nodes.Include) and \
isinstance(node.template.value, (tuple, list)):
for template_name in node.template.value:
- if isinstance(template_name, basestring):
+ if isinstance(template_name, string_types):
yield template_name
# something else we don't care about, we could warn here
else:
diff --git a/chromium/third_party/jinja2/nodes.py b/chromium/third_party/jinja2/nodes.py
index f9da1da5a29..c5697e6b5ec 100644
--- a/chromium/third_party/jinja2/nodes.py
+++ b/chromium/third_party/jinja2/nodes.py
@@ -13,13 +13,15 @@
:license: BSD, see LICENSE for more details.
"""
import operator
-from itertools import chain, izip
+
from collections import deque
-from jinja2.utils import Markup, MethodType, FunctionType
+from jinja2.utils import Markup
+from jinja2._compat import next, izip, with_metaclass, text_type, \
+ method_type, function_type
#: the types we support for context functions
-_context_function_types = (FunctionType, MethodType)
+_context_function_types = (function_type, method_type)
_binop_to_func = {
@@ -102,9 +104,9 @@ def get_eval_context(node, ctx):
return ctx
-class Node(object):
+class Node(with_metaclass(NodeType, object)):
"""Baseclass for all Jinja2 nodes. There are a number of nodes available
- of different types. There are three major types:
+ of different types. There are four major types:
- :class:`Stmt`: statements
- :class:`Expr`: expressions
@@ -118,7 +120,6 @@ class Node(object):
The `environment` attribute is set at the end of the parsing process for
all nodes automatically.
"""
- __metaclass__ = NodeType
fields = ()
attributes = ('lineno', 'environment')
abstract = True
@@ -142,7 +143,7 @@ class Node(object):
setattr(self, attr, attributes.pop(attr, None))
if attributes:
raise TypeError('unknown attribute %r' %
- iter(attributes).next())
+ next(iter(attributes)))
def iter_fields(self, exclude=None, only=None):
"""This method iterates over all fields that are defined and yields
@@ -231,6 +232,9 @@ class Node(object):
def __ne__(self, other):
return not self.__eq__(other)
+ # Restore Python 2 hashing behavior on Python 3
+ __hash__ = object.__hash__
+
def __repr__(self):
return '%s(%s)' % (
self.__class__.__name__,
@@ -440,7 +444,7 @@ class Const(Literal):
constant value in the generated code, otherwise it will raise
an `Impossible` exception.
"""
- from compiler import has_safe_repr
+ from .compiler import has_safe_repr
if not has_safe_repr(value):
raise Impossible()
return cls(value, lineno=lineno, environment=environment)
@@ -687,7 +691,7 @@ class Concat(Expr):
def as_const(self, eval_ctx=None):
eval_ctx = get_eval_context(self, eval_ctx)
- return ''.join(unicode(x.as_const(eval_ctx)) for x in self.nodes)
+ return ''.join(text_type(x.as_const(eval_ctx)) for x in self.nodes)
class Compare(Expr):
diff --git a/chromium/third_party/jinja2/parser.py b/chromium/third_party/jinja2/parser.py
index d44229ad0f0..f60cd018c51 100644
--- a/chromium/third_party/jinja2/parser.py
+++ b/chromium/third_party/jinja2/parser.py
@@ -10,8 +10,8 @@
"""
from jinja2 import nodes
from jinja2.exceptions import TemplateSyntaxError, TemplateAssertionError
-from jinja2.utils import next
from jinja2.lexer import describe_token, describe_token_expr
+from jinja2._compat import next, imap
#: statements that callinto
@@ -53,7 +53,7 @@ class Parser(object):
def _fail_ut_eof(self, name, end_token_stack, lineno):
expected = []
for exprs in end_token_stack:
- expected.extend(map(describe_token_expr, exprs))
+ expected.extend(imap(describe_token_expr, exprs))
if end_token_stack:
currently_looking = ' or '.join(
"'%s'" % describe_token_expr(expr)
@@ -223,7 +223,7 @@ class Parser(object):
# raise a nicer error message in that case.
if self.stream.current.type == 'sub':
self.fail('Block names in Jinja have to be valid Python '
- 'identifiers and may not contain hypens, use an '
+ 'identifiers and may not contain hyphens, use an '
'underscore instead.')
node.body = self.parse_statements(('name:endblock',), drop_needle=True)
@@ -698,7 +698,6 @@ class Parser(object):
arg = nodes.Const(attr_token.value, lineno=attr_token.lineno)
return nodes.Getitem(node, arg, 'load', lineno=token.lineno)
if token.type == 'lbracket':
- priority_on_attribute = False
args = []
while self.stream.current.type != 'rbracket':
if args:
diff --git a/chromium/third_party/jinja2/runtime.py b/chromium/third_party/jinja2/runtime.py
index a4a47a284ed..7791c645afe 100644
--- a/chromium/third_party/jinja2/runtime.py
+++ b/chromium/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
diff --git a/chromium/third_party/jinja2/sandbox.py b/chromium/third_party/jinja2/sandbox.py
index a1cbb29ac31..da479c1ba27 100644
--- a/chromium/third_party/jinja2/sandbox.py
+++ b/chromium/third_party/jinja2/sandbox.py
@@ -15,8 +15,8 @@
import operator
from jinja2.environment import Environment
from jinja2.exceptions import SecurityError
-from jinja2.utils import FunctionType, MethodType, TracebackType, CodeType, \
- FrameType, GeneratorType
+from jinja2._compat import string_types, function_type, method_type, \
+ traceback_type, code_type, frame_type, generator_type, PY2
#: maximum number of items a range may produce
@@ -29,6 +29,13 @@ UNSAFE_FUNCTION_ATTRIBUTES = set(['func_closure', 'func_code', 'func_dict',
#: unsafe method attributes. function attributes are unsafe for methods too
UNSAFE_METHOD_ATTRIBUTES = set(['im_class', 'im_func', 'im_self'])
+#: unsafe generator attirbutes.
+UNSAFE_GENERATOR_ATTRIBUTES = set(['gi_frame', 'gi_code'])
+
+# On versions > python 2 the special attributes on functions are gone,
+# but they remain on methods and generators for whatever reason.
+if not PY2:
+ UNSAFE_FUNCTION_ATTRIBUTES = set()
import warnings
@@ -90,7 +97,7 @@ def safe_range(*args):
"""A range that can't generate ranges with a length of more than
MAX_RANGE items.
"""
- rng = xrange(*args)
+ rng = range(*args)
if len(rng) > MAX_RANGE:
raise OverflowError('range too big, maximum size for range is %d' %
MAX_RANGE)
@@ -114,7 +121,7 @@ def is_internal_attribute(obj, attr):
"""Test if the attribute given is an internal python attribute. For
example this function returns `True` for the `func_code` attribute of
python objects. This is useful if the environment method
- :meth:`~SandboxedEnvironment.is_safe_attribute` is overriden.
+ :meth:`~SandboxedEnvironment.is_safe_attribute` is overridden.
>>> from jinja2.sandbox import is_internal_attribute
>>> is_internal_attribute(lambda: None, "func_code")
@@ -124,20 +131,20 @@ def is_internal_attribute(obj, attr):
>>> is_internal_attribute(str, "upper")
False
"""
- if isinstance(obj, FunctionType):
+ if isinstance(obj, function_type):
if attr in UNSAFE_FUNCTION_ATTRIBUTES:
return True
- elif isinstance(obj, MethodType):
+ elif isinstance(obj, method_type):
if attr in UNSAFE_FUNCTION_ATTRIBUTES or \
attr in UNSAFE_METHOD_ATTRIBUTES:
return True
elif isinstance(obj, type):
if attr == 'mro':
return True
- elif isinstance(obj, (CodeType, TracebackType, FrameType)):
+ elif isinstance(obj, (code_type, traceback_type, frame_type)):
return True
- elif isinstance(obj, GeneratorType):
- if attr == 'gi_frame':
+ elif isinstance(obj, generator_type):
+ if attr in UNSAFE_GENERATOR_ATTRIBUTES:
return True
return attr.startswith('__')
@@ -299,7 +306,7 @@ class SandboxedEnvironment(Environment):
try:
return obj[argument]
except (TypeError, LookupError):
- if isinstance(argument, basestring):
+ if isinstance(argument, string_types):
try:
attr = str(argument)
except Exception:
diff --git a/chromium/third_party/jinja2/tests.py b/chromium/third_party/jinja2/tests.py
index 50510b0d353..48a3e061829 100644
--- a/chromium/third_party/jinja2/tests.py
+++ b/chromium/third_party/jinja2/tests.py
@@ -10,26 +10,14 @@
"""
import re
from jinja2.runtime import Undefined
-
-try:
- from collections import Mapping as MappingType
-except ImportError:
- import UserDict
- MappingType = (UserDict.UserDict, UserDict.DictMixin, dict)
-
-# nose, nothing here to test
-__test__ = False
+from jinja2._compat import text_type, string_types, mapping_types
number_re = re.compile(r'^-?\d+(\.\d+)?$')
regex_type = type(number_re)
-try:
- test_callable = callable
-except NameError:
- def test_callable(x):
- return hasattr(x, '__call__')
+test_callable = callable
def test_odd(value):
@@ -76,17 +64,17 @@ def test_none(value):
def test_lower(value):
"""Return true if the variable is lowercased."""
- return unicode(value).islower()
+ return text_type(value).islower()
def test_upper(value):
"""Return true if the variable is uppercased."""
- return unicode(value).isupper()
+ return text_type(value).isupper()
def test_string(value):
"""Return true if the object is a string."""
- return isinstance(value, basestring)
+ return isinstance(value, string_types)
def test_mapping(value):
@@ -94,12 +82,12 @@ def test_mapping(value):
.. versionadded:: 2.6
"""
- return isinstance(value, MappingType)
+ return isinstance(value, mapping_types)
def test_number(value):
"""Return true if the variable is a number."""
- return isinstance(value, (int, long, float, complex))
+ return isinstance(value, (int, float, complex))
def test_sequence(value):
diff --git a/chromium/third_party/jinja2/utils.py b/chromium/third_party/jinja2/utils.py
index 49e9e9ae073..ddc47da0a04 100644
--- a/chromium/third_party/jinja2/utils.py
+++ b/chromium/third_party/jinja2/utils.py
@@ -9,21 +9,17 @@
:license: BSD, see LICENSE for more details.
"""
import re
-import sys
import errno
-try:
- from thread import allocate_lock
-except ImportError:
- from dummy_thread import allocate_lock
from collections import deque
-from itertools import imap
+from jinja2._compat import text_type, string_types, implements_iterator, \
+ allocate_lock, url_quote
_word_split_re = re.compile(r'(\s+)')
_punctuation_re = re.compile(
'^(?P<lead>(?:%s)*)(?P<middle>.*?)(?P<trail>(?:%s)*)$' % (
- '|'.join(imap(re.escape, ('(', '<', '&lt;'))),
- '|'.join(imap(re.escape, ('.', ',', ')', '>', '\n', '&gt;')))
+ '|'.join(map(re.escape, ('(', '<', '&lt;'))),
+ '|'.join(map(re.escape, ('.', ',', ')', '>', '\n', '&gt;')))
)
)
_simple_email_re = re.compile(r'^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$')
@@ -38,77 +34,7 @@ missing = type('MissingType', (), {'__repr__': lambda x: 'missing'})()
# internal code
internal_code = set()
-
-# concatenate a list of strings and convert them to unicode.
-# unfortunately there is a bug in python 2.4 and lower that causes
-# unicode.join trash the traceback.
-_concat = u''.join
-try:
- def _test_gen_bug():
- raise TypeError(_test_gen_bug)
- yield None
- _concat(_test_gen_bug())
-except TypeError, _error:
- if not _error.args or _error.args[0] is not _test_gen_bug:
- def concat(gen):
- try:
- return _concat(list(gen))
- except Exception:
- # this hack is needed so that the current frame
- # does not show up in the traceback.
- exc_type, exc_value, tb = sys.exc_info()
- raise exc_type, exc_value, tb.tb_next
- else:
- concat = _concat
- del _test_gen_bug, _error
-
-
-# for python 2.x we create outselves a next() function that does the
-# basics without exception catching.
-try:
- next = next
-except NameError:
- def next(x):
- return x.next()
-
-
-# if this python version is unable to deal with unicode filenames
-# when passed to encode we let this function encode it properly.
-# This is used in a couple of places. As far as Jinja is concerned
-# filenames are unicode *or* bytestrings in 2.x and unicode only in
-# 3.x because compile cannot handle bytes
-if sys.version_info < (3, 0):
- def _encode_filename(filename):
- if isinstance(filename, unicode):
- return filename.encode('utf-8')
- return filename
-else:
- def _encode_filename(filename):
- assert filename is None or isinstance(filename, str), \
- 'filenames must be strings'
- return filename
-
-from keyword import iskeyword as is_python_keyword
-
-
-# common types. These do exist in the special types module too which however
-# does not exist in IronPython out of the box. Also that way we don't have
-# to deal with implementation specific stuff here
-class _C(object):
- def method(self): pass
-def _func():
- yield None
-FunctionType = type(_func)
-GeneratorType = type(_func())
-MethodType = type(_C.method)
-CodeType = type(_C.method.func_code)
-try:
- raise TypeError()
-except TypeError:
- _tb = sys.exc_info()[2]
- TracebackType = type(_tb)
- FrameType = type(_tb.tb_frame)
-del _C, _tb, _func
+concat = u''.join
def contextfunction(f):
@@ -128,7 +54,7 @@ def contextfunction(f):
def evalcontextfunction(f):
- """This decoraotr can be used to mark a function or method as an eval
+ """This decorator can be used to mark a function or method as an eval
context callable. This is similar to the :func:`contextfunction`
but instead of passing the context, an evaluation context object is
passed. For more information about the eval context, see
@@ -152,7 +78,7 @@ def environmentfunction(f):
def internalcode(f):
"""Marks the function as internally used"""
- internal_code.add(f.func_code)
+ internal_code.add(f.__code__)
return f
@@ -191,7 +117,7 @@ def clear_caches():
def import_string(import_name, silent=False):
- """Imports an object based on a string. This use useful if you want to
+ """Imports an object based on a string. This is useful if you want to
use import paths as endpoints or something similar. An import path can
be specified either in dotted notation (``xml.sax.saxutils.escape``)
or with a colon as object delimiter (``xml.sax.saxutils:escape``).
@@ -222,7 +148,7 @@ def open_if_exists(filename, mode='rb'):
"""
try:
return open(filename, mode)
- except IOError, e:
+ except IOError as e:
if e.errno not in (errno.ENOENT, errno.EISDIR):
raise
@@ -271,7 +197,7 @@ def urlize(text, trim_url_limit=None, nofollow=False):
trim_url = lambda x, limit=trim_url_limit: limit is not None \
and (x[:limit] + (len(x) >=limit and '...'
or '')) or x
- words = _word_split_re.split(unicode(escape(text)))
+ words = _word_split_re.split(text_type(escape(text)))
nofollow_attr = nofollow and ' rel="nofollow"' or ''
for i, word in enumerate(words):
match = _punctuation_re.match(word)
@@ -280,6 +206,7 @@ def urlize(text, trim_url_limit=None, nofollow=False):
if middle.startswith('www.') or (
'@' not in middle and
not middle.startswith('http://') and
+ not middle.startswith('https://') and
len(middle) > 0 and
middle[0] in _letters + _digits and (
middle.endswith('.org') or
@@ -307,7 +234,7 @@ def generate_lorem_ipsum(n=5, html=True, min=20, max=100):
words = LOREM_IPSUM_WORDS.split()
result = []
- for _ in xrange(n):
+ for _ in range(n):
next_capitalized = True
last_comma = last_fullstop = 0
word = None
@@ -315,7 +242,7 @@ def generate_lorem_ipsum(n=5, html=True, min=20, max=100):
p = []
# each paragraph contains out of 20 to 100 words.
- for idx, _ in enumerate(xrange(randrange(min, max))):
+ for idx, _ in enumerate(range(randrange(min, max))):
while True:
word = choice(words)
if word != last:
@@ -349,6 +276,21 @@ def generate_lorem_ipsum(n=5, html=True, min=20, max=100):
return Markup(u'\n'.join(u'<p>%s</p>' % escape(x) for x in result))
+def unicode_urlencode(obj, charset='utf-8'):
+ """URL escapes a single bytestring or unicode string with the
+ given charset if applicable to URL safe quoting under all rules
+ that need to be considered under all supported Python versions.
+
+ If non strings are provided they are converted to their unicode
+ representation first.
+ """
+ if not isinstance(obj, string_types):
+ obj = text_type(obj)
+ if isinstance(obj, text_type):
+ obj = obj.encode(charset)
+ return text_type(url_quote(obj))
+
+
class LRUCache(object):
"""A simple LRU Cache implementation."""
@@ -366,18 +308,10 @@ class LRUCache(object):
# alias all queue methods for faster lookup
self._popleft = self._queue.popleft
self._pop = self._queue.pop
- if hasattr(self._queue, 'remove'):
- self._remove = self._queue.remove
+ self._remove = self._queue.remove
self._wlock = allocate_lock()
self._append = self._queue.append
- def _remove(self, obj):
- """Python 2.4 compatibility."""
- for idx, item in enumerate(self._queue):
- if item == obj:
- del self._queue[idx]
- break
-
def __getstate__(self):
return {
'capacity': self.capacity,
@@ -393,7 +327,7 @@ class LRUCache(object):
return (self.capacity,)
def copy(self):
- """Return an shallow copy of the instance."""
+ """Return a shallow copy of the instance."""
rv = self.__class__(self.capacity)
rv._mapping.update(self._mapping)
rv._queue = deque(self._queue)
@@ -410,11 +344,15 @@ class LRUCache(object):
"""Set `default` if the key is not in the cache otherwise
leave unchanged. Return the value of this key.
"""
+ self._wlock.acquire()
try:
- return self[key]
- except KeyError:
- self[key] = default
- return default
+ try:
+ return self[key]
+ except KeyError:
+ self[key] = default
+ return default
+ finally:
+ self._wlock.release()
def clear(self):
"""Clear the cache."""
@@ -443,19 +381,23 @@ class LRUCache(object):
"""Get an item from the cache. Moves the item up so that it has the
highest priority then.
- Raise an `KeyError` if it does not exist.
+ Raise a `KeyError` if it does not exist.
"""
- rv = self._mapping[key]
- if self._queue[-1] != key:
- try:
- self._remove(key)
- except ValueError:
- # if something removed the key from the container
- # when we read, ignore the ValueError that we would
- # get otherwise.
- pass
- self._append(key)
- return rv
+ self._wlock.acquire()
+ try:
+ rv = self._mapping[key]
+ if self._queue[-1] != key:
+ try:
+ self._remove(key)
+ except ValueError:
+ # if something removed the key from the container
+ # when we read, ignore the ValueError that we would
+ # get otherwise.
+ pass
+ self._append(key)
+ return rv
+ finally:
+ self._wlock.release()
def __setitem__(self, key, value):
"""Sets the value for an item. Moves the item up so that it
@@ -464,11 +406,7 @@ class LRUCache(object):
self._wlock.acquire()
try:
if key in self._mapping:
- try:
- self._remove(key)
- except ValueError:
- # __getitem__ is not locked, it might happen
- pass
+ self._remove(key)
elif len(self._mapping) == self.capacity:
del self._mapping[self._popleft()]
self._append(key)
@@ -478,7 +416,7 @@ class LRUCache(object):
def __delitem__(self, key):
"""Remove an item from the cache dict.
- Raise an `KeyError` if it does not exist.
+ Raise a `KeyError` if it does not exist.
"""
self._wlock.acquire()
try:
@@ -538,6 +476,7 @@ except ImportError:
pass
+@implements_iterator
class Cycler(object):
"""A cycle helper for templates."""
@@ -556,7 +495,7 @@ class Cycler(object):
"""Returns the current item."""
return self.items[self.pos]
- def next(self):
+ def __next__(self):
"""Goes one item ahead and returns it."""
rv = self.current
self.pos = (self.pos + 1) % len(self.items)
@@ -577,25 +516,5 @@ class Joiner(object):
return self.sep
-# try markupsafe first, if that fails go with Jinja2's bundled version
-# of markupsafe. Markupsafe was previously Jinja2's implementation of
-# the Markup object but was moved into a separate package in a patchleve
-# release
-try:
- from markupsafe import Markup, escape, soft_unicode
-except ImportError:
- from jinja2._markupsafe import Markup, escape, soft_unicode
-
-
-# partials
-try:
- from functools import partial
-except ImportError:
- class partial(object):
- def __init__(self, _func, *args, **kwargs):
- self._func = _func
- self._args = args
- self._kwargs = kwargs
- def __call__(self, *args, **kwargs):
- kwargs.update(self._kwargs)
- return self._func(*(self._args + args), **kwargs)
+# Imported here because that's where it was in the past
+from markupsafe import Markup, escape, soft_unicode