PYTHON 73
Nativetypes.py Guest on 16th April 2021 11:31:12 AM
  1. from ast import literal_eval
  2. from itertools import chain
  3. from itertools import islice
  4.  
  5. from . import nodes
  6. from ._compat import text_type
  7. from .compiler import CodeGenerator
  8. from .compiler import has_safe_repr
  9. from .environment import Environment
  10. from .environment import Template
  11.  
  12.  
  13. def native_concat(nodes):
  14.     """Return a native Python type from the list of compiled nodes. If
  15.    the result is a single node, its value is returned. Otherwise, the
  16.    nodes are concatenated as strings. If the result can be parsed with
  17.    :func:`ast.literal_eval`, the parsed value is returned. Otherwise,
  18.    the string is returned.
  19.  
  20.    :param nodes: Iterable of nodes to concatenate.
  21.    """
  22.     head = list(islice(nodes, 2))
  23.  
  24.     if not head:
  25.         return None
  26.  
  27.     if len(head) == 1:
  28.         raw = head[0]
  29.     else:
  30.         raw = u"".join([text_type(v) for v in chain(head, nodes)])
  31.  
  32.     try:
  33.         return literal_eval(raw)
  34.     except (ValueError, SyntaxError, MemoryError):
  35.         return raw
  36.  
  37.  
  38. class NativeCodeGenerator(CodeGenerator):
  39.     """A code generator which renders Python types by not adding
  40.    ``to_string()`` around output nodes.
  41.    """
  42.  
  43.     @staticmethod
  44.     def _default_finalize(value):
  45.         return value
  46.  
  47.     def _output_const_repr(self, group):
  48.         return repr(u"".join([text_type(v) for v in group]))
  49.  
  50.     def _output_child_to_const(self, node, frame, finalize):
  51.         const = node.as_const(frame.eval_ctx)
  52.  
  53.         if not has_safe_repr(const):
  54.             raise nodes.Impossible()
  55.  
  56.         if isinstance(node, nodes.TemplateData):
  57.             return const
  58.  
  59.         return finalize.const(const)
  60.  
  61.     def _output_child_pre(self, node, frame, finalize):
  62.         if finalize.src is not None:
  63.             self.write(finalize.src)
  64.  
  65.     def _output_child_post(self, node, frame, finalize):
  66.         if finalize.src is not None:
  67.             self.write(")")
  68.  
  69.  
  70. class NativeEnvironment(Environment):
  71.     """An environment that renders templates to native Python types."""
  72.  
  73.     code_generator_class = NativeCodeGenerator
  74.  
  75.  
  76. class NativeTemplate(Template):
  77.     environment_class = NativeEnvironment
  78.  
  79.     def render(self, *args, **kwargs):
  80.         """Render the template to produce a native Python type. If the
  81.        result is a single node, its value is returned. Otherwise, the
  82.        nodes are concatenated as strings. If the result can be parsed
  83.        with :func:`ast.literal_eval`, the parsed value is returned.
  84.        Otherwise, the string is returned.
  85.        """
  86.         vars = dict(*args, **kwargs)
  87.  
  88.         try:
  89.             return native_concat(self.root_render_func(self.new_context(vars)))
  90.         except Exception:
  91.             return self.environment.handle_exception()
  92.  
  93.  
  94. NativeEnvironment.template_class = NativeTemplate

Paste-bin is for source code and general debugging text.

Login or Register to edit, delete and keep track of your pastes and more.

Raw Paste

Login or Register to edit or fork this paste. It's free.