def macro(self, ident, block, args=None): code = Code() if args: proto = ("arg%d=None" % n for n in range(len(args))) params = ("%r: arg%d" % (arg, n) for n, arg in enumerate(args)) code.write( "def block(%s, extra=None):" % ", ".join(proto), code.indent, "params = { %s }" % ", ".join(params), "params.update(extra or {})") else: code.write( "def block(params=None):", code.indent, "params = params or {}") code.write( "output = Buffer()", "stash = context.localise(params)", "try:", code.indent, block, code.unindent, "finally:", " stash = context.delocalise()", "return output.get()") code.write(code.unindent, "stash.set(%r, block)" % str(ident)) return code.text()
def try_(self, block, catches): # [% TRY %] ... [% CATCH %] ... [% END %] handlers = [] final = catches.pop() default = None catchblock = Code() n = 0 for catch in catches: if catch[0]: match = catch[0] else: if default is None: default = catch[1] continue mblock = catch[1] handlers.append("'%s'" % match) catchblock.write((n == 0 and "if" or "elif") + " handler == '%s':" % match) n += 1 catchblock.write(catchblock.indent, mblock, catchblock.unindent) catchblock.write("error = 0") if default: default = Code.format("else:", Code.indent, default, "error = ''") else: default = "# NO DEFAULT" handlers = "[%s]" % ", ".join(handlers) return Code.format( "def block():", Code.indent, "output = Buffer()", "error = None", "try:", Code.indent, block, Code.unindent, "except Exception, e:", Code.indent, "error = context.catch(e, output)", "if error.type() in ('return', 'stop'):", " raise error", "stash.set('error', error)", "stash.set('e', error)", "handler = error.select_handler(%s)" % handlers, "if handler:", Code.indent, catchblock.text(), Code.unindent, default, Code.unindent, final, "if error:", " raise error", "return output.get()", Code.unindent, "output.write(block())")
def switch(self, expr, cases): # [% SWITCH %] [% CASE foo %] ... [% END %] code = Code() code.write("def block():", code.indent, "result = Regex(str(%s) + '$')" % expr) default = cases.pop() for match, block in cases: code.write("for match in Switch(%s):" % match, code.indent, "if result.match(str(match)):", code.indent, block, "return", code.unindent, code.unindent) if default is not None: code.write(default) code.write(code.unindent, "block()") return code.text()
def if_(self, expr, block, else_=None): # [% IF foo < bar %] ... [% ELSE %] ... [% END %] if else_: elses = else_[:] else: elses = [] if elses: else_ = elses.pop() else: else_ = None code = Code() code.write("if %s:" % expr, code.indent, block) for expr, block in elses: code.write(code.unindent, "elif %s:" % expr, code.indent, block) if else_ is not None: code.write(code.unindent, "else:", code.indent, else_) return code.text()