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

Side by Side Diff: chrome/common/extensions/docs/server2/manifest_data_source.py

Issue 16410002: Docserver manifest follow up (rewrite) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@gen-manifest-try-2
Patch Set: structural changes Created 7 years, 4 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 # 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 import json
4 5
5 from copy import deepcopy 6 from features_model import FeaturesModel
6 from operator import itemgetter 7 from third_party.json_schema_compiler.json_parse import Parse
7 8
8 from third_party.json_schema_compiler.json_parse import OrderedDict, Parse 9 def _ConvertAndSortDocs(properties, platform):
not at google - send to devlin 2013/07/31 18:50:20 "Convert" needs a less generic name (what's it con
jshumway 2013/08/01 22:27:50 Done.
10 '''Convert docs and children into lists and sort them, first by level, then
11 by name.
12 '''
13 def sort_key(item):
14 '''Key function to sort items primarily by level (according to index into
15 levels) then subsort by name.
16 '''
17 levels = ('required', 'recommended', 'only_one', 'optional')
18
19 return (levels.index(item.get('level', 'optional')), item['name'])
20
21 def convert_and_sort(properties):
22 for key, value in properties.items():
23 if 'example' in value:
24 value['has_example'] = True
25 example = json.dumps(value['example'])
26 if example == '{}':
27 value['example'] = '{...}'
28 elif example == '[]':
29 value['example'] = '[...]'
30 else:
31 value['example'] = example
32
33 if 'children' in value:
34 properties[key]['children'] = convert_and_sort(value['children'])
35
36 return sorted(properties.values(), key=sort_key)
37
38 name = properties['name']
39 name['example'] = name['example'].replace('{{title}}', platform.capitalize())
40
41 return convert_and_sort(properties)
42
43 def _Annotate(properties):
not at google - send to devlin 2013/07/31 18:50:20 "Annotate" needs a less generic name (what's it an
jshumway 2013/08/01 22:27:50 Done.
44 '''Add level annotations to level groups in a manifest property list and
45 child lists. Requeries a list of properties sorted by level, with children
46 in sorted lists as well.
47 '''
48 annotations = {
49 'required': 'Required',
50 'recommended': 'Recommended',
51 'only_one': 'Pick one (or none)',
52 'optional': 'Optional'
53 }
54
55 def add_annotation(item, annotation):
56 if not 'annotations' in item:
57 item['annotations'] = []
58 item['annotations'].insert(0, annotation)
59
60 def annotate(parent_level, properties):
61 current_level = parent_level
62 for item in properties:
63 level = item.get('level', 'optional')
64 if level != current_level:
65 add_annotation(item, annotations[level])
66 current_level = level
67 if 'children' in item:
68 annotate(level, item['children'])
69 if properties:
70 properties[-1]['is_last'] = True
71
72 annotate('required', properties)
73 return properties
74
75 def _RestructureChildren(features):
76 '''Features whose names are of the form 'parent.child' are moved to be part
77 of the 'parent' dictionary under the key 'children'. Names are changed to
78 the 'child' section of the original name.
79 '''
80 def add_child(features, parent, child_name, value):
81 value['name'] = child_name
82 if not 'children' in features[parent]:
83 features[parent]['children'] = {}
84 features[parent]['children'][child_name] = value
85
86 def insert_children(features):
87 for name in features.keys():
88 if '.' in name:
89 value = features.pop(name)
90 parent, child_name = name.split('.', 1)
91 add_child(features, parent, child_name, value)
92
93 for value in features.values():
94 if 'children' in value:
95 insert_children(value['children'])
96
97 insert_children(features)
98 return features
9 99
10 class ManifestDataSource(object): 100 class ManifestDataSource(object):
11 '''Provides a template with access to manifest properties specific to apps or 101 '''Provides a template with access to manifest properties specific to apps or
12 extensions. 102 extensions.
13 ''' 103 '''
14 def __init__(self, 104 def __init__(self,
15 compiled_fs_factory, 105 compiled_fs_factory,
16 file_system, 106 file_system,
17 manifest_path, 107 manifest_path,
18 features_path): 108 features_path):
19 self._manifest_path = manifest_path 109 self._manifest_path = manifest_path
20 self._features_path = features_path 110 self._features_path = features_path
21 self._file_system = file_system 111 self._file_system = file_system
22 self._cache = compiled_fs_factory.Create( 112 self._cache = compiled_fs_factory.Create(
23 self._CreateManifestData, ManifestDataSource) 113 self._CreateManifestData, ManifestDataSource)
24 114
25 def _ApplyAppsTransformations(self, manifest): 115 def GetFeatures(self):
26 manifest['required'][0]['example'] = 'Application' 116 manifest_json = Parse(self._file_system.ReadSingle(self._manifest_path))
27 manifest['optional'][-1]['is_last'] = True 117 manifest_features = FeaturesModel.LoadFeaturesJson(
118 Parse(self._file_system.ReadSingle(self._features_path)))
28 119
29 def _ApplyExtensionsTransformations(self, manifest): 120 return manifest_features.MergeWith(manifest_json)
30 manifest['optional'][-1]['is_last'] = True
31 121
32 def _CreateManifestData(self, _, content): 122 def _CreateManifestData(self, _, content):
33 '''Take the contents of |_manifest_path| and create apps and extensions 123 '''Combine the contents of |_manifest_path| and |_features_path| into a
34 versions of a manifest example based on the contents of |_features_path|. 124 master dictionary then create filtered lists to be used by templates.
35 ''' 125 '''
36 def create_manifest_dict(): 126 manifest_json = Parse(content)
37 manifest_dict = OrderedDict() 127 manifest_features = FeaturesModel.LoadFeaturesJson(
38 for category in ('required', 'only_one', 'recommended', 'optional'): 128 Parse(self._file_system.ReadSingle(self._features_path)))
39 manifest_dict[category] = []
40 return manifest_dict
41 129
42 apps = create_manifest_dict() 130 manifest_features = manifest_features.MergeWith(manifest_json)
43 extensions = create_manifest_dict() 131 apps_features = _Annotate(_ConvertAndSortDocs(_RestructureChildren(
132 manifest_features.Filter(platform='app').Get()), 'app'))
133 extensions_features = _Annotate(_ConvertAndSortDocs(_RestructureChildren(
134 manifest_features.Filter(platform='extension').Get()), 'extension'))
not at google - send to devlin 2013/07/31 18:50:20 pull this repeated code into a little helper funct
jshumway 2013/08/01 22:27:50 Done.
44 135
45 manifest_json = Parse(content) 136 return {
46 features_json = Parse(self._file_system.ReadSingle( 137 'apps': apps_features,
47 self._features_path)) 138 'extensions': extensions_features
48 139 }
49 def add_property(feature, manifest_key, category):
50 '''If |feature|, from features_json, has the correct extension_types, add
51 |manifest_key| to either apps or extensions.
52 '''
53 added = False
54 extension_types = feature['extension_types']
55 if extension_types == 'all' or 'platform_app' in extension_types:
56 apps[category].append(deepcopy(manifest_key))
57 added = True
58 if extension_types == 'all' or 'extension' in extension_types:
59 extensions[category].append(deepcopy(manifest_key))
60 added = True
61 return added
62
63 # Property types are: required, only_one, recommended, and optional.
64 for category in manifest_json:
65 for manifest_key in manifest_json[category]:
66 # If a property is in manifest.json but not _manifest_features, this
67 # will cause an error.
68 feature = features_json[manifest_key['name']]
69 if add_property(feature, manifest_key, category):
70 del features_json[manifest_key['name']]
71
72 # All of the properties left in features_json are assumed to be optional.
73 for feature in features_json.keys():
74 item = features_json[feature]
75 # Handles instances where a features entry is a union with a whitelist.
76 if isinstance(item, list):
77 item = item[0]
78 add_property(item, {'name': feature}, 'optional')
79
80 apps['optional'].sort(key=itemgetter('name'))
81 extensions['optional'].sort(key=itemgetter('name'))
82
83 self._ApplyAppsTransformations(apps)
84 self._ApplyExtensionsTransformations(extensions)
85
86 return {'apps': apps, 'extensions': extensions}
87 140
88 def get(self, key): 141 def get(self, key):
89 return self._cache.GetFromFile(self._manifest_path)[key] 142 return self._cache.GetFromFile(self._manifest_path)[key]
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698