Python micro-templating, similar to John Resig's implementation.
        Underscore templating handles arbitrary delimiters, preserves
        whitespace, and correctly escapes quotes within interpolated code.

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