"Yet Another Python Templating Utility, Version 1.2"
import sys
# utility stuff to avoid tests in the mainline code
class _nevermatch:
"Polymorphic with a regex that never matches"
def match(self, line):
return None
_never = _nevermatch() # one reusable instance of it suffices
def identity(string, why):
"A do-nothing-special-to-the-input, just-return-it function"
return string
def nohandle(string):
"A do-nothing handler that just re-raises the exception"
raise
# and now the real thing
class copier:
"Smart-copier (YAPTU) class"
def copyblock(self, i=0, last=None):
"Main copy method: process lines [i,last) of block"
def repl(match, self=self):
"return the eval of a found expression, for replacement"
# uncomment for debug: print '!!! replacing',match.group(1)
expr = self.preproc(match.group(1), 'eval')
try: return str(eval(expr, self.globals, self.locals))
except: return str(self.handle(expr))
block = self.locals['_bl']
if last is None: last = len(block)
while i Executing: {"+stat+"}"
exec stat in self.globals,self.locals
i=j+1
else: # normal line, just copy with substitution
self.ouf.write(self.regex.sub(repl,line))
i=i+1
def __init__(self, regex=_never, dict={},
restat=_never, restend=_never, recont=_never,
preproc=identity, handle=nohandle, ouf=sys.stdout):
"Initialize self's attributes"
self.regex = regex
self.globals = dict
self.locals = { '_cb':self.copyblock }
self.restat = restat
self.restend = restend
self.recont = recont
self.preproc = preproc
self.handle = handle
self.ouf = ouf
def copy(self, block=None, inf=sys.stdin):
"Entry point: copy-with-processing a file, or a block of lines"
if block is None: block = inf.readlines()
self.locals['_bl'] = block
self.copyblock()
if __name__=='__main__':
"Test: copy a block of lines, with full processing"
import re
rex=re.compile('@([^@]+)@')
rbe=re.compile('\+')
ren=re.compile('-')
rco=re.compile('= ')
x=23 # just a variable to try substitution
cop = copier(rex, globals(), rbe, ren, rco)
lines_block = [line+'\n' for line in """
A first, plain line -- it just gets copied.
A second line, with @x@ substitutions.
+ x+=1 # non-block statements MUST end with comments
-
Now the substitutions are @x@.
+ if x>23:
After all, @x@ is rather large!
= else:
After all, @x@ is rather small!
-
+ for i in range(3):
Also, @i@ times @x@ is @i*x@.
-
One last, plain line at the end.""".split('\n')]
print "*** input:"
print ''.join(lines_block)
print "*** output:"
cop.copy(lines_block)