1 # -*- coding: utf-8 -*-
8 :copyright: 2008 by Armin Ronacher.
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'})()
39 # concatenate a list of strings and convert them to unicode.
40 # unfortunately there is a bug in python 2.4 and lower that causes
41 # unicode.join trash the traceback.
45 raise TypeError(_test_gen_bug)
47 _concat(_test_gen_bug())
48 except TypeError, _error:
49 if not _error.args or _error.args[0] is not _test_gen_bug:
52 return _concat(list(gen))
54 # this hack is needed so that the current frame
55 # does not show up in the traceback.
56 exc_type, exc_value, tb = sys.exc_info()
57 raise exc_type, exc_value, tb.tb_next
60 del _test_gen_bug, _error
63 # ironpython without stdlib doesn't have keyword
65 from keyword import iskeyword as is_python_keyword
67 _py_identifier_re = re.compile(r'^[a-zA-Z_][a-zA-Z0-9]*$')
68 def is_python_keyword(name):
69 if _py_identifier_re.search(name) is None:
78 # common types. These do exist in the special types module too which however
79 # does not exist in IronPython out of the box.
81 def method(self): pass
84 FunctionType = type(_func)
85 GeneratorType = type(_func())
86 MethodType = type(_C.method)
87 CodeType = type(_C.method.func_code)
91 _tb = sys.exc_info()[2]
92 TracebackType = type(_tb)
93 FrameType = type(_tb.tb_frame)
97 def contextfunction(f):
98 """This decorator can be used to mark a function or method context callable.
99 A context callable is passed the active :class:`Context` as first argument when
100 called from the template. This is useful if a function wants to get access
101 to the context or functions provided on the context object. For example
102 a function that returns a sorted list of template variables the current
103 template exports could look like this::
106 def get_exported_names(context):
107 return sorted(context.exported_vars)
109 f.contextfunction = True
113 def environmentfunction(f):
114 """This decorator can be used to mark a function or method as environment
115 callable. This decorator works exactly like the :func:`contextfunction`
116 decorator just that the first argument is the active :class:`Environment`
119 f.environmentfunction = True
123 def is_undefined(obj):
124 """Check if the object passed is undefined. This does nothing more than
125 performing an instance check against :class:`Undefined` but looks nicer.
126 This can be used for custom filters or tests that want to react to
127 undefined variables. For example a custom default filter can look like
130 def default(var, default=''):
131 if is_undefined(var):
135 from jinja2.runtime import Undefined
136 return isinstance(obj, Undefined)
139 def consume(iterable):
140 """Consumes an iterable without doing anything with it."""
141 for event in iterable:
146 """Jinja2 keeps internal caches for environments and lexers. These are
147 used so that Jinja2 doesn't have to recreate environments and lexers all
148 the time. Normally you don't have to care about that but if you are
149 messuring memory consumption you may want to clean the caches.
151 from jinja2.environment import _spontaneous_environments
152 from jinja2.lexer import _lexer_cache
153 _spontaneous_environments.clear()
157 def import_string(import_name, silent=False):
158 """Imports an object based on a string. This use useful if you want to
159 use import paths as endpoints or something similar. An import path can
160 be specified either in dotted notation (``xml.sax.saxutils.escape``)
161 or with a colon as object delimiter (``xml.sax.saxutils:escape``).
163 If the `silent` is True the return value will be `None` if the import
166 :return: imported object
169 if ':' in import_name:
170 module, obj = import_name.split(':', 1)
171 elif '.' in import_name:
172 items = import_name.split('.')
173 module = '.'.join(items[:-1])
176 return __import__(import_name)
177 return getattr(__import__(module, None, None, [obj]), obj)
178 except (ImportError, AttributeError):
183 def open_if_exists(filename, mode='r'):
184 """Returns a file descriptor for the filename if that file exists,
188 return file(filename, mode)
190 if e.errno not in (errno.ENOENT, errno.EISDIR):
194 def pformat(obj, verbose=False):
195 """Prettyprint an object. Either use the `pretty` library or the
199 from pretty import pretty
200 return pretty(obj, verbose=verbose)
202 from pprint import pformat
206 def urlize(text, trim_url_limit=None, nofollow=False):
207 """Converts any URLs in text into clickable links. Works on http://,
208 https:// and www. links. Links can have trailing punctuation (periods,
209 commas, close-parens) and leading punctuation (opening parens) and
210 it'll still do the right thing.
212 If trim_url_limit is not None, the URLs in link text will be limited
213 to trim_url_limit characters.
215 If nofollow is True, the URLs in link text will get a rel="nofollow"
218 trim_url = lambda x, limit=trim_url_limit: limit is not None \
219 and (x[:limit] + (len(x) >=limit and '...'
221 words = _word_split_re.split(unicode(escape(text)))
222 nofollow_attr = nofollow and ' rel="nofollow"' or ''
223 for i, word in enumerate(words):
224 match = _punctuation_re.match(word)
226 lead, middle, trail = match.groups()
227 if middle.startswith('www.') or (
228 '@' not in middle and
229 not middle.startswith('http://') and
231 middle[0] in _letters + _digits and (
232 middle.endswith('.org') or
233 middle.endswith('.net') or
234 middle.endswith('.com')
236 middle = '<a href="http://%s"%s>%s</a>' % (middle,
237 nofollow_attr, trim_url(middle))
238 if middle.startswith('http://') or \
239 middle.startswith('https://'):
240 middle = '<a href="%s"%s>%s</a>' % (middle,
241 nofollow_attr, trim_url(middle))
242 if '@' in middle and not middle.startswith('www.') and \
243 not ':' in middle and _simple_email_re.match(middle):
244 middle = '<a href="mailto:%s">%s</a>' % (middle, middle)
245 if lead + middle + trail != word:
246 words[i] = lead + middle + trail
247 return u''.join(words)
250 def generate_lorem_ipsum(n=5, html=True, min=20, max=100):
251 """Generate some lorem impsum for the template."""
252 from jinja2.constants import LOREM_IPSUM_WORDS
253 from random import choice, random, randrange
254 words = LOREM_IPSUM_WORDS.split()
258 next_capitalized = True
259 last_comma = last_fullstop = 0
264 # each paragraph contains out of 20 to 100 words.
265 for idx, _ in enumerate(xrange(randrange(min, max))):
272 word = word.capitalize()
273 next_capitalized = False
275 if idx - randrange(3, 8) > last_comma:
279 # add end of sentences
280 if idx - randrange(10, 20) > last_fullstop:
281 last_comma = last_fullstop = idx
283 next_capitalized = True
286 # ensure that the paragraph ends with a dot.
290 elif not p.endswith('.'):
295 return u'\n\n'.join(result)
296 return Markup(u'\n'.join(u'<p>%s</p>' % escape(x) for x in result))
299 class Markup(unicode):
300 r"""Marks a string as being safe for inclusion in HTML/XML output without
301 needing to be escaped. This implements the `__html__` interface a couple
302 of frameworks and web applications use. :class:`Markup` is a direct
303 subclass of `unicode` and provides all the methods of `unicode` just that
304 it escapes arguments passed and always returns `Markup`.
306 The `escape` function returns markup objects so that double escaping can't
307 happen. If you want to use autoescaping in Jinja just enable the
308 autoescaping feature in the environment.
310 The constructor of the :class:`Markup` class can be used for three
311 different things: When passed an unicode object it's assumed to be safe,
312 when passed an object with an HTML representation (has an `__html__`
313 method) that representation is used, otherwise the object passed is
314 converted into a unicode string and then assumed to be safe:
316 >>> Markup("Hello <em>World</em>!")
317 Markup(u'Hello <em>World</em>!')
318 >>> class Foo(object):
319 ... def __html__(self):
320 ... return '<a href="#">foo</a>'
323 Markup(u'<a href="#">foo</a>')
325 If you want object passed being always treated as unsafe you can use the
326 :meth:`escape` classmethod to create a :class:`Markup` object:
328 >>> Markup.escape("Hello <em>World</em>!")
329 Markup(u'Hello <em>World</em>!')
331 Operations on a markup string are markup aware which means that all
332 arguments are passed through the :func:`escape` function:
334 >>> em = Markup("<em>%s</em>")
336 Markup(u'<em>foo & bar</em>')
337 >>> strong = Markup("<strong>%(text)s</strong>")
338 >>> strong % {'text': '<blink>hacker here</blink>'}
339 Markup(u'<strong><blink>hacker here</blink></strong>')
340 >>> Markup("<em>Hello</em> ") + "<foo>"
341 Markup(u'<em>Hello</em> <foo>')
345 def __new__(cls, base=u'', encoding=None, errors='strict'):
346 if hasattr(base, '__html__'):
347 base = base.__html__()
349 return unicode.__new__(cls, base)
350 return unicode.__new__(cls, base, encoding, errors)
355 def __add__(self, other):
356 if hasattr(other, '__html__') or isinstance(other, basestring):
357 return self.__class__(unicode(self) + unicode(escape(other)))
358 return NotImplemented
360 def __radd__(self, other):
361 if hasattr(other, '__html__') or isinstance(other, basestring):
362 return self.__class__(unicode(escape(other)) + unicode(self))
363 return NotImplemented
365 def __mul__(self, num):
366 if isinstance(num, (int, long)):
367 return self.__class__(unicode.__mul__(self, num))
368 return NotImplemented
371 def __mod__(self, arg):
372 if isinstance(arg, tuple):
373 arg = tuple(imap(_MarkupEscapeHelper, arg))
375 arg = _MarkupEscapeHelper(arg)
376 return self.__class__(unicode.__mod__(self, arg))
380 self.__class__.__name__,
381 unicode.__repr__(self)
385 return self.__class__(unicode.join(self, imap(escape, seq)))
386 join.__doc__ = unicode.join.__doc__
388 def split(self, *args, **kwargs):
389 return map(self.__class__, unicode.split(self, *args, **kwargs))
390 split.__doc__ = unicode.split.__doc__
392 def rsplit(self, *args, **kwargs):
393 return map(self.__class__, unicode.rsplit(self, *args, **kwargs))
394 rsplit.__doc__ = unicode.rsplit.__doc__
396 def splitlines(self, *args, **kwargs):
397 return map(self.__class__, unicode.splitlines(self, *args, **kwargs))
398 splitlines.__doc__ = unicode.splitlines.__doc__
401 r"""Unescape markup again into an unicode string. This also resolves
402 known HTML4 and XHTML entities:
404 >>> Markup("Main » <em>About</em>").unescape()
405 u'Main \xbb <em>About</em>'
407 from jinja2.constants import HTML_ENTITIES
410 if name in HTML_ENTITIES:
411 return unichr(HTML_ENTITIES[name])
413 if name[:2] in ('#x', '#X'):
414 return unichr(int(name[2:], 16))
415 elif name.startswith('#'):
416 return unichr(int(name[1:]))
420 return _entity_re.sub(handle_match, unicode(self))
423 r"""Unescape markup into an unicode string and strip all tags. This
424 also resolves known HTML4 and XHTML entities. Whitespace is
427 >>> Markup("Main » <em>About</em>").striptags()
430 stripped = u' '.join(_striptags_re.sub('', self).split())
431 return Markup(stripped).unescape()
435 """Escape the string. Works like :func:`escape` with the difference
436 that for subclasses of :class:`Markup` this function would return the
440 if rv.__class__ is not cls:
444 def make_wrapper(name):
445 orig = getattr(unicode, name)
446 def func(self, *args, **kwargs):
447 args = _escape_argspec(list(args), enumerate(args))
448 _escape_argspec(kwargs, kwargs.iteritems())
449 return self.__class__(orig(self, *args, **kwargs))
450 func.__name__ = orig.__name__
451 func.__doc__ = orig.__doc__
454 for method in '__getitem__', '__getslice__', 'capitalize', \
455 'title', 'lower', 'upper', 'replace', 'ljust', \
456 'rjust', 'lstrip', 'rstrip', 'center', 'strip', \
457 'translate', 'expandtabs', 'swapcase', 'zfill':
458 locals()[method] = make_wrapper(method)
461 if hasattr(unicode, 'partition'):
462 partition = make_wrapper('partition'),
463 rpartition = make_wrapper('rpartition')
466 if hasattr(unicode, 'format'):
467 format = make_wrapper('format')
469 del method, make_wrapper
472 def _escape_argspec(obj, iterable):
473 """Helper for various string-wrapped functions."""
474 for key, value in iterable:
475 if hasattr(value, '__html__') or isinstance(value, basestring):
476 obj[key] = escape(value)
480 class _MarkupEscapeHelper(object):
481 """Helper for Markup.__mod__"""
483 def __init__(self, obj):
486 __getitem__ = lambda s, x: _MarkupEscapeHelper(s.obj[x])
487 __unicode__ = lambda s: unicode(escape(s.obj))
488 __str__ = lambda s: str(escape(s.obj))
489 __repr__ = lambda s: str(escape(repr(s.obj)))
490 __int__ = lambda s: int(s.obj)
491 __float__ = lambda s: float(s.obj)
494 class LRUCache(object):
495 """A simple LRU Cache implementation."""
497 # this is fast for small capacities (something below 1000) but doesn't
498 # scale. But as long as it's only used as storage for templates this
501 def __init__(self, capacity):
502 self.capacity = capacity
504 self._queue = deque()
508 # alias all queue methods for faster lookup
509 self._popleft = self._queue.popleft
510 self._pop = self._queue.pop
511 if hasattr(self._queue, 'remove'):
512 self._remove = self._queue.remove
513 self._wlock = allocate_lock()
514 self._append = self._queue.append
516 def _remove(self, obj):
517 """Python 2.4 compatibility."""
518 for idx, item in enumerate(self._queue):
523 def __getstate__(self):
525 'capacity': self.capacity,
526 '_mapping': self._mapping,
527 '_queue': self._queue
530 def __setstate__(self, d):
531 self.__dict__.update(d)
534 def __getnewargs__(self):
535 return (self.capacity,)
538 """Return an shallow copy of the instance."""
539 rv = self.__class__(self.capacity)
540 rv._mapping.update(self._mapping)
541 rv._queue = deque(self._queue)
544 def get(self, key, default=None):
545 """Return an item from the cache dict or `default`"""
551 def setdefault(self, key, default=None):
552 """Set `default` if the key is not in the cache otherwise
553 leave unchanged. Return the value of this key.
562 """Clear the cache."""
563 self._wlock.acquire()
565 self._mapping.clear()
568 self._wlock.release()
570 def __contains__(self, key):
571 """Check if a key exists in this cache."""
572 return key in self._mapping
575 """Return the current size of the cache."""
576 return len(self._mapping)
580 self.__class__.__name__,
584 def __getitem__(self, key):
585 """Get an item from the cache. Moves the item up so that it has the
586 highest priority then.
588 Raise an `KeyError` if it does not exist.
590 rv = self._mapping[key]
591 if self._queue[-1] != key:
596 def __setitem__(self, key, value):
597 """Sets the value for an item. Moves the item up so that it
598 has the highest priority then.
600 self._wlock.acquire()
602 if key in self._mapping:
604 elif len(self._mapping) == self.capacity:
605 del self._mapping[self._popleft()]
607 self._mapping[key] = value
609 self._wlock.release()
611 def __delitem__(self, key):
612 """Remove an item from the cache dict.
613 Raise an `KeyError` if it does not exist.
615 self._wlock.acquire()
617 del self._mapping[key]
620 self._wlock.release()
623 """Return a list of items."""
624 result = [(key, self._mapping[key]) for key in list(self._queue)]
629 """Iterate over all items."""
630 return iter(self.items())
633 """Return a list of all values."""
634 return [x[1] for x in self.items()]
637 """Iterate over all values."""
638 return iter(self.values())
641 """Return a list of all keys ordered by most recent usage."""
645 """Iterate over all keys in the cache dict, ordered by
646 the most recent usage.
648 return reversed(tuple(self._queue))
652 def __reversed__(self):
653 """Iterate over the values in the cache dict, oldest items
656 return iter(tuple(self._queue))
661 # register the LRU cache as mutable mapping if possible
663 from collections import MutableMapping
664 MutableMapping.register(LRUCache)
669 class Cycler(object):
670 """A cycle helper for templates."""
672 def __init__(self, *items):
674 raise RuntimeError('at least one item has to be provided')
679 """Resets the cycle."""
684 """Returns the current item."""
685 return self.items[self.pos]
688 """Goes one item ahead and returns it."""
690 self.pos = (self.pos + 1) % len(self.items)
694 class Joiner(object):
695 """A joining helper for templates."""
697 def __init__(self, sep=u', '):
708 # we have to import it down here as the speedups module imports the
709 # markup type which is define above.
711 from jinja2._speedups import escape, soft_unicode
714 """Convert the characters &, <, >, ' and " in string s to HTML-safe
715 sequences. Use this if you need to display text that might contain
716 such characters in HTML. Marks return value as markup string.
718 if hasattr(s, '__html__'):
720 return Markup(unicode(s)
721 .replace('&', '&')
722 .replace('>', '>')
723 .replace('<', '<')
724 .replace("'", ''')
725 .replace('"', '"')
729 """Make a string unicode if it isn't already. That way a markup
730 string is not converted back to unicode.
732 if not isinstance(s, unicode):
739 from functools import partial
741 class partial(object):
742 def __init__(self, _func, *args, **kwargs):
745 self._kwargs = kwargs
746 def __call__(self, *args, **kwargs):
747 kwargs.update(self._kwargs)
748 return self._func(*(self._args + args), **kwargs)