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

Unified 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: more idiomatic/less explicit copying 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 side-by-side diff with in-line comments
Download patch
Index: chrome/common/extensions/docs/server2/manifest_data_source.py
diff --git a/chrome/common/extensions/docs/server2/manifest_data_source.py b/chrome/common/extensions/docs/server2/manifest_data_source.py
index d0c2c15208be535c59f6a4a4ce50b089750a6c60..898352f6d3addce1ac0e48f30fd5702a193e4df4 100644
--- a/chrome/common/extensions/docs/server2/manifest_data_source.py
+++ b/chrome/common/extensions/docs/server2/manifest_data_source.py
@@ -2,14 +2,107 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-from copy import deepcopy
-from operator import itemgetter
+import json
-from third_party.json_schema_compiler.json_parse import OrderedDict, Parse
+import features_utility as features
+from third_party.json_schema_compiler.json_parse import Parse
+
+def _ListifyAndSortDocs(features, app_name):
+ '''Convert a |feautres| dictionary, and all 'children' dictionaries, into
+ lists recursively. Sort lists first by 'level' then by name.
+ '''
+ def sort_key(item):
+ '''Key function to sort items primarily by level (according to index into
+ levels) then subsort by name.
+ '''
+ levels = ('required', 'recommended', 'only_one', 'optional')
+
+ return (levels.index(item.get('level', 'optional')), item['name'])
+
+ def convert_and_sort(features):
+ for key, value in features.items():
+ if 'example' in value:
+ value['has_example'] = True
+ example = json.dumps(value['example'])
+ if example == '{}':
+ value['example'] = '{...}'
+ elif example == '[]':
+ value['example'] = '[...]'
+ else:
+ value['example'] = example
+
+ if 'children' in value:
+ features[key]['children'] = convert_and_sort(value['children'])
+
+ return sorted(features.values(), key=sort_key)
+
+ name = features['name']
+ name['example'] = name['example'].replace('{{title}}', app_name)
+
+ return convert_and_sort(features)
+
+def _AddLevelAnnotations(features):
+ '''Add level annotations to |features|. |features| and children lists must be
+ sorted by 'level'. Annotations are added to the first item in a group of
+ features of the same 'level'.
+
+ The last item in a list has 'is_last' set to True.
+ '''
+ annotations = {
+ 'required': 'Required',
+ 'recommended': 'Recommended',
+ 'only_one': 'Pick one (or none)',
+ 'optional': 'Optional'
+ }
+
+ def add_annotation(item, annotation):
+ if not 'annotations' in item:
+ item['annotations'] = []
+ item['annotations'].insert(0, annotation)
+
+ def annotate(parent_level, features):
+ current_level = parent_level
+ for item in features:
+ level = item.get('level', 'optional')
+ if level != current_level:
+ add_annotation(item, annotations[level])
+ current_level = level
+ if 'children' in item:
+ annotate(level, item['children'])
+ if features:
+ features[-1]['is_last'] = True
+
+ annotate('required', features)
+ return features
+
+def _RestructureChildren(features):
+ '''Features whose names are of the form 'parent.child' are moved to be part
+ of the 'parent' dictionary under the key 'children'. Names are changed to
+ the 'child' section of the original name. Applied recursively so that
+ children can have children.
+ '''
+ def add_child(features, parent, child_name, value):
+ value['name'] = child_name
+ if not 'children' in features[parent]:
+ features[parent]['children'] = {}
+ features[parent]['children'][child_name] = value
+
+ def insert_children(features):
+ for name in features.keys():
+ if '.' in name:
+ value = features.pop(name)
+ parent, child_name = name.split('.', 1)
+ add_child(features, parent, child_name, value)
+
+ for value in features.values():
+ if 'children' in value:
+ insert_children(value['children'])
+
+ insert_children(features)
+ return features
class ManifestDataSource(object):
- '''Provides a template with access to manifest properties specific to apps or
- extensions.
+ '''Provides access to the properties in manifest features.
'''
def __init__(self,
compiled_fs_factory,
@@ -22,68 +115,37 @@ class ManifestDataSource(object):
self._cache = compiled_fs_factory.Create(
self._CreateManifestData, ManifestDataSource)
- def _ApplyAppsTransformations(self, manifest):
- manifest['required'][0]['example'] = 'Application'
- manifest['optional'][-1]['is_last'] = True
+ def GetFeatures(self):
+ '''Returns a dictionary of the contents of |_features_path| merged with
+ |_manifest_path|.
+ '''
+ manifest_json = Parse(self._file_system.ReadSingle(self._manifest_path))
+ manifest_features = FeaturesModel.FromJson(
+ Parse(self._file_system.ReadSingle(self._features_path)))
+
+ return manifest_features.MergeWith(manifest_json)
- def _ApplyExtensionsTransformations(self, manifest):
- manifest['optional'][-1]['is_last'] = True
def _CreateManifestData(self, _, content):
- '''Take the contents of |_manifest_path| and create apps and extensions
- versions of a manifest example based on the contents of |_features_path|.
+ '''Combine the contents of |_manifest_path| and |_features_path| and filter
+ the results into lists specific to apps or extensions for templates. Marks
+ up features with annotations.
'''
- def create_manifest_dict():
- manifest_dict = OrderedDict()
- for category in ('required', 'only_one', 'recommended', 'optional'):
- manifest_dict[category] = []
- return manifest_dict
-
- apps = create_manifest_dict()
- extensions = create_manifest_dict()
-
- manifest_json = Parse(content)
- features_json = Parse(self._file_system.ReadSingle(
- self._features_path))
-
- def add_property(feature, manifest_key, category):
- '''If |feature|, from features_json, has the correct extension_types, add
- |manifest_key| to either apps or extensions.
- '''
- added = False
- extension_types = feature['extension_types']
- if extension_types == 'all' or 'platform_app' in extension_types:
- apps[category].append(deepcopy(manifest_key))
- added = True
- if extension_types == 'all' or 'extension' in extension_types:
- extensions[category].append(deepcopy(manifest_key))
- added = True
- return added
-
- # Property types are: required, only_one, recommended, and optional.
- for category in manifest_json:
- for manifest_key in manifest_json[category]:
- # If a property is in manifest.json but not _manifest_features, this
- # will cause an error.
- feature = features_json[manifest_key['name']]
- if add_property(feature, manifest_key, category):
- del features_json[manifest_key['name']]
-
- # All of the properties left in features_json are assumed to be optional.
- for feature in features_json.keys():
- item = features_json[feature]
- # Handles instances where a features entry is a union with a whitelist.
- if isinstance(item, list):
- item = item[0]
- add_property(item, {'name': feature}, 'optional')
-
- apps['optional'].sort(key=itemgetter('name'))
- extensions['optional'].sort(key=itemgetter('name'))
-
- self._ApplyAppsTransformations(apps)
- self._ApplyExtensionsTransformations(extensions)
-
- return {'apps': apps, 'extensions': extensions}
+ def for_templates(manifest_features, platform):
+ return _AddLevelAnnotations(
+ _ListifyAndSortDocs(
+ _RestructureChildren(
+ features.Filtered(manifest_features, platform)),
+ app_name=platform.capitalize()))
+
+ manifest_json = Parse(self._file_system.ReadSingle(self._manifest_path))
+ manifest_features = features.MergedWith(
+ features.Parse(Parse(content)), manifest_json)
+
+ return {
+ 'apps': for_templates(manifest_features, 'app'),
+ 'extensions': for_templates(manifest_features, 'extension')
+ }
def get(self, key):
- return self._cache.GetFromFile(self._manifest_path)[key]
+ return self._cache.GetFromFile(self._features_path)[key]

Powered by Google App Engine
This is Rietveld 408576698