blob: acd72bd2e331df0ec8c10475a50fe289cf9be421 [file] [log] [blame]
Nathaniel Manistaae4fbcd2015-09-23 16:29:44 +00001#!/usr/bin/env python2.7
Jan Tattermusch7897ae92017-06-07 22:57:36 +02002# Copyright 2015 gRPC authors.
Craig Tillerc2c79212015-02-16 12:00:01 -08003#
Jan Tattermusch7897ae92017-06-07 22:57:36 +02004# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
Craig Tillerc2c79212015-02-16 12:00:01 -08007#
Jan Tattermusch7897ae92017-06-07 22:57:36 +02008# http://www.apache.org/licenses/LICENSE-2.0
Craig Tillerc2c79212015-02-16 12:00:01 -08009#
Jan Tattermusch7897ae92017-06-07 22:57:36 +020010# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
Nicolas Nobleddef2462015-01-06 18:08:25 -080015"""Simple Mako renderer.
16
17Just a wrapper around the mako rendering library.
18
19"""
20
21import getopt
22import imp
23import os
Craig Tiller560c9012016-02-24 16:34:38 -080024import cPickle as pickle
Craig Tiller1ebb7c82015-08-31 15:53:36 -070025import shutil
Nicolas Nobleddef2462015-01-06 18:08:25 -080026import sys
27
Nicolas Nobleddef2462015-01-06 18:08:25 -080028from mako.lookup import TemplateLookup
29from mako.runtime import Context
30from mako.template import Template
Nicolas Nobleddef2462015-01-06 18:08:25 -080031import bunch
Craig Tiller1ebb7c82015-08-31 15:53:36 -070032import yaml
Nicolas Nobleddef2462015-01-06 18:08:25 -080033
34
35# Imports a plugin
36def import_plugin(name):
ncteisen26d70b12017-12-11 16:40:56 -080037 _, base_ex = os.path.split(name)
38 base, _ = os.path.splitext(base_ex)
Nicolas Nobleddef2462015-01-06 18:08:25 -080039
ncteisen26d70b12017-12-11 16:40:56 -080040 with open(name, 'r') as plugin_file:
41 plugin_code = plugin_file.read()
42 plugin_module = imp.new_module(base)
43 exec plugin_code in plugin_module.__dict__
44 return plugin_module
Nicolas Nobleddef2462015-01-06 18:08:25 -080045
46
47def out(msg):
ncteisen26d70b12017-12-11 16:40:56 -080048 print >> sys.stderr, msg
Nicolas Nobleddef2462015-01-06 18:08:25 -080049
50
51def showhelp():
ncteisen26d70b12017-12-11 16:40:56 -080052 out('mako-renderer.py [-o out] [-m cache] [-P preprocessed_input] [-d dict] [-d dict...]'
53 ' [-t template] [-w preprocessed_output]')
Nicolas Nobleddef2462015-01-06 18:08:25 -080054
55
56def main(argv):
ncteisen26d70b12017-12-11 16:40:56 -080057 got_input = False
58 module_directory = None
59 preprocessed_output = None
60 dictionary = {}
61 json_dict = {}
62 got_output = False
63 plugins = []
64 output_name = None
65 got_preprocessed_input = False
66 output_merged = None
Nicolas Nobleddef2462015-01-06 18:08:25 -080067
ncteisen26d70b12017-12-11 16:40:56 -080068 try:
69 opts, args = getopt.getopt(argv, 'hM:m:d:o:p:t:P:w:')
70 except getopt.GetoptError:
71 out('Unknown option')
Nicolas Nobleddef2462015-01-06 18:08:25 -080072 showhelp()
ncteisen26d70b12017-12-11 16:40:56 -080073 sys.exit(2)
74
75 for opt, arg in opts:
76 if opt == '-h':
77 out('Displaying showhelp')
78 showhelp()
79 sys.exit()
80 elif opt == '-o':
81 if got_output:
82 out('Got more than one output')
83 showhelp()
84 sys.exit(3)
85 got_output = True
86 output_name = arg
87 elif opt == '-m':
88 if module_directory is not None:
89 out('Got more than one cache directory')
90 showhelp()
91 sys.exit(4)
92 module_directory = arg
93 elif opt == '-M':
94 if output_merged is not None:
95 out('Got more than one output merged path')
96 showhelp()
97 sys.exit(5)
98 output_merged = arg
99 elif opt == '-P':
100 assert not got_preprocessed_input
101 assert json_dict == {}
Mehrdad Afshari87cd9942018-01-02 14:40:00 -0800102 sys.path.insert(0,
103 os.path.abspath(
104 os.path.join(
105 os.path.dirname(sys.argv[0]), 'plugins')))
ncteisen26d70b12017-12-11 16:40:56 -0800106 with open(arg, 'r') as dict_file:
107 dictionary = pickle.load(dict_file)
108 got_preprocessed_input = True
109 elif opt == '-d':
110 assert not got_preprocessed_input
111 with open(arg, 'r') as dict_file:
112 bunch.merge_json(json_dict, yaml.load(dict_file.read()))
113 elif opt == '-p':
114 plugins.append(import_plugin(arg))
115 elif opt == '-w':
116 preprocessed_output = arg
117
118 if not got_preprocessed_input:
119 for plugin in plugins:
120 plugin.mako_plugin(json_dict)
121 if output_merged:
122 with open(output_merged, 'w') as yaml_file:
123 yaml_file.write(yaml.dump(json_dict))
124 for k, v in json_dict.items():
125 dictionary[k] = bunch.to_bunch(v)
126
127 if preprocessed_output:
128 with open(preprocessed_output, 'w') as dict_file:
129 pickle.dump(dictionary, dict_file)
130
131 cleared_dir = False
132 for arg in args:
133 got_input = True
134 with open(arg) as f:
135 srcs = list(yaml.load_all(f.read()))
136 for src in srcs:
137 if isinstance(src, basestring):
138 assert len(srcs) == 1
139 template = Template(
140 src,
141 filename=arg,
142 module_directory=module_directory,
143 lookup=TemplateLookup(directories=['.']))
144 with open(output_name, 'w') as output_file:
145 template.render_context(Context(output_file, **dictionary))
146 else:
147 # we have optional control data: this template represents
148 # a directory
149 if not cleared_dir:
150 if not os.path.exists(output_name):
151 pass
152 elif os.path.isfile(output_name):
153 os.unlink(output_name)
154 else:
155 shutil.rmtree(output_name, ignore_errors=True)
156 cleared_dir = True
157 items = []
158 if 'foreach' in src:
159 for el in dictionary[src['foreach']]:
160 if 'cond' in src:
161 args = dict(dictionary)
162 args['selected'] = el
163 if not eval(src['cond'], {}, args):
164 continue
165 items.append(el)
166 assert items
167 else:
168 items = [None]
169 for item in items:
170 args = dict(dictionary)
171 args['selected'] = item
172 item_output_name = os.path.join(
173 output_name,
174 Template(src['output_name']).render(**args))
175 if not os.path.exists(os.path.dirname(item_output_name)):
176 os.makedirs(os.path.dirname(item_output_name))
177 template = Template(
178 src['template'],
179 filename=arg,
180 module_directory=module_directory,
181 lookup=TemplateLookup(directories=['.']))
182 with open(item_output_name, 'w') as output_file:
183 template.render_context(Context(output_file, **args))
184
185 if not got_input and not preprocessed_output:
186 out('Got nothing to do')
Nicolas Nobleddef2462015-01-06 18:08:25 -0800187 showhelp()
Nicolas Nobleddef2462015-01-06 18:08:25 -0800188
Nicolas Nobleddef2462015-01-06 18:08:25 -0800189
Nicolas Nobleddef2462015-01-06 18:08:25 -0800190if __name__ == '__main__':
ncteisen26d70b12017-12-11 16:40:56 -0800191 main(sys.argv[1:])