3 # Copyright 2014 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
7 """Renders one or more template files using the Jinja template engine."""
14 from util
import build_utils
16 # Import jinja2 from third_party/jinja2
17 sys
.path
.append(os
.path
.join(os
.path
.dirname(__file__
), '../../../third_party'))
18 import jinja2
# pylint: disable=F0401
21 def ProcessFile(input_filename
, output_filename
, variables
):
22 with codecs
.open(input_filename
, 'r', 'utf-8') as input_file
:
23 input_
= input_file
.read()
24 env
= jinja2
.Environment(undefined
=jinja2
.StrictUndefined
)
25 template
= env
.from_string(input_
)
26 template
.filename
= os
.path
.abspath(input_filename
)
27 output
= template
.render(variables
)
28 with codecs
.open(output_filename
, 'w', 'utf-8') as output_file
:
29 output_file
.write(output
)
32 def ProcessFiles(input_filenames
, inputs_base_dir
, outputs_zip
, variables
):
33 with build_utils
.TempDir() as temp_dir
:
34 for input_filename
in input_filenames
:
35 relpath
= os
.path
.relpath(os
.path
.abspath(input_filename
),
36 os
.path
.abspath(inputs_base_dir
))
37 if relpath
.startswith(os
.pardir
):
38 raise Exception('input file %s is not contained in inputs base dir %s'
39 % input_filename
, inputs_base_dir
)
41 output_filename
= os
.path
.join(temp_dir
, relpath
)
42 parent_dir
= os
.path
.dirname(output_filename
)
43 build_utils
.MakeDirectory(parent_dir
)
44 ProcessFile(input_filename
, output_filename
, variables
)
46 build_utils
.ZipDir(outputs_zip
, temp_dir
)
50 parser
= optparse
.OptionParser()
51 build_utils
.AddDepfileOption(parser
)
52 parser
.add_option('--inputs', help='The template files to process.')
53 parser
.add_option('--output', help='The output file to generate. Valid '
54 'only if there is a single input.')
55 parser
.add_option('--outputs-zip', help='A zip file containing the processed '
56 'templates. Required if there are multiple inputs.')
57 parser
.add_option('--inputs-base-dir', help='A common ancestor directory of '
58 'the inputs. Each output\'s path in the output zip will '
59 'match the relative path from INPUTS_BASE_DIR to the '
60 'input. Required if --output-zip is given.')
61 parser
.add_option('--variables', help='Variables to be made available in the '
62 'template processing environment, as a GYP list (e.g. '
63 '--variables "channel=beta mstone=39")', default
='')
64 options
, args
= parser
.parse_args()
66 build_utils
.CheckOptions(options
, parser
, required
=['inputs'])
67 inputs
= build_utils
.ParseGypList(options
.inputs
)
69 if (options
.output
is None) == (options
.outputs_zip
is None):
70 parser
.error('Exactly one of --output and --output-zip must be given')
71 if options
.output
and len(inputs
) != 1:
72 parser
.error('--output cannot be used with multiple inputs')
73 if options
.outputs_zip
and not options
.inputs_base_dir
:
74 parser
.error('--inputs-base-dir must be given when --output-zip is used')
76 parser
.error('No positional arguments should be given.')
79 for v
in build_utils
.ParseGypList(options
.variables
):
81 parser
.error('--variables argument must contain "=": ' + v
)
82 name
, _
, value
= v
.partition('=')
83 variables
[name
] = value
86 ProcessFile(inputs
[0], options
.output
, variables
)
88 ProcessFiles(inputs
, options
.inputs_base_dir
, options
.outputs_zip
,
92 deps
= inputs
+ build_utils
.GetPythonDependencies()
93 build_utils
.WriteDepfile(options
.depfile
, deps
)
96 if __name__
== '__main__':