1 # -*- coding: utf-8 -*-
8 :copyright: (c) 2010 by the Jinja Team.
9 :license: BSD, see LICENSE for more details.
15 from thread import allocate_lock
17 from dummy_thread import allocate_lock
18 from collections import deque
19 from itertools import imap
22 _word_split_re = re.compile(r'(\s+)')
23 _punctuation_re = re.compile(
24 '^(?P<lead>(?:%s)*)(?P<middle>.*?)(?P<trail>(?:%s)*)$' % (
25 '|'.join(imap(re.escape, ('(', '<', '<'))),
26 '|'.join(imap(re.escape, ('.', ',', ')', '>', '\n', '>')))
29 _simple_email_re = re.compile(r'^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$')
30 _striptags_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
31 _entity_re = re.compile(r'&([^;]+);')
32 _letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
33 _digits = '0123456789'
35 # special singleton representing missing values for the runtime
36 missing = type('MissingType', (), {'__repr__': lambda x: 'missing'})()
42 # concatenate a list of strings and convert them to unicode.
43 # unfortunately there is a bug in python 2.4 and lower that causes
44 # unicode.join trash the traceback.
48 raise TypeError(_test_gen_bug)
50 _concat(_test_gen_bug())
51 except TypeError, _error:
52 if not _error.args or _error.args[0] is not _test_gen_bug:
55 return _concat(list(gen))
57 # this hack is needed so that the current frame
58 # does not show up in the traceback.
59 exc_type, exc_value, tb = sys.exc_info()
60 raise exc_type, exc_value, tb.tb_next
63 del _test_gen_bug, _error
66 # for python 2.x we create outselves a next() function that does the
67 # basics without exception catching.
75 # if this python version is unable to deal with unicode filenames
76 # when passed to encode we let this function encode it properly.
77 # This is used in a couple of places. As far as Jinja is concerned
78 # filenames are unicode *or* bytestrings in 2.x and unicode only in
79 # 3.x because compile cannot handle bytes
80 if sys.version_info < (3, 0):
81 def _encode_filename(filename):
82 if isinstance(filename, unicode):
83 return filename.encode('utf-8')
86 def _encode_filename(filename):
87 assert filename is None or isinstance(filename, str), \
88 'filenames must be strings'
91 from keyword import iskeyword as is_python_keyword
94 # common types. These do exist in the special types module too which however
95 # does not exist in IronPython out of the box. Also that way we don't have
96 # to deal with implementation specific stuff here
98 def method(self): pass
101 FunctionType = type(_func)
102 GeneratorType = type(_func())
103 MethodType = type(_C.method)
104 CodeType = type(_C.method.func_code)
108 _tb = sys.exc_info()[2]
109 TracebackType = type(_tb)
110 FrameType = type(_tb.tb_frame)
114 def contextfunction(f):
115 """This decorator can be used to mark a function or method context callable.
116 A context callable is passed the active :class:`Context` as first argument when
117 called from the template. This is useful if a function wants to get access
118 to the context or functions provided on the context object. For example
119 a function that returns a sorted list of template variables the current
120 template exports could look like this::
123 def get_exported_names(context):
124 return sorted(context.exported_vars)
126 f.contextfunction = True
130 def evalcontextfunction(f):
131 """This decoraotr can be used to mark a function or method as an eval
132 context callable. This is similar to the :func:`contextfunction`
133 but instead of passing the context, an evaluation context object is
134 passed. For more information about the eval context, see
137 .. versionadded:: 2.4
139 f.evalcontextfunction = True
143 def environmentfunction(f):
144 """This decorator can be used to mark a function or method as environment
145 callable. This decorator works exactly like the :func:`contextfunction`
146 decorator just that the first argument is the active :class:`Environment`
149 f.environmentfunction = True
154 """Marks the function as internally used"""
155 internal_code.add(f.func_code)
159 def is_undefined(obj):
160 """Check if the object passed is undefined. This does nothing more than
161 performing an instance check against :class:`Undefined` but looks nicer.
162 This can be used for custom filters or tests that want to react to
163 undefined variables. For example a custom default filter can look like
166 def default(var, default=''):
167 if is_undefined(var):
171 from jinja2.runtime import Undefined
172 return isinstance(obj, Undefined)
175 def consume(iterable):
176 """Consumes an iterable without doing anything with it."""
177 for event in iterable:
182 """Jinja2 keeps internal caches for environments and lexers. These are
183 used so that Jinja2 doesn't have to recreate environments and lexers all
184 the time. Normally you don't have to care about that but if you are
185 messuring memory consumption you may want to clean the caches.
187 from jinja2.environment import _spontaneous_environments
188 from jinja2.lexer import _lexer_cache
189 _spontaneous_environments.clear()
193 def import_string(import_name, silent=False):
194 """Imports an object based on a string. This use useful if you want to
195 use import paths as endpoints or something similar. An import path can
196 be specified either in dotted notation (``xml.sax.saxutils.escape``)
197 or with a colon as object delimiter (``xml.sax.saxutils:escape``).
199 If the `silent` is True the return value will be `None` if the import
202 :return: imported object
205 if ':' in import_name:
206 module, obj = import_name.split(':', 1)
207 elif '.' in import_name:
208 items = import_name.split('.')
209 module = '.'.join(items[:-1])
212 return __import__(import_name)
213 return getattr(__import__(module, None, None, [obj]), obj)
214 except (ImportError, AttributeError):
219 def open_if_exists(filename, mode='rb'):
220 """Returns a file descriptor for the filename if that file exists,
224 return open(filename, mode)
226 if e.errno not in (errno.ENOENT, errno.EISDIR):
230 def object_type_repr(obj):
231 """Returns the name of the object's type. For some recognized
232 singletons the name of the object is returned instead. (For
233 example for `None` and `Ellipsis`).
237 elif obj is Ellipsis:
239 # __builtin__ in 2.x, builtins in 3.x
240 if obj.__class__.__module__ in ('__builtin__', 'builtins'):
241 name = obj.__class__.__name__
243 name = obj.__class__.__module__ + '.' + obj.__class__.__name__
244 return '%s object' % name
247 def pformat(obj, verbose=False):
248 """Prettyprint an object. Either use the `pretty` library or the
252 from pretty import pretty
253 return pretty(obj, verbose=verbose)
255 from pprint import pformat
259 def urlize(text, trim_url_limit=None, nofollow=False):
260 """Converts any URLs in text into clickable links. Works on http://,
261 https:// and www. links. Links can have trailing punctuation (periods,
262 commas, close-parens) and leading punctuation (opening parens) and
263 it'll still do the right thing.
265 If trim_url_limit is not None, the URLs in link text will be limited
266 to trim_url_limit characters.
268 If nofollow is True, the URLs in link text will get a rel="nofollow"
271 trim_url = lambda x, limit=trim_url_limit: limit is not None \
272 and (x[:limit] + (len(x) >=limit and '...'
274 words = _word_split_re.split(unicode(escape(text)))
275 nofollow_attr = nofollow and ' rel="nofollow"' or ''
276 for i, word in enumerate(words):
277 match = _punctuation_re.match(word)
279 lead, middle, trail = match.groups()
280 if middle.startswith('www.') or (
281 '@' not in middle and
282 not middle.startswith('http://') and
284 middle[0] in _letters + _digits and (
285 middle.endswith('.org') or
286 middle.endswith('.net') or
287 middle.endswith('.com')
289 middle = '<a href="http://%s"%s>%s</a>' % (middle,
290 nofollow_attr, trim_url(middle))
291 if middle.startswith('http://') or \
292 middle.startswith('https://'):
293 middle = '<a href="%s"%s>%s</a>' % (middle,
294 nofollow_attr, trim_url(middle))
295 if '@' in middle and not middle.startswith('www.') and \
296 not ':' in middle and _simple_email_re.match(middle):
297 middle = '<a href="mailto:%s">%s</a>' % (middle, middle)
298 if lead + middle + trail != word:
299 words[i] = lead + middle + trail
300 return u''.join(words)
303 def generate_lorem_ipsum(n=5, html=True, min=20, max=100):
304 """Generate some lorem impsum for the template."""
305 from jinja2.constants import LOREM_IPSUM_WORDS
306 from random import choice, randrange
307 words = LOREM_IPSUM_WORDS.split()
311 next_capitalized = True
312 last_comma = last_fullstop = 0
317 # each paragraph contains out of 20 to 100 words.
318 for idx, _ in enumerate(xrange(randrange(min, max))):
325 word = word.capitalize()
326 next_capitalized = False
328 if idx - randrange(3, 8) > last_comma:
332 # add end of sentences
333 if idx - randrange(10, 20) > last_fullstop:
334 last_comma = last_fullstop = idx
336 next_capitalized = True
339 # ensure that the paragraph ends with a dot.
343 elif not p.endswith('.'):
348 return u'\n\n'.join(result)
349 return Markup(u'\n'.join(u'<p>%s</p>' % escape(x) for x in result))
352 class LRUCache(object):
353 """A simple LRU Cache implementation."""
355 # this is fast for small capacities (something below 1000) but doesn't
356 # scale. But as long as it's only used as storage for templates this
359 def __init__(self, capacity):
360 self.capacity = capacity
362 self._queue = deque()
366 # alias all queue methods for faster lookup
367 self._popleft = self._queue.popleft
368 self._pop = self._queue.pop
369 if hasattr(self._queue, 'remove'):
370 self._remove = self._queue.remove
371 self._wlock = allocate_lock()
372 self._append = self._queue.append
374 def _remove(self, obj):
375 """Python 2.4 compatibility."""
376 for idx, item in enumerate(self._queue):
381 def __getstate__(self):
383 'capacity': self.capacity,
384 '_mapping': self._mapping,
385 '_queue': self._queue
388 def __setstate__(self, d):
389 self.__dict__.update(d)
392 def __getnewargs__(self):
393 return (self.capacity,)
396 """Return an shallow copy of the instance."""
397 rv = self.__class__(self.capacity)
398 rv._mapping.update(self._mapping)
399 rv._queue = deque(self._queue)
402 def get(self, key, default=None):
403 """Return an item from the cache dict or `default`"""
409 def setdefault(self, key, default=None):
410 """Set `default` if the key is not in the cache otherwise
411 leave unchanged. Return the value of this key.
420 """Clear the cache."""
421 self._wlock.acquire()
423 self._mapping.clear()
426 self._wlock.release()
428 def __contains__(self, key):
429 """Check if a key exists in this cache."""
430 return key in self._mapping
433 """Return the current size of the cache."""
434 return len(self._mapping)
438 self.__class__.__name__,
442 def __getitem__(self, key):
443 """Get an item from the cache. Moves the item up so that it has the
444 highest priority then.
446 Raise an `KeyError` if it does not exist.
448 rv = self._mapping[key]
449 if self._queue[-1] != key:
453 # if something removed the key from the container
454 # when we read, ignore the ValueError that we would
460 def __setitem__(self, key, value):
461 """Sets the value for an item. Moves the item up so that it
462 has the highest priority then.
464 self._wlock.acquire()
466 if key in self._mapping:
470 # __getitem__ is not locked, it might happen
472 elif len(self._mapping) == self.capacity:
473 del self._mapping[self._popleft()]
475 self._mapping[key] = value
477 self._wlock.release()
479 def __delitem__(self, key):
480 """Remove an item from the cache dict.
481 Raise an `KeyError` if it does not exist.
483 self._wlock.acquire()
485 del self._mapping[key]
489 # __getitem__ is not locked, it might happen
492 self._wlock.release()
495 """Return a list of items."""
496 result = [(key, self._mapping[key]) for key in list(self._queue)]
501 """Iterate over all items."""
502 return iter(self.items())
505 """Return a list of all values."""
506 return [x[1] for x in self.items()]
509 """Iterate over all values."""
510 return iter(self.values())
513 """Return a list of all keys ordered by most recent usage."""
517 """Iterate over all keys in the cache dict, ordered by
518 the most recent usage.
520 return reversed(tuple(self._queue))
524 def __reversed__(self):
525 """Iterate over the values in the cache dict, oldest items
528 return iter(tuple(self._queue))
533 # register the LRU cache as mutable mapping if possible
535 from collections import MutableMapping
536 MutableMapping.register(LRUCache)
541 class Cycler(object):
542 """A cycle helper for templates."""
544 def __init__(self, *items):
546 raise RuntimeError('at least one item has to be provided')
551 """Resets the cycle."""
556 """Returns the current item."""
557 return self.items[self.pos]
560 """Goes one item ahead and returns it."""
562 self.pos = (self.pos + 1) % len(self.items)
566 class Joiner(object):
567 """A joining helper for templates."""
569 def __init__(self, sep=u', '):
580 # try markupsafe first, if that fails go with Jinja2's bundled version
581 # of markupsafe. Markupsafe was previously Jinja2's implementation of
582 # the Markup object but was moved into a separate package in a patchleve
585 from markupsafe import Markup, escape, soft_unicode
587 from jinja2._markupsafe import Markup, escape, soft_unicode
592 from functools import partial
594 class partial(object):
595 def __init__(self, _func, *args, **kwargs):
598 self._kwargs = kwargs
599 def __call__(self, *args, **kwargs):
600 kwargs.update(self._kwargs)
601 return self._func(*(self._args + args), **kwargs)