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. ...@@ -9,6 +9,8 @@ This module is only meant for internal use by the renderengine module.
import re import re
from template import ParsedTemplate
DEFAULT_DELIMITERS = ('{{', '}}') DEFAULT_DELIMITERS = ('{{', '}}')
END_OF_LINE_CHARACTERS = ['\r', '\n'] END_OF_LINE_CHARACTERS = ['\r', '\n']
...@@ -73,7 +75,7 @@ class Parser(object): ...@@ -73,7 +75,7 @@ class Parser(object):
def parse(self, template, index=0, section_key=None): 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. This method uses the current tag delimiter.
...@@ -126,19 +128,19 @@ class Parser(object): ...@@ -126,19 +128,19 @@ class Parser(object):
if tag_key != section_key: if tag_key != section_key:
raise ParsingError("Section end tag mismatch: %s != %s" % (repr(tag_key), repr(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) 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. # Save the rest of the template.
parse_tree.append(template[index:]) parse_tree.append(template[index:])
return parse_tree return ParsedTemplate(parse_tree)
def _parse_section(self, template, index_start, section_key): 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): 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): ...@@ -162,13 +164,13 @@ class Parser(object):
elif tag_type == '#': elif tag_type == '#':
buff, template, end_index = self._parse_section(template, end_index, tag_key) parsed_section, template, end_index = self._parse_section(template, end_index, tag_key)
func = engine._make_get_section(tag_key, buff, template, self._delimiters) func = engine._make_get_section(tag_key, parsed_section, template, self._delimiters)
elif tag_type == '^': elif tag_type == '^':
buff, template, end_index = self._parse_section(template, end_index, tag_key) parsed_section, template, end_index = self._parse_section(template, end_index, tag_key)
func = engine._make_get_inverse(tag_key, buff) func = engine._make_get_inverse(tag_key, parsed_section)
elif tag_type == '>': elif tag_type == '>':
......
...@@ -13,39 +13,6 @@ from parser import Parser ...@@ -13,39 +13,6 @@ from parser import Parser
NON_BLANK_RE = re.compile(r'^(.)', re.M) 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): class RenderEngine(object):
""" """
...@@ -175,7 +142,7 @@ class RenderEngine(object): ...@@ -175,7 +142,7 @@ class RenderEngine(object):
return get_partial return get_partial
def _make_get_inverse(self, name, parsed): def _make_get_inverse(self, name, parsed_template):
def get_inverse(context): def get_inverse(context):
""" """
Returns a string with type unicode. Returns a string with type unicode.
...@@ -184,25 +151,28 @@ class RenderEngine(object): ...@@ -184,25 +151,28 @@ class RenderEngine(object):
data = context.get(name) data = context.get(name)
if data: if data:
return u'' return u''
return render_parse_tree(parsed, context) return parsed_template.render(context)
return get_inverse 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): def get_section(context):
""" """
Returns: a string of type unicode. Returns: a string of type unicode.
""" """
template = template_ template = template_
parse_tree = parse_tree_ parsed_template = parsed_template_
data = context.get(name) data = context.get(name)
if not data: if not data:
data = [] data = []
elif callable(data): elif callable(data):
# TODO: should we check the arity? # TODO: should we check the arity?
template = data(template) 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 ] data = [ data ]
elif type(data) not in [list, tuple]: elif type(data) not in [list, tuple]:
data = [ data ] data = [ data ]
...@@ -210,16 +180,16 @@ class RenderEngine(object): ...@@ -210,16 +180,16 @@ class RenderEngine(object):
parts = [] parts = []
for element in data: for element in data:
context.push(element) context.push(element)
parts.append(render_parse_tree(parse_tree, context)) parts.append(parsed_template.render(context))
context.pop() context.pop()
return unicode(''.join(parts)) return unicode(''.join(parts))
return get_section 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) parser = Parser(self, delimiters=delimiters)
...@@ -240,9 +210,9 @@ class RenderEngine(object): ...@@ -240,9 +210,9 @@ class RenderEngine(object):
if type(template) is not unicode: if type(template) is not unicode:
raise Exception("Argument 'template' not unicode: %s: %s" % (type(template), repr(template))) 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): 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