# -*- coding: utf-8 -*-
"""
jinja builtin nodes
"""
from __future__ import generators
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 '<TextNode: %r>' % 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
syntax highlighted by Code2HTML, v. 0.9.1