OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2015 The Chromium Authors. All rights reserved. | 2 # Copyright 2015 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 itertools |
6 import json | 7 import json |
7 import os.path | 8 import os.path |
8 import sys | 9 import sys |
9 import optparse | 10 import optparse |
10 _script_path = os.path.realpath(__file__) | 11 _script_path = os.path.realpath(__file__) |
11 | 12 |
12 sys.path.insert(0, os.path.normpath(_script_path + "/../../json_comment_eater")) | 13 sys.path.insert(0, os.path.normpath(_script_path + "/../../json_comment_eater")) |
13 try: | 14 try: |
14 import json_comment_eater | 15 import json_comment_eater |
15 finally: | 16 finally: |
16 sys.path.pop(0) | 17 sys.path.pop(0) |
17 | 18 |
18 sys.path.insert(0, os.path.normpath(_script_path + "/../../json_to_struct")) | 19 sys.path.insert(0, os.path.normpath(_script_path + "/../../json_to_struct")) |
19 try: | 20 try: |
20 import json_to_struct | 21 import json_to_struct |
21 finally: | 22 finally: |
22 sys.path.pop(0) | 23 sys.path.pop(0) |
23 | 24 |
24 def _Load(filename): | 25 def _Load(filename): |
25 """Loads a JSON file into a Python object and return this object. | 26 """Loads a JSON file into a Python object and return this object. |
26 """ | 27 """ |
27 with open(filename, 'r') as handle: | 28 with open(filename, 'r') as handle: |
28 result = json.loads(json_comment_eater.Nom(handle.read())) | 29 result = json.loads(json_comment_eater.Nom(handle.read())) |
29 return result | 30 return result |
30 | 31 |
31 def _LoadFieldTrialConfig(filename): | 32 def _LoadFieldTrialConfig(filename, platform): |
32 """Loads a field trial config JSON and converts it into a format that can be | 33 """Loads a field trial config JSON and converts it into a format that can be |
33 used by json_to_struct. | 34 used by json_to_struct. |
34 """ | 35 """ |
35 return _FieldTrialConfigToDescription(_Load(filename)) | 36 return _FieldTrialConfigToDescription(_Load(filename), platform) |
36 | 37 |
37 def _CreateGroup(group_data): | 38 def _CreateExperiment(experiment_data): |
38 group = {'name': group_data['group_name']} | 39 experiment = {'name': experiment_data['name']} |
39 params_data = group_data.get('params') | 40 params_data = experiment_data.get('params') |
40 if (params_data): | 41 if (params_data): |
41 group['params'] = [{'key': param, 'value': params_data[param]} | 42 experiment['params'] = [{'key': param, 'value': params_data[param]} |
42 for param in sorted(params_data.keys())]; | 43 for param in sorted(params_data.keys())]; |
43 enable_features_data = group_data.get('enable_features') | 44 enable_features_data = experiment_data.get('enable_features') |
44 if enable_features_data: | 45 if enable_features_data: |
45 group['enable_features'] = enable_features_data | 46 experiment['enable_features'] = enable_features_data |
46 disable_features_data = group_data.get('disable_features') | 47 disable_features_data = experiment_data.get('disable_features') |
47 if disable_features_data: | 48 if disable_features_data: |
48 group['disable_features'] = disable_features_data | 49 experiment['disable_features'] = disable_features_data |
49 return group | 50 return experiment |
50 | 51 |
51 def _CreateTrial(trial_name, groups): | 52 def _CreateTrial(study_name, experiment_configs, platform): |
| 53 """Returns the applicable experiments for |study_name| and |platform|. This |
| 54 iterates through all of the experiment_configs for |study_name| and picks out |
| 55 the applicable experiments based off of the valid platforms. |
| 56 """ |
| 57 platform_experiment_lists = [ |
| 58 config['experiments'] for config in experiment_configs |
| 59 if platform in config['platforms']] |
| 60 platform_experiments = list(itertools.chain.from_iterable( |
| 61 platform_experiment_lists)) |
52 return { | 62 return { |
53 'name': trial_name, | 63 'name': study_name, |
54 'groups': [_CreateGroup(group) for group in groups], | 64 'groups': [_CreateExperiment(experiment) |
| 65 for experiment in platform_experiments], |
55 } | 66 } |
56 | 67 |
57 def _FieldTrialConfigToDescription(config): | 68 def _GenerateTrials(config, platform): |
| 69 for study_name in sorted(config.keys()): |
| 70 study = _CreateTrial(study_name, config[study_name], platform) |
| 71 # To avoid converting studies with empty groups (e.g. the study doesn't |
| 72 # apply to the target platform), this generator only yields studies that |
| 73 # have non-empty groups. |
| 74 if study['groups']: |
| 75 yield study |
| 76 |
| 77 def _FieldTrialConfigToDescription(config, platform): |
58 return { | 78 return { |
59 'elements': { | 79 'elements': { |
60 'kFieldTrialConfig': { | 80 'kFieldTrialConfig': { |
61 'trials': [_CreateTrial(trial_name, config[trial_name]) | 81 'trials': [study for study in _GenerateTrials(config, platform)] |
62 for trial_name in sorted(config.keys())] | |
63 } | 82 } |
64 } | 83 } |
65 } | 84 } |
66 | 85 |
67 def main(arguments): | 86 def main(arguments): |
68 parser = optparse.OptionParser( | 87 parser = optparse.OptionParser( |
69 description='Generates a struct from a JSON description.', | 88 description='Generates a struct from a JSON description.', |
70 usage='usage: %prog [option] -s schema description') | 89 usage='usage: %prog [option] -s schema -p platform description') |
71 parser.add_option('-b', '--destbase', | 90 parser.add_option('-b', '--destbase', |
72 help='base directory of generated files.') | 91 help='base directory of generated files.') |
73 parser.add_option('-d', '--destdir', | 92 parser.add_option('-d', '--destdir', |
74 help='directory to output generated files, relative to destbase.') | 93 help='directory to output generated files, relative to destbase.') |
75 parser.add_option('-n', '--namespace', | 94 parser.add_option('-n', '--namespace', |
76 help='C++ namespace for generated files. e.g search_providers.') | 95 help='C++ namespace for generated files. e.g search_providers.') |
| 96 parser.add_option('-p', '--platform', |
| 97 help='target platform for the field trial, mandatory.') |
77 parser.add_option('-s', '--schema', help='path to the schema file, ' | 98 parser.add_option('-s', '--schema', help='path to the schema file, ' |
78 'mandatory.') | 99 'mandatory.') |
79 parser.add_option('-o', '--output', help='output filename, ' | 100 parser.add_option('-o', '--output', help='output filename, ' |
80 'mandatory.') | 101 'mandatory.') |
81 parser.add_option('-y', '--year', | 102 parser.add_option('-y', '--year', |
82 help='year to put in the copy-right.') | 103 help='year to put in the copy-right.') |
83 (opts, args) = parser.parse_args(args=arguments) | 104 (opts, args) = parser.parse_args(args=arguments) |
84 | 105 |
85 if not opts.schema: | 106 if not opts.schema: |
86 parser.error('You must specify a --schema.') | 107 parser.error('You must specify a --schema.') |
87 | 108 |
| 109 if not opts.platform: |
| 110 parser.error('You must specify a --platform.') |
| 111 |
| 112 supported_platforms = ['android', 'chromeos', 'ios', 'linux', 'mac', 'win'] |
| 113 if opts.platform not in supported_platforms: |
| 114 parser.error('\'%s\' is an unknown platform. Supported platforms: %s' % |
| 115 (opts.platform, supported_platforms)) |
| 116 |
88 description_filename = os.path.normpath(args[0]) | 117 description_filename = os.path.normpath(args[0]) |
89 shortroot = opts.output | 118 shortroot = opts.output |
90 if opts.destdir: | 119 if opts.destdir: |
91 output_root = os.path.join(os.path.normpath(opts.destdir), shortroot) | 120 output_root = os.path.join(os.path.normpath(opts.destdir), shortroot) |
92 else: | 121 else: |
93 output_root = shortroot | 122 output_root = shortroot |
94 | 123 |
95 if opts.destbase: | 124 if opts.destbase: |
96 basepath = os.path.normpath(opts.destbase) | 125 basepath = os.path.normpath(opts.destbase) |
97 else: | 126 else: |
98 basepath = '' | 127 basepath = '' |
99 | 128 |
100 schema = _Load(opts.schema) | 129 schema = _Load(opts.schema) |
101 description = _LoadFieldTrialConfig(description_filename) | 130 description = _LoadFieldTrialConfig(description_filename, opts.platform) |
102 json_to_struct.GenerateStruct( | 131 json_to_struct.GenerateStruct( |
103 basepath, output_root, opts.namespace, schema, description, | 132 basepath, output_root, opts.namespace, schema, description, |
104 os.path.split(description_filename)[1], os.path.split(opts.schema)[1], | 133 os.path.split(description_filename)[1], os.path.split(opts.schema)[1], |
105 opts.year) | 134 opts.year) |
106 | 135 |
107 if __name__ == '__main__': | 136 if __name__ == '__main__': |
108 main(sys.argv[1:]) | 137 main(sys.argv[1:]) |
OLD | NEW |