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 environmentfunction(f):
131 """This decorator can be used to mark a function or method as environment
132 callable. This decorator works exactly like the :func:`contextfunction`
133 decorator just that the first argument is the active :class:`Environment`
136 f.environmentfunction = True
141 """Marks the function as internally used"""
142 internal_code.add(f.func_code)
146 def is_undefined(obj):
147 """Check if the object passed is undefined. This does nothing more than
148 performing an instance check against :class:`Undefined` but looks nicer.
149 This can be used for custom filters or tests that want to react to
150 undefined variables. For example a custom default filter can look like
153 def default(var, default=''):
154 if is_undefined(var):
158 from jinja2.runtime import Undefined
159 return isinstance(obj, Undefined)
162 def consume(iterable):
163 """Consumes an iterable without doing anything with it."""
164 for event in iterable:
169 """Jinja2 keeps internal caches for environments and lexers. These are
170 used so that Jinja2 doesn't have to recreate environments and lexers all
171 the time. Normally you don't have to care about that but if you are
172 messuring memory consumption you may want to clean the caches.
174 from jinja2.environment import _spontaneous_environments
175 from jinja2.lexer import _lexer_cache
176 _spontaneous_environments.clear()
180 def import_string(import_name, silent=False):
181 """Imports an object based on a string. This use useful if you want to
182 use import paths as endpoints or something similar. An import path can
183 be specified either in dotted notation (``xml.sax.saxutils.escape``)
184 or with a colon as object delimiter (``xml.sax.saxutils:escape``).
186 If the `silent` is True the return value will be `None` if the import
189 :return: imported object
192 if ':' in import_name:
193 module, obj = import_name.split(':', 1)
194 elif '.' in import_name:
195 items = import_name.split('.')
196 module = '.'.join(items[:-1])
199 return __import__(import_name)
200 return getattr(__import__(module, None, None, [obj]), obj)
201 except (ImportError, AttributeError):
206 def open_if_exists(filename, mode='rb'):
207 """Returns a file descriptor for the filename if that file exists,
211 return open(filename, mode)
213 if e.errno not in (errno.ENOENT, errno.EISDIR):
217 def pformat(obj, verbose=False):
218 """Prettyprint an object. Either use the `pretty` library or the
222 from pretty import pretty
223 return pretty(obj, verbose=verbose)
225 from pprint import pformat
229 def urlize(text, trim_url_limit=None, nofollow=False):
230 """Converts any URLs in text into clickable links. Works on http://,
231 https:// and www. links. Links can have trailing punctuation (periods,
232 commas, close-parens) and leading punctuation (opening parens) and
233 it'll still do the right thing.
235 If trim_url_limit is not None, the URLs in link text will be limited
236 to trim_url_limit characters.
238 If nofollow is True, the URLs in link text will get a rel="nofollow"
241 trim_url = lambda x, limit=trim_url_limit: limit is not None \
242 and (x[:limit] + (len(x) >=limit and '...'
244 words = _word_split_re.split(unicode(escape(text)))
245 nofollow_attr = nofollow and ' rel="nofollow"' or ''
246 for i, word in enumerate(words):
247 match = _punctuation_re.match(word)
249 lead, middle, trail = match.groups()
250 if middle.startswith('www.') or (
251 '@' not in middle and
252 not middle.startswith('http://') and
254 middle[0] in _letters + _digits and (
255 middle.endswith('.org') or
256 middle.endswith('.net') or
257 middle.endswith('.com')
259 middle = '<a href="http://%s"%s>%s</a>' % (middle,
260 nofollow_attr, trim_url(middle))
261 if middle.startswith('http://') or \
262 middle.startswith('https://'):
263 middle = '<a href="%s"%s>%s</a>' % (middle,
264 nofollow_attr, trim_url(middle))
265 if '@' in middle and not middle.startswith('www.') and \
266 not ':' in middle and _simple_email_re.match(middle):
267 middle = '<a href="mailto:%s">%s</a>' % (middle, middle)
268 if lead + middle + trail != word:
269 words[i] = lead + middle + trail
270 return u''.join(words)
273 def generate_lorem_ipsum(n=5, html=True, min=20, max=100):
274 """Generate some lorem impsum for the template."""
275 from jinja2.constants import LOREM_IPSUM_WORDS
276 from random import choice, randrange
277 words = LOREM_IPSUM_WORDS.split()
281 next_capitalized = True
282 last_comma = last_fullstop = 0
287 # each paragraph contains out of 20 to 100 words.
288 for idx, _ in enumerate(xrange(randrange(min, max))):
295 word = word.capitalize()
296 next_capitalized = False
298 if idx - randrange(3, 8) > last_comma:
302 # add end of sentences
303 if idx - randrange(10, 20) > last_fullstop:
304 last_comma = last_fullstop = idx
306 next_capitalized = True
309 # ensure that the paragraph ends with a dot.
313 elif not p.endswith('.'):
318 return u'\n\n'.join(result)
319 return Markup(u'\n'.join(u'<p>%s</p>' % escape(x) for x in result))
322 class Markup(unicode):
323 r"""Marks a string as being safe for inclusion in HTML/XML output without
324 needing to be escaped. This implements the `__html__` interface a couple
325 of frameworks and web applications use. :class:`Markup` is a direct
326 subclass of `unicode` and provides all the methods of `unicode` just that
327 it escapes arguments passed and always returns `Markup`.
329 The `escape` function returns markup objects so that double escaping can't
330 happen. If you want to use autoescaping in Jinja just enable the
331 autoescaping feature in the environment.
333 The constructor of the :class:`Markup` class can be used for three
334 different things: When passed an unicode object it's assumed to be safe,
335 when passed an object with an HTML representation (has an `__html__`
336 method) that representation is used, otherwise the object passed is
337 converted into a unicode string and then assumed to be safe:
339 >>> Markup("Hello <em>World</em>!")
340 Markup(u'Hello <em>World</em>!')
341 >>> class Foo(object):
342 ... def __html__(self):
343 ... return '<a href="#">foo</a>'
346 Markup(u'<a href="#">foo</a>')
348 If you want object passed being always treated as unsafe you can use the
349 :meth:`escape` classmethod to create a :class:`Markup` object:
351 >>> Markup.escape("Hello <em>World</em>!")
352 Markup(u'Hello <em>World</em>!')
354 Operations on a markup string are markup aware which means that all
355 arguments are passed through the :func:`escape` function:
357 >>> em = Markup("<em>%s</em>")
359 Markup(u'<em>foo & bar</em>')
360 >>> strong = Markup("<strong>%(text)s</strong>")
361 >>> strong % {'text': '<blink>hacker here</blink>'}
362 Markup(u'<strong><blink>hacker here</blink></strong>')
363 >>> Markup("<em>Hello</em> ") + "<foo>"
364 Markup(u'<em>Hello</em> <foo>')
368 def __new__(cls, base=u'', encoding=None, errors='strict'):
369 if hasattr(base, '__html__'):
370 base = base.__html__()
372 return unicode.__new__(cls, base)
373 return unicode.__new__(cls, base, encoding, errors)
378 def __add__(self, other):
379 if hasattr(other, '__html__') or isinstance(other, basestring):
380 return self.__class__(unicode(self) + unicode(escape(other)))
381 return NotImplemented
383 def __radd__(self, other):
384 if hasattr(other, '__html__') or isinstance(other, basestring):
385 return self.__class__(unicode(escape(other)) + unicode(self))
386 return NotImplemented
388 def __mul__(self, num):
389 if isinstance(num, (int, long)):
390 return self.__class__(unicode.__mul__(self, num))
391 return NotImplemented
394 def __mod__(self, arg):
395 if isinstance(arg, tuple):
396 arg = tuple(imap(_MarkupEscapeHelper, arg))
398 arg = _MarkupEscapeHelper(arg)
399 return self.__class__(unicode.__mod__(self, arg))
403 self.__class__.__name__,
404 unicode.__repr__(self)
408 return self.__class__(unicode.join(self, imap(escape, seq)))
409 join.__doc__ = unicode.join.__doc__
411 def split(self, *args, **kwargs):
412 return map(self.__class__, unicode.split(self, *args, **kwargs))
413 split.__doc__ = unicode.split.__doc__
415 def rsplit(self, *args, **kwargs):
416 return map(self.__class__, unicode.rsplit(self, *args, **kwargs))
417 rsplit.__doc__ = unicode.rsplit.__doc__
419 def splitlines(self, *args, **kwargs):
420 return map(self.__class__, unicode.splitlines(self, *args, **kwargs))
421 splitlines.__doc__ = unicode.splitlines.__doc__
424 r"""Unescape markup again into an unicode string. This also resolves
425 known HTML4 and XHTML entities:
427 >>> Markup("Main » <em>About</em>").unescape()
428 u'Main \xbb <em>About</em>'
430 from jinja2.constants import HTML_ENTITIES
433 if name in HTML_ENTITIES:
434 return unichr(HTML_ENTITIES[name])
436 if name[:2] in ('#x', '#X'):
437 return unichr(int(name[2:], 16))
438 elif name.startswith('#'):
439 return unichr(int(name[1:]))
443 return _entity_re.sub(handle_match, unicode(self))
446 r"""Unescape markup into an unicode string and strip all tags. This
447 also resolves known HTML4 and XHTML entities. Whitespace is
450 >>> Markup("Main » <em>About</em>").striptags()
453 stripped = u' '.join(_striptags_re.sub('', self).split())
454 return Markup(stripped).unescape()
458 """Escape the string. Works like :func:`escape` with the difference
459 that for subclasses of :class:`Markup` this function would return the
463 if rv.__class__ is not cls:
467 def make_wrapper(name):
468 orig = getattr(unicode, name)
469 def func(self, *args, **kwargs):
470 args = _escape_argspec(list(args), enumerate(args))
471 _escape_argspec(kwargs, kwargs.iteritems())
472 return self.__class__(orig(self, *args, **kwargs))
473 func.__name__ = orig.__name__
474 func.__doc__ = orig.__doc__
477 for method in '__getitem__', 'capitalize', \
478 'title', 'lower', 'upper', 'replace', 'ljust', \
479 'rjust', 'lstrip', 'rstrip', 'center', 'strip', \
480 'translate', 'expandtabs', 'swapcase', 'zfill':
481 locals()[method] = make_wrapper(method)
484 if hasattr(unicode, 'partition'):
485 partition = make_wrapper('partition'),
486 rpartition = make_wrapper('rpartition')
489 if hasattr(unicode, 'format'):
490 format = make_wrapper('format')
493 if hasattr(unicode, '__getslice__'):
494 __getslice__ = make_wrapper('__getslice__')
496 del method, make_wrapper
499 def _escape_argspec(obj, iterable):
500 """Helper for various string-wrapped functions."""
501 for key, value in iterable:
502 if hasattr(value, '__html__') or isinstance(value, basestring):
503 obj[key] = escape(value)
507 class _MarkupEscapeHelper(object):
508 """Helper for Markup.__mod__"""
510 def __init__(self, obj):
513 __getitem__ = lambda s, x: _MarkupEscapeHelper(s.obj[x])
514 __str__ = lambda s: str(escape(s.obj))
515 __unicode__ = lambda s: unicode(escape(s.obj))
516 __repr__ = lambda s: str(escape(repr(s.obj)))
517 __int__ = lambda s: int(s.obj)
518 __float__ = lambda s: float(s.obj)
521 class LRUCache(object):
522 """A simple LRU Cache implementation."""
524 # this is fast for small capacities (something below 1000) but doesn't
525 # scale. But as long as it's only used as storage for templates this
528 def __init__(self, capacity):
529 self.capacity = capacity
531 self._queue = deque()
535 # alias all queue methods for faster lookup
536 self._popleft = self._queue.popleft
537 self._pop = self._queue.pop
538 if hasattr(self._queue, 'remove'):
539 self._remove = self._queue.remove
540 self._wlock = allocate_lock()
541 self._append = self._queue.append
543 def _remove(self, obj):
544 """Python 2.4 compatibility."""
545 for idx, item in enumerate(self._queue):
550 def __getstate__(self):
552 'capacity': self.capacity,
553 '_mapping': self._mapping,
554 '_queue': self._queue
557 def __setstate__(self, d):
558 self.__dict__.update(d)
561 def __getnewargs__(self):
562 return (self.capacity,)
565 """Return an shallow copy of the instance."""
566 rv = self.__class__(self.capacity)
567 rv._mapping.update(self._mapping)
568 rv._queue = deque(self._queue)
571 def get(self, key, default=None):
572 """Return an item from the cache dict or `default`"""
578 def setdefault(self, key, default=None):
579 """Set `default` if the key is not in the cache otherwise
580 leave unchanged. Return the value of this key.
589 """Clear the cache."""
590 self._wlock.acquire()
592 self._mapping.clear()
595 self._wlock.release()
597 def __contains__(self, key):
598 """Check if a key exists in this cache."""
599 return key in self._mapping
602 """Return the current size of the cache."""
603 return len(self._mapping)
607 self.__class__.__name__,
611 def __getitem__(self, key):
612 """Get an item from the cache. Moves the item up so that it has the
613 highest priority then.
615 Raise an `KeyError` if it does not exist.
617 rv = self._mapping[key]
618 if self._queue[-1] != key:
622 # if something removed the key from the container
623 # when we read, ignore the ValueError that we would
629 def __setitem__(self, key, value):
630 """Sets the value for an item. Moves the item up so that it
631 has the highest priority then.
633 self._wlock.acquire()
635 if key in self._mapping:
639 # __getitem__ is not locked, it might happen
641 elif len(self._mapping) == self.capacity:
642 del self._mapping[self._popleft()]
644 self._mapping[key] = value
646 self._wlock.release()
648 def __delitem__(self, key):
649 """Remove an item from the cache dict.
650 Raise an `KeyError` if it does not exist.
652 self._wlock.acquire()
654 del self._mapping[key]
658 # __getitem__ is not locked, it might happen
661 self._wlock.release()
664 """Return a list of items."""
665 result = [(key, self._mapping[key]) for key in list(self._queue)]
670 """Iterate over all items."""
671 return iter(self.items())
674 """Return a list of all values."""
675 return [x[1] for x in self.items()]
678 """Iterate over all values."""
679 return iter(self.values())
682 """Return a list of all keys ordered by most recent usage."""
686 """Iterate over all keys in the cache dict, ordered by
687 the most recent usage.
689 return reversed(tuple(self._queue))
693 def __reversed__(self):
694 """Iterate over the values in the cache dict, oldest items
697 return iter(tuple(self._queue))
702 # register the LRU cache as mutable mapping if possible
704 from collections import MutableMapping
705 MutableMapping.register(LRUCache)
710 class Cycler(object):
711 """A cycle helper for templates."""
713 def __init__(self, *items):
715 raise RuntimeError('at least one item has to be provided')
720 """Resets the cycle."""
725 """Returns the current item."""
726 return self.items[self.pos]
729 """Goes one item ahead and returns it."""
731 self.pos = (self.pos + 1) % len(self.items)
735 class Joiner(object):
736 """A joining helper for templates."""
738 def __init__(self, sep=u', '):
749 # we have to import it down here as the speedups module imports the
750 # markup type which is define above.
752 from jinja2._speedups import escape, soft_unicode
755 """Convert the characters &, <, >, ' and " in string s to HTML-safe
756 sequences. Use this if you need to display text that might contain
757 such characters in HTML. Marks return value as markup string.
759 if hasattr(s, '__html__'):
761 return Markup(unicode(s)
762 .replace('&', '&')
763 .replace('>', '>')
764 .replace('<', '<')
765 .replace("'", ''')
766 .replace('"', '"')
770 """Make a string unicode if it isn't already. That way a markup
771 string is not converted back to unicode.
773 if not isinstance(s, unicode):
780 from functools import partial
782 class partial(object):
783 def __init__(self, _func, *args, **kwargs):
786 self._kwargs = kwargs
787 def __call__(self, *args, **kwargs):
788 kwargs.update(self._kwargs)
789 return self._func(*(self._args + args), **kwargs)