Chromium Code Reviews
[email protected] (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(211)

Side by Side Diff: components/variations/service/generate_ui_string_overrider.py

Issue 1374773002: Componentize script to generate UI string overrides mapping. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@get-resources-index
Patch Set: Created 5 years, 2 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/python 1 #!/usr/bin/python
2 # Copyright 2014 The Chromium Authors. All rights reserved. 2 # Copyright 2014 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 import argparse
6 import collections 7 import collections
7 import hashlib 8 import hashlib
8 import operator 9 import operator
9 import os 10 import os
10 import re 11 import re
11 import sys 12 import sys
12 13
13 14 SCRIPT_NAME = "generate_ui_string_overrider.py"
14 RESOURCE_EXTRACT_REGEX = re.compile('^#define (\S*) (\d*)$', re.MULTILINE) 15 RESOURCE_EXTRACT_REGEX = re.compile('^#define (\S*) (\d*)$', re.MULTILINE)
15 16
16 class Error(Exception): 17 class Error(Exception):
17 """Base error class for all exceptions in generated_resources_map.""" 18 """Base error class for all exceptions in generated_resources_map."""
18 19
19 20
20 class HashCollisionError(Error): 21 class HashCollisionError(Error):
21 """Multiple resource names hash to the same value.""" 22 """Multiple resource names hash to the same value."""
22 23
23 24
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 lines = [entry_pattern % (data_getter(r), r.name) for r in resources] 117 lines = [entry_pattern % (data_getter(r), r.name) for r in resources]
117 pattern = """const %(type)s %(name)s[] = { 118 pattern = """const %(type)s %(name)s[] = {
118 %(content)s 119 %(content)s
119 }; 120 };
120 """ 121 """
121 return pattern % {'type': array_type, 122 return pattern % {'type': array_type,
122 'name': array_name, 123 'name': array_name,
123 'content': '\n'.join(lines)} 124 'content': '\n'.join(lines)}
124 125
125 126
126 def _GenerateFileContent(resources_content): 127 def _GenerateSourceFileContent(resources_content, namespace, header_filename):
127 """Generates the .cc content from the given generated_resources.h content. 128 """Generates the .cc content from the given generated grit headers content.
128 129
129 Args: 130 Args:
130 resources_content: The input string to process, contains lines of the form 131 resources_content: The input string to process, contains lines of the form
131 "#define NAME INDEX". 132 "#define NAME INDEX".
132 133
134 namespace: The namespace in which the generated code should be scoped. If
135 not defined, then the code will be in the global namespace.
136
137 header_filename: Path to the corresponding .h.
138
133 Returns: 139 Returns:
134 .cc file content defining the kResourceHashes and kResourceIndices arrays. 140 .cc file content implementing the CreateUIStringOverrider() factory.
135 """ 141 """
136 hashed_tuples = _GetResourceListFromString(resources_content) 142 hashed_tuples = _GetResourceListFromString(resources_content)
137 143
138 collisions = _CheckForHashCollisions(hashed_tuples) 144 collisions = _CheckForHashCollisions(hashed_tuples)
139 if collisions: 145 if collisions:
140 error_message = "\n".join( 146 error_message = "\n".join(
141 ["hash: %i, name: %s" % (i[0], i[1]) for i in sorted(collisions)]) 147 ["hash: %i, name: %s" % (i[0], i[1]) for i in sorted(collisions)])
142 error_message = ("\nThe following names had hash collisions " 148 error_message = ("\nThe following names had hash collisions "
143 "(sorted by the hash value):\n%s\n" %(error_message)) 149 "(sorted by the hash value):\n%s\n" %(error_message))
144 raise HashCollisionError(error_message) 150 raise HashCollisionError(error_message)
145 151
146 hashes_array = _GenDataArray( 152 hashes_array = _GenDataArray(
147 hashed_tuples, " %iU, // %s", 'kResourceHashes', 'uint32_t', 153 hashed_tuples, " %iU, // %s", 'kResourceHashes', 'uint32_t',
148 operator.attrgetter('hash')) 154 operator.attrgetter('hash'))
149 indices_array = _GenDataArray( 155 indices_array = _GenDataArray(
150 hashed_tuples, " %s, // %s", 'kResourceIndices', 'int', 156 hashed_tuples, " %s, // %s", 'kResourceIndices', 'int',
151 operator.attrgetter('index')) 157 operator.attrgetter('index'))
152 158
159 namespace_prefix = ""
160 namespace_suffix = ""
161 if namespace:
162 namespace_prefix = "namespace %s {\n\n" % namespace
163 namespace_suffix = "\n} // namespace %s\n" % namespace
164
153 return ( 165 return (
154 "// This file was generated by generate_resources_map.py. Do not edit.\n" 166 "// This file was generated by %s. Do not edit.\n"
155 "\n\n" 167 "\n"
156 "#include " 168 "#include \"%s\"\n\n"
157 "\"chrome/browser/metrics/variations/generated_resources_map.h\"\n\n" 169 "%s"
158 "namespace chrome_variations {\n\n" 170 "namespace {\n\n"
159 "const size_t kNumResources = %i;\n\n" 171 "const size_t kNumResources = %i;\n\n"
160 "%s" 172 "%s"
161 "\n" 173 "\n"
162 "%s" 174 "%s"
163 "\n" 175 "\n"
164 "} // namespace chrome_variations\n") % ( 176 "} // namespace\n"
165 len(hashed_tuples), hashes_array, indices_array) 177 "\n"
178 "variations::UIStringOverrider CreateUIStringOverrider() {\n"
179 " return variations::UIStringOverrider(\n"
180 " kResourceHashes, kResourceIndices, kNumResources);\n"
181 "}\n"
182 "%s") % (
jwd 2015/09/29 15:02:54 Can you use dictionary based string interpolation
sdefresne 2015/09/30 09:38:43 Done.
183 SCRIPT_NAME, header_filename, namespace_prefix, len(hashed_tuples),
184 hashes_array, indices_array, namespace_suffix)
166 185
167 186
168 def main(resources_file, map_file): 187 def _GenerateHeaderFileContent(namespace, header_filename):
188 """Generates the .h for to the .cc generated by _GenerateSourceFileContent.
189
190 Args:
191 namespace: The namespace in which the generated code should be scoped. If
192 not defined, then the code will be in the global namespace.
193
194 header_filename: Path to the corresponding .h. Used to generate the include
195 guards.
196
197 Returns:
198 .cc file content implementing the CreateUIStringOverrider() factory.
199 """
200
201 include_guard = re.sub('[^A-Z]', '_', header_filename.upper()) + '_'
202
203 namespace_prefix = ""
204 namespace_suffix = ""
205 if namespace:
206 namespace_prefix = "namespace %s {\n\n" % namespace
207 namespace_suffix = "\n} // namespace %s\n" % namespace
208
209 return (
210 "// This file was generated by %s. Do not edit.\n"
211 "\n"
212 "#ifndef %s\n"
213 "#define %s\n"
214 "\n"
215 "#include \"components/variations/service/ui_string_overrider.h\"\n\n"
216 "%s"
217 "// Returns an initialized UIStringOverrider.\n"
218 "variations::UIStringOverrider CreateUIStringOverrider();\n"
219 "%s"
220 "\n"
221 "#endif // %s\n"
jwd 2015/09/29 15:02:54 optional nit: use dictionary string interpolation
sdefresne 2015/09/30 09:38:43 Done.
222 ) % (
223 SCRIPT_NAME, include_guard, include_guard, namespace_prefix,
224 namespace_suffix, include_guard)
225
226
227 def main():
228 arg_parser = argparse.ArgumentParser(
229 description="Generate UIStringOverrider factory from resources headers "
230 "generated by grit.")
231 arg_parser.add_argument(
232 "--output_dir", "-o", required=True,
233 help="Base directory to for generated files.")
234 arg_parser.add_argument(
235 "--source_filename", "-S", required=True,
236 help="File name of the generated source file.")
237 arg_parser.add_argument(
238 "--header_filename", "-H", required=True,
239 help="File name of the generated header file.")
240 arg_parser.add_argument(
241 "--namespace", "-N", default="",
242 help="Namespace of the generated factory function (code will be in "
243 "the global namespace if this is omitted).")
244 arg_parser.add_argument(
245 "--test_support", "-t", action="store_true", default=False,
246 help="Make internal variables accessible for testing.")
247 arg_parser.add_argument(
248 "inputs", metavar="FILENAME", nargs="+",
249 help="Path to resources header file generated by grit.")
250 arguments = arg_parser.parse_args()
251
169 generated_resources_h = "" 252 generated_resources_h = ""
170 with open(resources_file, "r") as resources: 253 for resources_file in arguments.inputs:
171 generated_resources_h = resources.read() 254 with open(resources_file, "r") as resources:
255 generated_resources_h += resources.read()
172 256
173 if len(generated_resources_h) == 0: 257 if len(generated_resources_h) == 0:
174 raise Error("No content loaded for %s." % (resources_file)) 258 raise Error("No content loaded for %s." % (resources_file))
175 259
176 file_content = _GenerateFileContent(generated_resources_h) 260 source_file_content = _GenerateSourceFileContent(
261 generated_resources_h, arguments.namespace, arguments.header_filename)
262 header_file_content = _GenerateHeaderFileContent(
263 arguments.namespace, arguments.header_filename)
177 264
178 with open(map_file, "w") as generated_file: 265 with open(os.path.join(
179 generated_file.write(file_content) 266 arguments.output_dir, arguments.source_filename), "w") as generated_file:
267 generated_file.write(source_file_content)
268 with open(os.path.join(
269 arguments.output_dir, arguments.header_filename), "w") as generated_file:
270 generated_file.write(header_file_content)
180 271
181 272
182 if __name__ == '__main__': 273 if __name__ == '__main__':
183 sys.exit(main(sys.argv[1], sys.argv[2])) 274 sys.exit(main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698