rudimentaere templating engine

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

rudimentaere templating engine

Beitragvon Costi » Donnerstag 8. November 2007, 19:29

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

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder