Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Unified Diff: third_party/pystache/src/renderengine.py

Issue 2962783004: Adding pystache to third_party (Closed)
Patch Set: Merge branch 'master' into mustache Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/pystache/src/parser.py ('k') | third_party/pystache/src/renderer.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/pystache/src/renderengine.py
diff --git a/third_party/pystache/src/renderengine.py b/third_party/pystache/src/renderengine.py
new file mode 100644
index 0000000000000000000000000000000000000000..c797b1765a5ae09ca1c6bd9cd3adeb6a219ea913
--- /dev/null
+++ b/third_party/pystache/src/renderengine.py
@@ -0,0 +1,181 @@
+# coding: utf-8
+
+"""
+Defines a class responsible for rendering logic.
+
+"""
+
+import re
+
+from pystache.common import is_string
+from pystache.parser import parse
+
+
+def context_get(stack, name):
+ """
+ Find and return a name from a ContextStack instance.
+
+ """
+ return stack.get(name)
+
+
+class RenderEngine(object):
+
+ """
+ Provides a render() method.
+
+ This class is meant only for internal use.
+
+ As a rule, the code in this class operates on unicode strings where
+ possible rather than, say, strings of type str or markupsafe.Markup.
+ This means that strings obtained from "external" sources like partials
+ and variable tag values are immediately converted to unicode (or
+ escaped and converted to unicode) before being operated on further.
+ This makes maintaining, reasoning about, and testing the correctness
+ of the code much simpler. In particular, it keeps the implementation
+ of this class independent of the API details of one (or possibly more)
+ unicode subclasses (e.g. markupsafe.Markup).
+
+ """
+
+ # TODO: it would probably be better for the constructor to accept
+ # and set as an attribute a single RenderResolver instance
+ # that encapsulates the customizable aspects of converting
+ # strings and resolving partials and names from context.
+ def __init__(self, literal=None, escape=None, resolve_context=None,
+ resolve_partial=None, to_str=None):
+ """
+ Arguments:
+
+ literal: the function used to convert unescaped variable tag
+ values to unicode, e.g. the value corresponding to a tag
+ "{{{name}}}". The function should accept a string of type
+ str or unicode (or a subclass) and return a string of type
+ unicode (but not a proper subclass of unicode).
+ This class will only pass basestring instances to this
+ function. For example, it will call str() on integer variable
+ values prior to passing them to this function.
+
+ escape: the function used to escape and convert variable tag
+ values to unicode, e.g. the value corresponding to a tag
+ "{{name}}". The function should obey the same properties
+ described above for the "literal" function argument.
+ This function should take care to convert any str
+ arguments to unicode just as the literal function should, as
+ this class will not pass tag values to literal prior to passing
+ them to this function. This allows for more flexibility,
+ for example using a custom escape function that handles
+ incoming strings of type markupsafe.Markup differently
+ from plain unicode strings.
+
+ resolve_context: the function to call to resolve a name against
+ a context stack. The function should accept two positional
+ arguments: a ContextStack instance and a name to resolve.
+
+ resolve_partial: the function to call when loading a partial.
+ The function should accept a template name string and return a
+ template string of type unicode (not a subclass).
+
+ to_str: a function that accepts an object and returns a string (e.g.
+ the built-in function str). This function is used for string
+ coercion whenever a string is required (e.g. for converting None
+ or 0 to a string).
+
+ """
+ self.escape = escape
+ self.literal = literal
+ self.resolve_context = resolve_context
+ self.resolve_partial = resolve_partial
+ self.to_str = to_str
+
+ # TODO: Rename context to stack throughout this module.
+
+ # From the spec:
+ #
+ # When used as the data value for an Interpolation tag, the lambda
+ # MUST be treatable as an arity 0 function, and invoked as such.
+ # The returned value MUST be rendered against the default delimiters,
+ # then interpolated in place of the lambda.
+ #
+ def fetch_string(self, context, name):
+ """
+ Get a value from the given context as a basestring instance.
+
+ """
+ val = self.resolve_context(context, name)
+
+ if callable(val):
+ # Return because _render_value() is already a string.
+ return self._render_value(val(), context)
+
+ if not is_string(val):
+ return self.to_str(val)
+
+ return val
+
+ def fetch_section_data(self, context, name):
+ """
+ Fetch the value of a section as a list.
+
+ """
+ data = self.resolve_context(context, name)
+
+ # From the spec:
+ #
+ # If the data is not of a list type, it is coerced into a list
+ # as follows: if the data is truthy (e.g. `!!data == true`),
+ # use a single-element list containing the data, otherwise use
+ # an empty list.
+ #
+ if not data:
+ data = []
+ else:
+ # The least brittle way to determine whether something
+ # supports iteration is by trying to call iter() on it:
+ #
+ # http://docs.python.org/library/functions.html#iter
+ #
+ # It is not sufficient, for example, to check whether the item
+ # implements __iter__ () (the iteration protocol). There is
+ # also __getitem__() (the sequence protocol). In Python 2,
+ # strings do not implement __iter__(), but in Python 3 they do.
+ try:
+ iter(data)
+ except TypeError:
+ # Then the value does not support iteration.
+ data = [data]
+ else:
+ if is_string(data) or isinstance(data, dict):
+ # Do not treat strings and dicts (which are iterable) as lists.
+ data = [data]
+ # Otherwise, treat the value as a list.
+
+ return data
+
+ def _render_value(self, val, context, delimiters=None):
+ """
+ Render an arbitrary value.
+
+ """
+ if not is_string(val):
+ # In case the template is an integer, for example.
+ val = self.to_str(val)
+ if type(val) is not unicode:
+ val = self.literal(val)
+ return self.render(val, context, delimiters)
+
+ def render(self, template, context_stack, delimiters=None):
+ """
+ Render a unicode template string, and return as unicode.
+
+ Arguments:
+
+ template: a template string of type unicode (but not a proper
+ subclass of unicode).
+
+ context_stack: a ContextStack instance.
+
+ """
+ parsed_template = parse(template, delimiters)
+
+ return parsed_template.render(self, context_stack)
« no previous file with comments | « third_party/pystache/src/parser.py ('k') | third_party/pystache/src/renderer.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698