ext_mustache.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. """
  2. The Mustache Extension provides output templating based on the
  3. `Mustache Templating Language <http://mustache.github.com>`_.
  4. Requirements
  5. ------------
  6. * pystache (``pip install pystache``)
  7. Configuration
  8. -------------
  9. To **prepend** a directory to the ``template_dirs`` list defined by the
  10. application/developer, an end-user can add the configuration option
  11. ``template_dir`` to their application configuration file under the main
  12. config section:
  13. .. code-block:: text
  14. [myapp]
  15. template_dir = /path/to/my/templates
  16. Usage
  17. -----
  18. .. code-block:: python
  19. from cement.core import foundation
  20. class MyApp(foundation.CementApp):
  21. class Meta:
  22. label = 'myapp'
  23. extensions = ['mustache']
  24. output_handler = 'mustache'
  25. template_module = 'myapp.templates'
  26. template_dirs = [
  27. '~/.myapp/templates',
  28. '/usr/lib/myapp/templates',
  29. ]
  30. # ...
  31. Note that the above ``template_module`` and ``template_dirs`` are the
  32. auto-defined defaults but are added here for clarity. From here, you
  33. would then put a Mustache template file in
  34. ``myapp/templates/my_template.mustache`` or
  35. ``/usr/lib/myapp/templates/my_template.mustache`` and then render a data
  36. dictionary with it:
  37. .. code-block:: python
  38. app.render(some_data_dict, 'my_template.mustache')
  39. Loading Partials
  40. ----------------
  41. Mustache supports ``partials``, or in other words template ``includes``.
  42. These are also loaded by the output handler, but require a full file name.
  43. The partials will be loaded in the same way as the base templates
  44. For example:
  45. **templates/base.mustache**
  46. .. code-block:: console
  47. Inside base.mustache
  48. {{> partial.mustache}}
  49. **template/partial.mustache**
  50. .. code-block:: console
  51. Inside partial.mustache
  52. Would output:
  53. .. code-block:: console
  54. Inside base.mustache
  55. Inside partial.mustache
  56. """
  57. import sys
  58. from pystache.renderer import Renderer
  59. from ..core import output, exc
  60. from ..utils.misc import minimal_logger
  61. LOG = minimal_logger(__name__)
  62. class PartialsLoader(object):
  63. def __init__(self, handler):
  64. self.handler = handler
  65. def get(self, template):
  66. stache = Renderer()
  67. return self.handler.load_template(template)
  68. class MustacheOutputHandler(output.TemplateOutputHandler):
  69. """
  70. This class implements the :ref:`IOutput <cement.core.output>`
  71. interface. It provides text output from template and uses the
  72. `Mustache Templating Language <http://mustache.github.com>`_. Please
  73. see the developer documentation on
  74. :ref:`Output Handling <dev_output_handling>`.
  75. **Note** This extension has an external dependency on ``pystache``. You
  76. must include ``pystache`` in your applications dependencies as Cement
  77. explicitly does **not** include external dependencies for optional
  78. extensions.
  79. """
  80. class Meta:
  81. """Handler meta-data."""
  82. interface = output.IOutput
  83. label = 'mustache'
  84. #: Whether or not to include ``mustache`` as an available to choice
  85. #: to override the ``output_handler`` via command line options.
  86. overridable = False
  87. def __init__(self, *args, **kw):
  88. super(MustacheOutputHandler, self).__init__(*args, **kw)
  89. self._partials_loader = PartialsLoader(self)
  90. def render(self, data_dict, **kw):
  91. """
  92. Take a data dictionary and render it using the given template file.
  93. Required Arguments:
  94. :param data_dict: The data dictionary to render.
  95. :keyword template: The path to the template, after the
  96. ``template_module`` or ``template_dirs`` prefix as defined in the
  97. application.
  98. :returns: str (the rendered template text)
  99. """
  100. template = kw.get('template', None)
  101. LOG.debug("rendering output using '%s' as a template." % template)
  102. content = self.load_template(template)
  103. stache = Renderer(partials=self._partials_loader)
  104. return stache.render(content, data_dict)
  105. def load(app):
  106. app.handler.register(MustacheOutputHandler)