| Index: third_party/handlebar/handlebar.py
|
| diff --git a/third_party/handlebar/handlebar.py b/third_party/handlebar/handlebar.py
|
| index 3e7b5a535d334ff3ef267acbbe22570ff6eddff6..c5a2c101629ab0ed9e25444a9d053d941982b7bd 100644
|
| --- a/third_party/handlebar/handlebar.py
|
| +++ b/third_party/handlebar/handlebar.py
|
| @@ -43,9 +43,6 @@ class CustomContext(object):
|
| print(Handlebar('hello {{world}}').render(CustomContext()).text)
|
| """
|
|
|
| -def _SafeStr(obj):
|
| - return obj if isinstance(obj, basestring) else str(obj)
|
| -
|
| class ParseException(Exception):
|
| """ Exception thrown while parsing the template.
|
| """
|
| @@ -65,22 +62,24 @@ class StringBuilder(object):
|
| """
|
| def __init__(self):
|
| self._buf = []
|
| - self._length = 0
|
|
|
| def __len__(self):
|
| - return self._length
|
| + self._Collapse()
|
| + return len(self._buf[0])
|
|
|
| - def append(self, obj):
|
| - string = _SafeStr(obj)
|
| + def append(self, string):
|
| self._buf.append(string)
|
| - self._length += len(string)
|
|
|
| def toString(self):
|
| - return u''.join(self._buf)
|
| + self._Collapse()
|
| + return self._buf[0]
|
|
|
| def __str__(self):
|
| return self.toString()
|
|
|
| + def _Collapse(self):
|
| + self._buf = [u''.join(self._buf)]
|
| +
|
| class RenderState(object):
|
| """ The state of a render call.
|
| """
|
| @@ -110,7 +109,7 @@ class RenderState(object):
|
| return self
|
| buf = StringBuilder()
|
| for message in messages:
|
| - buf.append(message)
|
| + buf.append(str(message))
|
| self.errors.append(buf.toString())
|
| return self
|
|
|
| @@ -144,16 +143,16 @@ class Identifier(object):
|
| return self._resolveFromContext(renderState.getFirstContext())
|
|
|
| resolved = self._resolveFromContexts(renderState.localContexts)
|
| - if resolved == None:
|
| + if resolved is None:
|
| resolved = self._resolveFromContexts(renderState.globalContexts)
|
| - if resolved == None:
|
| + if resolved is None:
|
| renderState.addError("Couldn't resolve identifier ", self._path)
|
| return resolved
|
|
|
| def _resolveFromContexts(self, contexts):
|
| for context in contexts:
|
| resolved = self._resolveFromContext(context)
|
| - if resolved != None:
|
| + if resolved is not None:
|
| return resolved
|
| return None
|
|
|
| @@ -162,7 +161,7 @@ class Identifier(object):
|
| for next in self._path:
|
| # Only require that contexts provide a get method, meaning that callers
|
| # can provide dict-like contexts (for example, to populate values lazily).
|
| - if result == None or not getattr(result, "get", None):
|
| + if result is None or not getattr(result, "get", None):
|
| return None
|
| result = result.get(next)
|
| return result
|
| @@ -236,32 +235,26 @@ class InlineNode(DecoratorNode):
|
| self._content.render(contentRenderState)
|
|
|
| renderState.errors.extend(contentRenderState.errors)
|
| -
|
| - for c in contentRenderState.text.toString():
|
| - if c != '\n':
|
| - renderState.text.append(c)
|
| + renderState.text.append(
|
| + contentRenderState.text.toString().replace('\n', ''))
|
|
|
| class IndentedNode(DecoratorNode):
|
| def __init__(self, content, indentation):
|
| DecoratorNode.__init__(self, content)
|
| - self._indentation = indentation
|
| + self._indent_str = ' ' * indentation
|
|
|
| def render(self, renderState):
|
| contentRenderState = renderState.inSameContext()
|
| self._content.render(contentRenderState)
|
|
|
| renderState.errors.extend(contentRenderState.errors)
|
| -
|
| - self._indent(renderState.text)
|
| - for i, c in enumerate(contentRenderState.text.toString()):
|
| - renderState.text.append(c)
|
| - if c == '\n' and i < len(contentRenderState.text) - 1:
|
| - self._indent(renderState.text)
|
| + renderState.text.append(self._indent_str)
|
| + # TODO: this might introduce an extra \n at the end? need test.
|
| + renderState.text.append(
|
| + contentRenderState.text.toString().replace('\n',
|
| + '\n' + self._indent_str))
|
| renderState.text.append('\n')
|
|
|
| - def _indent(self, buf):
|
| - buf.append(' ' * self._indentation)
|
| -
|
| class BlockNode(DecoratorNode):
|
| def __init__(self, content):
|
| DecoratorNode.__init__(self, content)
|
| @@ -354,19 +347,13 @@ class EscapedVariableNode(LeafNode):
|
|
|
| def render(self, renderState):
|
| value = self._id.resolve(renderState)
|
| - if value != None:
|
| - self._appendEscapedHtml(renderState.text, _SafeStr(value))
|
| -
|
| - def _appendEscapedHtml(self, escaped, unescaped):
|
| - for c in unescaped:
|
| - if c == '<':
|
| - escaped.append("<")
|
| - elif c == '>':
|
| - escaped.append(">")
|
| - elif c == '&':
|
| - escaped.append("&")
|
| - else:
|
| - escaped.append(c)
|
| + if value is None:
|
| + return
|
| +
|
| + string = value if isinstance(value, basestring) else str(value)
|
| + renderState.text.append(string.replace('&', '&')
|
| + .replace('<', '<')
|
| + .replace('>', '>'))
|
|
|
| class UnescapedVariableNode(LeafNode):
|
| """ {{{foo}}}
|
| @@ -377,8 +364,10 @@ class UnescapedVariableNode(LeafNode):
|
|
|
| def render(self, renderState):
|
| value = self._id.resolve(renderState)
|
| - if value != None:
|
| - renderState.text.append(value)
|
| + if value is None:
|
| + return
|
| + renderState.text.append(
|
| + value if isinstance(value, basestring) else str(value))
|
|
|
| class SectionNode(DecoratorNode):
|
| """ {{#foo}} ... {{/}}
|
| @@ -389,7 +378,7 @@ class SectionNode(DecoratorNode):
|
|
|
| def render(self, renderState):
|
| value = self._id.resolve(renderState)
|
| - if value == None:
|
| + if value is None:
|
| return
|
|
|
| if isinstance(value, list):
|
| @@ -420,7 +409,7 @@ class VertedSectionNode(DecoratorNode):
|
| renderState.localContexts.pop(0)
|
|
|
| def _VertedSectionNodeShouldRender(value):
|
| - if value == None:
|
| + if value is None:
|
| return False
|
| if isinstance(value, bool):
|
| return value
|
| @@ -457,8 +446,9 @@ class JsonNode(LeafNode):
|
|
|
| def render(self, renderState):
|
| value = self._id.resolve(renderState)
|
| - if value != None:
|
| - renderState.text.append(json.dumps(value, separators=(',',':')))
|
| + if value is None:
|
| + return
|
| + renderState.text.append(json.dumps(value, separators=(',',':')))
|
|
|
| class PartialNode(LeafNode):
|
| """ {{+foo}}
|
| @@ -549,7 +539,7 @@ class TokenStream(object):
|
| self.advance()
|
|
|
| def hasNext(self):
|
| - return self.nextToken != None
|
| + return self.nextToken is not None
|
|
|
| def advance(self):
|
| if self.nextContents == '\n':
|
|
|