还没有完善的Python模板引擎
暂时还没有完善,仅做记录
1 # coding:gb2312 2 3 s = """ 4 <?for a in range(5)> 5 <?for b in range(2)> 6 abcd 7 <for?> 8 ---------------------------- 9 <for?> 10 11 """ 12 13 14 class TemplateException(Exception): 15 def __init__(self, message, contents, line, innerException = None): 16 Exception.__init__(self, "{0} \n\t lien:{1} \n\t content: {2}".format(message, line, contents[line])) 17 self.innerException = innerException 18 self.contents = contents 19 self.line = line 20 self.msg = message 21 22 import re 23 24 class TagRender(object): 25 def __init__(self): 26 pass 27 28 def render(self, tag): 29 pass 30 31 class ForTagRender(TagRender): 32 def render(self, tag): 33 partten = re.compile("\\s*(?P<var>\\S+)\\s+(?:in)\\s+(?P<values>.+)") 34 match = partten.match(tag["exp"]) 35 36 if match: 37 var = match.groupdict()["var"] 38 values = match.groupdict()["values"] 39 expression = "[tag['innerTemplate'].render() for {0} in {1}]".format(var, values) 40 results = eval(expression) 41 #results = eval(exp) 42 else: 43 raise Exception("error....") 44 return "\n".join(results) 45 46 class Template(object): 47 __tagsrender__ = {} 48 @staticmethod 49 def reg_tag(name, tagrender): 50 if Template.__tagsrender__.has_key(name): 51 raise Exception("Template tag process {0} has existed.".format(name)) 52 else: 53 Template.__tagsrender__.setdefault(name, tagrender); 54 55 def match(self, text): 56 return re.compile("^(?:\\s*)<\\?(?P<tag>\\S+)(?P<exp>.*)(?P<end>\\??>)(?:\\s*)$").match(text) 57 58 def single_match(self, text): 59 return re.compile("^(?:\\s*)<\\?(?P<tag>\\S+)(?P<exp>.*)(?P<end>\\?>)(?:\\s*)$").match(text) 60 61 def end_match(self, text): 62 return re.compile("^(?:\\s*)<(?P<tag>\\S+)\\?>(?:\\s*)$").match(text) 63 64 def get_render(self): 65 if self.__render__ is not None: 66 return self.__render__ 67 68 def render(self): 69 tags = self.__tags[0:] 70 tags.reverse() 71 results = [] 72 contents = self.__content.splitlines() 73 index = 0 74 while tags: 75 tag = tags.pop() 76 results.extend(contents[index:tag["start"]]) 77 tagrender = Template.__tagsrender__.get(tag["tag"], None) 78 if not tagrender: 79 raise Exception("unknow tag...") 80 subtext = tagrender.render(tag) 81 if subtext != None: 82 results.append(subtext) 83 index = tag["end"] + 1 84 results.extend(contents[index:]) 85 return "\n".join(results) 86 def __init__(self, content, p_line = 0): 87 self.__content = content 88 self.__tags = tags = [] 89 _contents = content.splitlines() 90 tagsstack = [] 91 depth = 0 92 for i in range(len(_contents)): 93 text = _contents[i] 94 if Template.match(self, text): 95 # match start 96 depth += 1 97 if not Template.single_match(self, text): 98 tagsstack.append(Template.match(self, text).groupdict()["tag"]) 99 if depth == 1: 100 tag = { 101 "tag": Template.match(self, text).groupdict()["tag"], 102 "exp": Template.match(self, text).groupdict()["exp"], 103 "content": None, 104 "innerTemplate": None, 105 "start": i, 106 "end": -1 107 } 108 tags.append(tag) 109 if Template.single_match(self, text): 110 tag["exp"] = Template.single_match(self, text).groupdict()["exp"] 111 tag["end"] = i 112 tag["content"] = text 113 depth -= 1 114 else: 115 if Template.single_match(self, text): 116 depth -= 1 117 elif Template.end_match(self, text): 118 # match end 119 depth -= 1 120 tagName = Template.end_match(self, text).groupdict()["tag"] 121 if tagsstack.pop() != tagName: 122 raise TemplateException("Close tag name is not match.",_contents, i ) 123 if depth == 0: 124 tags[-1]["end"] = i 125 tags[-1]["content"] = "\n".join(_contents[tags[-1]["start"]:i+1]) 126 try: 127 innerContent = "\n".join(_contents[tags[-1]["start"]+1:i]) 128 tags[-1]["innerTemplate"] = Template(innerContent, tags[-1]["start"]) 129 except TemplateException, e: 130 raise TemplateException(e.msg, _contents, e.line + tags[-1]["start"] + 1, e) 131 elif depth > 0: 132 pass 133 else: #depth < 0 134 raise TemplateException("There some tags doesn't close.", _contents, i) 135 136 Template.reg_tag("for", ForTagRender()) 137 t = Template(s) 138 print t.render() 139 raw_input("Enter To Exit")