PK« Œ4w˜Assjinja/exceptions.py# -*- coding: utf-8 -*- """ jinja exceptions """ class SilentVariableFailure(Exception): pass class VariableDoesNotExist(Exception): pass class TemplateCharsetError(Exception): def __init__(self, msg, exc): self._msg = msg self._exc = exc def __str__(self): return '%s:\n%s' % (self._msg, self._exc) def __repr__(self): return '%s:\n%r' % (self._msg, self._exc) class TemplateSyntaxError(Exception): pass class TemplateRuntimeError(Exception): pass class TemplateDoesNotExist(Exception): pass class ContextPopException(Exception): pass class TagLexerError(ValueError): def __init__(self, msg, pos, databuf): from jinja.tagparser import ERROR_KEEP self._msg = msg self._data = ''.join(databuf)[max(0, pos - ERROR_KEEP): pos + ERROR_KEEP] self._datapos = min(pos, max(0, pos - ERROR_KEEP) + ERROR_KEEP) self._pos = pos + 1 def __str__(self): return '%s at %s.' % (self._msg, self._pos) def __repr__(self): return '<%s: %s at %s>' % (self.__class__.__name__, self._msg, self._pos) PKŽœÇ4÷ë· ¾<¾<jinja/filters.py# -*- coding: utf-8 -*- """ jinja filters ============= Contains all builtin template filters. Each template is able to use them by piping variables to them. The syntax is simple:: {{ variable | filter }} This will passes variable to the filter "filter". In case of having more than one filter you can combine them:: {{ variable | filter1 | filter2 }} If a filter requires an argument call it like this:: {{ variable | filter1 argument1 argument2 | filter2 argument }} Each argument can be a Context variable or a constant value (string or integer). """ from jinja.lib import stdlib from jinja.nodes import * import re def stringfilter(filter): """Decorator for filters that only operate on (unicode) strings. filter(s, *vars) --> filter(s, context, *vars) The decorated function will convert the first argument and all vars that are strings to unicode using the charset of the context. """ def newfilter(s, context, *vars): if not isinstance(s, unicode): s = str(s).decode(context.charset, 'replace') for idx, var in enumerate(vars): if isinstance(var, str): vars[idx] = str(var).decode(context.charset, 'replace') return filter(s, *vars) try: newfilter.__name__ = filter.__name__ newfilter.__doc__ = filter.__doc__ except: pass #requires python2.4 return newfilter def do_replace(s, old, new, count=None): """{{ s|replace old new[ count] }} Return a copy of s with all occurrences of substring old replaced by new. If the optional argument count is given, only the first count occurrences are replaced. """ if count is None: return s.replace(old, new) return s.replace(old, new, count) do_replace = stringfilter(do_replace) def do_upper(s): """{{ s|upper }} Return a copy of s converted to uppercase. """ return s.upper() do_upper = stringfilter(do_upper) def do_lower(s): """{{ s|lower }} Return a copy of s converted to lowercase. """ return s.lower() do_lower = stringfilter(do_lower) def do_escapexml(s): """ {{ s|escapexml }} XML escape &, <, and > in a string of data. """ from xml.sax.saxutils import escape return escape(s) do_escapexml = stringfilter(do_escapexml) def do_addslashes(s): """ {{ s|addslashes }} Adds slashes to s. """ return s.encode('utf-8').encode('string-escape').decode('utf-8') do_addslashes = stringfilter(do_addslashes) def do_capitalize(s): """ {{ s|capitalize }} Return a copy of the string s with only its first character capitalized. """ return s.capitalize() do_capitalize = stringfilter(do_capitalize) def do_title(s): """ {{ s|title }} Return a titlecased version of s, i.e. words start with uppercase characters, all remaining cased characters have lowercase. """ return s.title() do_title = stringfilter(do_title) def do_default(s, context, default_value=''): """ {{ s|default[ default_value] }} In case of s isn't set or True default will return default_value which is '' per default. """ if not s: return default_value return s def do_join(sequence, context, d=''): """ {{ sequence|join[ d] }} Return a string which is the concatenation of the strings in the sequence. The separator between elements is d which is an empty string per default. """ try: if not isinstance(d, unicode): d = str(d).decode(context.charset, 'replace') return reduce(lambda x, y: str(x) + d + str(y), sequence) except: return str(sequence).decode(context.charset, 'replace') def do_count(var, context): """ {{ var|count }} Return the length of var. In case if getting an integer or float it will convert it into a string an return the length of the new string. If the object doesn't provide a __len__ function it will return zero. """ try: if type(var) in (int, float, long): var = unicode(var) return unicode(len(var)) except TypeError: return u'0' def do_urlencode(s, plus=False): """ {{ s|urlencode[ plus] }} Return the urlencoded value of s. For detailed informations have a look at the help page of "urllib.quote" If plus is set to 1 it will use the "urllib.quote_plus" method. """ from urllib import quote, quote_plus if plus: return quote_plus(s) return quote(s) do_urlencode = stringfilter(do_urlencode) def do_striphtml(s): """ {{ s|striphtml }} Return a plaintext version of s. (removes all html tags). """ return re.sub(r'<[^>]*?>', '', s) do_striphtml = stringfilter(do_striphtml) def do_nl2pbr(s): """ {{ s|nl2pbr }} Convert newlines into

and
s. """ if not isinstance(s, basestring): s = str(s) s = re.sub(r'\r\n|\r|\n', '\n', s) paragraphs = re.split('\n{2,}', s) paragraphs = ['

%s

' % p.strip().replace('\n', '
') for p in paragraphs] return '\n\n'.join(paragraphs) do_nl2pbr = stringfilter(do_nl2pbr) def do_nl2br(s): """ {{ s|nl2br }} Convert newlines into
s. """ return re.sub(r'\r\n|\r|\n', '
\n', s) do_nl2br = stringfilter(do_nl2br) def do_autolink(s, nofollow=False): """ {{ s|autolink[ nofollow] }} Automatically creates tags for recognized links. If nofollow is True autolink will add a rel=nofollow tag to the url. """ from jinja.utils import urlize return urlize(s, nofollow=nofollow) do_autolink = stringfilter(do_autolink) def do_autolinktrunc(s, length=50, nofollow=False): """ {{ s|autolink[ length[ nofollow]] }} Same as autolink but truncate the url to a given character limit. """ from jinja.utils import urlize return urlize(s, length, nofollow) do_autolinktrunc = stringfilter(do_autolinktrunc) def do_reverse(iterable, context): """ {{ iterable|reverse }} Return a reversed copy of a given iterable. """ try: return list(reversed(iterable)) except NameError: return list(iterable)[::-1] def do_sort(iterable, context): """ {{ iterable|sort }} Return a sorted copy of a given iterable. """ try: return list(sorted(iterable)) except NameError: l = [] for item in iterable: l.append(item) l.sort() return l def do_slice(iterable, context, *args): """ {{ iterable|slice start, end, step }} Return a slice of an iterable. """ if not hasattr(iterable, '__getslice__') or\ not hasattr(iterable, '__getitem__'): try: iterable = list(iterable) except: iterable = str(iterable).decode(context.charset, 'replace') try: return iterable[slice(*[int(arg) for arg in args[:3]])] except: return iterable def do_deletedouble(iterable, context): """ {{ iterable|deletedouble }} Remove double items in an iterable. """ try: return list(set(iterable)) except NameError: from sets import Set return list(Set(iterable)) def do_format(s, context, f): """ {{ s|format f }} Apply python string format f on s. The leading "%" is left out. """ return ('%' + f) % s def do_indent(s, width=4, indentfirst=False, usetab=False): """ {{ s|indent[ width[ indentfirst[ usetab]]] }} Return a copy of s, each line indented by width spaces. If usetab is True it the filter will use tabs for indenting. If indentfirst is given it will also indent the first line. """ indention = ((usetab) and u'\t' or u' ') * width if indentfirst: return u'\n'.join([indention + line for line in s.splitlines()]) else: return s.replace(u'\n', u'\n' + indention) do_indent = stringfilter(do_indent) def do_truncate(s, length=255, killwords=False, end='...'): """ {{ s|truncate[ length[ killwords[ end]]] }} Return a truncated copy of s. If killwords is True the filter will cut the text at length and append end. Otherwise it will try to save the last word and append end. """ if len(s) <= length: return s if killwords: return s[:length] + end words = s.split(' ') result = [] m = 0 for word in words: m += len(word) + 1 if m > length: break result.append(word) return ' '.join(result) do_truncate = stringfilter(do_truncate) def do_wordwrap(s, pos=79, hard=False): """ {{ s|wordwrap[ hard] }} Return a copy of s, word get wrapped at pos, if hard is True word might get split. """ if len(s) < pos: return s if hard: return '\n'.join([s[idx:idx + pos] for idx in xrange(0, len(s), pos)]) # code from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/148061 return reduce(lambda line, word, pos=pos: '%s%s%s' % (line, ' \n'[(len(line)-line.rfind('\n')-1 + len(word.split('\n',1)[0]) >= pos)], word), s.split(' ')) do_wordwrap = stringfilter(do_wordwrap) def do_textile(s): """ {{ s|textile }} Return a textfile parsed copy of s. requires the PyTextile library available at http://dealmeida.net/projects/textile/ """ from textile import textile return textile(s) do_textile = stringfilter(do_textile) def do_markdown(s): """ {{ s|markdown }} Return a markdown parsed copy of s. requires the Python-markdown library from http://www.freewisdom.org/projects/python-markdown/ """ from markdown import markdown return markdown(s) do_markdown = stringfilter(do_markdown) def do_rst(s): """ {{ s|rst }} Return a reStructuredText parsed copy of s. requires docutils from http://docutils.sourceforge.net/ """ try: from docutils import publish_parts parts = publish_parts(source=s, writer_name='html4css1') return parts['fragment'] except: return s do_rst = stringfilter(do_rst) def do_cut(s, context, char): """ {{ s|cut char }} Equivalent to {{ s|replace char '' }}. """ if not isinstance(char, unicode): char = str(char).decode(context.charset, 'replace') return do_replace(s, context, char, u'') def do_cleanup(s): """ {{ s|cleanup }} Remove double whitespaces. """ return ' '.join(s.split()) do_cleanup = stringfilter(do_cleanup) def do_filesizeformat(i, context): """ {{ i|filesizeformat }} Format the value like a 'human-readable' file size (i.e. 13 KB, 4.1 MB, 102 bytes, etc). """ bytes = float(i) if bytes < 1024: return u"%d Byte%s" % (bytes, bytes != 1 and u's' or u'') if bytes < 1024 * 1024: return u"%.1f KB" % (bytes / 1024) if bytes < 1024 * 1024 * 1024: return u"%.1f MB" % (bytes / (1024 * 1024)) return u"%.1f GB" % (bytes / (1024 * 1024 * 1024)) def do_wordcount(s): """ {{ s|wordcount }} Return the number of words. """ return len(s.split()) do_wordcount = stringfilter(do_wordcount) def do_strip(s, chars='\r\n\t '): """ {{ s|strip[ chars] }} Return a copy of s with leading and trailing whitespace removed. If chars is given and not None, remove characters in chars instead. """ return s.strip(chars) do_strip = stringfilter(do_strip) def do_regexreplace(s, search, replace): """ {{ s|regexreplace search replace }} Perform a re.sub on s Example: {{ s|regexreplace '\\[b\\](.*?)\\[/b\\](?i)' '\\1' }} """ return re.sub(search, replace, s) do_regexreplace = stringfilter(do_regexreplace) def do_decode(s, context, encoding): """ {{ s|decode encoding }} Decode s to unicode with given encoding instead of the context's default. Example: {{ s|decode 'latin-1' }} """ if isinstance(s, unicode): # this is already unicode, so do nothing return s return str(s).decode(encoding, 'replace') def do_str(obj, context): """ {{ obj|str }} Converts an object to a string """ if isinstance(obj, unicode): # this is already unicode, so do nothing return obj return str(obj).decode(encoding, 'replace') def do_int(obj, context, default=0): """ {{ obj|int }} Converts an object to an integer if possible, otherwise returns default """ try: return int(obj) except: try: return int(default) except: return 0 def do_float(obj, context, default=0.0): """ {{ obj|float }} Converts an object to a float if possible, otherwise returns default """ try: return float(obj) except: try: return float(default) except: return 0.0 def do_bool(obj, context, default=False): """ {{ obj|bool }} Converts an object to a bool if possible, otherwise returns default """ try: return bool(obj) except: try: return bool(default) except: return False def do_makebool(obj, context, default=False): """ {{ obj|makebool }} Guesses an boolean (true, on, 1, yes) """ def check(obj): if not isinstance(obj, basestring): obj = str(obj).lower() else: obj = obj.lower() if obj in ('true', '1', 'yes', 'on'): return True elif obj in ('false', '0', 'no', 'off'): return False val = check(obj) if val is None: val = check(default) if val is None: return False return val builtin_filters = { 'replace': do_replace, 'upper': do_upper, 'lower': do_lower, 'escapexml': do_escapexml, 'e': do_escapexml, 'addslashes': do_addslashes, 'capitalize': do_capitalize, 'title': do_title, 'default': do_default, 'join': do_join, 'count': do_count, 'urlencode': do_urlencode, 'striphtml': do_striphtml, 'nl2pbr': do_nl2pbr, 'nl2br': do_nl2br, 'autolink': do_autolink, 'autolinktrunc': do_autolinktrunc, 'reverse': do_reverse, 'sort': do_sort, 'slice': do_slice, 'deletedouble': do_deletedouble, 'format': do_format, 'indent': do_indent, 'truncate': do_truncate, 'wordwrap': do_wordwrap, 'textile': do_textile, 'markdown': do_markdown, 'rst': do_rst, 'cut': do_cut, 'cleanup': do_cleanup, 'filesizeformat': do_filesizeformat, 'wordcount': do_wordcount, 'strip': do_strip, 'regexreplace': do_regexreplace, 'decode': do_decode, 'str': do_str, 'int': do_int, 'float': do_float, 'bool': do_bool, 'makebool': do_makebool, } for name, handler in builtin_filters.iteritems(): stdlib.register_filter(name, handler) PK« Œ4`{'}[[jinja/nodes.py# -*- coding: utf-8 -*- """ jinja builtin nodes """ from jinja.exceptions import VariableDoesNotExist, TemplateSyntaxError,\ TemplateCharsetError from jinja.tokens import NameVal, ValueToken, CommaVal from jinja.utils import resolve_variable __all__ = ['Node', 'TextNode', 'KeywordNode', 'VariableNode', 'ValueNode', 'ChoiceNode', 'CollectionNode'] class Node(object): """class for basenode.""" def findnodes(self): yield self class TextNode(Node): def __init__(self, parser, data): self._data = data def render(self, context): return self._data def __str__(self): return self._data def __repr__(self): return '' % self._data[:20] class KeywordNode(Node): def __init__(self, name): self._name = name def match(self, node): if not isinstance(node, NameVal): return 0, None, None if self._name != node().lower(): return 0, None, None return 10, self, None def __cmp__(self, other): if isinstance(other, basestring): return cmp(self._name.lower(), other.lower()) elif isinstance(other, KeywordNode): return cmp(self._name.lower(), other._name.lower()) else: raise TypeError, 'can\'t compare %r and %r types' % ( self.__class__.__name__, other.__class__.__name__ ) def __repr__(self): return '<%s: %r>' % (self.__class__.__name__, self._name) class VariableNode(Node): def __init__(self, name=None): self._name = name self._filters = None def match(self, node): if not isinstance(node, NameVal) or\ (self._name is not None and self._name != node()): return 0, None, None if self._name: return 10, self.__class__(node()), None else: return 0, self.__class__(node()), None def resolve(self, context, silent=True, default=u''): try: return resolve_variable(self._name, context) except VariableDoesNotExist: if silent: return default raise def define(self, context, value): context[self._name] = value def unset(self, context): if self._name in context: del context[self._name] def render(self, context): result = self.resolve(context) if not isinstance(result, unicode): try: return str(result).decode(context.charset) except UnicodeError, e: raise TemplateCharsetError("Could not resolve variable '%s'" % self._name, e) return result def __repr__(self): if self._name is not None: return '<%s: %r>' % (self.__class__.__name__, self._name) else: return '<%s>' % self.__class__.__name__ class ValueNode(Node): def __init__(self, value=()): self._value = value def match(self, node): if not isinstance(node, ValueToken): return 0, None, None return 10, self.__class__(node()), None def resolve(self, context=None, silent=True): return self._value def render(self, context): if not isinstance(self._value, unicode): try: return str(self._value).decode(context.charset) except UnicodeError, e: raise TemplateCharsetError("Could not resolve value %r" % self._value, e) return self._value def __repr__(self): if self._value != (): return "<%s: %r>" % (self.__class__.__name__, self._value) else: return "<%s>" % self.__class__.__name__ class ChoiceNode(Node): def __init__(self, *values): self._values = values or [ValueNode(), VariableNode()] def match(self, node): rv = [] for value in self._values: score, match, next = value.match(node) if match is not None: rv.append((score, match, next)) rv.sort() if not rv: return 0, None, None return rv[-1] class CollectionNode(Node): def __init__(self, *values): self._values = values or [ValueNode(), VariableNode()] def match(self, node): if node is None: return 0, [], None for value in self._values: score, match, next = value.match(node) if match is not None: return score, [match], _CollectionNodeComma(self) return 0, None, None def findnodes(self): for node in self._values: if not isinstance(node, Node): continue for n in node.findnodes(): yield n class _CollectionNodeComma(Node): def __init__(self, valuelist): self._valuelist = valuelist def match(self, node): if not isinstance(node, CommaVal): return 0, None, None return 10, None, self._valuelist PK« Œ4(ÔUã[[jinja/tagparser.py# -*- coding: utf-8 -*- """ jinja tag parser """ from jinja.nodes import * from jinja.tokens import * from jinja.exceptions import TagLexerError # Lexer constants. STATE_SEP_WS, STATE_START, STATE_START_SEP, STATE_NONE_BOOL_NAME, \ STATE_OCT_HEX_ZERO, STATE_OCT, STATE_HEX, STATE_INT, \ STATE_STRINGSINGLEQUOTE, STATE_STRINGSINGLEQUOTEESCAPE, \ STATE_STRINGDOUBLEQUOTE, STATE_STRINGDOUBLEQUOTEESCAPE = \ range(12) ERROR_KEEP = 20 # Parser constants. CHAIN_PROVIDER, CHAIN_FILTER, CHAIN_ANY = 1, 2, 3 class Lexer(object): """Lexer class for tokenizing a string of input into the tokens defined above. This is a feed-lexer, meaning that you feed input using the feed() function and have to finish input by calling finish(). This makes it suitable to parsing unknown-length input. Getting tokens is done by calling the pop() method, which pops a certain number of tokens from the list of read tokens.""" def __init__(self): """Initialize the lexer.""" self._state = STATE_START self._tokens = [] self._tokenpos = 0 self._databuffer = [] self._curpos = 0 self._buffer = [] self._invalid = False self._finished = False def feed(self, data): """Feed data to the lexer. A lexer can only be fed data if it is not invalid or finished. In case you try to feed data to the lexer in one of the previously mentioned states, a RuntimeError is raised. In case the lexer encounters invalid data, a TagLexerError (which is a subclass of ValueError) is raised and the lexer is put into invalid mode.""" if self._invalid: raise RuntimeError('Cannot feed to invalidated lexer.') if self._finished: raise RuntimeError('Cannot feed to finished lexer.') self._databuffer.append(data) for pos, c in enumerate(data): pos += self._curpos if self._state == STATE_SEP_WS: if c == ',': self._tokens.append(CommaVal()) self._state = STATE_START elif c == '|': self._tokens.append(PipeVal()) self._state = STATE_START elif not c.isspace(): self._invalid = True raise TagLexerError('Expected separator or whitespace', pos, self._databuffer) else: self._state = STATE_START_SEP elif self._state in (STATE_START, STATE_START_SEP): if c.isalpha() or c == '_': self._buffer.append(c) self._state = STATE_NONE_BOOL_NAME elif c == '0': self._buffer.append(c) self._state = STATE_OCT_HEX_ZERO elif c.isdigit(): self._buffer.append(c) self._state = STATE_INT elif c == '\'': self._buffer.append(c) self._state = STATE_STRINGSINGLEQUOTE elif c == '"': self._buffer.append(c) self._state = STATE_STRINGDOUBLEQUOTE elif c == ',' and self._state == STATE_START_SEP: self._tokens.append(CommaVal()) self._state = STATE_START elif c == '|' and self._state == STATE_START_SEP: self._tokens.append(PipeVal()) self._state = STATE_START elif not c.isspace(): self._invalid = True if self._state == STATE_START_SEP: raise TagLexerError('Expected token or separator', pos, self._databuffer) else: raise TagLexerError('Expected token', pos, self._databuffer) elif self._state == STATE_NONE_BOOL_NAME: if c.isalnum() or c in '._': self._buffer.append(c) elif c.isspace() or c in ',|': val = ''.join(self._buffer) if val.lower() == 'none': self._tokens.append(NoneVal(val)) elif val.lower() in ('false', 'true'): self._tokens.append(BoolVal(val)) else: self._tokens.append(NameVal(val)) self._buffer = [] if c == ',': self._tokens.append(CommaVal()) self._state = STATE_START elif c == '|': self._tokens.append(PipeVal()) self._state = STATE_START else: self._state = STATE_START_SEP else: self._invalid = True raise TagLexerError('Expected name or separator', pos, self._databuffer) elif self._state == STATE_OCT_HEX_ZERO: if c in '01234567': self._buffer.append(c) self._state = STATE_OCT elif c in 'xX': self._buffer.append(c) self._state = STATE_HEX elif c.isspace() or c in ',|': val = "".join(self._buffer) self._tokens.append(IntVal(val, 10)) self._buffer = [] if c == ',': self._tokens.append(CommaVal()) self._state = STATE_START elif c == '|': self._tokens.append(PipeVal()) self._state = STATE_START else: self._state = STATE_START_SEP else: self._invalid = True raise TagLexerError('Expected digit or separator', pos, self._databuffer) elif self._state == STATE_OCT: if c in '01234567': self._buffer.append(c) elif c.isspace() or c in ',|': val = ''.join(self._buffer) self._tokens.append(IntVal(val,8)) self._buffer = [] if c == ',': self._tokens.append(CommaVal()) self._state = STATE_START elif c == '|': self._tokens.append(PipeVal()) self._state = STATE_START else: self._state = STATE_START_SEP else: self._invalid = True raise TagLexerError('Expected octal digit or separator', pos, self._databuffer) elif self._state == STATE_HEX: if c.isdigit() or c in 'aAbBcCdDeEfF': self._buffer.append(c) elif c.isspace() or c in ',|': val = ''.join(self._buffer) self._tokens.append(IntVal(val,16)) self._buffer = [] if c == ',': self._tokens.append(CommaVal()) self._state = STATE_START elif c == '|': self._tokens.append(PipeVal()) self._state = STATE_START else: self._state = STATE_START_SEP else: self._invalid = True raise TagLexerError('Expected hex digit or separator', pos, self._databuffer) elif self._state == STATE_INT: if c.isdigit(): self._buffer.append(c) elif c.isspace() or c in ',|': val = ''.join(self._buffer) self._tokens.append(IntVal(val,10)) self._buffer = [] if c == ',': self._tokens.append(CommaVal()) self._state = STATE_START elif c == '|': self._tokens.append(PipeVal()) self._state = STATE_START else: self._state = STATE_START_SEP else: self._invalid = True raise TagLexerError('Expected decimal digit or separator', pos, self._databuffer) elif self._state == STATE_STRINGSINGLEQUOTE: if c == '\\': self._buffer.append(c) self._state = STATE_STRINGSINGLEQUOTEESCAPE elif c == '\'': self._buffer.append(c) val = ''.join(self._buffer) self._tokens.append(StringVal(val)) self._buffer = [] self._state = STATE_SEP_WS else: self._buffer.append(c) elif self._state == STATE_STRINGSINGLEQUOTEESCAPE: if c == '\n': self._buffer.pop() else: self._buffer.append(c) self._state = STATE_STRINGSINGLEQUOTE elif self._state == STATE_STRINGDOUBLEQUOTE: if c == '\\': self._buffer.append(c) self._state = STATE_STRINGDOUBLEQUOTEESCAPE elif c == '"': self._buffer.append(c) val = ''.join(self._buffer) self._tokens.append(StringVal(val)) self._buffer = [] self._state = STATE_SEP_WS else: self._buffer.append(c) elif self._state == STATE_STRINGDOUBLEQUOTEESCAPE: if c == '\n': self._buffer.pop() else: self._buffer.append(c) self._state = STATE_STRINGDOUBLEQUOTE self._curpos = pos+1 def finish(self): """Finish the lexing. A lexer can only be finished in case it is not invalid. Finishing a finished lexer will have no effect. Trying to finish an invalid Lexer will raise a RuntimeError, a processing error in the lexer will result in a TagLexerError, which is a subclass of ValueError.""" if self._invalid: raise RuntimeError('Cannot finish invalidated lexer.') if self._finished: return if self._state == STATE_NONE_BOOL_NAME: val = ''.join(self._buffer) if val.lower() == 'none': self._tokens.append(NoneVal(val)) elif val.lower() in ('false', 'true'): self._tokens.append(BoolVal(val)) else: self._tokens.append(NameVal(val)) self._buffer = [] elif self._state == STATE_OCT_HEX_ZERO: val = ''.join(self._buffer) self._tokens.append(IntVal(val, 10)) self._buffer = [] elif self._state == STATE_OCT: val = ''.join(self._buffer) self._tokens.append(IntVal(val, 8)) self._buffer = [] elif self._state == STATE_HEX: val = ''.join(self._buffer) self._tokens.append(IntVal(val, 16)) self._buffer = [] elif self._state == STATE_INT: val = ''.join(self._buffer) self._tokens.append(IntVal(val, 10)) self._buffer = [] elif self._state not in (STATE_SEP_WS,STATE_START_SEP): self._invalid = True if self._state == STATE_START: raise TagLexerError('No data or dangling separator', self._curpos, self._databuffer) else: raise TagLexerError('String not closed', self._curpos, self._databuffer) self._finished = True def pop(self, n=1): """Pops n tokens from the current token stack. The tokens are returned as a list in case n <> 1, if n == 1 the actual token is returned. In case no tokens are available, it raises a ValueError. In case you request more than one token, returns as many tokens as are available. For the special case n == 0 it returns True or False depending on whether there are tokens available.""" if self._invalid: raise RuntimeError('Cannot pop tokens from invalid lexer.') if n == 0: rv = self._tokenpos < len(self._tokens) elif n == 1: if self._tokenpos == len(self._tokens): raise ValueError('No tokens available.') rv = self._tokens[self._tokenpos] self._tokenpos += 1 else: if self._tokenpos == len(self._tokens): raise ValueError('No tokens available.') rv = self._tokens[self._tokenpos:self._tokenpos + n] self._tokenpos += len(rv) return rv def __repr__(self): if self._finished: return '<%s: %r>' % (self.__class__.__name__, self._tokens) else: return '<%s: running>' % self.__class__.__name__ class Parser(object): def __init__(self, rules=None): if rules is None: rules = {} self._lexer = Lexer() self._chains = dict([(name,(state,chain[:])) for name, (state, chain) in rules.iteritems()]) self._curchains = dict([(name,chain[:]) for name, (state, chain) in self._chains.iteritems() if state & CHAIN_PROVIDER]) self._output = [] self._curoutput = {} self._scores = {} self._invalid = False self._finished = False def feed(self, data): if self._invalid: raise RuntimeError, 'Cannot feed to invalidated parser.' if self._finished: raise RuntimeError, 'Cannot feed to finished parser.' try: self._lexer.feed(data) except RuntimeError: self._invalid = True raise self._process_feed() def finish(self): if self._invalid: raise RuntimeError, 'Cannot finish invalidated parser.' if self._finished: return try: self._lexer.finish() except RuntimeError: self._invalid = True raise self._process_feed() self._finish_chains() self._finished = True def collect(self): if self._invalid: raise RuntimeError, 'Cannot collect data from invalided parser.' return self._output def _finish_chains(self): # Remove all chains that didn't eat all tokens. to_delete = [] expected = [] for name, chain in self._curchains.iteritems(): if chain: # Eat any possible left opening bracket in case there are no # more tokens available. if isinstance(chain[0], tuple): # Continue chain. if chain[0][1] is None: del self._curoutput[name][-1][0] continue chain[0] = chain[0][1] # Remove possible remaining star reference. if ( self._curoutput[name] and isinstance(self._curoutput[name][-1],list) and self._curoutput[name][-1] and self._curoutput[name][-1][0] is chain[0] ): del self._curoutput[name][-1][0] # Eat the chain until it stops. while chain: score, match, _ = chain[0].match(None) if match is not None: self._curoutput.setdefault(name,[]) if ( self._curoutput[name] and isinstance(self._curoutput[name][-1], list) and self._curoutput[name][-1][0] is chain[0] ): self._curoutput[name][-1].extend(match) del self._curoutput[name][-1][0] else: self._curoutput[name].append(match) self._scores[name] = self._scores.get(name, 0) + score chain.pop(0) else: break # If anything left on chain, this chain didn't match. if chain: expected.append((name,chain[0])) to_delete.append(name) for name in to_delete: try: del self._curchains[name] del self._curoutput[name] del self._scores[name] except KeyError: pass # Check whether there are any chains left. if not self._curchains: self._invalid = True raise RuntimeError('Found no token, but expected one of %s.' % expected) # Get chain with highest score. Scoring rules are part of the nodes # return values. bestchain = max(zip(self._scores.values(),self._scores.keys()))[1] self._output.append((bestchain,self._curoutput[bestchain])) # Reset state, this time use only those chains that are allowed to # act as filters. self._curchains = dict([(name,chain[:]) for name, (state, chain) in self._chains.iteritems() if state & CHAIN_FILTER]) self._curoutput = {} self._scores = {} def _process_feed(self): skip = False while self._curchains: skip = True expected = [] to_delete = [] if not self._lexer._tokens: break token = self._lexer._tokens.pop(0) # Continue right away if we get a PipeVal which separates commands. if isinstance(token, PipeVal): self._finish_chains() continue # Update chains with new state if it's something else. for name, chain in self._curchains.iteritems(): # Loop until we truly have a match and no epsilon production. # An epsilon production is always tried in case a match fails. while True: # Check whether chain has any items left to match. if not chain: to_delete.append(name) break curmatch = chain.pop(0) # If we have a continuation (left open), try to match # nexttoken and reinsert whatever it tells us to. If no # match, continue with alternate token. if isinstance(curmatch,tuple): _, _, nexttoken = curmatch[0].match(token) if nexttoken is not None: chain.insert(0, curmatch[1]) chain.insert(0, nexttoken) break else: del self._curoutput[name][-1][0] curmatch = curmatch[1] if curmatch is None: to_delete.append(name) break # Try to match to current token if we had no continuation # or the actual continuation failed. score, match, nexttoken = curmatch.match(token) if match is not None: self._curoutput.setdefault(name,[]) if nexttoken: if chain: chain[0] = (nexttoken, chain[0]) else: chain.append((nexttoken,None)) if ( self._curoutput[name] and isinstance(self._curoutput[name][-1],list) and self._curoutput[name][-1] and self._curoutput[name][-1][0] is curmatch ): self._curoutput[name][-1].extend(match) else: self._curoutput[name].append(match) self._curoutput[name][-1].insert(0,curmatch) else: self._curoutput[name].append(match) self._scores[name] = self._scores.get(name, 0) + score break else: # Try to match epsilon production. score, match, _ = curmatch.match(None) if match is not None: self._curoutput.setdefault(name,[]) if ( self._curoutput[name] and isinstance(self._curoutput[name][-1],list) and self._curoutput[name][-1] and self._curoutput[name][-1][0] is curmatch ): self._curoutput[name][-1].extend(match) del self._curoutput[name][-1][0] else: self._curoutput[name].append(match) self._scores[name] = ( self._scores.get(name, 0) + score ) else: expected.append((name,curmatch)) to_delete.append(name) break # Delete all chains that have not matched. for name in to_delete: try: del self._curchains[name] del self._curoutput[name] del self._scores[name] except KeyError: pass # If we have no more possible states, parsing has failed. if not self._curchains: self._invalid = True if not skip: raise RuntimeError, 'No chains found' elif not expected: raise RuntimeError('Found dangling %s for %s' % (token,to_delete)) else: raise RuntimeError('Expected one of %s, found %s' % (expected,token)) def __repr__(self): return '<%s: output %r>' % (self.__class__.__name__, self._output) PK¹‘Ü4R6~~ÓÓ jinja/base.py# -*- coding: utf-8 -*- """ Jinja Template -------------- Base Module """ from jinja.config import * from jinja.exceptions import * from jinja.nodes import * from jinja.utils import template_tag_regex from jinja.lib import stdlib import re import types # Tokenizer TOKEN_TEXT = 0 TOKEN_VAR = 1 TOKEN_BLOCK = 2 class Context(object): def __init__(self, d=None, charset='utf-8'): self.dicts = [d or {}] self.charset = charset self.registry = {} self.filters = None def __repr__(self): return repr(self.dicts) def __iter__(self): for d in self.dicts: yield d def iterdata(self): for d in self.dicts: for key, value in d.iteritems(): yield key, value def dictrepr(self): return dict(list(self.iterdata())) def push(self): self.dicts = [{}] + self.dicts def pop(self): if len(self.dicts) == 1: self.dicts = [{}] del self.dicts[0] def __setitem__(self, key, value): """Set a variable in the current context.""" self.dicts[0][key] = value def __getitem__(self, key): """ Get a variable's value, starting at the current context and going upward. First it also checks for the special variable called CONTEXT returning the full context. """ if key == 'CONTEXT': return self for d in self.dicts: if key in d: return d[key] return '' def __delitem__(self, key): """Delete a variable from the context.""" # XXX: this doesn't delete from all dicts for d in self.dicts: if key in d: del d[key] return def __contains__(self, key): return self.has_key(key) def has_key(self, key): for d in self.dicts: if key in d: return True return False def get(self, key, otherwise=None): for d in self.dicts: if key in d: return d[key] return otherwise def update(self, other_dict): """ Like dict.update(). Pushes an entire dictionary's keys and values onto the context. """ self.dicts = [other_dict] + self.dicts class Token(object): def __init__(self, token_type, contents): self.token_type = token_type self.contents = contents def __str__(self): return '<%sToken "%s">' % ({ TOKEN_TEXT: 'Text', TOKEN_VAR: 'Var', TOKEN_BLOCK: 'Block' }[self.token_type], self.contents[:].replace('\n', '')) __repr__ = __str__ class NodeList(list): def render(self, context): bits = [] for node in self: if isinstance(node, Node): bits.append(node.render(context)) else: bits.append(node) return u''.join(bits) def findnodes(self): try: nodes = set() except NameError: from sets import Set nodes = Set() for node in self: nodes.update(node.findnodes()) return nodes def get_nodes_by_type(self, nodetype): for node in self.findnodes(): if isinstance(node, nodetype): yield node class Lexer(object): def __init__(self, template): self.template = template def tokenize(self): return [self.create_token(tag) for tag in template_tag_regex.split(self.template) if self.check_tag(tag)] def check_tag(self, tag): return not tag.startswith(COMMENT_TAG_START) def create_token(self, tag): if tag.startswith(VARIABLE_TAG_START): token = Token(TOKEN_VAR, tag[len(VARIABLE_TAG_START):-len(VARIABLE_TAG_END)].strip()) elif tag.startswith(BLOCK_TAG_START): token = Token(TOKEN_BLOCK, tag[len(BLOCK_TAG_START):-len(BLOCK_TAG_END)].strip()) else: token = Token(TOKEN_TEXT, tag) return token class Parser(object): def __init__(self, tokens, loader, lib=None, template_name=None): self.first = True self.tokens = tokens self.library = lib or stdlib self.loader = loader self.template_name = template_name def parse(self, parse_until=None): if parse_until is None: parse_until = [] nodelist = NodeList() while self.tokens: token = self.pop_token() # plain text token result in a text node if token.token_type == TOKEN_TEXT: if token.contents: nodelist.append(TextNode(self, token.contents)) # we found a var token, it's only a shortcut for {% print ... %} elif token.token_type == TOKEN_VAR: if token.contents: nodelist.append(self.library.parse(self, 'print %s' % token.contents)) else: raise TemplateSyntaxError, 'variable is empty' # ney. looks like a block, give it to the library parser elif token.token_type == TOKEN_BLOCK: if token.contents in parse_until: self.tokens.insert(0, token) return nodelist nodelist.append(self.library.parse(self, token.contents)) if nodelist: self.first = False if parse_until: raise TemplateSyntaxError, 'closing tag %s is missing' % parse_until return nodelist def pop_token(self): return self.tokens.pop(0) def get_last_token(self): return self.tokens.pop(0) def remove_dangling_token(self): del self.tokens[0] def subparse(self, endtag): result = self.parse([endtag]) self.remove_dangling_token() return result def forkparse(self, shift, endtag): result_one = self.parse([shift, endtag]) token = self.get_last_token() if token.contents == shift: result_two = self.parse([endtag]) self.remove_dangling_token() else: result_two = NodeList() return result_one, result_two PK¯šå4Gíx¶h—h— jinja/tags.py# -*- coding: utf-8 -*- """ jinja builtin tags """ from __future__ import generators from jinja.exceptions import TemplateRuntimeError, TemplateSyntaxError,\ TemplateCharsetError from jinja.lib import stdlib from jinja.nodes import * class VariableTag(Node): """ Variable Tag ============ Prints a variable stored in the context. With a dot "." you can access attributes and items:: ======================== ============================ Usage Result ======================== ============================ ``user.username`` ``user['username']`` ``arg.0`` ``arg[0]`` ``object.attribute`` ``object.attribute`` ======================== ============================ Usage:: {% print variable %} {% print variable | somefilter "filterarg" %} Instead of print you can use the following shortcuts:: {{ variable }} {{ variable | somefilter | otherfilter "filterarg" }} """ rules = { 'default': [KeywordNode('print'), ChoiceNode()] } def __init__(self, parser, matched_tag, handler_args, stack): self._variable = handler_args[1] self._filters = [(f, args[1:][0]) for f, _, args in stack] def findnodes(self): yield self._variable def render(self, context): if context.filters is None: filters = self._filters[:] else: filters = self._filters + context.filters # there aren't any filters applied to this variable, so render it if not filters: return self._variable.render(context) # we have some of these cute things, apply them filter by filter var = self._variable.resolve(context) for f, args in filters: var = f(var, context, *[arg.resolve(context) for arg in args]) if not isinstance(var, unicode): try: return str(var).decode(context.charset) except UnicodeError, e: raise TemplateCharsetError('Could not convert variable', e) return var def __repr__(self): return '' % (self._variable, self._filters) stdlib.register_tag(VariableTag) class ForLoopTag(Node): """ For Loop ======== Iterate through the given list. This can eighter be a hardcoded list ("row1", "row2", "row3"...) or a variable containing an iterable. The syntax is "for ITEM in ITERABLE[ reversed]" where reversed is optional. You can access the current iteration from the loop body with {{ ITEM }}. The for loop sets a number of variables available within the loop: ======================= ======================================= Variable Description ======================= ======================================= ``loop.counter`` The current iteration of the loop ``loop.counter0`` The current iteration of the loop, starting counting by 0. ``loop.revcounter`` The number of iterations from the end of the loop. ``loop.revcounter0`` The number of iterations from the end of the loop, starting counting by 0. ``loop.length0`` Lenght of the loop, zero indexed ``loop.length`` Length of the loop. ``loop.first`` True if first iteration. ``loop.last`` True if last iteration. ``loop.even`` True if current iteration is even. ``loop.odd`` True if current iteration is odd. ``loop.parent The context of the parent loop. ======================= ======================================= Example Usage:: {% for user in userlist %} {{ user.name }} on index {{ loop.counter0 }} {% endfor %} And here a hardcoded version:: {% for row in "row1", "row2", "row3" reversed %} {{ row }} {% endfor %} Loops can also have a ``elsefor`` statement:: {% for user in users %} {{ user }} {% elsefor %} no users found {% endfor %} This acts the same as:: {% if users %} {% for user in users %} {{ user }} {% endfor %} {% else %} no users found {% endif %} """ rules = { 'normal': [ KeywordNode('for'), VariableNode(), KeywordNode('in'), CollectionNode()], 'reversed': [ KeywordNode('for'), VariableNode(), KeywordNode('in'), CollectionNode(), KeywordNode('reversed')] } def __init__(self, parser, matched_tag, handler_args, stack): self._reversed = matched_tag == 'reversed' self._variable = handler_args[1] self._iterable = handler_args[3] self._body_loop, self._body_else = parser.forkparse('elsefor', 'endfor') def findnodes(self): yield self for node in self._body_loop: for n in node.findnodes(): yield n for node in self._body_else: for n in node.findnodes(): yield n def render(self, context, iterable=None): from jinja.base import NodeList nodelist = NodeList() if iterable is None: if len(self._iterable) == 1 and isinstance(self._iterable[0], VariableNode): iterable = self._iterable[0].resolve(context, default=[]) elif len(self._iterable) > 1: iterable = [v.resolve(context) for v in self._iterable] else: raise TemplateRuntimeError('for loop requires a list') # get len of iterable # if not available iterate through all elements and count # the iterations try: len_values = len(iterable) except TypeError: counted = enumerate(iterable) iterable = [] for len_values, item in counted: iterable.append(item) len_values += 1 # find parent loop if 'loop' in context: parent = context['loop'] else: parent = {} # create a new layer for new context variables context.push() # reverse iterator if required # this should also work for iterators that are not sequence or # on python versions older than 2.4 if self._reversed: try: iterable = reversed(iterable) except (NameError, TypeError): if hasattr(iterable, '__len__'): def save_reversed(i): idx = 0 while idx < len(i): yield i[idx] idx += 1 iterable = save_reversed(iterable) else: iterable = list(iterable)[::-1] # iterate through list and numerate iterations for i, item in enumerate(iterable): self._variable.define(context, item) context['loop'] = { 'counter0': i, 'counter': i + 1, 'revcounter': len_values - i, 'revcounter0': len_values - i - 1, 'first': (i == 0), 'last': (i == len_values - 1), 'even': i % 2 != 0, 'odd': i % 2 == 0, 'length0': len_values - 1, 'length': len_values, 'parent': parent, '__forloop__': self } for node in self._body_loop: nodelist.append(node.render(context)) # pop the highest layer in the context context.pop() if nodelist: return nodelist.render(context) return self._body_else.render(context) def __repr__(self): return '' % ( self._variable, self._iterable, (self._reversed) and ' reversed' or '' ) stdlib.register_tag(ForLoopTag) class RangeLoopTag(Node): """ Range Loop ========== Counts from X to Y, by stepping Z:: {% range X to Y step Z %} ... {% endrange %} When not defining "step Z" it will assume that step is one. If you want to cound downwards you can use ``downto``: {% range X downto Y step Z %} ... {% endrange """ rules = { 'inc_default': [ KeywordNode('range'), VariableNode(), KeywordNode('from'), ChoiceNode(), KeywordNode('to'), ChoiceNode()], 'inc_stepped': [ KeywordNode('range'), VariableNode(), KeywordNode('from'), ChoiceNode(), KeywordNode('to'), ChoiceNode(), KeywordNode('step'), ChoiceNode()], 'dec_default': [ KeywordNode('range'), VariableNode(), KeywordNode('from'), ChoiceNode(), KeywordNode('downto'), ChoiceNode()], 'dec_stepped': [ KeywordNode('range'), VariableNode(), KeywordNode('from'), ChoiceNode(), KeywordNode('downto'), ChoiceNode(), KeywordNode('step'), ChoiceNode()] } def __init__(self, parser, matched_tag, handler_args, stack): self._variable = handler_args[1] self._lbound = handler_args[3] self._ubound = handler_args[5] if matched_tag in ('inc_stepped', 'dec_stepped'): self._step = handler_args[7] self._increment = matched_tag[:3] == 'inc' self._body = parser.subparse('endrange') def findnodes(self): yield self for node in self._body: for n in node.findnodes(): yield n def render(self, context): from jinja.base import NodeList nodelist = NodeList() # find parent loop if 'loop' in context: parent = context['loop'] else: parent = {} # resolve bounds and fix stepping depending # on possible reverse counting if hasattr(self, '_step'): step = self._step.resolve(context) else: step = 1 lbound = self._lbound.resolve(context) ubound = self._ubound.resolve(context) if not self._increment: step *= -1 ubound -= 1 else: ubound += 1 # add layer to context context.push() iterable = xrange(lbound, ubound, step) len_values = len(iterable) for i, item in enumerate(iterable): self._variable.define(context, item) context['loop'] = { 'counter0': i, 'counter': i + 1, 'revcounter': len_values - i, 'revcounter0': len_values - i - 1, 'first': (i == 0), 'last': (i == len_values - 1), 'even': i % 2 != 0, 'odd': i % 2 == 0, 'length0': len_values - 1, 'length': len_values, 'parent': parent } for node in self._body: nodelist.append(node.render(context)) # pop highest layer and render nodelist context.pop() return nodelist.render(context) def __repr__(self): if self._increment: range_type = 'to' else: range_type = 'downto' if hasattr(self, '_step'): step = 'step %r' % self._step else: step = '' return '' % ( self._lbound, range_type, self._ubound, step ) stdlib.register_tag(RangeLoopTag) class RecurseTag(Node): """ Recursion ========= For use with for loops:: And the context would look like this:: c = Context({ 'menu': [ dict( caption='Pages', submenu=[ dict(href='index.html', caption='Index'), dict(href='downloads.html', caption='Downloads'), dict( caption='Users', submenu=[ dict(href='peter.html', caption='Peter'), dict(href='max.html', caption='Max'), dict(href='suzan.html', caption='Suzan') ] ), dict( caption='Files', submenu=[ dict( caption='Images', submenu=[ dict(href='vienna.html', caption='Vienna'), dict(href='roma.html', caption='Roma'), dict(href='tokyo.html', caption='Tokyo') ] ), dict( caption='Videos', submenu=[ dict(href='party.html', caption='Party') ] ) ] ) ] ), dict(caption='About', href='about.html') ] }) The purpose of this tag is that it recuses by calling a given loop again with another variable. If you don't want to use the current loop you can specify another:: {% recurse myvariable in loop.parent.parent %} """ rules = { 'auto': [ KeywordNode('recurse'), VariableNode()], 'in': [ KeywordNode('recurse'), VariableNode(), KeywordNode('in'), VariableNode()] } def __init__(self, parser, matched_tag, handler_args, stack): if matched_tag == 'in': self._loop = handler_args[3] else: self._loop = None self._variable = handler_args[1] def findnodes(self): yield self def render(self, context): from copy import deepcopy, copy try: if self._loop is None: loop = context['loop'] else: loop = self._loop.resolve(context) except: raise TemplateRuntimeError, 'recursion over non for loop' iterable = self._variable.resolve(context) result = loop['__forloop__'].render(context, iterable) return result def __repr__(self): return '' % ( self._loop, self._variable ) stdlib.register_tag(RecurseTag) class CycleTag(Node): """ Cycling ======= Cycle among the given strings each time this tag is encountered. Within a loop, cycles among the given strings each time through the loop:: {% for o in some_list %} ... {% endfor %} You can also cycle into a variable:: {% for o in some_list %} {% cycle class through "row1", "row2" %} ... ... {% endfor %} It's also possible to iterate through an iterable variable:: {% for item in some_list %} ... ... {% endfor %} In this example row_colors is a application provided list with the following content: ["red", "blue", "green"]... It's also possible to cycle through a sequence variable. Then each cycling will return the next item from the sequence. The cycle tag will reset each time the parent loop iterates. If you don't want this behaviour add a ``noreset`` to the call:: {% cycle "row1", "row2" inline noreset %} """ rules = { 'default': [ KeywordNode('cycle'), VariableNode(), KeywordNode('through'), VariableNode()], 'list_default': [ KeywordNode('cycle'), VariableNode(), KeywordNode('through'), CollectionNode()], 'inline': [ KeywordNode('cycle'), VariableNode(), KeywordNode('inline')], 'list_inline': [ KeywordNode('cycle'), CollectionNode(), KeywordNode('inline')], 'default_nr': [ KeywordNode('cycle'), VariableNode(), KeywordNode('through'), VariableNode(), KeywordNode('noreset')], 'list_default_nr': [ KeywordNode('cycle'), VariableNode(), KeywordNode('through'), CollectionNode(), KeywordNode('noreset')], 'inline_nr': [ KeywordNode('cycle'), VariableNode(), KeywordNode('inline'), KeywordNode('noreset')], 'list_inline_nr': [ KeywordNode('cycle'), CollectionNode(), KeywordNode('inline'), KeywordNode('noreset')], } def __init__(self, parser, matched_tag, handler_args, stack): if matched_tag in ('default', 'list_default', 'default_nr', 'list_default_nr'): self._variable = handler_args[1] self._iterable = handler_args[3] else: self._variable = None self._iterable = handler_args[1] self._reset = matched_tag in ('default', 'list_default', 'inline', 'list_inline') self._pos = -1 self._parent_iter = None def reset(self): self._pos = -1 def cycle(self, length): self._pos += 1 if self._pos >= length: self._pos = 0 def render(self, context): if isinstance(self._iterable, list): iterable = self._iterable else: iterable = self._iterable.resolve(context) # auto reset cycle on parent loop iteration if self._reset: if 'loop' in context and context['loop']['parent']: parent = context['loop']['parent'] new_iter = parent['counter0'] if not self._parent_iter is None and\ self._parent_iter != new_iter: self.reset() self._parent_iter = new_iter self.cycle(len(iterable)) # we are working in inline mode if self._variable is None: return iterable[self._pos].render(context) # send output to variable self._variable.define(context, iterable[self._pos].resolve(context)) return '' def __repr__(self): return '' % (self._variable, self._iterable) stdlib.register_tag(CycleTag) class FilterTag(Node): """ Filter ====== Parse the content and call the registered filters on it:: {% filter | escapexml %} HTML PAGE {% endfilter %} """ rules = { 'default': [KeywordNode('filter')] } def __init__(self, parser, matched_tag, handler_args, stack): self._filters = [(f, args[1:][0]) for f, _, args in stack] self._body = parser.subparse('endfilter') def findnodes(self): yield self for node in self._body: for n in node.findnodes(): yield n def render(self, context): parsed = [] for node in self._body: parsed.append(node.render(context)) parsed = ''.join(parsed) for f, args in self._filters: parsed = f(parsed, *[arg.resolve(context) for arg in args]) return parsed def __repr__(self): return '' % self._filters stdlib.register_tag(FilterTag) class DefaultFilterTag(Node): """ Default Filter ============== Sets the default filter for variable output:: {% setfilter | escapexml %} and to disable it:: {% setfilter off %} """ rules = { 'default': [KeywordNode('setfilter')], 'off': [KeywordNode('setfilter'), KeywordNode('off')] } def __init__(self, parser, matched_tag, handler_args, stack): if matched_tag == 'default': self._filters = [(f, args[1:][0]) for f, _, args in stack] else: self._filters = None def findnodes(self): yield self for node in self._body: for n in node.findnodes(): yield n def render(self, context): if self._filters is None: context.filters = None else: context.filters = self._filters def __repr__(self): return '' % self._filters stdlib.register_tag(DefaultFilterTag) class ConditionTag(Node): """ Conditions ========== The ``{% if %}`` tag evaluates a variable, and if that variable is "true" (i.e. exists, is not empty, and is not a false boolean value) the contents of the block are output:: {% if users_online %} We currently have users on this webpage. {% else %} No users found. stupid -.- {% endif %} As you can see, the ``if`` tag can take an option ``{% else %}`` clause that will be displayed if the test fails. """ rules = { 'default': [KeywordNode('if'), ChoiceNode()], 'negated': [KeywordNode('if'), KeywordNode('not'), ChoiceNode()] } def __init__(self, parser, matched_tag, handler_args, stack): self._body_true, self._body_false = parser.forkparse('else', 'endif') if matched_tag == 'negated': self._variable = handler_args[2] self._negated = True else: self._variable = handler_args[1] self._negated = False self._filters = [(f, args[1:][0]) for f, _, args in stack] def findnodes(self): yield self for node in self._body_true: for n in node.findnodes(): yield n for node in self._body_false: for n in node.findnodes(): yield n def render(self, context): if context.filters is None: filters = self._filters[:] else: filters = self._filters + context.filters var = self._variable.resolve(context) for f, args in filters: var = f(var, context, *[arg.resolve(context) for arg in args]) if self._negated: var = not var if var: return self._body_true.render(context) return self._body_false.render(context) def __repr__(self): if self._negated: neg = 'not ' else: neg = '' return '' % (neg, self._variable) stdlib.register_tag(ConditionTag) class ComparisonTag(Node): """ Comparison ========== You can use `equals` to compare two variables:: {% if variable equals other_variable %} ... {% endif %} or:: {% if not variable equals other_variable %} ... {% endif %} """ rules = { 'default': [KeywordNode('if'), ChoiceNode(), KeywordNode('equals'), ChoiceNode()], 'negated': [KeywordNode('if'), KeywordNode('not'), ChoiceNode(), KeywordNode('equals'), ChoiceNode()] } def __init__(self, parser, matched_tag, handler_args, stack): self._body_true, self._body_false = parser.forkparse('else', 'endif') self._negated = matched_tag == 'negated' self._var1 = handler_args[1 + self._negated] self._var2 = handler_args[3 + self._negated] def findnodes(self): yield self for node in self._body_true: for n in node.findnodes(): yield n for node in self._body_false: for n in node.findnodes(): yield n def render(self, context): var1 = self._var1.resolve(context) var2 = self._var2.resolve(context) if self._negated: test = var1 != var2 else: test = var1 == var2 if test: return self._body_true.render(context) return self._body_false.render(context) def __repr__(self): return '' % ( not self._negated and 'not ' or '', self._var1, self._var2 ) stdlib.register_tag(ComparisonTag) class BlockTag(Node): """ Blocks ====== Defines a block in a template, a childtemplate can override. Usage:: {% block "name" %} default content {% endblock %} alternative way:: {% marker "name" set "default content" %} or without default value:: {% marker "name" %} """ rules = { 'standard': [KeywordNode('block'), ValueNode()], 'default': [KeywordNode('marker'), ValueNode(), KeywordNode('set'), ValueNode()], 'marker': [KeywordNode('marker'), ValueNode()], } def __init__(self, parser, matched_tag, handler_args, stack): from jinja.base import NodeList self._name = handler_args[1].resolve() if matched_tag == 'standard': self._body = parser.subparse('endblock') elif matched_tag == 'default': self._body = handler_args[3] else: self._body = NodeList() def findnodes(self): yield self for node in self._body.findnodes(): for n in node.findnodes(): yield n def replace(self, node): if not isinstance(node, BlockTag): raise TypeError, 'invalid nodetype %r' % node.__class__ self._body = node._body def render(self, context): return self._body.render(context) def __repr__(self): return '' % (self._name, self._body) stdlib.register_tag(BlockTag) class PrepareTag(Node): """ Prepare ======= Prepares a block for later usage:: {% prepare "name" %} ... {% endprepare %} Or with arguments:: {% prepare "name" accepting text %} ... {{ text }} ... {% prepare %} You can call those blocks from everywhere using {% call %}:: {% call "name", "This is an argument" %} missing arguments get ignored. """ rules = { 'call': [KeywordNode('call'), ValueNode(), CollectionNode()], 'define': [KeywordNode('prepare'), ValueNode()], 'ext-define': [KeywordNode('prepare'), ValueNode(), KeywordNode('accepting'), CollectionNode()] } def __init__(self, parser, matched_tag, handler_args, stack): from jinja.base import NodeList self._name = handler_args[1].resolve() if matched_tag == 'call': self._call = True self._args = handler_args[2] else: self._call = False if matched_tag == 'define': self._args = [] else: self._args = handler_args[3] self._body = parser.subparse('endprepare') def findnodes(self): yield self if not self._call: for node in self._body.findnodes(): for n in node.findnodes(): yield n def render(self, context): if not self._call: context.registry['prepared', self._name] = (self._body, self._args) return '' else: try: body, args = context.registry['prepared', self._name] except KeyError: raise TemplateRuntimeError, 'callable %r not found' % self._name # push the arguments into the context context.push() for pos, arg in enumerate(args): try: value = self._args[pos].resolve(context) arg.define(context, value) except IndexError: arg.unset(context) result = body.render(context) context.pop() return result def __repr__(self): if self._call: return '' % (self._name, self._args) return '' % (self._name, self._args, self._body) stdlib.register_tag(PrepareTag) class ExtendsTag(Node): """ Template Inheritance ==================== Template inheritance allows you to build a base "skeleton" template that contains all the common elements of your site and defines **blocks** or **markers** that child templates can override. Here a small example for a base template:: {% marker "title" set "Index" %} - MyWebpage
{% marker "content" %}
In this example, the ``{% block %}`` and ``{% marker %}`` tags defines some blocks that child templates can fill in. And here a possible child template:: {% extends "base" %} {% marker "title" set "Downloads" %} {% block "content" %} This is the page content. {% endblock %} You can also inherit from this new child template. """ rules = { 'default': [KeywordNode('extends'), ValueNode()] } def __init__(self, parser, matched_tag, handler_args, stack): self._name = handler_args[1].resolve() # must set _template here because __repr__ uses it when # TemplateSyntaxError is raised below self._template = '?' if not parser.first: raise TemplateSyntaxError, 'extends has to be first in template' if not hasattr(parser, '_extends'): parser._extends = self._name else: raise TemplateSyntaxError, 'extends called twice' load = parser.loader.load_and_compile_uncached self._nodelist = parser.parse() self._template = load(self._name, parser.library, parser.template_name) overwrites = {} for node in self._nodelist.get_nodes_by_type(BlockTag): overwrites[node._name] = node for node in self._template.get_nodes_by_type(BlockTag): if node._name in overwrites: node.replace(overwrites[node._name]) def findnodes(self): for node in self._template.findnodes(): yield node def render(self, context): return self._template.render(context) def __repr__(self): return '' % (self._name, self._template) stdlib.register_tag(ExtendsTag) class IncludeTag(Node): """ Including Templates =================== Using ``{% include %}`` you can load a template and render it with the current context. This is a way of "including" other templates within the current template:: {% include "header" %} this is the current content {% include "footer" %} Normally the use of ``{% extends %}`` is much more flexible but sometimes it may be usefull to include a template at a given position. You can also use {% require %} which does the same as include but doesn't render anything and loads a template only once. """ rules = { 'default': [KeywordNode('include'), ValueNode()], 'require': [KeywordNode('require'), ValueNode()], 'require_as': [KeywordNode('require'), ValueNode(), KeywordNode('as'), VariableNode()] } def __init__(self, parser, matched_tag, handler_args, stack): name = handler_args[1].resolve() load = parser.loader.load_and_compile_uncached self._name = name self._nodelist = load(name, parser.library, parser.template_name) self._render = matched_tag == 'default' self._dump = matched_tag == 'require_as' if (self._dump): self._variable = handler_args[3] def findnodes(self): yield self for node in self._nodelist: for n in node.findnodes(): yield n def render(self, context): load = ('template', self._name) if self._render or not load in context.registry: context.registry[load] = True result = self._nodelist.render(context) if self._render: return result elif self._dump: self._variable.define(context, result) return '' def __repr__(self): return '' % (self._name, self._nodelist) stdlib.register_tag(IncludeTag) class IfChangedTag(Node): """ Ouput if Changed ================ Check if a value has changed from the last iteration of a loop. The 'ifchanged' block tag is used within a loop. It checks its own rendered contents against its previous state and only displays its content if the value has changed. """ rules = { 'default': [KeywordNode('ifchanged')] } def __init__(self, parser, matched_tag, handler_args, stack): self._nodelist = parser.subparse('endifchanged') self._last = None def findnodes(self): yield self for node in self._nodelist: for n in node.findnodes(): yield n def render(self, context): result = self._nodelist.render(context) if result != self._last: self._last = result return result return '' def __repr__(self): return '' % (self._nodelist) stdlib.register_tag(IfChangedTag) class CaptureTag(Node): """ Capture Output ============== Captures output and stores it in a variable:: {% capture as title %}{% marker "title" %}{% endcapture %} This allows the double usage of block tags. """ rules = { 'default': [KeywordNode('capture'), KeywordNode('as'), VariableNode()] } def __init__(self, parser, matched_tag, handler_args, stack): self._variable = handler_args[2] self._body = parser.subparse('endcapture') def findnodes(self): yield self for node in self._body: for n in node.findnodes(): yield n def render(self, context): var = self._variable.define(context, self._body.render(context)) return '' def __repr__(self): return '' % (self._variable, self._body) stdlib.register_tag(CaptureTag) class DefineTag(Node): """ Modify / Set Variables ====================== Sets an variable. Usage:: {% define my_variable "Some Value" %} You can also append filters:: {% define escaped content | escapexml %} """ rules = { 'default': [KeywordNode('define'), VariableNode(), ChoiceNode()] } def __init__(self, parser, matched_tag, handler_args, stack): self._variable = handler_args[1] self._value = handler_args[2] self._filters = [(f, args[1:][0]) for f, _, args in stack] def findnodes(self): yield self._variable def render(self, context): value = self._value.resolve(context) for f, args in self._filters: value = f(value, *[arg.resolve(context) for arg in args]) self._variable.define(context, value) return '' def __repr__(self): return '' % (self._variable, self._value) stdlib.register_tag(DefineTag) class DebugTag(Node): """ Debug Output ============ Returns the current context:: {% debug %} """ rules = { 'default': [KeywordNode('debug')] } def __init__(self, parser, matched_tag, handler_args, stack): pass def render(self, context): from pprint import pformat return pformat(context.dictrepr()) def __repr__(self): return '' stdlib.register_tag(DebugTag) PK¿Þ4vÀ0J J jinja/__init__.py# -*- coding: utf-8 -*- """ ===== Jinja ===== Jinja is a small but very fast und easy to use stand-alone template engine written in pure python. Since version 0.6 it uses a new parser that increases parsing performance a lot by caching the nodelists on the harddisk if wanted. It includes multiple template inheritance and other features like simple value escaping... Template Syntax =============== This is a small example template in which you can see, how jinja's syntax looks like: My Webpage

My Webpage

{{ variable }} Usage ===== Here a small example:: from jinja import Template, Context, FileSystemLoader t = Template('mytemplate', FileSystemLoader('/path/to/the/templates')) c = Context({ 'navigation' [ {'href': '#', 'caption': 'Index'}, {'href': '#', 'caption': 'Spam'} ], 'variable': 'hello world' }) print t.render(c) """ from jinja.base import Context from jinja.loader import FileSystemLoader, CachedFileSystemLoader, StringLoader,\ EggLoader, ChoiceLoader import jinja.tags as tags import jinja.filters as filters import jinja.exceptions as exceptions import jinja.lib as lib __author__ = 'Armin Ronacher ' __version__ = '0.8' __license__ = 'BSD License' __all__ = ['Context', 'Template', 'FileSystemLoader', 'CachedFileSystemLoader', 'StringLoader', 'EggLoader', 'ChoiceLoader'] # XXX: accessing attributes on this loader will raise DeprecationWarnings # in future jinja versions (0.9) - (old loaders won't work in future # jinja version [1.0 or later]) class _OldLoader(object): def __init__(self, loader): self._loader = loader def load(self, name, parent=None): return self._loader.load(name) def load_and_compile(self, name, lib=None, parent=None): return self._loader.load_and_compile(name, lib) def load_and_compile_uncached(self, name, lib=None, parent=None): return self._loader.load_and_compile(name, lib) class Template(object): def __init__(self, template_name, loader, lib=None): # support for jinja 0.7 loaders if not hasattr(loader, 'load_and_compile_uncached'): loader = _OldLoader(loader) self.nodelist = loader.load_and_compile(template_name, lib) def render(self, context): return self.nodelist.render(context) PKYvÍ43ÞȘ˜jinja/utils.py# -*- coding: utf-8 -*- """ jinja utils """ from jinja.config import * from jinja.exceptions import * from jinja.lib import stdlib import string import re # Const for Regexes LEADING_PUNCTUATION = ['(', '<', '<'] TRAILING_PUNCTUATION = ['.', ',', ')', '>', '\n', '>'] # Precompiles Regexes integer_re = re.compile('^(\d+)$') word_split_re = re.compile(r'(\s+)') punctuation_re = re.compile('^(?P(?:%s)*)(?P.*?)(?P(?:%s)*)$' % \ ('|'.join([re.escape(p) for p in LEADING_PUNCTUATION]), '|'.join([re.escape(p) for p in TRAILING_PUNCTUATION]))) simple_email_re = re.compile(r'^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$') template_tag_regex = re.compile(r'(%s.*?%s|%s.*?%s|%s.*?%s)(?sm)' % ( re.escape(BLOCK_TAG_START), re.escape(BLOCK_TAG_END), re.escape(COMMENT_TAG_START), re.escape(COMMENT_TAG_END), re.escape(VARIABLE_TAG_START), re.escape(VARIABLE_TAG_END))) def string_unescape(s): # FIXME: slow? return s.encode('utf-8').decode('string-escape').decode('utf-8') def resolve_variable(path, context): """resolves a variable in the following order: 1.) None constants (None) 2.) string constants ("some string") 3.) integer constants (42) 4.) boolean constants (True, False) 5.) dictionary lookup (path['subpath']['subsubpath']) 6.) list lookup: (path['subpath'][0]) 7.) attribute lookup (path.subpath.subsubpath) """ assert path and isinstance(path, unicode) if path == u'None': return None elif path[0] in u'"\'' and path[0] == path[-1]: return string_unescape(path[1:-1]) elif integer_re.match(path) is not None: return int(path) elif path.lower() in [u'true', u'false']: return path.lower() == u'true' else: current = context bits = path.split(u'.') for bit in bits: try: current = current[bit] # fail on key error # this ensures that the user can't access # attributes of dict like objects. except KeyError: raise VariableDoesNotExist() # on all other errors, try accessing indices and attributes except: try: current = current[int(bit)] # IndexError: it _is_ a sequence, so fail if the index # is not found except IndexError: raise VariableDoesNotExist() except: try: current = getattr(current, bit) except AttributeError: raise VariableDoesNotExist() if callable(current): try: current = current() except: raise VariableDoesNotExist() return current def urlize(text, trim_url_limit=None, nofollow=False): """ Converts any URLs in text into clickable links. Works on http://, https:// and www. links. Links can have trailing punctuation (periods, commas, close-parens) and leading punctuation (opening parens) and it'll still do the right thing. If trim_url_limit is not None, the URLs in link text will be limited to trim_url_limit characters. If nofollow is True, the URLs in link text will get a rel="nofollow" attribute. """ trim_url = lambda x, limit=trim_url_limit: limit is not None and (x[:limit] + (len(x) >=limit and '...' or '')) or x words = word_split_re.split(text) nofollow_attr = nofollow and ' rel="nofollow"' or '' for i, word in enumerate(words): match = punctuation_re.match(word) if match: lead, middle, trail = match.groups() if middle.startswith('www.') or ('@' not in middle and not middle.startswith('http://') and \ len(middle) > 0 and middle[0] in string.letters + string.digits and \ (middle.endswith('.org') or middle.endswith('.net') or middle.endswith('.com'))): middle = '%s' % (middle, nofollow_attr, trim_url(middle)) if middle.startswith('http://') or middle.startswith('https://'): middle = '%s' % (middle, nofollow_attr, trim_url(middle)) if '@' in middle and not middle.startswith('www.') and not ':' in middle \ and simple_email_re.match(middle): middle = '%s' % (middle, middle) if lead + middle + trail != word: words[i] = lead + middle + trail return ''.join(words) def registerfilter(name): """ Small decorator for adding filters to the standardlib. Usage: @registerfilter('replace') def handle_replace(s, search, replace): return s.replace(search, replace) Requires python2.4 or higher. """ def wrapped(f): stdlib.register_filter(name, f) return wrapped PK« Œ4î\ËÆL L jinja/tokens.py# -*- coding: utf-8 -*- """ jinja builtin tokens """ __all__ = ['Token', 'NameVal', 'CommaVal', 'PipeVal', 'ValueToken', 'StringVal', 'BoolVal', 'IntVal', 'NoneVal'] class Token(object): """Base Token class. All classes derive from this.""" def __init__(self,token): self._token = token def __repr__(self): return '<%s: %r>' % (self.__class__.__name__, self._token) class NameVal(Token): """A name token. A name token is [A-Za-z_][A-Za-z0-9_]* and only output in case its name doesn't match a different name.""" def __call__(self): """Get the value of this token, interpreted.""" return self._token class CommaVal(Token): """Comma value to represent a literal comma (,) in the code.""" def __init__(self): super(CommaVal, self).__init__(None) def __call__(self): """Get the value of this token, interpreted.""" return None class PipeVal(Token): """Pipe value to represent a literal pipe (|) in the code.""" def __init__(self): super(PipeVal, self).__init__(None) def __call__(self): """Get the value of this token, interpreted.""" return None class ValueToken(Token): """Base class for all value tokens. A value token is a token which has a value.""" class StringVal(ValueToken): """String value token. A string value is defined as a string starting with \" or \' and escaped by the normal escaping rules of Python.""" def __call__(self): from jinja.utils import string_unescape """Get the value of this token, interpreted.""" return string_unescape(self._token[1:-1])\ .replace(u'\\{', u'{')\ .replace(u'\\}', u'}') class BoolVal(ValueToken): """Boolean value. A token that is either true or false.""" def __call__(self): """Get the value of this token, interpreted.""" return self._token.lower() == 'true' class IntVal(ValueToken): """An integer value. It has a value and a base.""" def __init__(self,token,base): super(IntVal, self).__init__(token) self._base = base def __call__(self): """Get the value of this token, interpreted.""" return int(self._token, self._base) def __repr__(self): return '<%s: %r, base %r>' % (self.__class__.__name__, self._token, self._base) class NoneVal(ValueToken): """The none value. A token that always has the value none.""" def __call__(self): """Get the value of this token, interpreted.""" return None PK« Œ4àþ‡EÞÞjinja/config.py# -*- coding: utf-8 -*- """ jinja configuration """ # Syntax Configuration BLOCK_TAG_START = '{%' BLOCK_TAG_END = '%}' COMMENT_TAG_START = '{*' COMMENT_TAG_END = '*}' VARIABLE_TAG_START = '{{' VARIABLE_TAG_END = '}}' PK€œÇ4Ù̓ü ü jinja/lib.py# -*- coding: utf-8 -*- """ jinja tag library """ from jinja.tagparser import Parser, CHAIN_PROVIDER, CHAIN_FILTER def create_alias(f): """ Helper function for the alias function of the filter registry. """ def wrapped(*args, **kwargs): return f(*args, **kwargs) wrapped.link = True try: wrapped.__name__ = 'alias::%s' % f.__name__ wrapped.__doc__ = f.__doc__ except: pass #requires python2.4 return wrapped class ParserLibrary(object): def __init__(self, base=None): if base is None: self.rules = {} else: self.rules = base.rules.copy() def __repr__(self): return '' % ( len(self.filters), len(self.tags)) def clone(self): """Clone the current library.""" return ParserLibrary(self) def register_tag(self, tag): """Register a new Tag.""" for name, rule in tag.rules.iteritems(): self.rules[(tag, name)] = (CHAIN_PROVIDER, rule) def register_filter(self, name, f): """Register a filter node.""" from jinja.nodes import KeywordNode, CollectionNode rule = [KeywordNode(name), CollectionNode()] if (f, None) in self.rules: self.rules[create_alias(f), None] = (CHAIN_FILTER, rule) else: self.rules[f, None] = (CHAIN_FILTER, rule) def unregister_tag(self, tag): """Unregister a tag.""" for name, rule in tag.rules.iteritems(): key = tag, name if key in self.rules: del self.rules[key] def parse(self, tmplparser, line): parser = Parser(self.rules) parser.feed(line) parser.finish() stack = [] tag = None tag_args = None for (handler, name), args in parser.collect(): if tag is None: tag = handler tag_args = (name, args) else: stack.append((handler, name, args)) if not tag is None: return tag(tmplparser, tag_args[0], tag_args[1], stack) def register(self, name): """ Decorator for registering filters: @stdlib.register("name") def myfilter(...): pass """ def wrapped(f): self.register_filter(name, f) return f return wrapped def filters(self): """Return the list of filters.""" result = {} for (tag, name), (chain_type, rule) in self.rules.iteritems(): if name is None: result[rule[0]._name] = tag return result filters = property(filters, doc=filters.__doc__) def tags(self): """Return the list of registered tags.""" result = set() for (tag, name), (chain_type, rule) in self.rules.iteritems(): if not name is None: result.add(tag) return list(result) tags = property(tags, doc=tags.__doc__) stdlib = ParserLibrary() PKÃTá4=A×Yããjinja/loader.py# -*- coding: utf-8 -*- """ jinja template loader """ from jinja.base import Lexer, Parser from jinja.exceptions import TemplateDoesNotExist, TemplateSyntaxError, \ TemplateCharsetError import os from md5 import md5 try: import cPickle as pickle except ImportError: import pickle try: from pkg_resources import resource_exists, resource_string except ImportError: resource_exists = resource_string = None __all__ = ['FileSystemLoader', 'CachedFileSystemLoader', 'StringLoader', 'EggLoader', 'ChoiceLoader'] class BaseLoader(object): def load(self, name, parent=None): """This method isn't allowed to cache the data""" raise NotImplementedError() def load_and_compile(self, name, lib=None, parent=None): """Get's called when the template requires an nodelist to render on.""" template = self.load(name, parent) lexer = Lexer(template) parser = Parser(lexer.tokenize(), self, lib) return parser.parse() def load_and_compile_uncached(self, name, lib=None, parent=None): """Get's called for the extends tag to get a fresh nodelist to manipulate.""" return self.load_and_compile(name, lib, parent) class FileSystemLoader(BaseLoader): """ Loads templates from the filesystem:: from jinja import FileSystemLoader loader = FileSystemLoader('/template/search/path') """ def __init__(self, path, suffix='.html', charset='utf-8'): self.path = path self.suffix = suffix self.charset = charset def load(self, name, parent=None): name = os.sep.join([p for p in name.split(os.sep) if p and p[0] != '.']) fn = os.path.join(self.path, name) + self.suffix if os.path.exists(fn): contents = file(fn).read() else: raise TemplateDoesNotExist(name) try: return contents.decode(self.charset) except UnicodeDecodeError, e: raise TemplateCharsetError("Could not decode template '%s'" % fn, e) class CachedFileSystemLoader(FileSystemLoader): """ Same as ``FileSystemLoader`` but caches the parsed nodelist in a binary cPickle dump. """ def __init__(self, path, suffix='.html', cache_dir=None, charset='utf-8'): super(CachedFileSystemLoader, self).__init__(path, suffix, charset) if cache_dir is None: self.cache_dir = path self.prefix = True else: self.cache_dir = cache_dir self.prefix = False def load_and_compile(self, name, lib=None, parent=None): if self.prefix: prefix = '.' else: prefix = '' hash_ = md5('%s/%s' % (self.path, name)).hexdigest() cache_name = os.path.join(self.cache_dir, prefix + hash_) + '.cache' template_name = os.path.join(self.path, name) + self.suffix if not os.path.exists(cache_name) or \ os.path.getmtime(cache_name) < os.path.getmtime(template_name): nodelist = FileSystemLoader.load_and_compile(self, name, lib, parent) try: pickle.dump(nodelist, file(cache_name, 'wb'), protocol=2) except IOError: pass else: try: nodelist = pickle.load(file(cache_name, 'rb')) except IOError: nodelist = FileSystemLoader.load_and_compile(self, name, lib. parent) return nodelist def load_and_compile_uncached(self, name, lib=None, parent=None): super(CachedFileSystemLoader, self).load_and_compile(name, lib, parent) class StringLoader(BaseLoader): """ A non thread safe version of a loader getting their templates from strings. If you want a thread safe behaviour you have to create a new loader for each template:: from jinja import Template, StringLoader t = Template('''my template here''', StringLoader()) """ def __init__(self, charset='utf-8'): self.charset = charset self.template = False def load(self, tpl, parent=None): try: return unicode(tpl, self.charset) except UnicodeDecodeError, e: raise TemplateCharsetError('Could not decode template', e) def load_and_compile(self, name, lib=None, parent=None): if self.template: raise TemplateSyntaxError('StringLoader doesn\'t allow ' 'template inheritance') self.template = True rv = super(StringLoader, self).load_and_compile(name, lib, parent) self.template = False return rv class EggLoader(FileSystemLoader): """ Loads templates from an egg:: from jinja import EggLoader loader = EggLoader('MyEgg', 'internal/path/to/templates') """ # contributed by Jon Rosebaugh def __init__(self, package, path, suffix='.html', charset='utf-8'): if resource_exists is resource_string is None: raise RuntimeError('pkg_resources not found') super(EggLoader, self).__init__(path, suffix, charset) self.package = package def load(self, name, parent=None): name = '/'.join([p for p in name.split('/') if p and p[0] != '.']) name = '/'.join([self.path, name]) + self.suffix if resource_exists(self.package, name): contents = resource_string(self.package, name) else: raise TemplateDoesNotExist(name) try: return contents.decode(self.charset) except UnicodeDecodeError, e: raise TemplateCharsetError("Could not decode template '%s'" % fn, e) class ChoiceLoader(object): """ Takes a number of loader instances. The ``load`` and ``load_and_compile`` method try to to call the functions of all given loaders:: from jinja import ChoiceLoader, FileSystemLoader, EggLoader loader = ChoiceLoader( FileSystemLoader('/path/to/my/templates'), EggLoader('MyEgg', 'internal/path/to/templates') ) """ def __init__(self, *loaders): self.loaders = loaders def load(self, name, parent=None): for loader in self.loaders: try: return loader.load(name, parent=None) except TemplateDoesNotExist: continue raise TemplateDoesNotExist(name) def load_and_compile(self, name, lib=None, parent=None): for loader in self.loaders: try: return loader.load_and_compile(name, lib, parent) except TemplateDoesNotExist: continue raise TemplateDoesNotExist(name) def load_and_compile_uncached(self, name, lib=None, parent=None): for loader in self.loaders: try: return loader.load_and_compile_uncached(name, lib, parent) except TemplateDoesNotExist: continue raise TemplateDoesNotExist(name) PKO´æ4èü À††jinja/exceptions.pyc;ò ó9(sselfs __class__s__name__s_msgs_pos(sself((s.build/bdist.linux-i686/egg/jinja/exceptions.pys__repr__6s(s__name__s __module__s__init__s__str__s__repr__(((s.build/bdist.linux-i686/egg/jinja/exceptions.pys TagLexerError*s  N( s__doc__s ExceptionsSilentVariableFailuresVariableDoesNotExistsTemplateCharsetErrorsTemplateSyntaxErrorsTemplateRuntimeErrorsTemplateDoesNotExistsContextPopExceptions ValueErrors TagLexerError(sTemplateCharsetErrorsContextPopExceptionsTemplateSyntaxErrors TagLexerErrorsTemplateDoesNotExistsSilentVariableFailuresVariableDoesNotExistsTemplateRuntimeError((s.build/bdist.linux-i686/egg/jinja/exceptions.pys?s PKO´æ4MEc‚ÐUÐUjinja/filters.pyc;ò ‡Dc@szdZdklZdkTdkZd„Zed„ZeeƒZd„ZeeƒZd„Z ee ƒZ d„Z ee ƒZ d „Z ee ƒZ d „Z ee ƒZ d „Z ee ƒZ d d „Zd d„Zd„Zed„ZeeƒZd„ZeeƒZd„ZeeƒZd„ZeeƒZed„ZeeƒZded„ZeeƒZd„Zd„Zd„Zd„Zd„Zdeed„ZeeƒZdedd „ZeeƒZd!ed"„ZeeƒZd#„Z ee ƒZ d$„Z!ee!ƒZ!d%„Z"ee"ƒZ"d&„Z#d'„Z$ee$ƒZ$d(„Z%d)„Z&ee&ƒZ&d*d+„Z'ee'ƒZ'd,„Z(ee(ƒZ(d-„Z)d.„Z*d/d0„Z+d1d2„Z,ed3„Z-ed4„Z.hd5e<d6e<d7e <d8e <d9e <d:e <d;e <d<e <d=e<d>e<d?e<d@e<dAe<dBe<dCe<dDe<dEe<dFe<dGe<dHe<dIe<dJe<dKe<dLe<dMe<dNe <dOe!<dPe"<dQe#<dRe$<dSe%<dTe&<dUe'<dVe(<dWe)<dXe*<dYe+<dZe,<d[e-<d\e. filter(s, context, *vars) The decorated function will convert the first argument and all vars that are strings to unicode using the charset of the context. cs‘t|tƒ ot|ƒi|idƒ}nxMt|ƒD]?\}}t|tƒo#t|ƒi|idƒ|| in a string of data. (sescapeN(sxml.sax.saxutilssescapess(sssescape((s+build/bdist.linux-i686/egg/jinja/filters.pys do_escapexmlUs cCs#|idƒidƒidƒSdS(s4 {{ s|addslashes }} Adds slashes to s. sutf-8s string-escapeN(sssencodesdecode(ss((s+build/bdist.linux-i686/egg/jinja/filters.pys do_addslashes`scCs|iƒSdS(sn {{ s|capitalize }} Return a copy of the string s with only its first character capitalized. N(sss capitalize(ss((s+build/bdist.linux-i686/egg/jinja/filters.pys do_capitalizejscCs|iƒSdS(s {{ s|title }} Return a titlecased version of s, i.e. words start with uppercase characters, all remaining cased characters have lowercase. N(ssstitle(ss((s+build/bdist.linux-i686/egg/jinja/filters.pysdo_titleusscCs| o|Sn|SdS(sŒ {{ s|default[ default_value] }} In case of s isn't set or True default will return default_value which is '' per default. N(sss default_value(ssscontexts default_value((s+build/bdist.linux-i686/egg/jinja/filters.pys do_default€scsnyGtˆtƒ otˆƒi|idƒ‰nt‡d†|ƒSWn t|ƒi|idƒSnXdS(sà {{ sequence|join[ d] }} Return a string which is the concatenation of the strings in the sequence. The separator between elements is d which is an empty string per default. sreplacecst|ƒˆt|ƒS(N(sstrsxsdsy(sxsy(sd(s+build/bdist.linux-i686/egg/jinja/filters.pys—sN( s isinstancesdsunicodesstrsdecodescontextscharsetsreducessequence(ssequencescontextsd((sds+build/bdist.linux-i686/egg/jinja/filters.pysdo_joinŒscCs^y@t|ƒtttfjot|ƒ}ntt|ƒƒSWntj o dSnXdS(sþ {{ var|count }} Return the length of var. In case if getting an integer or float it will convert it into a string an return the length of the new string. If the object doesn't provide a __len__ function it will return zero. u0N(stypesvarsintsfloatslongsunicodeslens TypeError(svarscontext((s+build/bdist.linux-i686/egg/jinja/filters.pysdo_countœs cCs6dkl}l}|o||ƒSn||ƒSdS(sÛ {{ s|urlencode[ plus] }} Return the urlencoded value of s. For detailed informations have a look at the help page of "urllib.quote" If plus is set to 1 it will use the "urllib.quote_plus" method. (squotes quote_plusN(surllibsquotes quote_plussplusss(sssplussquotes quote_plus((s+build/bdist.linux-i686/egg/jinja/filters.pys do_urlencode®s cCstidd|ƒSdS(sZ {{ s|striphtml }} Return a plaintext version of s. (removes all html tags). s<[^>]*?>sN(sressubss(ss((s+build/bdist.linux-i686/egg/jinja/filters.pys do_striphtml¾scCs–t|tƒ ot|ƒ}ntidd|ƒ}tid|ƒ}gi}|D]&}|d|i ƒi ddƒƒqV~}di |ƒSdS(sD {{ s|nl2pbr }} Convert newlines into

and
s. s \r\n|\r|\ns s {2,}s

%s

s
s N(s isinstancesss basestringsstrsressubssplits paragraphssappends_[1]spsstripsreplacesjoin(sssps_[1]s paragraphs((s+build/bdist.linux-i686/egg/jinja/filters.pys do_nl2pbrÈs=cCstidd|ƒSdS(s; {{ s|nl2br }} Convert newlines into
s. s \r\n|\r|\ns
N(sressubss(ss((s+build/bdist.linux-i686/egg/jinja/filters.pysdo_nl2br×scCs!dkl}||d|ƒSdS(s¬ {{ s|autolink[ nofollow] }} Automatically creates tags for recognized links. If nofollow is True autolink will add a rel=nofollow tag to the url. (surlizesnofollowN(s jinja.utilssurlizesssnofollow(sssnofollowsurlize((s+build/bdist.linux-i686/egg/jinja/filters.pys do_autolinkás i2cCs!dkl}||||ƒSdS(su {{ s|autolink[ length[ nofollow]] }} Same as autolink but truncate the url to a given character limit. (surlizeN(s jinja.utilssurlizessslengthsnofollow(ssslengthsnofollowsurlize((s+build/bdist.linux-i686/egg/jinja/filters.pysdo_autolinktruncîs cCsEytt|ƒƒSWn*tj ot|ƒddd…SnXdS(sQ {{ iterable|reverse }} Return a reversed copy of a given iterable. Niÿÿÿÿ(slistsreversedsiterables NameError(siterablescontext((s+build/bdist.linux-i686/egg/jinja/filters.pys do_reverseùs cCs`ytt|ƒƒSWnEtj o9g}x|D]}|i|ƒq2W|iƒ|SnXdS(sL {{ iterable|sort }} Return a sorted copy of a given iterable. N(slistssortedsiterables NameErrorslsitemsappendssort(siterablescontextslsitem((s+build/bdist.linux-i686/egg/jinja/filters.pysdo_sorts cGsªt|dƒ pt|dƒ o9yt|ƒ}Wq[t|ƒi|idƒ}q[Xny=|tgi}|d D]}|t |ƒƒqv~ŒSWn |SnXdS(sS {{ iterable|slice start, end, step }} Return a slice of an iterable. s __getslice__s __getitem__sreplaceiN( shasattrsiterableslistsstrsdecodescontextscharsetsslicesappends_[1]sargssargsint(siterablescontextsargss_[1]sarg((s+build/bdist.linux-i686/egg/jinja/filters.pysdo_slices"#=cCsKytt|ƒƒSWn0tj o$dkl}t||ƒƒSnXdS(sN {{ iterable|deletedouble }} Remove double items in an iterable. (sSetN(slistssetsiterables NameErrorssetssSet(siterablescontextsSet((s+build/bdist.linux-i686/egg/jinja/filters.pysdo_deletedouble's  cCsd||SdS(s_ {{ s|format f }} Apply python string format f on s. The leading "%" is left out. s%N(sfss(ssscontextsf((s+build/bdist.linux-i686/egg/jinja/filters.pys do_format4sicCss|odpd|}|o<digi}|iƒD]}|||ƒq9~ƒSn|i dd|ƒSdS(sõ {{ s|indent[ width[ indentfirst[ usetab]]] }} Return a copy of s, each line indented by width spaces. If usetab is True it the filter will use tabs for indenting. If indentfirst is given it will also indent the first line. u u u N( susetabswidths indentions indentfirstsjoinsappends_[1]sss splitlinesslinesreplace(ssswidths indentfirstsusetabs indentions_[1]sline((s+build/bdist.linux-i686/egg/jinja/filters.pys do_indent=s <iÿs...cCs¢t|ƒ|jo|Sn|o|| |Sn|idƒ}g}d}xA|D]9}|t|ƒd7}||joPn|i |ƒqTWdi |ƒSdS(sè {{ s|truncate[ length[ killwords[ end]]] }} Return a truncated copy of s. If killwords is True the filter will cut the text at length and append end. Otherwise it will try to save the last word and append end. s iiN( slenssslengths killwordssendssplitswordssresultsmswordsappendsjoin(ssslengths killwordssendsmsresultswordssword((s+build/bdist.linux-i686/egg/jinja/filters.pys do_truncateMs iOcCs‘t|ƒ|jo|Sn|oOdigi}tdt|ƒ|ƒD]}|||||!ƒqH~ƒSnt |d„|i dƒƒSdS(s} {{ s|wordwrap[ hard] }} Return a copy of s, word get wrapped at pos, if hard is True word might get split. s icCsLd|dt|ƒ|idƒdt|iddƒdƒ|j|fS(Ns%s%s%ss s ii(slineslensrfindswordssplitspos(slineswordspos((s+build/bdist.linux-i686/egg/jinja/filters.pysqss N( slensssposshardsjoinsappends_[1]sxrangesidxsreducessplit(sssposshardsidxs_[1]((s+build/bdist.linux-i686/egg/jinja/filters.pys do_wordwrapesO cCsdkl}||ƒSdS(s¦ {{ s|textile }} Return a textfile parsed copy of s. requires the PyTextile library available at http://dealmeida.net/projects/textile/ (stextileN(stextiless(ssstextile((s+build/bdist.linux-i686/egg/jinja/filters.pys do_textilexs cCsdkl}||ƒSdS(s² {{ s|markdown }} Return a markdown parsed copy of s. requires the Python-markdown library from http://www.freewisdom.org/projects/python-markdown/ (smarkdownN(smarkdownss(sssmarkdown((s+build/bdist.linux-i686/egg/jinja/filters.pys do_markdown†s cCs@y.dkl}|d|ddƒ}|dSWn |SnXdS(s‡ {{ s|rst }} Return a reStructuredText parsed copy of s. requires docutils from http://docutils.sourceforge.net/ (s publish_partsssources writer_names html4css1sfragmentN(sdocutilss publish_partssssparts(ssspartss publish_parts((s+build/bdist.linux-i686/egg/jinja/filters.pysdo_rst”s  cCsGt|tƒ ot|ƒi|idƒ}nt|||dƒSdS(sF {{ s|cut char }} Equivalent to {{ s|replace char '' }}. sreplaceuN( s isinstancescharsunicodesstrsdecodescontextscharsets do_replacess(ssscontextschar((s+build/bdist.linux-i686/egg/jinja/filters.pysdo_cut¥scCsdi|iƒƒSdS(s9 {{ s|cleanup }} Remove double whitespaces. s N(sjoinssssplit(ss((s+build/bdist.linux-i686/egg/jinja/filters.pys do_cleanup°scCs¡t|ƒ}|djo&d||djodpdfSn|ddjod|dSn|dddjod|ddSnd|dddSd S( s‚ {{ i|filesizeformat }} Format the value like a 'human-readable' file size (i.e. 13 KB, 4.1 MB, 102 bytes, etc). iu %d Byte%siusuu%.1f KBu%.1f MBu%.1f GBN(sfloatsisbytes(siscontextsbytes((s+build/bdist.linux-i686/egg/jinja/filters.pysdo_filesizeformatºs  &cCst|iƒƒSdS(s< {{ s|wordcount }} Return the number of words. N(slenssssplit(ss((s+build/bdist.linux-i686/egg/jinja/filters.pys do_wordcountËss cCs|i|ƒSdS(s­ {{ s|strip[ chars] }} Return a copy of s with leading and trailing whitespace removed. If chars is given and not None, remove characters in chars instead. N(sssstripschars(ssschars((s+build/bdist.linux-i686/egg/jinja/filters.pysdo_stripÕscCsti|||ƒSdS(s  {{ s|regexreplace search replace }} Perform a re.sub on s Example: {{ s|regexreplace '\[b\](.*?)\[/b\](?i)' '\1' }} N(sressubssearchsreplacess(ssssearchsreplace((s+build/bdist.linux-i686/egg/jinja/filters.pysdo_regexreplaceàscCs2t|tƒo|Snt|ƒi|dƒSdS(s§ {{ s|decode encoding }} Decode s to unicode with given encoding instead of the context's default. Example: {{ s|decode 'latin-1' }} sreplaceN(s isinstancesssunicodesstrsdecodesencoding(ssscontextsencoding((s+build/bdist.linux-i686/egg/jinja/filters.pys do_decodeíscCs2t|tƒo|Snt|ƒitdƒSdS(s; {{ obj|str }} Converts an object to a string sreplaceN(s isinstancesobjsunicodesstrsdecodesencoding(sobjscontext((s+build/bdist.linux-i686/egg/jinja/filters.pysdo_strüsicCs8yt|ƒSWn#yt|ƒSWq4dSq4XnXdS(sh {{ obj|int }} Converts an object to an integer if possible, otherwise returns default iN(sintsobjsdefault(sobjscontextsdefault((s+build/bdist.linux-i686/egg/jinja/filters.pysdo_intsf0.0cCs8yt|ƒSWn#yt|ƒSWq4dSq4XnXdS(sg {{ obj|float }} Converts an object to a float if possible, otherwise returns default f0.0N(sfloatsobjsdefault(sobjscontextsdefault((s+build/bdist.linux-i686/egg/jinja/filters.pysdo_floatscCs8yt|ƒSWn#yt|ƒSWq4tSq4XnXdS(se {{ obj|bool }} Converts an object to a bool if possible, otherwise returns default N(sboolsobjsdefaultsFalse(sobjscontextsdefault((s+build/bdist.linux-i686/egg/jinja/filters.pysdo_bool(scCsOd„}||ƒ}|tjo%||ƒ}|tjotSqGn|SdS(sG {{ obj|makebool }} Guesses an boolean (true, on, 1, yes) cCsyt|tƒ ot|ƒiƒ}n |iƒ}|ddddfjotSn"|ddddfjotSndS( Nstrues1syessonsfalses0snosoff(s isinstancesobjs basestringsstrslowersTruesFalse(sobj((s+build/bdist.linux-i686/egg/jinja/filters.pyscheck>s N(schecksobjsvalsNonesdefaultsFalse(sobjscontextsdefaultsvalscheck((s+build/bdist.linux-i686/egg/jinja/filters.pys do_makebool8s     sreplacesupperslowers escapexmlses addslashess capitalizestitlesdefaultsjoinscounts urlencodes striphtmlsnl2pbrsnl2brsautolinks autolinktruncsreversessortsslices deletedoublesformatsindentstruncateswordwrapstextilesmarkdownsrstscutscleanupsfilesizeformats wordcountsstrips regexreplacesdecodesstrsintsfloatsboolsmakebool(4s__doc__s jinja.libsstdlibs jinja.nodessres stringfiltersNones do_replacesdo_uppersdo_lowers do_escapexmls do_addslashess do_capitalizesdo_titles do_defaultsdo_joinsdo_countsFalses do_urlencodes do_striphtmls do_nl2pbrsdo_nl2brs do_autolinksdo_autolinktruncs do_reversesdo_sortsdo_slicesdo_deletedoubles do_formats do_indents do_truncates do_wordwraps do_textiles do_markdownsdo_rstsdo_cuts do_cleanupsdo_filesizeformats do_wordcountsdo_stripsdo_regexreplaces do_decodesdo_strsdo_intsdo_floatsdo_bools do_makeboolsbuiltin_filterss iteritemssnameshandlersregister_filter(-sdo_strs do_truncates do_wordcounts do_makeboolsdo_titlesstdlibs do_textilesbuiltin_filterss do_urlencodesdo_uppers do_markdownsdo_countsdo_boolsnamesdo_cutsreshandlers do_capitalizes do_defaults do_replaces do_nl2pbrs do_indentsdo_stripsdo_nl2brs do_striphtmls do_autolinksdo_ints do_reversesdo_regexreplacesdo_rsts do_addslashessdo_sorts do_formatsdo_filesizeformatsdo_autolinktruncsdo_joins do_escapexmls do_wordwrapsdo_slices do_decodesdo_floats do_cleanupsdo_deletedoublesdo_lowers stringfilter((s+build/bdist.linux-i686/egg/jinja/filters.pys?sŽ                                                 ÿo+ PKO´æ4.Y¤Q[*[*jinja/nodes.pyc;ò ó9i(sselfs_data(sself((s)build/bdist.linux-i686/egg/jinja/nodes.pys__repr__!s(s__name__s __module__s__init__srenders__str__s__repr__(((s)build/bdist.linux-i686/egg/jinja/nodes.pysTextNodes   cBs,tZd„Zd„Zd„Zd„ZRS(NcCs ||_dS(N(snamesselfs_name(sselfsname((s)build/bdist.linux-i686/egg/jinja/nodes.pys__init__&scCs]t|tƒ odttfSn|i|ƒiƒjodttfSnd|tfSdS(Nii (s isinstancesnodesNameValsNonesselfs_nameslower(sselfsnode((s)build/bdist.linux-i686/egg/jinja/nodes.pysmatch)s cCs†t|tƒo t|iiƒ|iƒƒSnSt|tƒo#t|iiƒ|iiƒƒSn td|i i |i i f‚dS(Nscan't compare %r and %r types( s isinstancesothers basestringscmpsselfs_nameslowers KeywordNodes TypeErrors __class__s__name__(sselfsother((s)build/bdist.linux-i686/egg/jinja/nodes.pys__cmp__0s  #cCsd|ii|ifSdS(Ns<%s: %r>(sselfs __class__s__name__s_name(sself((s)build/bdist.linux-i686/egg/jinja/nodes.pys__repr__:s(s__name__s __module__s__init__smatchs__cmp__s__repr__(((s)build/bdist.linux-i686/egg/jinja/nodes.pys KeywordNode$s   cBsPtZed„Zd„Zedd„Zd„Zd„Zd„Z d„Z RS( NcCs||_t|_dS(N(snamesselfs_namesNones_filters(sselfsname((s)build/bdist.linux-i686/egg/jinja/nodes.pys__init__@s cCs‰t|tƒ p |itj o|i|ƒjodttfSn|iod|i|ƒƒtfSnd|i|ƒƒtfSdS(Nii (s isinstancesnodesNameValsselfs_namesNones __class__(sselfsnode((s)build/bdist.linux-i686/egg/jinja/nodes.pysmatchDs 4 ucCs@yt|i|ƒSWn%tj o|o|Sn‚nXdS(N(sresolve_variablesselfs_namescontextsVariableDoesNotExistssilentsdefault(sselfscontextssilentsdefault((s)build/bdist.linux-i686/egg/jinja/nodes.pysresolveMs cCs|||is<%s>(sselfs_namesNones __class__s__name__(sself((s)build/bdist.linux-i686/egg/jinja/nodes.pys__repr__fs( s__name__s __module__sNones__init__smatchsTruesresolvesdefinesunsetsrenders__repr__(((s)build/bdist.linux-i686/egg/jinja/nodes.pys VariableNode>s     cBs>tZfd„Zd„Zeed„Zd„Zd„ZRS(NcCs ||_dS(N(svaluesselfs_value(sselfsvalue((s)build/bdist.linux-i686/egg/jinja/nodes.pys__init__oscCs?t|tƒ odttfSnd|i|ƒƒtfSdS(Nii (s isinstancesnodes ValueTokensNonesselfs __class__(sselfsnode((s)build/bdist.linux-i686/egg/jinja/nodes.pysmatchrscCs |iSdS(N(sselfs_value(sselfscontextssilent((s)build/bdist.linux-i686/egg/jinja/nodes.pysresolvewscCsnt|itƒ oOyt|iƒi|iƒSWqctj o}t d|i|ƒ‚qcXn|iSdS(NsCould not resolve value %r( s isinstancesselfs_valuesunicodesstrsdecodescontextscharsets UnicodeErrorsesTemplateCharsetError(sselfscontextse((s)build/bdist.linux-i686/egg/jinja/nodes.pysrenderzs cCs=|ifjod|ii|ifSnd|iiSdS(Ns<%s: %r>s<%s>(sselfs_values __class__s__name__(sself((s)build/bdist.linux-i686/egg/jinja/nodes.pys__repr__ƒs( s__name__s __module__s__init__smatchsNonesTruesresolvesrenders__repr__(((s)build/bdist.linux-i686/egg/jinja/nodes.pys ValueNodems    cBstZd„Zd„ZRS(NcGs |ptƒtƒg|_dS(N(svaluess ValueNodes VariableNodesselfs_values(sselfsvalues((s)build/bdist.linux-i686/egg/jinja/nodes.pys__init__ŒscCsˆg}xP|iD]E}|i|ƒ\}}}|tj o|i |||fƒqqW|i ƒ| odttfSn|dSdS(Niiÿÿÿÿ( srvsselfs_valuessvaluesmatchsnodesscoresnextsNonesappendssort(sselfsnodesrvsvaluesnextsscoresmatch((s)build/bdist.linux-i686/egg/jinja/nodes.pysmatchs   (s__name__s __module__s__init__smatch(((s)build/bdist.linux-i686/egg/jinja/nodes.pys ChoiceNodeŠs cBs#tZd„Zd„Zd„ZRS(NcGs |ptƒtƒg|_dS(N(svaluess ValueNodes VariableNodesselfs_values(sselfsvalues((s)build/bdist.linux-i686/egg/jinja/nodes.pys__init__scCs‚|tjodgtfSnxP|iD]E}|i|ƒ\}}}|tj o||gt|ƒfSq(q(WdttfSdS(Ni( snodesNonesselfs_valuessvaluesmatchsscoresnexts_CollectionNodeComma(sselfsnodesvaluesnextsscoresmatch((s)build/bdist.linux-i686/egg/jinja/nodes.pysmatch s   ccsKxD|iD]9}t|tƒ oq nx|iƒD] }|Vq5Wq WdS(N(sselfs_valuessnodes isinstancesNodes findnodessn(sselfsnodesn((s)build/bdist.linux-i686/egg/jinja/nodes.pys findnodes©s  (s__name__s __module__s__init__smatchs findnodes(((s)build/bdist.linux-i686/egg/jinja/nodes.pysCollectionNode›s  s_CollectionNodeCommacBstZd„Zd„ZRS(NcCs ||_dS(N(s valuelistsselfs _valuelist(sselfs valuelist((s)build/bdist.linux-i686/egg/jinja/nodes.pys__init__³scCs6t|tƒ odttfSndt|ifSdS(Nii (s isinstancesnodesCommaValsNonesselfs _valuelist(sselfsnode((s)build/bdist.linux-i686/egg/jinja/nodes.pysmatch¶s(s__name__s __module__s__init__smatch(((s)build/bdist.linux-i686/egg/jinja/nodes.pys_CollectionNodeComma±s N(s__doc__sjinja.exceptionssVariableDoesNotExistsTemplateSyntaxErrorsTemplateCharsetErrors jinja.tokenssNameVals ValueTokensCommaVals jinja.utilssresolve_variables__all__sobjectsNodesTextNodes KeywordNodes VariableNodes ValueNodes ChoiceNodesCollectionNodes_CollectionNodeComma(sNodesTemplateCharsetErrorsTextNodes__all__s_CollectionNodeCommasTemplateSyntaxErrors ValueNodesresolve_variablesCommaValsNameValsVariableDoesNotExistsCollectionNodes ValueTokens KeywordNodes ChoiceNodes VariableNode((s)build/bdist.linux-i686/egg/jinja/nodes.pys?s /PKO´æ4ë¤>±??jinja/tagparser.pyc;ò ó9tZdZd„Zd„Zd„Zdd„Zd„ZRS(sŠLexer class for tokenizing a string of input into the tokens defined above. This is a feed-lexer, meaning that you feed input using the feed() function and have to finish input by calling finish(). This makes it suitable to parsing unknown-length input. Getting tokens is done by calling the pop() method, which pops a certain number of tokens from the list of read tokens.cCsLt|_g|_d|_g|_d|_g|_t|_ t|_ dS(sInitialize the lexer.iN( s STATE_STARTsselfs_states_tokenss _tokenposs _databuffers_curposs_buffersFalses_invalids _finished(sself((s-build/bdist.linux-i686/egg/jinja/tagparser.pys__init__s       cCs¬ |iotdƒ‚n|iotdƒ‚n|ii|ƒxT t|ƒD]F \}}||i 7}|i t jo—|djo |i itƒƒt|_ q— |djo |i itƒƒt|_ q— |iƒ o"t|_td||iƒ‚q— t|_ qQ|i ttfjo¶|iƒp |djo|ii|ƒt|_ q— |djo|ii|ƒt|_ q— |iƒo|ii|ƒt|_ q— |djo|ii|ƒt|_ q— |d jo|ii|ƒt|_ q— |djo |i tjo |i itƒƒt|_ q— |djo |i tjo |i itƒƒt|_ q— |iƒ oKt|_|i tjotd ||iƒ‚qÙtd ||iƒ‚q— qQ|i tjob|iƒp |d jo|ii|ƒq— |iƒp |d joødi|iƒ}|i ƒdjo|i it!|ƒƒnJ|i ƒddfjo|i it"|ƒƒn|i it#|ƒƒg|_|djo |i itƒƒt|_ qK|djo |i itƒƒt|_ qKt|_ q— t|_td||iƒ‚qQ|i tjo+|djo|ii|ƒt$|_ q— |djo|ii|ƒt%|_ q— |iƒp |d jo›di|iƒ}|i it&|dƒƒg|_|djo |i itƒƒt|_ q†|djo |i itƒƒt|_ q†t|_ q— t|_td||iƒ‚qQ|i t$joø|djo|ii|ƒq— |iƒp |d jo›di|iƒ}|i it&|dƒƒg|_|djo |i itƒƒt|_ qŽ|djo |i itƒƒt|_ qŽt|_ q— t|_td||iƒ‚qQ|i t%jo|iƒp |djo|ii|ƒq— |iƒp |d jo›di|iƒ}|i it&|dƒƒg|_|djo |i itƒƒt|_ q£|djo |i itƒƒt|_ q£t|_ q— t|_td||iƒ‚qQ|i tjoø|iƒo|ii|ƒq— |iƒp |d jo›di|iƒ}|i it&|dƒƒg|_|djo |i itƒƒt|_ q«|djo |i itƒƒt|_ q«t|_ q— t|_td||iƒ‚qQ|i tjo™|djo|ii|ƒt'|_ q— |djoN|ii|ƒdi|iƒ}|i it(|ƒƒg|_t |_ q— |ii|ƒqQ|i t'jo;|djo|ii)ƒn|ii|ƒt|_ qQ|i tjo™|djo|ii|ƒt*|_ q— |d joN|ii|ƒdi|iƒ}|i it(|ƒƒg|_t |_ q— |ii|ƒqQ|i t*jo;|djo|ii)ƒn|ii|ƒt|_ qQqQW|d|_ d S(!s~Feed data to the lexer. A lexer can only be fed data if it is not invalid or finished. In case you try to feed data to the lexer in one of the previously mentioned states, a RuntimeError is raised. In case the lexer encounters invalid data, a TagLexerError (which is a subclass of ValueError) is raised and the lexer is put into invalid mode.s!Cannot feed to invalidated lexer.sCannot feed to finished lexer.s,s|s Expected separator or whitespaces_s0s's"sExpected token or separatorsExpected tokens._s,|ssnonesfalsestruesExpected name or separators01234567sxXi sExpected digit or separatoris!Expected octal digit or separators aAbBcCdDeEfFisExpected hex digit or separators#Expected decimal digit or separators\s iN(+sselfs_invalids RuntimeErrors _finisheds _databuffersappendsdatas enumeratesposscs_curposs_states STATE_SEP_WSs_tokenssCommaVals STATE_STARTsPipeValsisspacesTrues TagLexerErrorsSTATE_START_SEPsisalphas_buffersSTATE_NONE_BOOL_NAMEsSTATE_OCT_HEX_ZEROsisdigits STATE_INTsSTATE_STRINGSINGLEQUOTEsSTATE_STRINGDOUBLEQUOTEsisalnumsjoinsvalslowersNoneValsBoolValsNameVals STATE_OCTs STATE_HEXsIntValsSTATE_STRINGSINGLEQUOTEESCAPEs StringValspopsSTATE_STRINGDOUBLEQUOTEESCAPE(sselfsdataspossvalsc((s-build/bdist.linux-i686/egg/jinja/tagparser.pysfeed*s`                                                                                    cCse|iotdƒ‚n|iodSn|itjo•di|iƒ}|i ƒdjo|i i t |ƒƒnJ|i ƒddfjo|i i t |ƒƒn|i i t|ƒƒg|_nˆ|itjo8di|iƒ}|i i t|dƒƒg|_n@|itjo8di|iƒ}|i i t|dƒƒg|_nø|itjo8di|iƒ}|i i t|d ƒƒg|_n°|itjo8di|iƒ}|i i t|dƒƒg|_nh|ittfjoQt|_|itjotd |i|iƒ‚qXtd |i|iƒ‚nt|_dS( s:Finish the lexing. A lexer can only be finished in case it is not invalid. Finishing a finished lexer will have no effect. Trying to finish an invalid Lexer will raise a RuntimeError, a processing error in the lexer will result in a TagLexerError, which is a subclass of ValueError.s Cannot finish invalidated lexer.Nssnonesfalsestruei iisNo data or dangling separatorsString not closed(sselfs_invalids RuntimeErrors _finisheds_statesSTATE_NONE_BOOL_NAMEsjoins_buffersvalslowers_tokenssappendsNoneValsBoolValsNameValsSTATE_OCT_HEX_ZEROsIntVals STATE_OCTs STATE_HEXs STATE_INTs STATE_SEP_WSsSTATE_START_SEPsTrues STATE_STARTs TagLexerErrors_curposs _databuffer(sselfsval((s-build/bdist.linux-i686/egg/jinja/tagparser.pysfinishósJ          icCsü|iotdƒ‚n|djo|it|iƒj}n²|djoL|it|iƒjotdƒ‚n|i|i}|id7_nY|it|iƒjotdƒ‚n|i|i|i|!}|it|ƒ7_|SdS(sžPops n tokens from the current token stack. The tokens are returned as a list in case n <> 1, if n == 1 the actual token is returned. In case no tokens are available, it raises a ValueError. In case you request more than one token, returns as many tokens as are available. For the special case n == 0 it returns True or False depending on whether there are tokens available.s%Cannot pop tokens from invalid lexer.iisNo tokens available.N( sselfs_invalids RuntimeErrorsns _tokenposslens_tokenssrvs ValueError(sselfsnsrv((s-build/bdist.linux-i686/egg/jinja/tagparser.pyspop#s   cCs7|iod|ii|ifSnd|iiSdS(Ns<%s: %r>s <%s: running>(sselfs _finisheds __class__s__name__s_tokens(sself((s-build/bdist.linux-i686/egg/jinja/tagparser.pys__repr__<s (s__name__s __module__s__doc__s__init__sfeedsfinishspops__repr__(((s-build/bdist.linux-i686/egg/jinja/tagparser.pysLexers  É 0 sParsercBsJtZed„Zd„Zd„Zd„Zd„Zd„Zd„Z RS(NcCsþ|tjo h}ntƒ|_tgi}|iƒD])\}\}}||||ffƒq:~ƒ|_ tgi}|i iƒD]2\}\}}|t @o|||fƒqŒqŒ~ƒ|_g|_h|_h|_t|_t|_dS(N(srulessNonesLexersselfs_lexersdictsappends_[1]s iteritemssnamesstateschains_chainssCHAIN_PROVIDERs _curchainss_outputs _curoutputs_scoressFalses_invalids _finished(sselfsrulessnameschains_[1]sstate((s-build/bdist.linux-i686/egg/jinja/tagparser.pys__init__Es   O[    cCsr|io td‚n|io td‚ny|ii|ƒWntj ot|_‚nX|iƒdS(Ns"Cannot feed to invalidated parser.sCannot feed to finished parser.( sselfs_invalids RuntimeErrors _finisheds_lexersfeedsdatasTrues _process_feed(sselfsdata((s-build/bdist.linux-i686/egg/jinja/tagparser.pysfeedTs     cCs}|io td‚n|iodSny|iiƒWntj ot|_‚nX|iƒ|iƒt|_dS(Ns!Cannot finish invalidated parser.( sselfs_invalids RuntimeErrors _finisheds_lexersfinishsTrues _process_feeds_finish_chains(sself((s-build/bdist.linux-i686/egg/jinja/tagparser.pysfinish`s      cCs"|io td‚n|iSdS(Ns*Cannot collect data from invalided parser.(sselfs_invalids RuntimeErrors_output(sself((s-build/bdist.linux-i686/egg/jinja/tagparser.pyscollectns  c Csag} g}x(|iiƒD]\}}|ot|dtƒoD|ddt jo|i |dd=qn|dd|d}y"|i|=|i |=|i|=Wq>tj oq>Xq>W|i ot|_td|ƒ‚ntt|iiƒ|iiƒƒƒd}|ii||i |fƒtgi} |i!iƒD]2\}\}}|t#@o| ||fƒq q ~ ƒ|_h|_ h|_dS(Niiiÿÿÿÿs'Found no token, but expected one of %s.($s to_deletesexpectedsselfs _curchainss iteritemssnameschains isinstancestuplesNones _curoutputslistsmatchsscores_s setdefaultsextendsappends_scoressgetspopsKeyErrorsTrues_invalids RuntimeErrorsmaxszipsvaluesskeyss bestchains_outputsdicts_[1]s_chainssstates CHAIN_FILTER( sselfschainsstatesscoresexpectedsmatchs_s bestchainsnames_[1]s to_delete((s-build/bdist.linux-i686/egg/jinja/tagparser.pys_finish_chainsssV [ I      +[ c Cs„t}x|iot}g} g}|ii oPn|iii dƒ}t |t ƒo|i ƒq nx\|iiƒD]K\} }x<to4| o|i| ƒPn|i dƒ}t |tƒo‘|di|ƒ\} } }|tj o)|id|dƒ|id|ƒPq^|i| dd=|d}|tjo|i| ƒPq^n|i|ƒ\}}}|tj o+|ii| gƒ|oØ|o||df|d} y"|i| =|i| =|i| =WqÔt j oqÔXqÔWq W|i oZt|_!| o t"d‚q€| ot"d||fƒ‚q€t"d| |fƒ‚ndS(NiiiÿÿÿÿsNo chains foundsFound dangling %s for %ssExpected one of %s, found %s(#sFalsesskipsselfs _curchainssTruesexpecteds to_deletes_lexers_tokensspopstokens isinstancesPipeVals_finish_chainss iteritemssnameschainsappendscurmatchstuplesmatchs_s nexttokensNonesinserts _curoutputsscores setdefaultslistsextends_scoressgetsKeyErrors_invalids RuntimeError( sselfs nexttokenschainsskipstokensscoresmatchs to_deletescurmatchsexpecteds_sname((s-build/bdist.linux-i686/egg/jinja/tagparser.pys _process_feed¹sŽ          W  W$       cCsd|ii|ifSdS(Ns<%s: output %r>(sselfs __class__s__name__s_output(sself((s-build/bdist.linux-i686/egg/jinja/tagparser.pys__repr__#s( s__name__s __module__sNones__init__sfeedsfinishscollects_finish_chainss _process_feeds__repr__(((s-build/bdist.linux-i686/egg/jinja/tagparser.pysParserCs    F jN(s__doc__s jinja.nodess jinja.tokenssjinja.exceptionss TagLexerErrorsranges STATE_SEP_WSs STATE_STARTsSTATE_START_SEPsSTATE_NONE_BOOL_NAMEsSTATE_OCT_HEX_ZEROs STATE_OCTs STATE_HEXs STATE_INTsSTATE_STRINGSINGLEQUOTEsSTATE_STRINGSINGLEQUOTEESCAPEsSTATE_STRINGDOUBLEQUOTEsSTATE_STRINGDOUBLEQUOTEESCAPEs ERROR_KEEPsCHAIN_PROVIDERs CHAIN_FILTERs CHAIN_ANYsobjectsLexersParser(sSTATE_START_SEPs STATE_STARTsLexers CHAIN_ANYsSTATE_STRINGSINGLEQUOTEsParsers CHAIN_FILTERs TagLexerErrorsSTATE_STRINGSINGLEQUOTEESCAPEs STATE_INTsSTATE_STRINGDOUBLEQUOTEs STATE_SEP_WSs STATE_HEXsSTATE_OCT_HEX_ZEROsSTATE_STRINGDOUBLEQUOTEESCAPEs ERROR_KEEPsCHAIN_PROVIDERs STATE_OCTsSTATE_NONE_BOOL_NAME((s-build/bdist.linux-i686/egg/jinja/tagparser.pys?s 0ÿ.PKO´æ4B8Ñ,,jinja/base.pyc;ò ¿ª¢Dc@sËdZdkTdkTdkTdklZdklZdkZdk Z dZ dZ dZ de fd „ƒYZd e fd „ƒYZd efd „ƒYZde fd„ƒYZde fd„ƒYZdS(s7 Jinja Template -------------- Base Module (s*(stemplate_tag_regex(sstdlibNiiisContextcBstZedd„Zd„Zd„Zd„Zd„Zd„Zd„Z d „Z d „Z d „Z d „Z d „Zed„Zd„ZRS(Nsutf-8cCs2|phg|_||_h|_t|_dS(N(sdsselfsdictsscharsetsregistrysNonesfilters(sselfsdscharset((s(build/bdist.linux-i686/egg/jinja/base.pys__init__s  cCst|iƒSdS(N(sreprsselfsdicts(sself((s(build/bdist.linux-i686/egg/jinja/base.pys__repr__sccsx|iD] }|Vq WdS(N(sselfsdictssd(sselfsd((s(build/bdist.linux-i686/egg/jinja/base.pys__iter__"s ccs?x8|iD]-}x$|iƒD]\}}||fVqWq WdS(N(sselfsdictssds iteritemsskeysvalue(sselfsvaluesdskey((s(build/bdist.linux-i686/egg/jinja/base.pysiterdata&s   cCstt|iƒƒƒSdS(N(sdictslistsselfsiterdata(sself((s(build/bdist.linux-i686/egg/jinja/base.pysdictrepr+scCshg|i|_dS(N(sselfsdicts(sself((s(build/bdist.linux-i686/egg/jinja/base.pyspush.scCs4t|iƒdjohg|_n|id=dS(Nii(slensselfsdicts(sself((s(build/bdist.linux-i686/egg/jinja/base.pyspop1scCs||id|sTextsVarsBlocks s(s TOKEN_TEXTs TOKEN_VARs TOKEN_BLOCKsselfs token_typescontentssreplace(sself((s(build/bdist.linux-i686/egg/jinja/base.pys__str__ns(s__name__s __module__s__init__s__str__s__repr__(((s(build/bdist.linux-i686/egg/jinja/base.pysTokenhs  sNodeListcBs#tZd„Zd„Zd„ZRS(NcCs_g}xE|D]=}t|tƒo|i|i|ƒƒq |i|ƒq Wdi|ƒSdS(Nu( sbitssselfsnodes isinstancesNodesappendsrenderscontextsjoin(sselfscontextsnodesbits((s(build/bdist.linux-i686/egg/jinja/base.pysrenderyscCsey tƒ}Wn)tj odkl}|ƒ}nXx!|D]}|i|iƒƒq@W|SdS(N(sSet( ssetsnodess NameErrorssetssSetsselfsnodesupdates findnodes(sselfsnodesSetsnodes((s(build/bdist.linux-i686/egg/jinja/base.pys findnodes‚s  ccs3x,|iƒD]}t||ƒo|Vq q WdS(N(sselfs findnodessnodes isinstancesnodetype(sselfsnodetypesnode((s(build/bdist.linux-i686/egg/jinja/base.pysget_nodes_by_typeŒs (s__name__s __module__srenders findnodessget_nodes_by_type(((s(build/bdist.linux-i686/egg/jinja/base.pysNodeListws sLexercBs,tZd„Zd„Zd„Zd„ZRS(NcCs ||_dS(N(stemplatesself(sselfstemplate((s(build/bdist.linux-i686/egg/jinja/base.pys__init__”scCsRgi}ti|iƒD]-}|i|ƒo||i|ƒƒqq~SdS(N( sappends_[1]stemplate_tag_regexssplitsselfstemplatestags check_tags create_token(sselfs_[1]stag((s(build/bdist.linux-i686/egg/jinja/base.pystokenize—scCs|itƒ SdS(N(stags startswithsCOMMENT_TAG_START(sselfstag((s(build/bdist.linux-i686/egg/jinja/base.pys check_tag›scCs‘|itƒo-tt|ttƒttƒ !iƒƒ}nM|it ƒo-tt |tt ƒtt ƒ !iƒƒ}ntt |ƒ}|SdS(N( stags startswithsVARIABLE_TAG_STARTsTokens TOKEN_VARslensVARIABLE_TAG_ENDsstripstokensBLOCK_TAG_STARTs TOKEN_BLOCKs BLOCK_TAG_ENDs TOKEN_TEXT(sselfstagstoken((s(build/bdist.linux-i686/egg/jinja/base.pys create_tokenžs --(s__name__s __module__s__init__stokenizes check_tags create_token(((s(build/bdist.linux-i686/egg/jinja/base.pysLexer’s   sParsercBsPtZeed„Zed„Zd„Zd„Zd„Zd„Zd„Z RS(NcCs8t|_||_|pt|_||_||_dS(N( sTruesselfsfirststokensslibsstdlibslibrarysloaders template_name(sselfstokenssloaderslibs template_name((s(build/bdist.linux-i686/egg/jinja/base.pys__init__ªs    cCsY|tjo g}ntƒ}x|io |iƒ}|it jo+|i o|i t ||i ƒƒq n­|it jo>|i o'|i |ii|d|i ƒƒq td‚n_|itjoN|i |jo|iid|ƒ|Sn|i |ii||i ƒƒn|o t|_q#q#W|otd|‚n|SdS(Nsprint %ssvariable is emptyisclosing tag %s is missing(s parse_untilsNonesNodeListsnodelistsselfstokenss pop_tokenstokens token_types TOKEN_TEXTscontentssappendsTextNodes TOKEN_VARslibrarysparsesTemplateSyntaxErrors TOKEN_BLOCKsinsertsFalsesfirst(sselfs parse_untilstokensnodelist((s(build/bdist.linux-i686/egg/jinja/base.pysparse±s.      ! ' #cCs|iidƒSdS(Ni(sselfstokensspop(sself((s(build/bdist.linux-i686/egg/jinja/base.pys pop_tokenÍscCs|iidƒSdS(Ni(sselfstokensspop(sself((s(build/bdist.linux-i686/egg/jinja/base.pysget_last_tokenÐscCs|id=dS(Ni(sselfstokens(sself((s(build/bdist.linux-i686/egg/jinja/base.pysremove_dangling_tokenÓscCs$|i|gƒ}|iƒ|SdS(N(sselfsparsesendtagsresultsremove_dangling_token(sselfsendtagsresult((s(build/bdist.linux-i686/egg/jinja/base.pyssubparseÖs cCsh|i||gƒ}|iƒ}|i|jo |i|gƒ}|i ƒn t ƒ}||fSdS(N( sselfsparsesshiftsendtags result_onesget_last_tokenstokenscontentss result_twosremove_dangling_tokensNodeList(sselfsshiftsendtags result_ones result_twostoken((s(build/bdist.linux-i686/egg/jinja/base.pys forkparseÛs  ( s__name__s __module__sNones__init__sparses pop_tokensget_last_tokensremove_dangling_tokenssubparses forkparse(((s(build/bdist.linux-i686/egg/jinja/base.pysParser¨s     (s__doc__s jinja.configsjinja.exceptionss jinja.nodess jinja.utilsstemplate_tag_regexs jinja.libsstdlibsrestypess TOKEN_TEXTs TOKEN_VARs TOKEN_BLOCKsobjectsContextsTokenslistsNodeListsLexersParser( s TOKEN_VARstemplate_tag_regexsLexersNodeListsContextsParsersTokensres TOKEN_BLOCKs TOKEN_TEXTsstdlibstypes((s(build/bdist.linux-i686/egg/jinja/base.pys?s    QPKO´æ4¿Äý˜¾˜¾jinja/tags.pyc;ò õ«Dc@s—dZdklZdklZlZlZdklZdk Tde fd„ƒYZ ei e ƒde fd„ƒYZ ei e ƒd e fd „ƒYZei eƒd e fd „ƒYZei eƒd e fd„ƒYZei eƒde fd„ƒYZei eƒde fd„ƒYZei eƒde fd„ƒYZei eƒde fd„ƒYZei eƒde fd„ƒYZei eƒde fd„ƒYZei eƒde fd„ƒYZei eƒde fd„ƒYZei eƒde fd „ƒYZei eƒd!e fd"„ƒYZei eƒd#e fd$„ƒYZei eƒd%e fd&„ƒYZei eƒd'S((s jinja builtin tags (s generators(sTemplateRuntimeErrorsTemplateSyntaxErrorsTemplateCharsetError(sstdlib(s*s VariableTagcBsPtZdZhdedƒeƒg(sselfs _variables_filters(sself((s(build/bdist.linux-i686/egg/jinja/tags.pys__repr__Es( s__name__s __module__s__doc__s KeywordNodes ChoiceNodesruless__init__s findnodessrenders__repr__(((s(build/bdist.linux-i686/egg/jinja/tags.pys VariableTag s    s ForLoopTagc Bs’tZdZhdedƒeƒedƒeƒg<dedƒeƒedƒeƒedƒgs reverseds(sselfs _variables _iterables _reversed(sself((s(build/bdist.linux-i686/egg/jinja/tags.pys__repr__ïs( s__name__s __module__s__doc__s KeywordNodes VariableNodesCollectionNodesruless__init__s findnodessNonesrenders__repr__(((s(build/bdist.linux-i686/egg/jinja/tags.pys ForLoopTagKs ?]  Ks RangeLoopTagc Bs.tZdZhdedƒeƒedƒeƒedƒeƒg<dedƒeƒedƒeƒedƒeƒedƒeƒg<dedƒeƒedƒeƒedƒeƒg<d edƒeƒedƒeƒedƒeƒedƒeƒg(sselfs _increments range_typeshasattrs_stepssteps_lbounds_ubound(sselfs range_typesstep((s(build/bdist.linux-i686/egg/jinja/tags.pys__repr__`s  ( s__name__s __module__s__doc__s KeywordNodes VariableNodes ChoiceNodesruless__init__s findnodessrenders__repr__(((s(build/bdist.linux-i686/egg/jinja/tags.pys RangeLoopTagùs ü  3s RecurseTagcBswtZdZhdedƒeƒg<dedƒeƒedƒeƒg {% for item in menu %}
  • {{ item.caption|escapexml }} {% if item.submenu %}
      {% recurse item.submenu %}
    {% endif %}
  • {% endfor %} And the context would look like this:: c = Context({ 'menu': [ dict( caption='Pages', submenu=[ dict(href='index.html', caption='Index'), dict(href='downloads.html', caption='Downloads'), dict( caption='Users', submenu=[ dict(href='peter.html', caption='Peter'), dict(href='max.html', caption='Max'), dict(href='suzan.html', caption='Suzan') ] ), dict( caption='Files', submenu=[ dict( caption='Images', submenu=[ dict(href='vienna.html', caption='Vienna'), dict(href='roma.html', caption='Roma'), dict(href='tokyo.html', caption='Tokyo') ] ), dict( caption='Videos', submenu=[ dict(href='party.html', caption='Party') ] ) ] ) ] ), dict(caption='About', href='about.html') ] }) The purpose of this tag is that it recuses by calling a given loop again with another variable. If you don't want to use the current loop you can specify another:: {% recurse myvariable in loop.parent.parent %} sautosrecursesincCs8|djo|d|_n t|_|d|_dS(Nsinii(s matched_tags handler_argssselfs_loopsNones _variable(sselfsparsers matched_tags handler_argssstack((s(build/bdist.linux-i686/egg/jinja/tags.pys__init__Äs  ccs|VdS(N(sself(sself((s(build/bdist.linux-i686/egg/jinja/tags.pys findnodesËscCsŠdkl}l}y4|itjo|d}n|ii|ƒ}Wntd‚nX|i i|ƒ}|di ||ƒ}|SdS(N(sdeepcopyscopysloopsrecursion over non for loops __forloop__( scopysdeepcopysselfs_loopsNonescontextsloopsresolvesTemplateRuntimeErrors _variablesiterablesrendersresult(sselfscontextsiterablesdeepcopyscopysloopsresult((s(build/bdist.linux-i686/egg/jinja/tags.pysrenderÎs cCsd|i|ifSdS(Ns(sselfs_loops _variable(sself((s(build/bdist.linux-i686/egg/jinja/tags.pys__repr__Ûs( s__name__s __module__s__doc__s KeywordNodes VariableNodesruless__init__s findnodessrenders__repr__(((s(build/bdist.linux-i686/egg/jinja/tags.pys RecurseTagss IE   sCycleTagc Bs…tZdZhdedƒeƒedƒeƒg<dedƒeƒedƒeƒg<dedƒeƒedƒg<dedƒeƒedƒg<dedƒeƒedƒeƒedƒg<d edƒeƒedƒeƒedƒg<d edƒeƒedƒedƒg<d edƒeƒedƒedƒg ... {% endfor %} You can also cycle into a variable:: {% for o in some_list %} {% cycle class through "row1", "row2" %} ... ... {% endfor %} It's also possible to iterate through an iterable variable:: {% for item in some_list %} ... ... {% endfor %} In this example row_colors is a application provided list with the following content: ["red", "blue", "green"]... It's also possible to cycle through a sequence variable. Then each cycling will return the next item from the sequence. The cycle tag will reset each time the parent loop iterates. If you don't want this behaviour add a ``noreset`` to the call:: {% cycle "row1", "row2" inline noreset %} sdefaultscyclesthroughs list_defaultsinlines list_inlines default_nrsnoresetslist_default_nrs inline_nrslist_inline_nrcCs~|ddddfjo|d|_|d|_nt|_|d|_|ddddfj|_d |_t|_dS( Nsdefaults list_defaults default_nrslist_default_nriisinlines list_inlineiÿÿÿÿ( s matched_tags handler_argssselfs _variables _iterablesNones_resets_poss _parent_iter(sselfsparsers matched_tags handler_argssstack((s(build/bdist.linux-i686/egg/jinja/tags.pys__init__+s    cCs d|_dS(Niÿÿÿÿ(sselfs_pos(sself((s(build/bdist.linux-i686/egg/jinja/tags.pysreset8scCs0|id7_|i|jo d|_ndS(Nii(sselfs_posslength(sselfslength((s(build/bdist.linux-i686/egg/jinja/tags.pyscycle;scCst|itƒo |i}n|ii|ƒ}|iotd|jo |ddoT|dd}|d}|i t j o |i |jo|i ƒn||_ q°n|i t|ƒƒ|it jo||ii|ƒSn|ii|||ii|ƒƒdSdS(Nsloopsparentscounter0s(s isinstancesselfs _iterableslistsiterablesresolvescontexts_resetsparentsnew_iters _parent_itersNonesresetscycleslens _variables_possrendersdefine(sselfscontextsnew_itersparentsiterable((s(build/bdist.linux-i686/egg/jinja/tags.pysrender@s   !#cCsd|i|ifSdS(Ns(sselfs _variables _iterable(sself((s(build/bdist.linux-i686/egg/jinja/tags.pys__repr__Ys( s__name__s __module__s__doc__s KeywordNodes VariableNodesCollectionNodesruless__init__sresetscyclesrenders__repr__(((s(build/bdist.linux-i686/egg/jinja/tags.pysCycleTagäs ,ÿK   s FilterTagcBsJtZdZhdedƒg HTML PAGE {% endfilter %} sdefaultsfilterc CsWgi}|D]'\}}}|||ddfƒq~|_|i dƒ|_ dS(Niis endfilter( sappends_[1]sstacksfs_sargssselfs_filterssparserssubparses_body( sselfsparsers matched_tags handler_argssstacksargssfs_[1]s_((s(build/bdist.linux-i686/egg/jinja/tags.pys__init__tsAccs7|Vx,|iD]!}x|iƒD] }|Vq!WqWdS(N(sselfs_bodysnodes findnodessn(sselfsnodesn((s(build/bdist.linux-i686/egg/jinja/tags.pys findnodesxs   cCsšg}x'|iD]}|i|i|ƒƒqWdi|ƒ}xP|iD]E\}}||gi}|D]}||i |ƒƒqi~Œ}qIW|SdS(Ns(sparsedsselfs_bodysnodesappendsrenderscontextsjoins_filterssfsargss_[1]sargsresolve(sselfscontextsnodesfsargss_[1]sargsparsed((s(build/bdist.linux-i686/egg/jinja/tags.pysrender~s  =cCsd|iSdS(Ns(sselfs_filters(sself((s(build/bdist.linux-i686/egg/jinja/tags.pys__repr__‡s( s__name__s __module__s__doc__s KeywordNodesruless__init__s findnodessrenders__repr__(((s(build/bdist.linux-i686/egg/jinja/tags.pys FilterTag`s    sDefaultFilterTagcBsetZdZhdedƒg<dedƒedƒg(sselfs_filters(sself((s(build/bdist.linux-i686/egg/jinja/tags.pys__repr__²s( s__name__s __module__s__doc__s KeywordNodesruless__init__s findnodessrenders__repr__(((s(build/bdist.linux-i686/egg/jinja/tags.pysDefaultFilterTags 3   s ConditionTagcBsqtZdZhdedƒeƒg<dedƒedƒeƒg(sselfs_negatedsnegs _variable(sselfsneg((s(build/bdist.linux-i686/egg/jinja/tags.pys__repr__ñs  ( s__name__s __module__s__doc__s KeywordNodes ChoiceNodesruless__init__s findnodessrenders__repr__(((s(build/bdist.linux-i686/egg/jinja/tags.pys ConditionTag¸s ? s ComparisonTagcBstZdZhdedƒeƒedƒeƒg<dedƒedƒeƒedƒeƒgsnot s(sselfs_negateds_var1s_var2(sself((s(build/bdist.linux-i686/egg/jinja/tags.pys__repr__.s( s__name__s __module__s__doc__s KeywordNodes ChoiceNodesruless__init__s findnodessrenders__repr__(((s(build/bdist.linux-i686/egg/jinja/tags.pys ComparisonTagûs ]  sBlockTagcBs˜tZdZhdedƒeƒg<dedƒeƒedƒeƒg<dedƒeƒg(sselfs_names_body(sself((s(build/bdist.linux-i686/egg/jinja/tags.pys__repr__ms( s__name__s __module__s__doc__s KeywordNodes ValueNodesruless__init__s findnodessreplacesrenders__repr__(((s(build/bdist.linux-i686/egg/jinja/tags.pysBlockTag8s ]   s PrepareTagcBs•tZdZhdedƒeƒeƒg<dedƒeƒg<dedƒeƒedƒeƒgs (sselfs_calls_names_argss_body(sself((s(build/bdist.linux-i686/egg/jinja/tags.pys__repr__¾s ( s__name__s __module__s__doc__s KeywordNodes ValueNodesCollectionNodesruless__init__s findnodessrenders__repr__(((s(build/bdist.linux-i686/egg/jinja/tags.pys PrepareTagss c   s ExtendsTagcBsPtZdZhdedƒeƒg {% marker "title" set "Index" %} - MyWebpage
    {% marker "content" %}
    In this example, the ``{% block %}`` and ``{% marker %}`` tags defines some blocks that child templates can fill in. And here a possible child template:: {% extends "base" %} {% marker "title" set "Downloads" %} {% block "content" %} This is the page content. {% endblock %} You can also inherit from this new child template. sdefaultsextendscCs|diƒ|_d|_|i o td‚nt|dƒ o|i|_ n td‚|i i }|i ƒ|_||i|i|iƒ|_h}x'|iitƒD]}|||i(sselfs_names _template(sself((s(build/bdist.linux-i686/egg/jinja/tags.pys__repr__s( s__name__s __module__s__doc__s KeywordNodes ValueNodesruless__init__s findnodessrenders__repr__(((s(build/bdist.linux-i686/egg/jinja/tags.pys ExtendsTagÇs *   s IncludeTagcBstZdZhdedƒeƒg<dedƒeƒg<dedƒeƒedƒeƒgs   cCsˆd|if}|ip||ij oVt|i|<|ii|ƒ}|io|Sq€|i o|i i ||ƒq€ndSdS(Nstemplates( sselfs_namesloads_renderscontextsregistrysTrues _nodelistsrendersresults_dumps _variablesdefine(sselfscontextsloadsresult((s(build/bdist.linux-i686/egg/jinja/tags.pysrenderDs   cCsd|i|ifSdS(Ns(sselfs_names _nodelist(sself((s(build/bdist.linux-i686/egg/jinja/tags.pys__repr__Os( s__name__s __module__s__doc__s KeywordNodes ValueNodes VariableNodesruless__init__s findnodessrenders__repr__(((s(build/bdist.linux-i686/egg/jinja/tags.pys IncludeTags ]  s IfChangedTagcBsJtZdZhdedƒg(sselfs _nodelist(sself((s(build/bdist.linux-i686/egg/jinja/tags.pys__repr__us( s__name__s __module__s__doc__s KeywordNodesruless__init__s findnodessrenders__repr__(((s(build/bdist.linux-i686/egg/jinja/tags.pys IfChangedTagUs    s CaptureTagcBsYtZdZhdedƒedƒeƒg(sselfs _variables_body(sself((s(build/bdist.linux-i686/egg/jinja/tags.pys__repr__™s( s__name__s __module__s__doc__s KeywordNodes VariableNodesruless__init__s findnodessrenders__repr__(((s(build/bdist.linux-i686/egg/jinja/tags.pys CaptureTag{s '   s DefineTagcBsVtZdZhdedƒeƒeƒg(sselfs _variables_value(sself((s(build/bdist.linux-i686/egg/jinja/tags.pys__repr__Âs( s__name__s __module__s__doc__s KeywordNodes VariableNodes ChoiceNodesruless__init__s findnodessrenders__repr__(((s(build/bdist.linux-i686/egg/jinja/tags.pys DefineTagŸs $   sDebugTagcBsAtZdZhdedƒg((sself((s(build/bdist.linux-i686/egg/jinja/tags.pys__repr__Ýs(s__name__s __module__s__doc__s KeywordNodesruless__init__srenders__repr__(((s(build/bdist.linux-i686/egg/jinja/tags.pysDebugTagÈs   N(s__doc__s __future__s generatorssjinja.exceptionssTemplateRuntimeErrorsTemplateSyntaxErrorsTemplateCharsetErrors jinja.libsstdlibs jinja.nodessNodes VariableTags register_tags ForLoopTags RangeLoopTags RecurseTagsCycleTags FilterTagsDefaultFilterTags ConditionTags ComparisonTagsBlockTags PrepareTags ExtendsTags IncludeTags IfChangedTags CaptureTags DefineTagsDebugTag(sCycleTags VariableTags FilterTagsDebugTags IfChangedTags IncludeTags ComparisonTagsstdlibs RecurseTags ExtendsTagsTemplateSyntaxErrors ForLoopTags generatorss CaptureTags PrepareTagsTemplateRuntimeErrors DefineTagsTemplateCharsetErrorsBlockTagsDefaultFilterTags RangeLoopTags ConditionTag((s(build/bdist.linux-i686/egg/jinja/tags.pys?sL  < « w n y * ( @ : 8 Q O 9 # ! & PKO´æ4‡iIqjinja/__init__.pyc;ò ø¥Dc@sÅdZdklZdklZlZlZlZlZdk i Z dk i Z dk iZdkiZdZdZdZddd d d d d gZdefd„ƒYZdefd„ƒYZdS(sQ ===== Jinja ===== Jinja is a small but very fast und easy to use stand-alone template engine written in pure python. Since version 0.6 it uses a new parser that increases parsing performance a lot by caching the nodelists on the harddisk if wanted. It includes multiple template inheritance and other features like simple value escaping... Template Syntax =============== This is a small example template in which you can see, how jinja's syntax looks like: My Webpage

    My Webpage

    {{ variable }} Usage ===== Here a small example:: from jinja import Template, Context, FileSystemLoader t = Template('mytemplate', FileSystemLoader('/path/to/the/templates')) c = Context({ 'navigation' [ {'href': '#', 'caption': 'Index'}, {'href': '#', 'caption': 'Spam'} ], 'variable': 'hello world' }) print t.render(c) (sContext(sFileSystemLoadersCachedFileSystemLoaders StringLoaders EggLoaders ChoiceLoaderNs,Armin Ronacher s0.8s BSD LicensesContextsTemplatesFileSystemLoadersCachedFileSystemLoaders StringLoaders EggLoaders ChoiceLoaders _OldLoadercBs;tZd„Zed„Zeed„Zeed„ZRS(NcCs ||_dS(N(sloadersselfs_loader(sselfsloader((s,build/bdist.linux-i686/egg/jinja/__init__.pys__init__OscCs|ii|ƒSdS(N(sselfs_loadersloadsname(sselfsnamesparent((s,build/bdist.linux-i686/egg/jinja/__init__.pysloadRscCs|ii||ƒSdS(N(sselfs_loadersload_and_compilesnameslib(sselfsnameslibsparent((s,build/bdist.linux-i686/egg/jinja/__init__.pysload_and_compileUscCs|ii||ƒSdS(N(sselfs_loadersload_and_compilesnameslib(sselfsnameslibsparent((s,build/bdist.linux-i686/egg/jinja/__init__.pysload_and_compile_uncachedXs(s__name__s __module__s__init__sNonesloadsload_and_compilesload_and_compile_uncached(((s,build/bdist.linux-i686/egg/jinja/__init__.pys _OldLoaderMs  cBstZed„Zd„ZRS(NcCs:t|dƒ ot|ƒ}n|i||ƒ|_dS(Nsload_and_compile_uncached(shasattrsloaders _OldLoadersload_and_compiles template_nameslibsselfsnodelist(sselfs template_namesloaderslib((s,build/bdist.linux-i686/egg/jinja/__init__.pys__init__^scCs|ii|ƒSdS(N(sselfsnodelistsrenderscontext(sselfscontext((s,build/bdist.linux-i686/egg/jinja/__init__.pysrenderds(s__name__s __module__sNones__init__srender(((s,build/bdist.linux-i686/egg/jinja/__init__.pysTemplate\s (s__doc__s jinja.basesContexts jinja.loadersFileSystemLoadersCachedFileSystemLoaders StringLoaders EggLoaders ChoiceLoaders jinja.tagsstagss jinja.filterssfilterssjinja.exceptionss exceptionss jinja.libslibs __author__s __version__s __license__s__all__sobjects _OldLoadersTemplate(sfiltersslibs EggLoaderstagssFileSystemLoaders StringLoaders __author__sCachedFileSystemLoaders ChoiceLoadersContexts exceptionss _OldLoadersTemplates __version__s __license__s__all__((s,build/bdist.linux-i686/egg/jinja/__init__.pys?:s %    PKO´æ4 }Uh­­jinja/utils.pyc;ò ª´ŽDc @sdZdkTdkTdklZdkZdkZdddgZddd d d d gZei d ƒZ ei dƒZ ei ddi gi ZeD]Zeeieƒƒq•[ƒdi gi ZeD]ZeeieƒƒqË[ƒfƒZei dƒZei deieƒeieƒeieƒeieƒeieƒeieƒfƒZd„Zd„Zeed„Zd„ZdS(s jinja utils (s*(sstdlibNs(ss s>s^(\d+)$s(\s+)s4^(?P(?:%s)*)(?P.*?)(?P(?:%s)*)$s|s&^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$s(%s.*?%s|%s.*?%s|%s.*?%s)(?sm)cCs#|idƒidƒidƒSdS(Nsutf-8s string-escape(sssencodesdecode(ss((s)build/bdist.linux-i686/egg/jinja/utils.pysstring_unescapescCs¼|o t|tƒpt‚|djotSn‚|ddjo|d|djot|dd!ƒSnGti|ƒtj ot|ƒSn#|i ƒddgjo|i ƒdjSnö|}|i dƒ}xÝ|D]Õ}y||}Wntj otƒ‚nsy|t|ƒ}Wqtj otƒ‚qyt||ƒ}Wq{tj otƒ‚q{XqXnXt|ƒo$y |ƒ}Wq°tƒ‚q°XqÛqÛW|Sd S( sqresolves a variable in the following order: 1.) None constants (None) 2.) string constants ("some string") 3.) integer constants (42) 4.) boolean constants (True, False) 5.) dictionary lookup (path['subpath']['subsubpath']) 6.) list lookup: (path['subpath'][0]) 7.) attribute lookup (path.subpath.subsubpath) uNoneiu"'iÿÿÿÿiutrueufalseu.N(spaths isinstancesunicodesAssertionErrorsNonesstring_unescapes integer_resmatchsintslowerscontextscurrentssplitsbitssbitsKeyErrorsVariableDoesNotExists IndexErrorsgetattrsAttributeErrorscallable(spathscontextscurrentsbitsbits((s)build/bdist.linux-i686/egg/jinja/utils.pysresolve_variable#sD  &    c Csí|d„}ti|ƒ} |odpd}xªt| ƒD]œ\}}t i |ƒ} | oz| i ƒ\}} }| idƒpyd| jol| idƒ o[t| ƒdjoH| dtitijo-| idƒp| id ƒp | id ƒod | ||| ƒf} n| idƒp | id ƒod | ||| ƒf} nd| jo,| idƒ od| j o ti | ƒod| | f} n|| ||jo|| || |ass rel="nofollow"sswww.s@shttp://is.orgs.nets.coms%sshttps://s%ss:s%sN(strim_url_limitstrim_urls word_split_ressplitstextswordssnofollows nofollow_attrs enumeratesiswordspunctuation_resmatchsgroupssleadsmiddlestrails startswithslensstringsletterssdigitssendswithssimple_email_resjoin( stextstrim_url_limitsnofollowswordstrim_urlstrailsis nofollow_attrsleadsmiddleswordssmatch((s)build/bdist.linux-i686/egg/jinja/utils.pysurlizeVs$   Œ <cs‡d†}|SdS(só Small decorator for adding filters to the standardlib. Usage: @registerfilter('replace') def handle_replace(s, search, replace): return s.replace(search, replace) Requires python2.4 or higher. cstiˆ|ƒdS(N(sstdlibsregister_filtersnamesf(sf(sname(s)build/bdist.linux-i686/egg/jinja/utils.pyswrapped€sN(swrapped(snameswrapped((snames)build/bdist.linux-i686/egg/jinja/utils.pysregisterfiltervs  ( s__doc__s jinja.configsjinja.exceptionss jinja.libsstdlibsstringsresLEADING_PUNCTUATIONsTRAILING_PUNCTUATIONscompiles integer_res word_split_resjoinsappends_[1]spsescapespunctuation_ressimple_email_resBLOCK_TAG_STARTs BLOCK_TAG_ENDsCOMMENT_TAG_STARTsCOMMENT_TAG_ENDsVARIABLE_TAG_STARTsVARIABLE_TAG_ENDstemplate_tag_regexsstring_unescapesresolve_variablesNonesFalsesurlizesregisterfilter(stemplate_tag_regexspunctuation_resstdlibsLEADING_PUNCTUATIONsurlizesstring_unescapesres word_split_resstrings integer_resTRAILING_PUNCTUATIONsresolve_variables_[1]spssimple_email_resregisterfilter((s)build/bdist.linux-i686/egg/jinja/utils.pys?s    [  3 PKO´æ4›Ú¡Æddjinja/tokens.pyc;ò ó9(sselfs __class__s__name__s_token(sself((s*build/bdist.linux-i686/egg/jinja/tokens.pys__repr__s(s__name__s __module__s__doc__s__init__s__repr__(((s*build/bdist.linux-i686/egg/jinja/tokens.pysToken s  cBstZdZd„ZRS(syA name token. A name token is [A-Za-z_][A-Za-z0-9_]* and only output in case its name doesn't match a different name.cCs |iSdS(s)Get the value of this token, interpreted.N(sselfs_token(sself((s*build/bdist.linux-i686/egg/jinja/tokens.pys__call__s(s__name__s __module__s__doc__s__call__(((s*build/bdist.linux-i686/egg/jinja/tokens.pysNameVals cBs tZdZd„Zd„ZRS(s9Comma value to represent a literal comma (,) in the code.cCstt|ƒitƒdS(N(ssupersCommaValsselfs__init__sNone(sself((s*build/bdist.linux-i686/egg/jinja/tokens.pys__init__!scCstSdS(s)Get the value of this token, interpreted.N(sNone(sself((s*build/bdist.linux-i686/egg/jinja/tokens.pys__call__$s(s__name__s __module__s__doc__s__init__s__call__(((s*build/bdist.linux-i686/egg/jinja/tokens.pysCommaVals  cBs tZdZd„Zd„ZRS(s7Pipe value to represent a literal pipe (|) in the code.cCstt|ƒitƒdS(N(ssupersPipeValsselfs__init__sNone(sself((s*build/bdist.linux-i686/egg/jinja/tokens.pys__init__,scCstSdS(s)Get the value of this token, interpreted.N(sNone(sself((s*build/bdist.linux-i686/egg/jinja/tokens.pys__call__/s(s__name__s __module__s__doc__s__init__s__call__(((s*build/bdist.linux-i686/egg/jinja/tokens.pysPipeVal)s  cBstZdZRS(sPBase class for all value tokens. A value token is a token which has a value.(s__name__s __module__s__doc__(((s*build/bdist.linux-i686/egg/jinja/tokens.pys ValueToken4s cBstZdZd„ZRS(s†String value token. A string value is defined as a string starting with " or ' and escaped by the normal escaping rules of Python.cCs=dkl}||idd!ƒiddƒiddƒSdS(N(sstring_unescapeiiÿÿÿÿu\{u{u\}u}(s jinja.utilssstring_unescapesselfs_tokensreplace(sselfsstring_unescape((s*build/bdist.linux-i686/egg/jinja/tokens.pys__call__=s (s__name__s __module__s__doc__s__call__(((s*build/bdist.linux-i686/egg/jinja/tokens.pys StringVal9s cBstZdZd„ZRS(s4Boolean value. A token that is either true or false.cCs|iiƒdjSdS(s)Get the value of this token, interpreted.strueN(sselfs_tokenslower(sself((s*build/bdist.linux-i686/egg/jinja/tokens.pys__call__Hs(s__name__s __module__s__doc__s__call__(((s*build/bdist.linux-i686/egg/jinja/tokens.pysBoolValEs cBs)tZdZd„Zd„Zd„ZRS(s,An integer value. It has a value and a base.cCs#tt|ƒi|ƒ||_dS(N(ssupersIntValsselfs__init__stokensbases_base(sselfstokensbase((s*build/bdist.linux-i686/egg/jinja/tokens.pys__init__PscCst|i|iƒSdS(s)Get the value of this token, interpreted.N(sintsselfs_tokens_base(sself((s*build/bdist.linux-i686/egg/jinja/tokens.pys__call__TscCs!d|ii|i|ifSdS(Ns<%s: %r, base %r>(sselfs __class__s__name__s_tokens_base(sself((s*build/bdist.linux-i686/egg/jinja/tokens.pys__repr__Xs(s__name__s __module__s__doc__s__init__s__call__s__repr__(((s*build/bdist.linux-i686/egg/jinja/tokens.pysIntValMs   cBstZdZd„ZRS(s7The none value. A token that always has the value none.cCstSdS(s)Get the value of this token, interpreted.N(sNone(sself((s*build/bdist.linux-i686/egg/jinja/tokens.pys__call__`s(s__name__s __module__s__doc__s__call__(((s*build/bdist.linux-i686/egg/jinja/tokens.pysNoneVal]s N( s__doc__s__all__sobjectsTokensNameValsCommaValsPipeVals ValueTokens StringValsBoolValsIntValsNoneVal( sIntVals__all__s StringValsNoneValsBoolValsCommaValsNameValsTokensPipeVals ValueToken((s*build/bdist.linux-i686/egg/jinja/tokens.pys?s!     PKO´æ49’Nüüjinja/config.pyc;ò ó9(slensselfsfiltersstags(sself((s'build/bdist.linux-i686/egg/jinja/lib.pys__repr__ scCst|ƒSdS(sClone the current library.N(s ParserLibrarysself(sself((s'build/bdist.linux-i686/egg/jinja/lib.pysclone$scCs=x6|iiƒD]%\}}t|f|i||ftZdZdedd„Zeed„Zeed„ZRS(sc Same as ``FileSystemLoader`` but caches the parsed nodelist in a binary cPickle dump. s.htmlsutf-8cCsUtt|ƒi|||ƒ|tjo||_t |_ n||_t |_ dS(N( ssupersCachedFileSystemLoadersselfs__init__spathssuffixscharsets cache_dirsNonesTruesprefixsFalse(sselfspathssuffixs cache_dirscharset((s*build/bdist.linux-i686/egg/jinja/loader.pys__init__Os     c CsX|io d}nd}td|i|fƒiƒ}tii|i ||ƒd}tii|i|ƒ|i }tii |ƒ p"tii|ƒtii|ƒjoUti||||ƒ}y#ti|t|dƒddƒWqPtj oqPXnKytit|dƒƒ}Wn+tj oti|||iƒ}nX|SdS( Ns.ss%s/%ss.cacheswbsprotocolisrb(sselfsprefixsmd5spathsnames hexdigestshash_sossjoins cache_dirs cache_namessuffixs template_namesexistssgetmtimesFileSystemLoadersload_and_compileslibsparentsnodelistspicklesdumpsfilesIOErrorsload( sselfsnameslibsparentsnodelists template_namesprefixshash_s cache_name((s*build/bdist.linux-i686/egg/jinja/loader.pysload_and_compileXs"   9# cCs tt|ƒi|||ƒdS(N(ssupersCachedFileSystemLoadersselfsload_and_compilesnameslibsparent(sselfsnameslibsparent((s*build/bdist.linux-i686/egg/jinja/loader.pysload_and_compile_uncachedps(s__name__s __module__s__doc__sNones__init__sload_and_compilesload_and_compile_uncached(((s*build/bdist.linux-i686/egg/jinja/loader.pysCachedFileSystemLoaderIs  cBs5tZdZdd„Zed„Zeed„ZRS(s$ A non thread safe version of a loader getting their templates from strings. If you want a thread safe behaviour you have to create a new loader for each template:: from jinja import Template, StringLoader t = Template('''my template here''', StringLoader()) sutf-8cCs||_t|_dS(N(scharsetsselfsFalsestemplate(sselfscharset((s*build/bdist.linux-i686/egg/jinja/loader.pys__init__~s cCs?yt||iƒSWn$tj o}td|ƒ‚nXdS(NsCould not decode template(sunicodestplsselfscharsetsUnicodeDecodeErrorsesTemplateCharsetError(sselfstplsparentse((s*build/bdist.linux-i686/egg/jinja/loader.pysload‚scCsR|iotdƒ‚nt|_tt|ƒi|||ƒ}t |_|SdS(Ns/StringLoader doesn't allow template inheritance( sselfstemplatesTemplateSyntaxErrorsTruessupers StringLoadersload_and_compilesnameslibsparentsrvsFalse(sselfsnameslibsparentsrv((s*build/bdist.linux-i686/egg/jinja/loader.pysload_and_compileˆs    (s__name__s __module__s__doc__s__init__sNonesloadsload_and_compile(((s*build/bdist.linux-i686/egg/jinja/loader.pys StringLoaderts   cBs)tZdZddd„Zed„ZRS(s Loads templates from an egg:: from jinja import EggLoader loader = EggLoader('MyEgg', 'internal/path/to/templates') s.htmlsutf-8cCsWttjo tjnotdƒ‚ntt|ƒi|||ƒ||_ dS(Nspkg_resources not found( sresource_existssresource_stringsNones RuntimeErrorssupers EggLoadersselfs__init__spathssuffixscharsetspackage(sselfspackagespathssuffixscharset((s*build/bdist.linux-i686/egg/jinja/loader.pys__init__œscCsìdigi}|idƒD],}|o|ddjo||ƒqq~ƒ}di|i|gƒ|i}t |i |ƒot |i |ƒ}n t |ƒ‚y|i|iƒSWn(tj o}tdt|ƒ‚nXdS(Ns/is.sCould not decode template '%s'(sjoinsappends_[1]snamessplitspsselfspathssuffixsresource_existsspackagesresource_stringscontentssTemplateDoesNotExistsdecodescharsetsUnicodeDecodeErrorsesTemplateCharsetErrorsfn(sselfsnamesparentses_[1]spscontents((s*build/bdist.linux-i686/egg/jinja/loader.pysload¢sU (s__name__s __module__s__doc__s__init__sNonesload(((s*build/bdist.linux-i686/egg/jinja/loader.pys EggLoader’s cBsAtZdZd„Zed„Zeed„Zeed„ZRS(sz Takes a number of loader instances. The ``load`` and ``load_and_compile`` method try to to call the functions of all given loaders:: from jinja import ChoiceLoader, FileSystemLoader, EggLoader loader = ChoiceLoader( FileSystemLoader('/path/to/my/templates'), EggLoader('MyEgg', 'internal/path/to/templates') ) cGs ||_dS(N(sloaderssself(sselfsloaders((s*build/bdist.linux-i686/egg/jinja/loader.pys__init__¾scCsTxA|iD]6}y|i|dtƒSWq tj o q q Xq Wt|ƒ‚dS(Nsparent(sselfsloaderssloadersloadsnamesNonesTemplateDoesNotExist(sselfsnamesparentsloader((s*build/bdist.linux-i686/egg/jinja/loader.pysloadÁs  cCsTxA|iD]6}y|i|||ƒSWq tj o q q Xq Wt|ƒ‚dS(N(sselfsloaderssloadersload_and_compilesnameslibsparentsTemplateDoesNotExist(sselfsnameslibsparentsloader((s*build/bdist.linux-i686/egg/jinja/loader.pysload_and_compileÉs  cCsTxA|iD]6}y|i|||ƒSWq tj o q q Xq Wt|ƒ‚dS(N(sselfsloaderssloadersload_and_compile_uncachedsnameslibsparentsTemplateDoesNotExist(sselfsnameslibsparentsloader((s*build/bdist.linux-i686/egg/jinja/loader.pysload_and_compile_uncachedÑs  (s__name__s __module__s__doc__s__init__sNonesloadsload_and_compilesload_and_compile_uncached(((s*build/bdist.linux-i686/egg/jinja/loader.pys ChoiceLoader¯s   (s__doc__s jinja.basesLexersParsersjinja.exceptionssTemplateDoesNotExistsTemplateSyntaxErrorsTemplateCharsetErrorsossmd5scPicklespickles ImportErrors pkg_resourcessresource_existssresource_stringsNones__all__sobjects BaseLoadersFileSystemLoadersCachedFileSystemLoaders StringLoaders EggLoaders ChoiceLoader(sresource_existssParsersTemplateCharsetErrorsresource_strings__all__s EggLoadersTemplateSyntaxErrorspicklesLexers BaseLoadersTemplateDoesNotExistsCachedFileSystemLoaders ChoiceLoaders StringLoadersFileSystemLoadersossmd5((s*build/bdist.linux-i686/egg/jinja/loader.pys?s&   +PKO´æ4Q ”&[ [ EGG-INFO/PKG-INFOMetadata-Version: 1.0 Name: Jinja Version: 0.8 Summary: A small but fast und easy to use stand-alone template engine written in pure python. Home-page: http://wsgiarea.pocoo.org/jinja/ Author: Armin Ronacher Author-email: armin.ronacher@active-4.com License: BSD Description: Jinja is a small but very fast und easy to use stand-alone template engine written in pure python. Since version 0.6 it uses a new parser that increases parsing performance a lot by caching the nodelists on the harddisk if wanted. It includes multiple template inheritance and other features like simple value escaping... Template Syntax =============== This is a small example template in which you can see, how jinja's syntax looks like:: My Webpage

    My Webpage

    {{ variable }} Usage ===== Here a small example:: from jinja import Template, Context, FileSystemLoader t = Template('mytemplate', FileSystemLoader('/path/to/the/templates')) c = Context({ 'navigation' [ {'href': '#', 'caption': 'Index'}, {'href': '#', 'caption': 'Spam'} ], 'variable': 'hello world' }) print t.render(c) Unicode Support =============== Jinja comes with built-in Unicode support. As a matter of fact, the return value of ``Template.render()`` will be a Python unicode object. You can still output ``str`` objects as well when you encode the result:: s = t.render(c).encode('utf-8') For more examples check out the `documentation`_ on the `jinja webpage`_. .. _documentation: http://wsgiarea.pocoo.org/jinja/docs/ .. _jinja webpage: http://wsgiarea.pocoo.org/jinja/ Keywords: wsgi web templateengine templates Platform: any Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Topic :: Internet :: WWW/HTTP Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content PKO´æ4vÂÄÞYYEGG-INFO/SOURCES.txtez_setup.py setup.cfg setup.py Jinja.egg-info/PKG-INFO Jinja.egg-info/SOURCES.txt Jinja.egg-info/top_level.txt docs/generate.py docs/build/basics-dev.html docs/build/basics.html docs/build/conditions.html docs/build/filter-dev.html docs/build/filters.html docs/build/index.html docs/build/inheritance.html docs/build/loops.html docs/build/parts.html docs/build/tag-dev.html docs/build/utils.html docs/source/basics-dev.txt docs/source/basics.txt docs/source/conditions.txt docs/source/filter-dev.txt docs/source/filters.txt docs/source/index.txt docs/source/inheritance.txt docs/source/loops.txt docs/source/parts.txt docs/source/tag-dev.txt docs/source/utils.txt jinja/__init__.py jinja/base.py jinja/config.py jinja/exceptions.py jinja/filters.py jinja/lib.py jinja/loader.py jinja/nodes.py jinja/tagparser.py jinja/tags.py jinja/tokens.py jinja/utils.py PKO´æ4åŽEGG-INFO/top_level.txtjinja PKP´æ4EGG-INFO/zip-safePK« Œ4w˜Ass¤jinja/exceptions.pyPKŽœÇ4÷ë· ¾<¾<¤¤jinja/filters.pyPK« Œ4`{'}[[¤Ajinja/nodes.pyPK« Œ4(ÔUã[[¤Vjinja/tagparser.pyPK¹‘Ü4R6~~ÓÓ ¤H±jinja/base.pyPK¯šå4Gíx¶h—h— ¤FÊjinja/tags.pyPK¿Þ4vÀ0J J ¤Ùajinja/__init__.pyPKYvÍ43ÞȘ˜¤Rmjinja/utils.pyPK« Œ4î\ËÆL L ¤jinja/tokens.pyPK« Œ4àþ‡EÞÞ¤‹jinja/config.pyPK€œÇ4Ù̓ü ü ¤šŒjinja/lib.pyPKÃTá4=A×Yãã¤À˜jinja/loader.pyPKO´æ4èü À††¤Ð´jinja/exceptions.pycPKO´æ4MEc‚ÐUÐU¤ˆÄjinja/filters.pycPKO´æ4.Y¤Q[*[*¤‡jinja/nodes.pycPKO´æ4ë¤>±??¤Ejinja/tagparser.pycPKO´æ4B8Ñ,,¤A„jinja/base.pycPKO´æ4¿Äý˜¾˜¾¤r°jinja/tags.pycPKO´æ4‡iIq¤6ojinja/__init__.pycPKO´æ4 }Uh­­¤kjinja/utils.pycPKO´æ4›Ú¡Ædd¤E˜jinja/tokens.pycPKO´æ49’Nüü¤×°jinja/config.pycPKP´æ4 ^Gff ¤³jinja/lib.pycPKP´æ4¬”â Ñ,Ñ,¤’Èjinja/loader.pycPKO´æ4Q ”&[ [ ¤‘õEGG-INFO/PKG-INFOPKO´æ4vÂÄÞYY¤EGG-INFO/SOURCES.txtPKO´æ4厤¦EGG-INFO/top_level.txtPKP´æ4¤àEGG-INFO/zip-safePKÊ