rudimentaere templating engine

Code-Stücke können hier veröffentlicht werden.
Antworten
Costi
User
Beiträge: 545
Registriert: Donnerstag 17. August 2006, 14:21

etwas laenger her, das ich das geschrieben habe,vieliecht kann aber nhemand damit was nafangen (beispiel am code-ende):

Code: Alles auswählen

from inspect import getargspec

END = 0
BLOCK = 1
class EasyTmpl(object):
	def __init__(self):
		self.writing_on = 'main'
		self.data = {'main': []}
		self.last_blocks = ['main']

	def feed(self, arg):
		if hasattr(arg, 'next'):
			for i in arg:
				self.feed(i)
		elif isinstance(arg, tuple):
			cmd, bname = arg
			
			if cmd == BLOCK:
				if not bname in self.data:
					self.write('\n\n<!--BLOCK %s-->\n%%(%s)s\n<!--END %s-->\n\n' % (bname, bname, bname))
				self.data[bname] = []
				self.writing_on = bname 
				self.last_blocks.append(bname)

			elif cmd == END:
				if not bname == self.last_blocks[-1]:
					raise ValueError('its not the right time to end the block "%s" e a vez do "%s"' % (bname, self.last_blocks[-1]))
				self.last_blocks.pop()
				self.writing_on = self.last_blocks[-1]
			else:
				assert False
		else:
			return self.write(str(arg))
					
	def write(self, data):
		self.data[self.writing_on].append(data)
	
	def __str__(self):
		# self.new_data is for _str_helper
		self.new_data = {}
		for key in self.data:
			self.new_data[key] = ''.join(self.data[key])
		return self._str_helper(self.new_data['main'])
		#return str(self.blocks)
	
	def _str_helper(self, stri):
		for key in self.new_data:
			if '%%(%s)s' % key in stri:
				stri = stri.replace('%%(%s)s' % key, self._str_helper(self.new_data[key]))
				#stri = stri % {key: self._str_helper(self.new_data[key])} #klapt leider nicht, weil zb 	bei ``<hr value="10%">`` python denkt ``"`` waere son string formating zeugs
		return stri
	
class Renderer(object):
	"""
	>>>def base():
	...	yield '''
	...	head
	...	'''
	...	yield BLOCK, "content"
	...	yield 'haubinhalt'
	...	yield END, 'content'
	...	yield "ende"
	>>>
	>>>def index(user):
	...	yield BLOCK, 'content'
	...	yield 'helo, ' + user
	...	yield END, 'content'
	>>>
	>>>r = Renderer(base, index)
	>>>print r.render(user="test")
	"""
	def __init__(self, *tmpls):
		self.et = EasyTmpl()
		self.tmpls = tmpls
		
	def render(self, **kw):
		for tmpl in self.tmpls:
			args, varargs, varkw, defaults = getargspec(tmpl)
			alreadyused = ()
			if varargs or varkw:
				raise ValueError('sory, the function %s may not get "*" or "**" arguments' % (tmpl.func_name))
				
			kw2use = {}
			for key, value in kw.iteritems():
				if key in args:
					kw2use[key] = value
					alreadyused += (key,)
			print "calling", tmpl, 'with', kw2use
			self.et.feed(tmpl(**kw2use))
		
		if len(kw) - len(alreadyused):
			print('WARNING: Renderer: the arguments %s where not used' % ' '.join(set(kw.keys()) - set(alreadyused)))
			
			self.et.feed(tmpl(**kw2use))
		return str(self.et)
			

class TmplManager(dict):
	def __init__(self):
		dict.__init__(self)
	def render(self, tmplname, **namespace):
		rargs = []
		while True:
			if not tmplname in self:
				raise ValueError("the template %s was not found" % tmplname)
			rargs .insert(0, self[tmplname])
			tmpl = self[tmplname].extends
			if tmpl != None:
				tmplname = tmpl
			else:
				break
		return Renderer(*rargs).render(**namespace)
tmpl_manager = TmplManager()

def render(tmplname, **namespace):
	return tmpl_manager.render(tmplname, **namespace)

def register(extends=None):
	def tmp(func):
		func.extends = extends
		tmpl_manager[func.__name__] = func
		return func
	return tmp


if __name__ == "__main__":
	@register(extends="base")
	def index(user):
		yield BLOCK, 'content'
		yield 'helo, ' + user
		yield END, 'content'

	@register()
	def base():
		yield '''
		head
		'''
		yield BLOCK, "content"
		yield 'haubinhalt'
		yield END, 'content'
		yield "ende"
	
	
	print render('index', user='test')
	#import cProfile
	#cProfile.run("render('index', user='test')")

cp != mv
Antworten