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
3 # found in the LICENSE file.
7 from data_source
import DataSource
8 import features_utility
9 from future
import Gettable
, Future
10 from manifest_features
import ConvertDottedKeysToNested
12 def _ListifyAndSortDocs(features
, app_name
):
13 '''Convert a |feautres| dictionary, and all 'children' dictionaries, into
14 lists recursively. Sort lists first by 'level' then by name.
17 '''Key function to sort items primarily by level (according to index into
18 levels) then subsort by name.
20 levels
= ('required', 'recommended', 'only_one', 'optional')
22 return (levels
.index(item
.get('level', 'optional')), item
['name'])
24 def coerce_example_to_feature(feature
):
25 '''To display json in examples more clearly, convert the example of
26 |feature| into the feature format, with a name and children, to be rendered
27 by the templates. Only applicable to examples that are dictionaries.
29 if not isinstance(feature
.get('example'), dict):
30 if 'example' in feature
:
31 feature
['example'] = json
.dumps(feature
['example'])
33 # Add any keys/value pairs in the dict as children
34 for key
, value
in feature
['example'].iteritems():
35 if not 'children' in feature
:
36 feature
['children'] = {}
37 feature
['children'][key
] = { 'name': key
, 'example': value
}
38 del feature
['example']
39 del feature
['has_example']
41 def convert_and_sort(features
):
42 for key
, value
in features
.items():
43 if 'example' in value
:
44 value
['has_example'] = True
45 example
= json
.dumps(value
['example'])
47 value
['example'] = '{...}'
49 value
['example'] = '[...]'
50 elif example
== '[{}]':
51 value
['example'] = '[{...}]'
53 coerce_example_to_feature(value
)
54 if 'children' in value
:
55 features
[key
]['children'] = convert_and_sort(value
['children'])
56 return sorted(features
.values(), key
=sort_key
)
58 # Replace {{platform}} in the 'name' manifest property example with
59 # |app_name|, the convention that the normal template rendering uses.
60 # TODO(kalman): Make the example a template and pass this through there.
61 if 'name' in features
:
62 name
= features
['name']
63 name
['example'] = name
['example'].replace('{{platform}}', app_name
)
65 features
= convert_and_sort(features
)
69 def _AddLevelAnnotations(features
):
70 '''Add level annotations to |features|. |features| and children lists must be
71 sorted by 'level'. Annotations are added to the first item in a group of
72 features of the same 'level'.
74 The last item in a list has 'is_last' set to True.
77 'required': 'Required',
78 'recommended': 'Recommended',
79 'only_one': 'Pick one (or none)',
80 'optional': 'Optional'
83 def add_annotation(item
, annotation
):
84 if not 'annotations' in item
:
85 item
['annotations'] = []
86 item
['annotations'].insert(0, annotation
)
88 def annotate(parent_level
, features
):
89 current_level
= parent_level
91 level
= item
.get('level', 'optional')
92 if level
!= current_level
:
93 add_annotation(item
, annotations
[level
])
95 if 'children' in item
:
96 annotate(level
, item
['children'])
98 features
[-1]['is_last'] = True
100 annotate('required', features
)
103 class ManifestDataSource(DataSource
):
104 '''Provides access to the properties in manifest features.
106 def __init__(self
, server_instance
, _
):
107 self
._features
_bundle
= server_instance
.features_bundle
108 self
._object
_store
= server_instance
.object_store_creator
.Create(
111 def _CreateManifestData(self
):
112 future_manifest_features
= self
._features
_bundle
.GetManifestFeatures()
114 manifest_features
= future_manifest_features
.Get()
115 def for_templates(manifest_features
, platform
):
116 return _AddLevelAnnotations(_ListifyAndSortDocs(
117 ConvertDottedKeysToNested(
118 features_utility
.Filtered(manifest_features
, platform
+ 's')),
119 app_name
=platform
.capitalize()))
121 'apps': for_templates(manifest_features
, 'app'),
122 'extensions': for_templates(manifest_features
, 'extension')
124 return Future(delegate
=Gettable(resolve
))
126 def _GetCachedManifestData(self
):
127 data
= self
._object
_store
.Get('manifest_data').Get()
129 data
= self
._CreateManifestData
().Get()
130 self
._object
_store
.Set('manifest_data', data
)
134 return self
._CreateManifestData
()
137 return self
._GetCachedManifestData
().get(key
)