1 # -*- coding: utf-8 -*-
8 :copyright: (c) 2009 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 # ironpython without stdlib doesn't have keyword
68 from keyword import iskeyword as is_python_keyword
70 _py_identifier_re = re.compile(r'^[a-zA-Z_][a-zA-Z0-9]*$')
71 def is_python_keyword(name):
72 if _py_identifier_re.search(name) is None:
81 # common types. These do exist in the special types module too which however
82 # does not exist in IronPython out of the box.
84 def method(self): pass
87 FunctionType = type(_func)
88 GeneratorType = type(_func())
89 MethodType = type(_C.method)
90 CodeType = type(_C.method.func_code)
94 _tb = sys.exc_info()[2]
95 TracebackType = type(_tb)
96 FrameType = type(_tb.tb_frame)
100 def contextfunction(f):
101 """This decorator can be used to mark a function or method context callable.
102 A context callable is passed the active :class:`Context` as first argument when
103 called from the template. This is useful if a function wants to get access
104 to the context or functions provided on the context object. For example
105 a function that returns a sorted list of template variables the current
106 template exports could look like this::
109 def get_exported_names(context):
110 return sorted(context.exported_vars)
112 f.contextfunction = True
116 def environmentfunction(f):
117 """This decorator can be used to mark a function or method as environment
118 callable. This decorator works exactly like the :func:`contextfunction`
119 decorator just that the first argument is the active :class:`Environment`
122 f.environmentfunction = True
127 """Marks the function as internally used"""
128 internal_code.add(f.func_code)
132 def is_undefined(obj):
133 """Check if the object passed is undefined. This does nothing more than
134 performing an instance check against :class:`Undefined` but looks nicer.
135 This can be used for custom filters or tests that want to react to
136 undefined variables. For example a custom default filter can look like
139 def default(var, default=''):
140 if is_undefined(var):
144 from jinja2.runtime import Undefined
145 return isinstance(obj, Undefined)
148 def consume(iterable):
149 """Consumes an iterable without doing anything with it."""
150 for event in iterable:
155 """Jinja2 keeps internal caches for environments and lexers. These are
156 used so that Jinja2 doesn't have to recreate environments and lexers all
157 the time. Normally you don't have to care about that but if you are
158 messuring memory consumption you may want to clean the caches.
160 from jinja2.environment import _spontaneous_environments
161 from jinja2.lexer import _lexer_cache
162 _spontaneous_environments.clear()
166 def import_string(import_name, silent=False):
167 """Imports an object based on a string. This use useful if you want to
168 use import paths as endpoints or something similar. An import path can
169 be specified either in dotted notation (``xml.sax.saxutils.escape``)
170 or with a colon as object delimiter (``xml.sax.saxutils:escape``).
172 If the `silent` is True the return value will be `None` if the import
175 :return: imported object
178 if ':' in import_name:
179 module, obj = import_name.split(':', 1)
180 elif '.' in import_name:
181 items = import_name.split('.')
182 module = '.'.join(items[:-1])
185 return __import__(import_name)
186 return getattr(__import__(module, None, None, [obj]), obj)
187 except (ImportError, AttributeError):
192 def open_if_exists(filename, mode='r'):
193 """Returns a file descriptor for the filename if that file exists,
197 return file(filename, mode)
199 if e.errno not in (errno.ENOENT, errno.EISDIR):
203 def pformat(obj, verbose=False):
204 """Prettyprint an object. Either use the `pretty` library or the
208 from pretty import pretty
209 return pretty(obj, verbose=verbose)
211 from pprint import pformat
215 def urlize(text, trim_url_limit=None, nofollow=False):
216 """Converts any URLs in text into clickable links. Works on http://,
217 https:// and www. links. Links can have trailing punctuation (periods,
218 commas, close-parens) and leading punctuation (opening parens) and
219 it'll still do the right thing.
221 If trim_url_limit is not None, the URLs in link text will be limited
222 to trim_url_limit characters.
224 If nofollow is True, the URLs in link text will get a rel="nofollow"
227 trim_url = lambda x, limit=trim_url_limit: limit is not None \
228 and (x[:limit] + (len(x) >=limit and '...'
230 words = _word_split_re.split(unicode(escape(text)))
231 nofollow_attr = nofollow and ' rel="nofollow"' or ''
232 for i, word in enumerate(words):
233 match = _punctuation_re.match(word)
235 lead, middle, trail = match.groups()
236 if middle.startswith('www.') or (
237 '@' not in middle and
238 not middle.startswith('http://') and
240 middle[0] in _letters + _digits and (
241 middle.endswith('.org') or
242 middle.endswith('.net') or
243 middle.endswith('.com')
245 middle = '<a href="http://%s"%s>%s</a>' % (middle,
246 nofollow_attr, trim_url(middle))
247 if middle.startswith('http://') or \
248 middle.startswith('https://'):
249 middle = '<a href="%s"%s>%s</a>' % (middle,
250 nofollow_attr, trim_url(middle))
251 if '@' in middle and not middle.startswith('www.') and \
252 not ':' in middle and _simple_email_re.match(middle):
253 middle = '<a href="mailto:%s">%s</a>' % (middle, middle)
254 if lead + middle + trail != word:
255 words[i] = lead + middle + trail
256 return u''.join(words)
259 def generate_lorem_ipsum(n=5, html=True, min=20, max=100):
260 """Generate some lorem impsum for the template."""
261 from jinja2.constants import LOREM_IPSUM_WORDS
262 from random import choice, random, randrange
263 words = LOREM_IPSUM_WORDS.split()
267 next_capitalized = True
268 last_comma = last_fullstop = 0
273 # each paragraph contains out of 20 to 100 words.
274 for idx, _ in enumerate(xrange(randrange(min, max))):
281 word = word.capitalize()
282 next_capitalized = False
284 if idx - randrange(3, 8) > last_comma:
288 # add end of sentences
289 if idx - randrange(10, 20) > last_fullstop:
290 last_comma = last_fullstop = idx
292 next_capitalized = True
295 # ensure that the paragraph ends with a dot.
299 elif not p.endswith('.'):
304 return u'\n\n'.join(result)
305 return Markup(u'\n'.join(u'<p>%s</p>' % escape(x) for x in result))
308 class Markup(unicode):
309 r"""Marks a string as being safe for inclusion in HTML/XML output without
310 needing to be escaped. This implements the `__html__` interface a couple
311 of frameworks and web applications use. :class:`Markup` is a direct
312 subclass of `unicode` and provides all the methods of `unicode` just that
313 it escapes arguments passed and always returns `Markup`.
315 The `escape` function returns markup objects so that double escaping can't
316 happen. If you want to use autoescaping in Jinja just enable the
317 autoescaping feature in the environment.
319 The constructor of the :class:`Markup` class can be used for three
320 different things: When passed an unicode object it's assumed to be safe,
321 when passed an object with an HTML representation (has an `__html__`
322 method) that representation is used, otherwise the object passed is
323 converted into a unicode string and then assumed to be safe:
325 >>> Markup("Hello <em>World</em>!")
326 Markup(u'Hello <em>World</em>!')
327 >>> class Foo(object):
328 ... def __html__(self):
329 ... return '<a href="#">foo</a>'
332 Markup(u'<a href="#">foo</a>')
334 If you want object passed being always treated as unsafe you can use the
335 :meth:`escape` classmethod to create a :class:`Markup` object:
337 >>> Markup.escape("Hello <em>World</em>!")
338 Markup(u'Hello <em>World</em>!')
340 Operations on a markup string are markup aware which means that all
341 arguments are passed through the :func:`escape` function:
343 >>> em = Markup("<em>%s</em>")
345 Markup(u'<em>foo & bar</em>')
346 >>> strong = Markup("<strong>%(text)s</strong>")
347 >>> strong % {'text': '<blink>hacker here</blink>'}
348 Markup(u'<strong><blink>hacker here</blink></strong>')
349 >>> Markup("<em>Hello</em> ") + "<foo>"
350 Markup(u'<em>Hello</em> <foo>')
354 def __new__(cls, base=u'', encoding=None, errors='strict'):
355 if hasattr(base, '__html__'):
356 base = base.__html__()
358 return unicode.__new__(cls, base)
359 return unicode.__new__(cls, base, encoding, errors)
364 def __add__(self, other):
365 if hasattr(other, '__html__') or isinstance(other, basestring):
366 return self.__class__(unicode(self) + unicode(escape(other)))
367 return NotImplemented
369 def __radd__(self, other):
370 if hasattr(other, '__html__') or isinstance(other, basestring):
371 return self.__class__(unicode(escape(other)) + unicode(self))
372 return NotImplemented
374 def __mul__(self, num):
375 if isinstance(num, (int, long)):
376 return self.__class__(unicode.__mul__(self, num))
377 return NotImplemented
380 def __mod__(self, arg):
381 if isinstance(arg, tuple):
382 arg = tuple(imap(_MarkupEscapeHelper, arg))
384 arg = _MarkupEscapeHelper(arg)
385 return self.__class__(unicode.__mod__(self, arg))
389 self.__class__.__name__,
390 unicode.__repr__(self)
394 return self.__class__(unicode.join(self, imap(escape, seq)))
395 join.__doc__ = unicode.join.__doc__
397 def split(self, *args, **kwargs):
398 return map(self.__class__, unicode.split(self, *args, **kwargs))
399 split.__doc__ = unicode.split.__doc__
401 def rsplit(self, *args, **kwargs):
402 return map(self.__class__, unicode.rsplit(self, *args, **kwargs))
403 rsplit.__doc__ = unicode.rsplit.__doc__
405 def splitlines(self, *args, **kwargs):
406 return map(self.__class__, unicode.splitlines(self, *args, **kwargs))
407 splitlines.__doc__ = unicode.splitlines.__doc__
410 r"""Unescape markup again into an unicode string. This also resolves
411 known HTML4 and XHTML entities:
413 >>> Markup("Main » <em>About</em>").unescape()
414 u'Main \xbb <em>About</em>'
416 from jinja2.constants import HTML_ENTITIES
419 if name in HTML_ENTITIES:
420 return unichr(HTML_ENTITIES[name])
422 if name[:2] in ('#x', '#X'):
423 return unichr(int(name[2:], 16))
424 elif name.startswith('#'):
425 return unichr(int(name[1:]))
429 return _entity_re.sub(handle_match, unicode(self))
432 r"""Unescape markup into an unicode string and strip all tags. This
433 also resolves known HTML4 and XHTML entities. Whitespace is
436 >>> Markup("Main » <em>About</em>").striptags()
439 stripped = u' '.join(_striptags_re.sub('', self).split())
440 return Markup(stripped).unescape()
444 """Escape the string. Works like :func:`escape` with the difference
445 that for subclasses of :class:`Markup` this function would return the
449 if rv.__class__ is not cls:
453 def make_wrapper(name):
454 orig = getattr(unicode, name)
455 def func(self, *args, **kwargs):
456 args = _escape_argspec(list(args), enumerate(args))
457 _escape_argspec(kwargs, kwargs.iteritems())
458 return self.__class__(orig(self, *args, **kwargs))
459 func.__name__ = orig.__name__
460 func.__doc__ = orig.__doc__
463 for method in '__getitem__', '__getslice__', 'capitalize', \
464 'title', 'lower', 'upper', 'replace', 'ljust', \
465 'rjust', 'lstrip', 'rstrip', 'center', 'strip', \
466 'translate', 'expandtabs', 'swapcase', 'zfill':
467 locals()[method] = make_wrapper(method)
470 if hasattr(unicode, 'partition'):
471 partition = make_wrapper('partition'),
472 rpartition = make_wrapper('rpartition')
475 if hasattr(unicode, 'format'):
476 format = make_wrapper('format')
478 del method, make_wrapper
481 def _escape_argspec(obj, iterable):
482 """Helper for various string-wrapped functions."""
483 for key, value in iterable:
484 if hasattr(value, '__html__') or isinstance(value, basestring):
485 obj[key] = escape(value)
489 class _MarkupEscapeHelper(object):
490 """Helper for Markup.__mod__"""
492 def __init__(self, obj):
495 __getitem__ = lambda s, x: _MarkupEscapeHelper(s.obj[x])
496 __unicode__ = lambda s: unicode(escape(s.obj))
497 __str__ = lambda s: str(escape(s.obj))
498 __repr__ = lambda s: str(escape(repr(s.obj)))
499 __int__ = lambda s: int(s.obj)
500 __float__ = lambda s: float(s.obj)
503 class LRUCache(object):
504 """A simple LRU Cache implementation."""
506 # this is fast for small capacities (something below 1000) but doesn't
507 # scale. But as long as it's only used as storage for templates this
510 def __init__(self, capacity):
511 self.capacity = capacity
513 self._queue = deque()
517 # alias all queue methods for faster lookup
518 self._popleft = self._queue.popleft
519 self._pop = self._queue.pop
520 if hasattr(self._queue, 'remove'):
521 self._remove = self._queue.remove
522 self._wlock = allocate_lock()
523 self._append = self._queue.append
525 def _remove(self, obj):
526 """Python 2.4 compatibility."""
527 for idx, item in enumerate(self._queue):
532 def __getstate__(self):
534 'capacity': self.capacity,
535 '_mapping': self._mapping,
536 '_queue': self._queue
539 def __setstate__(self, d):
540 self.__dict__.update(d)
543 def __getnewargs__(self):
544 return (self.capacity,)
547 """Return an shallow copy of the instance."""
548 rv = self.__class__(self.capacity)
549 rv._mapping.update(self._mapping)
550 rv._queue = deque(self._queue)
553 def get(self, key, default=None):
554 """Return an item from the cache dict or `default`"""
560 def setdefault(self, key, default=None):
561 """Set `default` if the key is not in the cache otherwise
562 leave unchanged. Return the value of this key.
571 """Clear the cache."""
572 self._wlock.acquire()
574 self._mapping.clear()
577 self._wlock.release()
579 def __contains__(self, key):
580 """Check if a key exists in this cache."""
581 return key in self._mapping
584 """Return the current size of the cache."""
585 return len(self._mapping)
589 self.__class__.__name__,
593 def __getitem__(self, key):
594 """Get an item from the cache. Moves the item up so that it has the
595 highest priority then.
597 Raise an `KeyError` if it does not exist.
599 rv = self._mapping[key]
600 if self._queue[-1] != key:
604 # if something removed the key from the container
605 # when we read, ignore the ValueError that we would
611 def __setitem__(self, key, value):
612 """Sets the value for an item. Moves the item up so that it
613 has the highest priority then.
615 self._wlock.acquire()
617 if key in self._mapping:
619 elif len(self._mapping) == self.capacity:
620 del self._mapping[self._popleft()]
622 self._mapping[key] = value
624 self._wlock.release()
626 def __delitem__(self, key):
627 """Remove an item from the cache dict.
628 Raise an `KeyError` if it does not exist.
630 self._wlock.acquire()
632 del self._mapping[key]
635 self._wlock.release()
638 """Return a list of items."""
639 result = [(key, self._mapping[key]) for key in list(self._queue)]
644 """Iterate over all items."""
645 return iter(self.items())
648 """Return a list of all values."""
649 return [x[1] for x in self.items()]
652 """Iterate over all values."""
653 return iter(self.values())
656 """Return a list of all keys ordered by most recent usage."""
660 """Iterate over all keys in the cache dict, ordered by
661 the most recent usage.
663 return reversed(tuple(self._queue))
667 def __reversed__(self):
668 """Iterate over the values in the cache dict, oldest items
671 return iter(tuple(self._queue))
676 # register the LRU cache as mutable mapping if possible
678 from collections import MutableMapping
679 MutableMapping.register(LRUCache)
684 class Cycler(object):
685 """A cycle helper for templates."""
687 def __init__(self, *items):
689 raise RuntimeError('at least one item has to be provided')
694 """Resets the cycle."""
699 """Returns the current item."""
700 return self.items[self.pos]
703 """Goes one item ahead and returns it."""
705 self.pos = (self.pos + 1) % len(self.items)
709 class Joiner(object):
710 """A joining helper for templates."""
712 def __init__(self, sep=u', '):
723 # we have to import it down here as the speedups module imports the
724 # markup type which is define above.
726 from jinja2._speedups import escape, soft_unicode
729 """Convert the characters &, <, >, ' and " in string s to HTML-safe
730 sequences. Use this if you need to display text that might contain
731 such characters in HTML. Marks return value as markup string.
733 if hasattr(s, '__html__'):
735 return Markup(unicode(s)
736 .replace('&', '&')
737 .replace('>', '>')
738 .replace('<', '<')
739 .replace("'", ''')
740 .replace('"', '"')
744 """Make a string unicode if it isn't already. That way a markup
745 string is not converted back to unicode.
747 if not isinstance(s, unicode):
754 from functools import partial
756 class partial(object):
757 def __init__(self, _func, *args, **kwargs):
760 self._kwargs = kwargs
761 def __call__(self, *args, **kwargs):
762 kwargs.update(self._kwargs)
763 return self._func(*(self._args + args), **kwargs)