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.
5 from copy
import deepcopy
8 from data_source
import DataSource
9 from future
import Future
10 from manifest_features
import ConvertDottedKeysToNested
11 from platform_util
import GetPlatforms
, PluralToSingular
14 def _ListifyAndSortDocs(features
, app_name
):
15 '''Convert a |feautres| dictionary, and all 'children' dictionaries, into
16 lists recursively. Sort lists first by 'level' then by name.
19 '''Key function to sort items primarily by level (according to index into
20 levels) then subsort by name.
22 levels
= ('required', 'recommended', 'only_one', 'optional')
24 return (levels
.index(item
.get('level', 'optional')), item
['name'])
26 def coerce_example_to_feature(feature
):
27 '''To display json in examples more clearly, convert the example of
28 |feature| into the feature format, with a name and children, to be rendered
29 by the templates. Only applicable to examples that are dictionaries.
31 if not isinstance(feature
.get('example'), dict):
32 if 'example' in feature
:
33 feature
['example'] = json
.dumps(feature
['example'])
35 # Add any keys/value pairs in the dict as children
36 for key
, value
in feature
['example'].iteritems():
37 if not 'children' in feature
:
38 feature
['children'] = {}
39 feature
['children'][key
] = { 'name': key
, 'example': value
}
40 del feature
['example']
41 del feature
['has_example']
43 def convert_and_sort(features
):
44 for key
, value
in features
.items():
45 if 'example' in value
:
46 value
['has_example'] = True
47 example
= json
.dumps(value
['example'])
49 value
['example'] = '{...}'
51 value
['example'] = '[...]'
52 elif example
== '[{}]':
53 value
['example'] = '[{...}]'
55 coerce_example_to_feature(value
)
56 if 'children' in value
:
57 features
[key
]['children'] = convert_and_sort(value
['children'])
58 return sorted(features
.values(), key
=sort_key
)
60 # Replace {{platform}} in the 'name' manifest property example with
61 # |app_name|, the convention that the normal template rendering uses.
62 # TODO(kalman): Make the example a template and pass this through there.
63 if 'name' in features
:
64 name
= features
['name']
65 name
['example'] = name
['example'].replace('{{platform}}', app_name
)
67 features
= convert_and_sort(features
)
71 def _AddLevelAnnotations(features
):
72 '''Add level annotations to |features|. |features| and children lists must be
73 sorted by 'level'. Annotations are added to the first item in a group of
74 features of the same 'level'.
76 The last item in a list has 'is_last' set to True.
79 'required': 'Required',
80 'recommended': 'Recommended',
81 'only_one': 'Pick one (or none)',
82 'optional': 'Optional'
85 def add_annotation(item
, annotation
):
86 if not 'annotations' in item
:
87 item
['annotations'] = []
88 item
['annotations'].insert(0, annotation
)
90 def annotate(parent_level
, features
):
91 current_level
= parent_level
93 level
= item
.get('level', 'optional')
94 if level
!= current_level
:
95 add_annotation(item
, annotations
[level
])
97 if 'children' in item
:
98 annotate(level
, item
['children'])
100 features
[-1]['is_last'] = True
102 annotate('required', features
)
105 class ManifestDataSource(DataSource
):
106 '''Provides access to the properties in manifest features.
108 def __init__(self
, server_instance
, _
):
109 self
._platform
_bundle
= server_instance
.platform_bundle
110 self
._object
_store
= server_instance
.object_store_creator
.Create(
113 def _CreateManifestDataForPlatform(self
, platform
):
114 future_manifest_features
= self
._platform
_bundle
.GetFeaturesBundle(
115 platform
).GetManifestFeatures()
117 manifest_features
= future_manifest_features
.Get()
118 return _AddLevelAnnotations(_ListifyAndSortDocs(
119 ConvertDottedKeysToNested(deepcopy(manifest_features
)),
120 app_name
=PluralToSingular(platform
).capitalize()))
121 return Future(callback
=resolve
)
123 def _CreateManifestData(self
):
124 manifest_data_futures
= dict((p
, self
._CreateManifestDataForPlatform
(p
))
125 for p
in GetPlatforms())
127 return dict((platform
, future
.Get())
128 for platform
, future
in manifest_data_futures
.iteritems())
129 return Future(callback
=resolve
)
131 def _GetCachedManifestData(self
):
132 data
= self
._object
_store
.Get('manifest_data').Get()
134 data
= self
._CreateManifestData
().Get()
135 self
._object
_store
.Set('manifest_data', data
)
139 return self
._GetCachedManifestData
().get(key
)
142 return self
._CreateManifestData
()