You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
192 lines
6.3 KiB
192 lines
6.3 KiB
4 months ago
|
#!/usr/bin/env python2.7
|
||
|
# 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 imp
|
||
|
import os
|
||
|
import cPickle as pickle
|
||
|
import shutil
|
||
|
import sys
|
||
|
|
||
|
from mako.lookup import TemplateLookup
|
||
|
from mako.runtime import Context
|
||
|
from mako.template import Template
|
||
|
import bunch
|
||
|
import yaml
|
||
|
|
||
|
|
||
|
# Imports a plugin
|
||
|
def import_plugin(name):
|
||
|
_, base_ex = os.path.split(name)
|
||
|
base, _ = os.path.splitext(base_ex)
|
||
|
|
||
|
with open(name, 'r') as plugin_file:
|
||
|
plugin_code = plugin_file.read()
|
||
|
plugin_module = imp.new_module(base)
|
||
|
exec plugin_code in plugin_module.__dict__
|
||
|
return plugin_module
|
||
|
|
||
|
|
||
|
def out(msg):
|
||
|
print >> sys.stderr, msg
|
||
|
|
||
|
|
||
|
def showhelp():
|
||
|
out('mako-renderer.py [-o out] [-m cache] [-P preprocessed_input] [-d dict] [-d dict...]'
|
||
|
' [-t template] [-w preprocessed_output]')
|
||
|
|
||
|
|
||
|
def main(argv):
|
||
|
got_input = False
|
||
|
module_directory = None
|
||
|
preprocessed_output = None
|
||
|
dictionary = {}
|
||
|
json_dict = {}
|
||
|
got_output = False
|
||
|
plugins = []
|
||
|
output_name = None
|
||
|
got_preprocessed_input = False
|
||
|
output_merged = None
|
||
|
|
||
|
try:
|
||
|
opts, args = getopt.getopt(argv, 'hM:m:d:o:p:t:P:w:')
|
||
|
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 == {}
|
||
|
sys.path.insert(0,
|
||
|
os.path.abspath(
|
||
|
os.path.join(
|
||
|
os.path.dirname(sys.argv[0]), 'plugins')))
|
||
|
with open(arg, 'r') as dict_file:
|
||
|
dictionary = pickle.load(dict_file)
|
||
|
got_preprocessed_input = True
|
||
|
elif opt == '-d':
|
||
|
assert not got_preprocessed_input
|
||
|
with open(arg, 'r') as dict_file:
|
||
|
bunch.merge_json(json_dict, yaml.load(dict_file.read()))
|
||
|
elif opt == '-p':
|
||
|
plugins.append(import_plugin(arg))
|
||
|
elif opt == '-w':
|
||
|
preprocessed_output = arg
|
||
|
|
||
|
if not got_preprocessed_input:
|
||
|
for plugin in plugins:
|
||
|
plugin.mako_plugin(json_dict)
|
||
|
if output_merged:
|
||
|
with open(output_merged, 'w') as yaml_file:
|
||
|
yaml_file.write(yaml.dump(json_dict))
|
||
|
for k, v in json_dict.items():
|
||
|
dictionary[k] = bunch.to_bunch(v)
|
||
|
|
||
|
if preprocessed_output:
|
||
|
with open(preprocessed_output, 'w') as dict_file:
|
||
|
pickle.dump(dictionary, dict_file)
|
||
|
|
||
|
cleared_dir = False
|
||
|
for arg in args:
|
||
|
got_input = True
|
||
|
with open(arg) as f:
|
||
|
srcs = list(yaml.load_all(f.read()))
|
||
|
for src in srcs:
|
||
|
if isinstance(src, basestring):
|
||
|
assert len(srcs) == 1
|
||
|
template = Template(
|
||
|
src,
|
||
|
filename=arg,
|
||
|
module_directory=module_directory,
|
||
|
lookup=TemplateLookup(directories=['.']))
|
||
|
with open(output_name, 'w') as output_file:
|
||
|
template.render_context(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:
|
||
|
template.render_context(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:])
|