Commit c35b3303 by Chris Jerdonek

Created a ParsedTemplate class.

parent 5c91b4ba
......@@ -9,6 +9,8 @@ This module is only meant for internal use by the renderengine module.
import re
from template import ParsedTemplate
DEFAULT_DELIMITERS = ('{{', '}}')
END_OF_LINE_CHARACTERS = ['\r', '\n']
......@@ -73,7 +75,7 @@ class Parser(object):
def parse(self, template, index=0, section_key=None):
"""
Parse a template string into a parse tree.
Parse a template string into a ParsedTemplate instance.
This method uses the current tag delimiter.
......@@ -126,19 +128,19 @@ class Parser(object):
if tag_key != section_key:
raise ParsingError("Section end tag mismatch: %s != %s" % (repr(tag_key), repr(section_key)))
return parse_tree, template[start_index:match_index], end_index
return ParsedTemplate(parse_tree), template[start_index:match_index], end_index
index = self._handle_tag_type(template, parse_tree, tag_type, tag_key, leading_whitespace, start_index, match_index, end_index)
# Save the rest of the template.
parse_tree.append(template[index:])
return parse_tree
return ParsedTemplate(parse_tree)
def _parse_section(self, template, index_start, section_key):
parse_tree, template, index_end = self.parse(template=template, index=index_start, section_key=section_key)
parsed_template, template, index_end = self.parse(template=template, index=index_start, section_key=section_key)
return parse_tree, template, index_end
return parsed_template, template, index_end
def _handle_tag_type(self, template, parse_tree, tag_type, tag_key, leading_whitespace, start_index, match_index, end_index):
......@@ -162,13 +164,13 @@ class Parser(object):
elif tag_type == '#':
buff, template, end_index = self._parse_section(template, end_index, tag_key)
func = engine._make_get_section(tag_key, buff, template, self._delimiters)
parsed_section, template, end_index = self._parse_section(template, end_index, tag_key)
func = engine._make_get_section(tag_key, parsed_section, template, self._delimiters)
elif tag_type == '^':
buff, template, end_index = self._parse_section(template, end_index, tag_key)
func = engine._make_get_inverse(tag_key, buff)
parsed_section, template, end_index = self._parse_section(template, end_index, tag_key)
func = engine._make_get_inverse(tag_key, parsed_section)
elif tag_type == '>':
......
......@@ -13,39 +13,6 @@ from parser import Parser
NON_BLANK_RE = re.compile(r'^(.)', re.M)
def render_parse_tree(parse_tree, context):
"""
Returns: a string of type unicode.
The elements of parse_tree can be any of the following:
* a unicode string
* the return value of a call to any of the following:
* RenderEngine._make_get_literal():
Args: context
Returns: unicode
* RenderEngine._make_get_escaped():
Args: context
Returns: unicode
* RenderEngine._make_get_partial()
Args: context
Returns: unicode
* RenderEngine._make_get_section()
Args: context
Returns: unicode
* _make_get_inverse()
Args: context
Returns: unicode
"""
get_unicode = lambda val: val(context) if callable(val) else val
parts = map(get_unicode, parse_tree)
s = ''.join(parts)
return unicode(s)
class RenderEngine(object):
"""
......@@ -175,7 +142,7 @@ class RenderEngine(object):
return get_partial
def _make_get_inverse(self, name, parsed):
def _make_get_inverse(self, name, parsed_template):
def get_inverse(context):
"""
Returns a string with type unicode.
......@@ -184,25 +151,28 @@ class RenderEngine(object):
data = context.get(name)
if data:
return u''
return render_parse_tree(parsed, context)
return parsed_template.render(context)
return get_inverse
def _make_get_section(self, name, parse_tree_, template_, delims):
# 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.
def _make_get_section(self, name, parsed_template_, template_, delims):
def get_section(context):
"""
Returns: a string of type unicode.
"""
template = template_
parse_tree = parse_tree_
parsed_template = parsed_template_
data = context.get(name)
if not data:
data = []
elif callable(data):
# TODO: should we check the arity?
template = data(template)
parse_tree = self._parse_to_tree(template_string=template, delimiters=delims)
parsed_template = self._parse(template_string=template, delimiters=delims)
data = [ data ]
elif type(data) not in [list, tuple]:
data = [ data ]
......@@ -210,16 +180,16 @@ class RenderEngine(object):
parts = []
for element in data:
context.push(element)
parts.append(render_parse_tree(parse_tree, context))
parts.append(parsed_template.render(context))
context.pop()
return unicode(''.join(parts))
return get_section
def _parse_to_tree(self, template_string, delimiters=None):
def _parse(self, template_string, delimiters=None):
"""
Parse the given template into a parse tree using a new parser.
Parse the given template, and return a ParsedTemplate instance.
"""
parser = Parser(self, delimiters=delimiters)
......@@ -240,9 +210,9 @@ class RenderEngine(object):
if type(template) is not unicode:
raise Exception("Argument 'template' not unicode: %s: %s" % (type(template), repr(template)))
parse_tree = self._parse_to_tree(template_string=template)
parsed_template = self._parse(template_string=template)
return render_parse_tree(parse_tree, context)
return parsed_template.render(context)
def render(self, template, context):
"""
......
# coding: utf-8
"""
Exposes a class that represents a parsed (or compiled) template.
This module is meant only for internal use.
"""
class ParsedTemplate(object):
def __init__(self, parse_tree):
self._parse_tree = parse_tree
def render(self, context):
"""
Returns: a string of type unicode.
The elements of parse_tree can be any of the following:
* a unicode string
* the return value of a call to any of the following:
* RenderEngine._make_get_literal():
Args: context
Returns: unicode
* RenderEngine._make_get_escaped():
Args: context
Returns: unicode
* RenderEngine._make_get_partial()
Args: context
Returns: unicode
* RenderEngine._make_get_section()
Args: context
Returns: unicode
* _make_get_inverse()
Args: context
Returns: unicode
"""
get_unicode = lambda val: val(context) if callable(val) else val
parts = map(get_unicode, self._parse_tree)
s = ''.join(parts)
return unicode(s)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment