1#!/usr/bin/env python 2# Copyright (c) 2013 The Chromium Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6import copy 7import cStringIO 8import optparse 9import os 10import re 11import sys 12 13 14STATEMENT_RE = "\[\[(.*?)\]\]" # [[...]] 15EXPR_RE = "\{\{(.*?)\}\}" # {{...}} 16 17def TemplateToPython(template, statement_re, expr_re): 18 output = cStringIO.StringIO() 19 indent_re = re.compile(r'\s*') 20 indent_string = '' 21 for line in template.splitlines(1): # 1 => keep line ends 22 m = statement_re.match(line) 23 if m: 24 statement = m.group(1) 25 indent_string = indent_re.match(statement).group() 26 if statement.rstrip()[-1:] == ':': 27 indent_string += ' ' 28 output.write(statement + '\n') 29 else: 30 line_ending = '' 31 while line and line[-1] in '\\"\n\r': 32 line_ending = line[-1] + line_ending 33 line = line[:-1] 34 35 ms = list(expr_re.finditer(line)) 36 if ms: 37 # Only replace % with %% outside of the expr matches. 38 new_line = '' 39 start = 0 40 for m in ms: 41 new_line += line[start:m.start()].replace('%', '%%') 42 new_line += line[m.start():m.end()] 43 start = m.end() 44 new_line += line[start:].replace('%', '%%') 45 line = new_line 46 47 subst_line = r'r"""%s""" %% (%s,)' % ( 48 re.sub(expr_re, '%s', line), 49 ', '.join(re.findall(expr_re, line))) 50 else: 51 subst_line = r'r"""%s"""' % line 52 53 out_string = r'%s__outfile__.write(%s + %s)' % ( 54 indent_string, 55 subst_line, 56 repr(line_ending)) 57 output.write(out_string + '\n') 58 59 return output.getvalue() 60 61 62def RunTemplate(srcfile, dstfile, template_dict, statement_re=None, 63 expr_re=None): 64 statement_re = statement_re or re.compile(STATEMENT_RE) 65 expr_re = expr_re or re.compile(EXPR_RE) 66 script = TemplateToPython(srcfile.read(), statement_re, expr_re) 67 template_dict = copy.copy(template_dict) 68 template_dict['__outfile__'] = dstfile 69 exec script in template_dict 70 71 72def RunTemplateFile(srcpath, dstpath, template_dict, statement_re=None, 73 expr_re=None): 74 with open(srcpath) as srcfile: 75 with open(dstpath, 'w') as dstfile: 76 RunTemplate(srcfile, dstfile, template_dict, statement_re, expr_re) 77 78 79def RunTemplateFileIfChanged(srcpath, dstpath, replace): 80 dststr = cStringIO.StringIO() 81 with open(srcpath) as srcfile: 82 RunTemplate(srcfile, dststr, replace) 83 84 if os.path.exists(dstpath): 85 with open(dstpath) as dstfile: 86 if dstfile.read() == dststr.getvalue(): 87 return 88 89 with open(dstpath, 'w') as dstfile: 90 dstfile.write(dststr.getvalue()) 91 92 93def RunTemplateString(src, template_dict, statement_re=None, expr_re=None): 94 srcstr = cStringIO.StringIO(src) 95 dststr = cStringIO.StringIO() 96 RunTemplate(srcstr, dststr, template_dict, statement_re, expr_re) 97 return dststr.getvalue() 98 99 100def main(args): 101 parser = optparse.OptionParser() 102 _, args = parser.parse_args(args) 103 if not args: 104 return 105 106 with open(args[0]) as f: 107 print TemplateToPython( 108 f.read(), re.compile(STATEMENT_RE), re.compile(EXPR_RE)) 109 110if __name__ == '__main__': 111 sys.exit(main(sys.argv[1:])) 112