## ## parse template with recognizing '#endfor', '#endif', and so on. ## ## ex: ## import tenjin ## from tenjin.helpers import * ## from my_template import MyTemplate ## engine = tenjin.Engine(templateclass=MyTemplate) ## print("------------- script") ## print(engine.get_template("file.pyhtml").script) ## print("------------- output") ## print(engine.render("file.pyhtml") ## import re import tenjin class TemplateSyntaxError(Exception): pass def _args2dict(*args): return dict([ (w, w) for w in args ]) START_WORDS = _args2dict('for', 'if', 'while', 'def', 'try:', 'with', 'class') END_WORDS = _args2dict('#endfor', '#endif', '#endwhile', '#enddef', '#endtry', '#endwith', '#endclass') CONT_WORDS = _args2dict('elif', 'else:', 'except', 'except:', 'finally:') class MyTemplate(tenjin.Template): def parse_stmts(self, buf, input): if not input: return rexp = self.stmt_pattern() is_bol = True index = 0 for m in rexp.finditer(input): mspace, code, rspace = m.groups() #mspace, close, rspace = m.groups() #code = input[m.start()+4+len(mspace):m.end()-len(close)-(rspace and len(rspace) or 0)] text = input[index:m.start()] index = m.end() ## detect spaces at beginning of line lspace = None if text == '': if is_bol: lspace = '' elif text[-1] == '\n': lspace = '' else: rindex = text.rfind('\n') if rindex < 0: if is_bol and text.isspace(): lspace = text text = '' else: s = text[rindex+1:] if s.isspace(): lspace = s text = text[:rindex+1] #is_bol = rspace is not None ## add text, spaces, and statement self.parse_exprs(buf, text, is_bol) is_bol = rspace is not None #if lspace: # buf.append(lspace) #if mspace != " ": # #buf.append(mspace) # buf.append(mspace == "\t" and "\t" or "\n") # don't append "\r\n"! if code: code = self.statement_hook(code) self.add_stmt(buf, code) #self._set_spaces(code, lspace, mspace) #if rspace: # #buf.append(rspace) # buf.append("\n") # don't append "\r\n"! rest = input[index:] if rest: self.parse_exprs(buf, rest) def parse_exprs(self, buf, input, is_bol=False): buf2 = [] tenjin.Template.parse_exprs(self, buf2, input, is_bol) if buf2: buf.append(''.join(buf2)) def add_stmt(self, buf, code): if not code: return lines = code.splitlines() if lines[-1][-1] != "\n": lines[-1] = lines[-1] + "\n" buf.extend(lines) def after_convert(self, buf): tenjin.Template.after_convert(self, buf) block = self.parse_lines(buf) buf[:] = [] self._join_block(block, buf, 0) depth = -1 ## ## ex. ## input = r""" ## if items: ## _buf.extend(('
| #{i} | ${item} |
Not found.
"""[1:] expected = r""" _buf.extend((''' \n''', )); if items: _buf.extend(('''| ''', to_str(i), ''' | ''', escape(to_str(item)), ''' |
Not found.
\n''', )); #endif _buf.extend((''' \n''', )); """[1:] # template = MyTemplate() actual = template.convert(input) assert expected == actual #print(actual) #import pprint #pprint.pprint(result) ## if-statement input = r""" 0: ?>Positive.
Negative.
Zero.
"""[1:] expected = r""" for x in nums: if x > 0: _buf.extend(('''Positive.
\n''', )); elif x < 0: _buf.extend(('''Negative.
\n''', )); else: _buf.extend(('''Zero.
\n''', )); #endif #endfor """[1:] actual = template.convert(input) assert expected == actual