From a3999641857c1e7b620f3a2513576b493a6101d8 Mon Sep 17 00:00:00 2001 From: Chris Jerdonek Date: Sat, 5 May 2012 13:26:22 -0700 Subject: More progress on removing RenderEngine from Parser. --- pystache/parser.py | 62 +++++++++++++++++++++++++++++++++++++++++++----- pystache/renderengine.py | 37 +---------------------------- 2 files changed, 57 insertions(+), 42 deletions(-) (limited to 'pystache') diff --git a/pystache/parser.py b/pystache/parser.py index cb12306..ad542c3 100644 --- a/pystache/parser.py +++ b/pystache/parser.py @@ -14,6 +14,7 @@ from pystache.parsed import ParsedTemplate DEFAULT_DELIMITERS = (u'{{', u'}}') END_OF_LINE_CHARACTERS = [u'\r', u'\n'] +NON_BLANK_RE = re.compile(ur'^(.)', re.M) def _compile_template_re(delimiters=None): @@ -52,13 +53,31 @@ class ParsingError(Exception): pass +## Node types + + +class CommentNode(object): + + def render(self, engine, context): + return u'' + + +class ChangeNode(object): + + def __init__(self, delimiters): + self.delimiters = delimiters + + def render(self, engine, context): + return u'' + + class VariableNode(object): def __init__(self, key): self.key = key def render(self, engine, context): - s = engine._get_string_value(context, self.key) + s = engine.fetch_string(context, self.key) return engine.escape(s) @@ -68,10 +87,41 @@ class LiteralNode(object): self.key = key def render(self, engine, context): - s = engine._get_string_value(context, self.key) + s = engine.fetch_string(context, self.key) return engine.literal(s) +class PartialNode(object): + + def __init__(self, key, indent): + self.key = key + self.indent = indent + + def render(self, engine, context): + template = engine.resolve_partial(self.key) + # Indent before rendering. + template = re.sub(NON_BLANK_RE, self.indent + ur'\1', template) + + return engine.render(template, context) + + +class InvertedNode(object): + + def __init__(self, key, parsed_section): + self.key = key + self.parsed_section = parsed_section + + def render(self, engine, context): + # TODO: is there a bug because we are not using the same + # logic as in fetch_string()? + data = engine.resolve_context(context, self.key) + # Note that lambdas are considered truthy for inverted sections + # per the spec. + if data: + return u'' + return engine._render_parsed(self.parsed_section, context) + + class Parser(object): _delimiters = None @@ -204,12 +254,12 @@ class Parser(object): """ # TODO: switch to using a dictionary instead of a bunch of ifs and elifs. if tag_type == '!': - return u'' + return CommentNode() if tag_type == '=': delimiters = tag_key.split() self._change_delimiters(delimiters) - return u'' + return ChangeNode(delimiters) if tag_type == '': return VariableNode(tag_key) @@ -218,7 +268,7 @@ class Parser(object): return LiteralNode(tag_key) if tag_type == '>': - return self.engine._make_get_partial(tag_key, leading_whitespace) + return PartialNode(tag_key, leading_whitespace) raise Exception("Invalid symbol for interpolation tag: %s" % repr(tag_type)) @@ -233,6 +283,6 @@ class Parser(object): template, section_start_index, section_end_index) if tag_type == '^': - return self.engine._make_get_inverse(tag_key, parsed_section) + return InvertedNode(tag_key, parsed_section) raise Exception("Invalid symbol for section tag: %s" % repr(tag_type)) diff --git a/pystache/renderengine.py b/pystache/renderengine.py index 80f795d..39b536c 100644 --- a/pystache/renderengine.py +++ b/pystache/renderengine.py @@ -11,9 +11,6 @@ from pystache.common import is_string from pystache.parser import Parser -NON_BLANK_RE = re.compile(ur'^(.)', re.M) - - def context_get(stack, name): """ Find and return a name from a ContextStack instance. @@ -90,7 +87,7 @@ class RenderEngine(object): # The returned value MUST be rendered against the default delimiters, # then interpolated in place of the lambda. # - def _get_string_value(self, context, tag_name): + def fetch_string(self, context, tag_name): """ Get a value from the given context as a basestring instance. @@ -106,38 +103,6 @@ class RenderEngine(object): return val - def _make_get_partial(self, tag_key, leading_whitespace): - - template = self.resolve_partial(tag_key) - # Indent before rendering. - template = re.sub(NON_BLANK_RE, leading_whitespace + ur'\1', template) - - def get_partial(context): - """ - Returns: a string of type unicode. - - """ - # TODO: can we do the parsing before calling this function? - return self.render(template, context) - - return get_partial - - def _make_get_inverse(self, name, parsed_template): - def get_inverse(context): - """ - Returns a string with type unicode. - - """ - # TODO: is there a bug because we are not using the same - # logic as in _get_string_value()? - data = self.resolve_context(context, name) - # Per the spec, lambdas in inverted sections are considered truthy. - if data: - return u'' - return self._render_parsed(parsed_template, context) - - return get_inverse - # TODO: the template_ and parsed_template_ arguments don't both seem # to be necessary. Can we remove one of them? For example, if # callable(data) is True, then the initial parsed_template isn't used. -- cgit v1.2.1