| #!/usr/bin/env python |
| # Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import argparse |
| import copy |
| import cStringIO |
| import os |
| import re |
| import sys |
| |
| |
| STATEMENT_RE = "\[\[(.*?)\]\]" # [[...]] |
| EXPR_RE = "\{\{(.*?)\}\}" # {{...}} |
| |
| def TemplateToPython(template, statement_re, expr_re): |
| output = cStringIO.StringIO() |
| indent_re = re.compile(r'\s*') |
| indent_string = '' |
| for line in template.splitlines(1): # 1 => keep line ends |
| m = statement_re.match(line) |
| if m: |
| statement = m.group(1) |
| indent_string = indent_re.match(statement).group() |
| if statement.rstrip()[-1:] == ':': |
| indent_string += ' ' |
| output.write(statement + '\n') |
| else: |
| line_ending = '' |
| while line and line[-1] in '\\"\n\r': |
| line_ending = line[-1] + line_ending |
| line = line[:-1] |
| |
| ms = list(expr_re.finditer(line)) |
| if ms: |
| # Only replace % with %% outside of the expr matches. |
| new_line = '' |
| start = 0 |
| for m in ms: |
| new_line += line[start:m.start()].replace('%', '%%') |
| new_line += line[m.start():m.end()] |
| start = m.end() |
| new_line += line[start:].replace('%', '%%') |
| line = new_line |
| |
| subst_line = r'r"""%s""" %% (%s,)' % ( |
| re.sub(expr_re, '%s', line), |
| ', '.join(re.findall(expr_re, line))) |
| else: |
| subst_line = r'r"""%s"""' % line |
| |
| out_string = r'%s__outfile__.write(%s + %s)' % ( |
| indent_string, |
| subst_line, |
| repr(line_ending)) |
| output.write(out_string + '\n') |
| |
| return output.getvalue() |
| |
| |
| def RunTemplate(srcfile, dstfile, template_dict, statement_re=None, |
| expr_re=None): |
| statement_re = statement_re or re.compile(STATEMENT_RE) |
| expr_re = expr_re or re.compile(EXPR_RE) |
| script = TemplateToPython(srcfile.read(), statement_re, expr_re) |
| template_dict = copy.copy(template_dict) |
| template_dict['__outfile__'] = dstfile |
| exec script in template_dict |
| |
| |
| def RunTemplateFile(srcpath, dstpath, template_dict, statement_re=None, |
| expr_re=None): |
| with open(srcpath) as srcfile: |
| with open(dstpath, 'w') as dstfile: |
| RunTemplate(srcfile, dstfile, template_dict, statement_re, expr_re) |
| |
| |
| def RunTemplateFileIfChanged(srcpath, dstpath, replace): |
| dststr = cStringIO.StringIO() |
| with open(srcpath) as srcfile: |
| RunTemplate(srcfile, dststr, replace) |
| |
| if os.path.exists(dstpath): |
| with open(dstpath) as dstfile: |
| if dstfile.read() == dststr.getvalue(): |
| return |
| |
| with open(dstpath, 'w') as dstfile: |
| dstfile.write(dststr.getvalue()) |
| |
| |
| def RunTemplateString(src, template_dict, statement_re=None, expr_re=None): |
| srcstr = cStringIO.StringIO(src) |
| dststr = cStringIO.StringIO() |
| RunTemplate(srcstr, dststr, template_dict, statement_re, expr_re) |
| return dststr.getvalue() |
| |
| |
| def main(args): |
| parser = argparse.ArgumentParser() |
| parser.add_argument('template') |
| options = parser.parse_args(args) |
| |
| with open(options.template) as f: |
| print TemplateToPython( |
| f.read(), re.compile(STATEMENT_RE), re.compile(EXPR_RE)) |
| |
| if __name__ == '__main__': |
| sys.exit(main(sys.argv[1:])) |