Index: third_party/jinja2/utils.py |
diff --git a/third_party/jinja2/utils.py b/third_party/jinja2/utils.py |
index 49e9e9ae0737dd5876b1ca67d8f00185dcad0370..ddc47da0a0462d480d4513f75f667f1472deb822 100644 |
--- a/third_party/jinja2/utils.py |
+++ b/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, ('(', '<', '<'))), |
- '|'.join(imap(re.escape, ('.', ',', ')', '>', '\n', '>'))) |
+ '|'.join(map(re.escape, ('(', '<', '<'))), |
+ '|'.join(map(re.escape, ('.', ',', ')', '>', '\n', '>'))) |
) |
) |
_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 |