簡単なpythonテンプレートエンジンを共有


pythonテンプレートエンジンも多いですが、新しい構文を作成するのではなくpythonオリジナルを使用してテンプレートを作成したいのですが、python自体のインデントはテンプレートには向いていないのでインデントを削除すればいいのです

#coding:utf-8
__author__="sdm"
__author_email='[email protected]'

__date__ ="$2009-8-25 21:04:13$"

'''
pytpl   php    


'''
import sys
import StringIO
import os.path
import os
#     
_tpl_cache={}
class Pytpl:

    def __init__(self,tpl_path='./'):
        self.tpl_path=tpl_path
        self.data={}
        self.output = StringIO.StringIO()
        pass

    def set(self,name,value):
        '''
              
        '''
        self.data[name]=value;
        pass

    def get(self,name):
        '''
              
        '''
        t={}
        return t.get(name,'')
        pass

    def tpl(self,tplname):
        '''
            
        '''
        f=self.tpl_path+tplname
        if not os.path.exists(f):
            raise Exception('tpl:[%s] is not exists' % f)
        
        mtime=os.stat(f).st_mtime

        if  not _tpl_cache.has_key(f) or  _tpl_cache[f]['time']<mtime:
            src_code=self.__compile__(open(f).read())
            try:
                t=open(f+'.py','w')
                t.write(src_code)
                t.close()
            except:
                pass
            
            py_code=compile(src_code, f+'.py','exec')
            _tpl_cache[f]={'code':py_code,'time':mtime}
            

        else:
            py_code= _tpl_cache[f]['code']
            
        exec(py_code, {'self':self}, self.data)
        return self.output.getvalue()


    def execute(self,code,data,tplname):
        '''
              
        '''
        py_file_name=tplname+'.py'
        f=open(py_file_name,'w')
        f.write(code)
        f.close()
        execfile(py_file_name, {'self':self}, data)

    def __compile__ (self,code):
        '''
            
           <?  
        '''
        tlen=len(code);
        flag_start='<?'
        flag_end='?>'
        #      
        status=0
        i=0
        #    
        pos_end=0
        pos_start=0
        #  
        global indent
        indent=0
        py_code=[]

        def place_t_code(c,t_indent):
            '''
                   
            '''
            global indent
            if(c[0]=='='):
                return (' ' *4*indent) +  'echo ( \'%s\' % ('+c[1:]+'))'
            lines=c.split("
") t=[] for i in lines: indent2=indent tmp=i.strip("
\r") c=tmp[len(tmp)-1:len(tmp)] # if(c=='{'): indent+=1 tmp=tmp[0:len(tmp)-1]+":" elif(c=='}'): indent-=1 tmp=tmp[0:len(tmp)-1] t.append((' ' *4*indent2) +tmp ) return "
".join(t) while 1: if i>=tlen:break c=code[i]; if status==0: # pos_start=code.find(flag_start,pos_end); if(pos_start>-1): s=code[pos_end:pos_start] t_code= 'echo ( '+repr(s)+')' t_code=' '*indent*4 +t_code if s: py_code.append(t_code) i=pos_start last_pos=i # status=1 continue else: # pos_start=tlen t_code='echo ( '+repr(code[pos_end:pos_start])+' ) ' t_code=' '*indent*4 +t_code py_code.append(t_code) break if status==1: # pos_end=code.find(flag_end,i) if(pos_end>-1): # <? t_code=place_t_code(code[pos_start+2:pos_end],indent) # ?> pos_end+=2 py_code.append(t_code) else: # pos_end=tlen # <? t_code=place_t_code(code[pos_start+2:pos_end],indent) py_code.append(t_code) break status=0 i=pos_end pass i+=1 py_code_str="#coding:utf-8
import sys;global echo;echo=self.output.write
" py_code_str+="
".join(py_code) py_code_str=py_code_str.replace("\t", " ") return py_code_str def test(): tpl=Pytpl('./'); tpl.set('title', ' 3') print tpl.tpl('test.html') pass if __name__ == "__main__": test()

test.py

import pytpl
tpl=pytpl.Pytpl('./')
tpl.set('title', 'test title')
print tpl.tpl('test.html')

実行結果

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>test title</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>

small3
11
    
  </body>
</html>

テンプレートhtml

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title><?=title?></title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>

<?
      
def add(a,b){
    if(a+b<10){
        echo('small');
    }
return a+b;
}
echo(add(1,2));
echo("
"); echo(add(10,1)); ?> </body> </html>

---
コンパイルされた中間テンプレート

#coding:utf-8
import sys;global echo;echo=self.output.write
echo ( '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>') echo ( '%s' % (title)) echo ( '</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>

') def add(a,b): if(a+b<10): echo('small'); return a+b; echo(add(1,2)); echo("
"); echo(add(10,1)); echo ( '

</body>
</html>

' )

プロジェクトはすでにgooglecodeに加入しています
http://code.google.com/p/pythontpl/