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__', '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')
479 if hasattr(unicode, '__getslice__'):
480 __getslice__ = make_wrapper('__getslice__')
482 del method, make_wrapper
485 def _escape_argspec(obj, iterable):
486 """Helper for various string-wrapped functions."""
487 for key, value in iterable:
488 if hasattr(value, '__html__') or isinstance(value, basestring):
489 obj[key] = escape(value)
493 class _MarkupEscapeHelper(object):
494 """Helper for Markup.__mod__"""
496 def __init__(self, obj):
499 __getitem__ = lambda s, x: _MarkupEscapeHelper(s.obj[x])
500 __unicode__ = lambda s: unicode(escape(s.obj))
501 __str__ = lambda s: str(escape(s.obj))
502 __repr__ = lambda s: str(escape(repr(s.obj)))
503 __int__ = lambda s: int(s.obj)
504 __float__ = lambda s: float(s.obj)
507 class LRUCache(object):
508 """A simple LRU Cache implementation."""
510 # this is fast for small capacities (something below 1000) but doesn't
511 # scale. But as long as it's only used as storage for templates this
514 def __init__(self, capacity):
515 self.capacity = capacity
517 self._queue = deque()
521 # alias all queue methods for faster lookup
522 self._popleft = self._queue.popleft
523 self._pop = self._queue.pop
524 if hasattr(self._queue, 'remove'):
525 self._remove = self._queue.remove
526 self._wlock = allocate_lock()
527 self._append = self._queue.append
529 def _remove(self, obj):
530 """Python 2.4 compatibility."""
531 for idx, item in enumerate(self._queue):
536 def __getstate__(self):
538 'capacity': self.capacity,
539 '_mapping': self._mapping,
540 '_queue': self._queue
543 def __setstate__(self, d):
544 self.__dict__.update(d)
547 def __getnewargs__(self):
548 return (self.capacity,)
551 """Return an shallow copy of the instance."""
552 rv = self.__class__(self.capacity)
553 rv._mapping.update(self._mapping)
554 rv._queue = deque(self._queue)
557 def get(self, key, default=None):
558 """Return an item from the cache dict or `default`"""
564 def setdefault(self, key, default=None):
565 """Set `default` if the key is not in the cache otherwise
566 leave unchanged. Return the value of this key.
575 """Clear the cache."""
576 self._wlock.acquire()
578 self._mapping.clear()
581 self._wlock.release()
583 def __contains__(self, key):
584 """Check if a key exists in this cache."""
585 return key in self._mapping
588 """Return the current size of the cache."""
589 return len(self._mapping)
593 self.__class__.__name__,
597 def __getitem__(self, key):
598 """Get an item from the cache. Moves the item up so that it has the
599 highest priority then.
601 Raise an `KeyError` if it does not exist.
603 rv = self._mapping[key]
604 if self._queue[-1] != key:
608 # if something removed the key from the container
609 # when we read, ignore the ValueError that we would
615 def __setitem__(self, key, value):
616 """Sets the value for an item. Moves the item up so that it
617 has the highest priority then.
619 self._wlock.acquire()
621 if key in self._mapping:
623 elif len(self._mapping) == self.capacity:
624 del self._mapping[self._popleft()]
626 self._mapping[key] = value
628 self._wlock.release()
630 def __delitem__(self, key):
631 """Remove an item from the cache dict.
632 Raise an `KeyError` if it does not exist.
634 self._wlock.acquire()
636 del self._mapping[key]
639 self._wlock.release()
642 """Return a list of items."""
643 result = [(key, self._mapping[key]) for key in list(self._queue)]
648 """Iterate over all items."""
649 return iter(self.items())
652 """Return a list of all values."""
653 return [x[1] for x in self.items()]
656 """Iterate over all values."""
657 return iter(self.values())
660 """Return a list of all keys ordered by most recent usage."""
664 """Iterate over all keys in the cache dict, ordered by
665 the most recent usage.
667 return reversed(tuple(self._queue))
671 def __reversed__(self):
672 """Iterate over the values in the cache dict, oldest items
675 return iter(tuple(self._queue))
680 # register the LRU cache as mutable mapping if possible
682 from collections import MutableMapping
683 MutableMapping.register(LRUCache)
688 class Cycler(object):
689 """A cycle helper for templates."""
691 def __init__(self, *items):
693 raise RuntimeError('at least one item has to be provided')
698 """Resets the cycle."""
703 """Returns the current item."""
704 return self.items[self.pos]
707 """Goes one item ahead and returns it."""
709 self.pos = (self.pos + 1) % len(self.items)
713 class Joiner(object):
714 """A joining helper for templates."""
716 def __init__(self, sep=u', '):
727 # we have to import it down here as the speedups module imports the
728 # markup type which is define above.
730 from jinja2._speedups import escape, soft_unicode
733 """Convert the characters &, <, >, ' and " in string s to HTML-safe
734 sequences. Use this if you need to display text that might contain
735 such characters in HTML. Marks return value as markup string.
737 if hasattr(s, '__html__'):
739 return Markup(unicode(s)
740 .replace('&', '&')
741 .replace('>', '>')
742 .replace('<', '<')
743 .replace("'", ''')
744 .replace('"', '"')
748 """Make a string unicode if it isn't already. That way a markup
749 string is not converted back to unicode.
751 if not isinstance(s, unicode):
758 from functools import partial
760 class partial(object):
761 def __init__(self, _func, *args, **kwargs):
764 self._kwargs = kwargs
765 def __call__(self, *args, **kwargs):
766 kwargs.update(self._kwargs)
767 return self._func(*(self._args + args), **kwargs)