Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Side by Side Diff: services/catalog/public/tools/sourcify_manifest.py

Issue 2659523002: Generate better catalog C++ sources (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright 2017 The Chromium Authors. All rights reserved. 2 # Copyright 2017 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Generates a C++ source file which defines a string constant containing the 6 """Generates C++ source and header files defining function to create an
7 contents of a catalog manifest file. Useful for baking catalogs into binaries 7 in-memory representation of a static catalog manifest at runtime."""
8 which don't want to hit disk before initializing the catalog.""" 8
9 9
10 import argparse 10 import argparse
11 import imp
11 import json 12 import json
12 import os.path 13 import os.path
13 import sys 14 import sys
14 15
15 16
16 # Token used to delimit raw strings in the generated source file. It's illegal 17 _H_FILE_TEMPLATE = "catalog.h.tmpl"
17 # for this token to appear within the contents of the input manifest itself. 18 _CC_FILE_TEMPLATE = "catalog.cc.tmpl"
18 _RAW_STRING_DELIMITER = "#CATALOG_JSON#" 19
20
21 # Disable lint check for finding modules:
22 # pylint: disable=F0401
23
24 def _GetDirAbove(dirname):
25 """Returns the directory "above" this file containing |dirname| (which must
26 also be "above" this file)."""
27 path = os.path.abspath(__file__)
28 while True:
29 path, tail = os.path.split(path)
30 assert tail
31 if tail == dirname:
32 return path
33
34
35 try:
36 imp.find_module("jinja2")
37 except ImportError:
38 sys.path.append(os.path.join(_GetDirAbove("services"), "third_party"))
39 import jinja2
40
41
42 def ApplyTemplate(path_to_template, output_path, global_vars, **kwargs):
43 def make_ascii(maybe_unicode):
44 if type(maybe_unicode) is str:
45 return maybe_unicode
46 assert type(maybe_unicode) is unicode
47 return maybe_unicode.encode("ascii", "ignore")
48
49 with open(output_path, "w") as output_file:
50 jinja_env = jinja2.Environment(
51 loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
52 keep_trailing_newline=True, **kwargs)
53 jinja_env.globals.update(global_vars)
54 jinja_env.filters.update({
55 "is_dict": lambda x : type(x) is dict,
56 "is_list": lambda x : type(x) is list,
57 "is_number": lambda x : type(x) is int or type(x) is float,
58 "is_bool": lambda x: type(x) is bool,
59 "is_string": lambda x: type(x) is str,
60 "is_unicode": lambda x: type(x) is unicode,
61 "make_ascii": make_ascii,
62 })
63 output_file.write(jinja_env.get_template(path_to_template).render())
19 64
20 65
21 def main(): 66 def main():
22 parser = argparse.ArgumentParser( 67 parser = argparse.ArgumentParser(
23 description="Generates a C++ constant containing a catalog manifest.") 68 description="Generates a C++ constant containing a catalog manifest.")
24 parser.add_argument("--input") 69 parser.add_argument("--input")
25 parser.add_argument("--output") 70 parser.add_argument("--output-filename-base")
26 parser.add_argument("--symbol-name") 71 parser.add_argument("--output-function-name")
27 parser.add_argument("--pretty", action="store_true") 72 parser.add_argument("--module-path")
28 args, _ = parser.parse_known_args() 73 args, _ = parser.parse_known_args()
29 74
30 if args.input is None or args.output is None or args.symbol_name is None: 75 if args.input is None:
31 raise Exception("--input, --output, and --symbol-name are required") 76 raise Exception("--input is required")
77 if args.output_filename_base is None:
78 raise Exception("--output-filename-base is required")
79 if args.output_function_name is None:
80 raise Exception("--output-function-name is required")
81 if args.module_path is None:
82 raise Exception("--module-path is required")
32 83
33 with open(args.input, 'r') as input_file: 84 with open(args.input, "r") as input_file:
34 manifest_contents = input_file.read() 85 catalog = json.load(input_file)
35 86
36 if manifest_contents.find(_RAW_STRING_DELIMITER) >= 0: 87 qualified_function_name = args.output_function_name.split("::")
37 raise Exception( 88 namespaces = qualified_function_name[0:-1]
38 "Unexpected '%s' found in input manifest." % _RAW_STRING_DELIMITER) 89 function_name = qualified_function_name[-1]
39 90
40 qualified_symbol_name = args.symbol_name.split("::") 91 def raise_error(error, value):
41 namespace = qualified_symbol_name[0:-1] 92 raise Exception(error)
42 symbol_name = qualified_symbol_name[-1]
43 93
44 with open(args.output, 'w') as output_file: 94 global_vars = {
45 output_file.write( 95 "catalog": catalog,
46 "// This is a generated file produced by\n" 96 "function_name": function_name,
47 "// src/services/catalog/public/tools/sourcify_manifest.py.\n\n") 97 "namespaces": namespaces,
48 for name in namespace: 98 "path": args.module_path,
49 output_file.write("namespace %s {\n" % name) 99 "raise": raise_error,
50 output_file.write("\nextern const char %s[];" % symbol_name) 100 }
51 output_file.write("\nconst char %s[] = R\"%s(%s)%s\";\n\n" % 101
52 (symbol_name, _RAW_STRING_DELIMITER, manifest_contents, 102 input_h_filename = _H_FILE_TEMPLATE
53 _RAW_STRING_DELIMITER)) 103 output_h_filename = "%s.h" % args.output_filename_base
54 for name in reversed(namespace): 104 ApplyTemplate(input_h_filename, output_h_filename, global_vars)
55 output_file.write("} // %s\n" % name) 105
106 input_cc_filename = _CC_FILE_TEMPLATE
107 output_cc_filename = "%s.cc" % args.output_filename_base
108 ApplyTemplate(input_cc_filename, output_cc_filename, global_vars)
56 109
57 return 0 110 return 0
58 111
59 if __name__ == "__main__": 112 if __name__ == "__main__":
60 sys.exit(main()) 113 sys.exit(main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698