Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 ''' | 5 ''' |
| 6 Provides a Manifest Feature abstraction, similar to but more strict than the | 6 Provides a Manifest Feature abstraction, similar to but more strict than the |
| 7 Feature schema (see feature_utility.py). | 7 Feature schema (see feature_utility.py). |
| 8 | 8 |
| 9 Each Manifest Feature has a 'level' in addition to the keys defined in a | 9 Each Manifest Feature has a 'level' in addition to the keys defined in a |
| 10 Feature. 'level' can be 'required', 'only_one', 'recommended', or 'optional', | 10 Feature. 'level' can be 'required', 'only_one', 'recommended', or 'optional', |
| 11 indicating how an app or extension should define a manifest property. If 'level' | 11 indicating how an app or extension should define a manifest property. If 'level' |
| 12 is missing, 'optional' is assumed. | 12 is missing, 'optional' is assumed. |
| 13 ''' | 13 ''' |
| 14 | 14 |
| 15 import json | |
| 16 | |
| 17 from features import Features | |
| 15 import features_utility | 18 import features_utility |
| 19 from third_party.json_schema_compiler.json_parse import Parse | |
| 16 | 20 |
| 17 def CreateManifestFeatures(features_json, manifest_json, filter_platform=None): | 21 def CreateManifestFeatures(features_json, manifest_json, filter_platform=None): |
| 18 '''Create a manifest features dictionary by normalizing |features_json| and | 22 '''Create a manifest features dictionary by normalizing |features_json| and |
| 19 merging it with |manifest_json|. If filter_platform is 'app' or 'extension' | 23 merging it with |manifest_json|. If filter_platform is 'app' or 'extension' |
| 20 then irrelevant features will be removed. | 24 then irrelevant features will be removed. |
| 21 ''' | 25 ''' |
| 22 assert filter_platform in ['app', 'extension', None] | 26 assert filter_platform in ['app', 'extension', None] |
| 23 manifest_features = features_utility.MergedWith( | 27 manifest_features = features_utility.MergedWith( |
| 24 features_utility.Parse(features_json), manifest_json) | 28 features_utility.Parse(features_json), manifest_json) |
| 25 | 29 |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 53 value = features.pop(name) | 57 value = features.pop(name) |
| 54 parent, child_name = name.split('.', 1) | 58 parent, child_name = name.split('.', 1) |
| 55 add_child(features, parent, child_name, value) | 59 add_child(features, parent, child_name, value) |
| 56 | 60 |
| 57 for value in features.values(): | 61 for value in features.values(): |
| 58 if 'children' in value: | 62 if 'children' in value: |
| 59 insert_children(value['children']) | 63 insert_children(value['children']) |
| 60 | 64 |
| 61 insert_children(features) | 65 insert_children(features) |
| 62 return features | 66 return features |
| 67 | |
| 68 def _ListifyAndSortDocs(features, app_name): | |
|
not at google - send to devlin
2013/09/23 18:31:30
most of this code is specifically for passing to t
| |
| 69 '''Convert a |features| dictionary, and all 'children' dictionaries, into | |
| 70 lists recursively. Sort lists first by 'level' then by name. | |
| 71 ''' | |
| 72 def sort_key(item): | |
| 73 '''Key function to sort items primarily by level (according to index into | |
| 74 levels) then subsort by name. | |
| 75 ''' | |
| 76 levels = ('required', 'recommended', 'only_one', 'optional') | |
| 77 | |
| 78 return (levels.index(item.get('level', 'optional')), item['name']) | |
| 79 | |
| 80 def coerce_example_to_feature(feature): | |
| 81 '''To display json in examples more clearly, convert the example of | |
| 82 |feature| into the feature format, with a name and children, to be rendered | |
| 83 by the templates. Only applicable to examples that are dictionaries. | |
| 84 ''' | |
| 85 if not isinstance(feature.get('example'), dict): | |
| 86 if 'example' in feature: | |
| 87 feature['example'] = json.dumps(feature['example']) | |
| 88 return | |
| 89 # Add any keys/value pairs in the dict as children | |
| 90 for key, value in feature['example'].iteritems(): | |
| 91 if not 'children' in feature: | |
| 92 feature['children'] = {} | |
| 93 feature['children'][key] = { 'name': key, 'example': value } | |
| 94 del feature['example'] | |
| 95 del feature['has_example'] | |
| 96 | |
| 97 def convert_and_sort(features): | |
| 98 for key, value in features.items(): | |
| 99 if 'example' in value: | |
| 100 value['has_example'] = True | |
| 101 example = json.dumps(value['example']) | |
| 102 if example == '{}': | |
| 103 value['example'] = '{...}' | |
| 104 elif example == '[]': | |
| 105 value['example'] = '[...]' | |
| 106 else: | |
| 107 coerce_example_to_feature(value) | |
| 108 if 'children' in value: | |
| 109 features[key]['children'] = convert_and_sort(value['children']) | |
| 110 return sorted(features.values(), key=sort_key) | |
| 111 | |
| 112 # Replace {{title}} in the 'name' manifest property example with |app_name| | |
| 113 if 'name' in features: | |
| 114 name = features['name'] | |
| 115 name['example'] = name['example'].replace('{{title}}', app_name) | |
| 116 | |
| 117 features = convert_and_sort(features) | |
| 118 | |
| 119 return features | |
| 120 | |
| 121 def _AddLevelAnnotations(features): | |
| 122 '''Add level annotations to |features|. |features| and children lists must be | |
| 123 sorted by 'level'. Annotations are added to the first item in a group of | |
| 124 features of the same 'level'. | |
| 125 | |
| 126 The last item in a list has 'is_last' set to True. | |
| 127 ''' | |
| 128 annotations = { | |
| 129 'required': 'Required', | |
| 130 'recommended': 'Recommended', | |
| 131 'only_one': 'Pick one (or none)', | |
| 132 'optional': 'Optional' | |
| 133 } | |
| 134 | |
| 135 def add_annotation(item, annotation): | |
| 136 if not 'annotations' in item: | |
| 137 item['annotations'] = [] | |
| 138 item['annotations'].insert(0, annotation) | |
| 139 | |
| 140 def annotate(parent_level, features): | |
| 141 current_level = parent_level | |
| 142 for item in features: | |
| 143 level = item.get('level', 'optional') | |
| 144 if level != current_level: | |
| 145 add_annotation(item, annotations[level]) | |
| 146 current_level = level | |
| 147 if 'children' in item: | |
| 148 annotate(level, item['children']) | |
| 149 if features: | |
| 150 features[-1]['is_last'] = True | |
| 151 | |
| 152 annotate('required', features) | |
| 153 return features | |
| 154 | |
| 155 class ManifestFeatures(Features): | |
| 156 '''Subclass of Features to provide special annotation and ordering as well as | |
| 157 the merging of _manifest_features.json data with manifest.json. | |
| 158 ''' | |
| 159 def __init__(self, | |
| 160 compiled_fs_factory, | |
| 161 manifest_features_path, | |
| 162 file_system, | |
| 163 manifest_json_path): | |
| 164 self._file_system = file_system | |
| 165 self._manifest_json_path = manifest_json_path | |
| 166 super(ManifestFeatures, self).__init__(compiled_fs_factory, | |
| 167 manifest_features_path) | |
| 168 | |
| 169 def Parse(self, features_json): | |
| 170 manifest_json = Parse( | |
| 171 self._file_system.ReadSingle(self._manifest_json_path)) | |
| 172 return CreateManifestFeatures(features_json, manifest_json) | |
| 173 | |
| 174 def FilterByPlatform(self, features, platform): | |
| 175 features = super(ManifestFeatures, self).FilterByPlatform(features, | |
| 176 platform) | |
| 177 return _AddLevelAnnotations( | |
| 178 _ListifyAndSortDocs(ConvertDottedKeysToNested(features), | |
| 179 app_name=platform.capitalize())) | |
| OLD | NEW |