docs: def template(self, data=None, settings=None):
          """
          Python micro-templating, similar to John Resig's implementation.
          Underscore templating handles arbitrary delimiters, preserves
          whitespace, and correctly escapes quotes within interpolated code.
          """
          if settings is None:
              settings = {}
          ts = _.templateSettings
          _.defaults(ts, self.templateSettings)
          _.extend(settings, ts)
  
          # settings = {
          #     "interpolate": self.templateSettings.get('interpolate'),
          #     "evaluate": self.templateSettings.get('evaluate'),
          #     "escape": self.templateSettings.get('escape')
          # }
  
          _.extend(settings, {
              "escaper": r"\\|'|\r|\n|\t|\u2028|\u2029",
              "unescaper": r"\\(\\|'|r|n|t|u2028|u2029)"
          })
  
          src = self.obj
          #src = re.sub('"', r'\"', src)
          #src = re.sub(r'\\', r"\\", src)
          ns = self.Namespace()
          ns.indent_level = 1
  
          def unescape(code):
              def unescapes(matchobj):
                  a = re.sub("^[\'\"]|[\'\"]$", "", ("%r" % matchobj.group(1)))
                  # Python doesn't accept \n as a key
                  if a == '\n':
                      a = "bn"
                  if a == '\r':
                      a = "br"
                  if a == '\t':
                      a = "bt"
                  if a == '\u2028':
                      a = 'bu2028'
                  if a == '\u2029':
                      a = 'bu2029'
                  return self.escapes[a]
              return re.sub(settings.get('unescaper'), unescapes, code)
  
          def escapes(matchobj):
              a = matchobj.group(0)
              # Python doesn't accept \n as a key
              if a == '\n':
                  a = "bn"
              if a == '\r':
                  a = "br"
              if a == '\t':
                  a = "bt"
              if a == '\u2028':
                  a = 'bu2028'
              if a == '\u2029':
                  a = 'bu2029'
              return '\\' + self.escapes[a]
  
          def indent(n=None):
              if n is not None:
                  ns.indent_level += n
              return "  " * ns.indent_level
  
          def interpolate(matchobj):
              if getattr(str, 'decode', False):
                  key = (matchobj.group(1).decode('string-escape')).strip()
              else:
                  key = (bytes(matchobj.group(1), "utf-8").decode()).strip()
              return "' + str(" + unescape(key) + " or '') + '"
  
          def evaluate(matchobj):
              if getattr(str, 'decode', False):
                  code = (matchobj.group(1).decode('string-escape')).strip()
              else:
                  code = (bytes(matchobj.group(1), "utf-8").decode()).strip()
              if code.startswith("end"):
                  return "')\n" + indent(-1) + "ns.__p += ('"
              elif code.endswith(':'):
                  return "')\n" + indent() + unescape(code) + \
                         "\n" + indent(+1) + "ns.__p += ('"
              else:
                  return "')\n" + indent() + unescape(code) + \
                         "\n" + indent() + "ns.__p += ('"
  
          def escape(matchobj):
              if getattr(str, 'decode', False):
                  key = (matchobj.group(1).decode('string-escape')).strip()
              else:
                  key = (bytes(matchobj.group(1), "utf-8").decode()).strip()
              return "' + _.escape(str(" + unescape(key) + " or '')) + '"
  
          source = indent() + 'class closure(object):\n    pass' + \
                              ' # for full closure support\n'
          source += indent() + 'ns = closure()\n'
          source += indent() + "ns.__p = ''\n"
          #src = re.sub("^[\'\"]|[\'\"]$", "", ("%r" % src))
          src = re.sub(settings.get("escaper"), escapes, src)
          source += indent() + "ns.__p += ('" + \
              re.sub(settings.get('escape'), escape, src) + "')\n"
          source = re.sub(settings.get('interpolate'), interpolate, source)
          source = re.sub(settings.get('evaluate'), evaluate, source)
  
          if getattr(str, 'decode', False):
              source += indent() + 'return ns.__p.decode("string_escape")\n'
          else:
              source += indent() + 'return bytes(ns.__p, "utf-8").decode()\n'
  
          f = self.create_function(settings.get("variable")
                                   or "obj=None", source)
  
          if data is not None:
              return f(data)
          return f