123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- #!/usr/bin/env python3
- # Copyright 2015 gRPC authors.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- """Simple Mako renderer.
- Just a wrapper around the mako rendering library.
- """
- import getopt
- import glob
- import importlib.util
- import os
- import pickle
- import shutil
- import sys
- from typing import List
- from mako import exceptions
- from mako.lookup import TemplateLookup
- from mako.runtime import Context
- from mako.template import Template
- import yaml
- PROJECT_ROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..",
- "..")
- # TODO(lidiz) find a better way for plugins to reference each other
- sys.path.append(os.path.join(PROJECT_ROOT, 'tools', 'buildgen', 'plugins'))
- def out(msg: str) -> None:
- print(msg, file=sys.stderr)
- def showhelp() -> None:
- out('mako-renderer.py [-o out] [-m cache] [-P preprocessed_input] [-d dict] [-d dict...]'
- ' [-t template] [-w preprocessed_output]')
- def render_template(template: Template, context: Context) -> None:
- """Render the mako template with given context.
- Prints an error template to indicate where and what in the template caused
- the render failure.
- """
- try:
- template.render_context(context)
- except:
- out(exceptions.text_error_template().render())
- raise
- def main(argv: List[str]) -> None:
- got_input = False
- module_directory = None
- preprocessed_output = None
- dictionary = {}
- json_dict = {}
- got_output = False
- output_name = None
- got_preprocessed_input = False
- output_merged = None
- try:
- opts, args = getopt.getopt(argv, 'hM:m:o:t:P:')
- except getopt.GetoptError:
- out('Unknown option')
- showhelp()
- sys.exit(2)
- for opt, arg in opts:
- if opt == '-h':
- out('Displaying showhelp')
- showhelp()
- sys.exit()
- elif opt == '-o':
- if got_output:
- out('Got more than one output')
- showhelp()
- sys.exit(3)
- got_output = True
- output_name = arg
- elif opt == '-m':
- if module_directory is not None:
- out('Got more than one cache directory')
- showhelp()
- sys.exit(4)
- module_directory = arg
- elif opt == '-M':
- if output_merged is not None:
- out('Got more than one output merged path')
- showhelp()
- sys.exit(5)
- output_merged = arg
- elif opt == '-P':
- assert not got_preprocessed_input
- assert json_dict == {}
- with open(arg, 'rb') as dict_file:
- dictionary = pickle.load(dict_file)
- got_preprocessed_input = True
- cleared_dir = False
- for arg in args:
- got_input = True
- with open(arg) as f:
- srcs = list(yaml.load_all(f.read(), Loader=yaml.FullLoader))
- for src in srcs:
- if isinstance(src, str):
- assert len(srcs) == 1
- template = Template(src,
- filename=arg,
- module_directory=module_directory,
- lookup=TemplateLookup(directories=['.']))
- with open(output_name, 'w') as output_file:
- render_template(template, Context(output_file,
- **dictionary))
- else:
- # we have optional control data: this template represents
- # a directory
- if not cleared_dir:
- if not os.path.exists(output_name):
- pass
- elif os.path.isfile(output_name):
- os.unlink(output_name)
- else:
- shutil.rmtree(output_name, ignore_errors=True)
- cleared_dir = True
- items = []
- if 'foreach' in src:
- for el in dictionary[src['foreach']]:
- if 'cond' in src:
- args = dict(dictionary)
- args['selected'] = el
- if not eval(src['cond'], {}, args):
- continue
- items.append(el)
- assert items
- else:
- items = [None]
- for item in items:
- args = dict(dictionary)
- args['selected'] = item
- item_output_name = os.path.join(
- output_name,
- Template(src['output_name']).render(**args))
- if not os.path.exists(os.path.dirname(item_output_name)):
- os.makedirs(os.path.dirname(item_output_name))
- template = Template(
- src['template'],
- filename=arg,
- module_directory=module_directory,
- lookup=TemplateLookup(directories=['.']))
- with open(item_output_name, 'w') as output_file:
- render_template(template, Context(output_file, **args))
- if not got_input and not preprocessed_output:
- out('Got nothing to do')
- showhelp()
- if __name__ == '__main__':
- main(sys.argv[1:])
|