Tips and tricks --------------- This module contains some **mstache** integration tips alongside general Mustache syntax tricks which can be useful for other implementations too (as long they're spec compliant). Lambda examples =============== Lambda functions are not always straightforward, especially when requiring context data, as they're unable to directly access the current scope. The standard solution is using the render function, usually multiple times, to retrieve the required data from context, as string, and then performing some parsing. Datetime strformat ~~~~~~~~~~~~~~~~~~ In this example we implement the common-case-scenario of formatting a :py:class:`datetime.datetime` object using a lambda forwarding the custom format to :py:meth:`datetime.datetime.strftime`. .. code:: python import datetime import typing import mstache def strftime(text: str, render: collections.abc.Callable[[str], str]) -> str: """Render date/datetime scope with given strftime format.""" iso = render('{{.}}').replace(' ', 'T') # __str__ is stable try: dt = ( datetime.datetime.fromisoformat(iso) if 'T' in iso else datetime.date.fromisoformat(iso) ) except ValueError: return '' return dt.strftime(render(text)) print(mstache.render( '{{#dt}}{{#strftime}}%Y.%m.%d{{/strftime}}{{/dt}}', { 'dt': datetime.datetime.now(), 'strftime': strftime, }, )) # 2021.03.25 Streaming patterns ================== Streaming is a first-class citizen for **mstache**, enabling powerful patterns which are not only memory-efficient but more responsive than their buffered counterparts, especially over networks. You can easily integrate :py:func:`mstache.stream` on most common scenarios with just a tiny bit of preprocessing, here are some examples. JSON streaming ~~~~~~~~~~~~~~ In this example we stream enveloped JSON by preprocessing that envelope as our template and then serializing every generator item individually (using :py:func:`enumerate` to enable comma insertion logic) while rendering. .. code:: python import json import mstache # Given any row generator (like a database row cursor) rows = ( (i, 'a', 'b', 'c') for i in range(1000, 10000) ) # Streaming JSON template render stream = mstache.stream(template, '{"results": [{{#rows}}{{&.}}{{/rows}}]}', # enveloped JSON template { 'rows': ( # generator of partial JSON strings f',{json.dumps(row)}' if i else json.dumps(row) for i, row in enumerate(rows) ), }, ) for chunk in stream: print(chunk) # {"results": [ # [1000, "a", "b", "c"] # ,[1001, "a", "b", "c"] # ... # ,[9999, "a", "b", "c"] # ]}